diff -ur dvipdfmx-20110311.orig/src/dvi.c dvipdfmx-20110311/src/dvi.c
--- dvipdfmx-20110311.orig/src/dvi.c	Wed Mar 09 16:43:18 2011
+++ dvipdfmx-20110311/src/dvi.c	Sat Nov 05 22:25:11 2011
@@ -58,6 +58,10 @@
 #define TEX_FONTS_ALLOC_SIZE 16u
 #define VF_NESTING_MAX       16u
 
+/* UTF-32 over U+FFFF -> UTF-16 surrogate pair */
+#define UTF32toUTF16HS(x)  (0xd800 + (((x-0x10000) >> 10) & 0x3ff))
+#define UTF32toUTF16LS(x)  (0xdc00 + (  x                 & 0x3ff))
+
 /* Interal Variables */
 static FILE          *dvi_file  = NULL;
 
@@ -734,7 +738,7 @@
 {
   struct loaded_font *font;
   spt_t               width, height, depth;
-  unsigned char       wbuf[2];
+  unsigned char       wbuf[4];
 
   if (current_font < 0) {
     ERROR("No font selected!");
@@ -753,7 +757,14 @@
 
   switch (font->type) {
   case  PHYSICAL:
-    if (ch > 255) { /* _FIXME_ */
+    if (ch > 65535) { /* _FIXME_ */
+      wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff;
+      wbuf[1] =  UTF32toUTF16HS(ch)       & 0xff;
+      wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff;
+      wbuf[3] =  UTF32toUTF16LS(ch)       & 0xff;
+      pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4,
+			 width, font->font_id, 2);
+    } else if (ch > 255) { /* _FIXME_ */
       wbuf[0] = (ch >> 8) & 0xff;
       wbuf[1] =  ch & 0xff;
       pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
@@ -805,7 +816,7 @@
 {
   struct loaded_font *font;
   spt_t               width, height, depth;
-  unsigned char       wbuf[2];
+  unsigned char       wbuf[4];
 
   if (current_font < 0) {
     ERROR("No font selected!");
@@ -821,7 +832,14 @@
     /* Treat a single character as a one byte string and use the
      * string routine.
      */
-    if (ch > 255) { /* _FIXME_ */
+    if (ch > 65535) { /* _FIXME_ */
+      wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff;
+      wbuf[1] =  UTF32toUTF16HS(ch)       & 0xff;
+      wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff;
+      wbuf[3] =  UTF32toUTF16LS(ch)       & 0xff;
+      pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4,
+			 width, font->font_id, 2);
+    } else if (ch > 255) { /* _FIXME_ */
       wbuf[0] = (ch >> 8) & 0xff;
       wbuf[1] =  ch & 0xff;
       pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
@@ -899,6 +917,12 @@
 }
 
 static void
+do_set3 (void)
+{
+  dvi_set(get_unsigned_triple(dvi_file));
+}
+
+static void
 do_setrule (void)
 {
   SIGNED_QUAD  width, height;
@@ -935,6 +959,12 @@
   dvi_put(get_unsigned_pair(dvi_file));
 }
 
+static void
+do_put3 (void)
+{
+  dvi_put(get_unsigned_triple(dvi_file));
+}
+
 void
 dvi_push (void) 
 {
@@ -1414,8 +1444,9 @@
     switch (opcode) {
     case SET1: do_set1(); break;
     case SET2: do_set2(); break;
-    case SET3: case SET4:
-      ERROR("Multibyte (>16 bits) character not supported!");
+    case SET3: do_set3(); break;
+    case SET4:
+      ERROR("Multibyte (>24 bits) character not supported!");
       break;
 
     case SET_RULE:
@@ -1424,8 +1455,9 @@
 
     case PUT1: do_put1(); break;
     case PUT2: do_put2(); break;
-    case PUT3: case PUT4:
-      ERROR ("Multibyte character (>16 bits) not supported!");
+    case PUT3: do_put3(); break;
+    case PUT4:
+      ERROR ("Multibyte character (>24 bits) not supported!");
       break;
 
     case PUT_RULE:
diff -ur dvipdfmx-20110311.orig/src/tfm.c dvipdfmx-20110311/src/tfm.c
--- dvipdfmx-20110311.orig/src/tfm.c	Sat Mar 05 13:44:49 2011
+++ dvipdfmx-20110311/src/tfm.c	Sat Nov 05 22:33:49 2011
@@ -55,6 +55,12 @@
 #define IS_JFM(i) ((i) == JFM_ID || (i) == JFMV_ID)
 #endif /* !WITHOUT_ASCII_PTEX */
 
+#if !defined(WITHOUT_ASCII_PTEX)
+#define CHARACTER_INDEX(i)  ((i>0xFFFFul ? 0x10000ul : i))
+#else
+#define CHARACTER_INDEX(i)  ((i))
+#endif
+
 /*
  * TFM Record structure:
  * Multiple TFM's may be read in at once.
@@ -162,7 +168,7 @@
 struct coverage
 {
   long           first_char;
-  unsigned short num_chars;
+  long           num_chars;
 };
 
 /*
@@ -208,7 +214,7 @@
 {
   if (charcode >= map->coverage.first_char &&
       charcode <= map->coverage.first_char + map->coverage.num_chars)
-    return map->indices[charcode - map->coverage.first_char];
+    return map->indices[CHARACTER_INDEX(charcode - map->coverage.first_char)];
   else
     return -1;
 
@@ -224,7 +230,7 @@
 	 charcode >= map->coverages[idx].first_char; idx--) {
     if (charcode <=
 	map->coverages[idx].first_char + map->coverages[idx].num_chars)
-      return map->indices[idx];
+      return map->indices[CHARACTER_INDEX(idx)];
   }
 
   return -1;
@@ -479,12 +485,13 @@
     fm->charmap.type = MAPTYPE_CHAR;
     fm->charmap.data = map = NEW(1, struct char_map);
     map->coverage.first_char = 0;
-    map->coverage.num_chars  = 0xFFFFu;
-    map->indices    = NEW(0x10000L, unsigned short);
+    map->coverage.num_chars  = 0x10FFFFu;
+    map->indices    = NEW(0x10001ul, unsigned short);
 
     for (code = 0; code <= 0xFFFFu; code++) {
       map->indices[code] = tfm->chartypes[code];
     }
+    map->indices[0x10000ul] = tfm->chartypes[0];
   } else {
     struct range_map *map;
 
@@ -493,7 +500,7 @@
     map->num_coverages = 1;
     map->coverages     = NEW(map->num_coverages, struct coverage);
     map->coverages[0].first_char = 0;
-    map->coverages[0].num_chars  = 0xFFFFu;
+    map->coverages[0].num_chars  = 0x10FFFFu;
     map->indices = NEW(1, unsigned short);
     map->indices[0] = 0; /* Only default type used. */
   }
@@ -784,7 +791,7 @@
     jfm_do_char_type_array(tfm_file, &tfm);
     jfm_make_charmap(fm, &tfm);
     fm->firstchar = 0;
-    fm->lastchar  = 0xFFFFl;
+    fm->lastchar  = 0x10FFFFl;
     fm->fontdir   = (tfm.id == JFMV_ID) ? FONT_DIR_VERT : FONT_DIR_HORIZ;
     fm->source    = SOURCE_TYPE_JFM;
   }
diff -ur dvipdfmx-20110311.orig/src/vf.c dvipdfmx-20110311/src/vf.c
--- dvipdfmx-20110311.orig/src/vf.c	Sat Mar 05 13:44:49 2011
+++ dvipdfmx-20110311/src/vf.c	Sat Nov 05 22:35:40 2011
@@ -238,11 +238,11 @@
 	ch = get_unsigned_quad (vf_file);
 	/* Skip over TFM width since we already know it */
 	get_unsigned_quad (vf_file);
-	if (ch < 65536L) 
+	if (ch < 0x1000000L) 
 	  read_a_char_def (vf_file, thisfont, pkt_len, ch);
 	else {
 	  fprintf (stderr, "char=%ld\n", ch);
-	  ERROR ("Long character (>16 bits) in VF file.\nI can't handle long characters!\n");
+	  ERROR ("Long character (>24 bits) in VF file.\nI can't handle long characters!\n");
 	}
 	break;
       }
@@ -455,6 +455,12 @@
   return;
 }
 
+static void vf_set3(unsigned char **start, unsigned char *end) 
+{
+  vf_set (unsigned_triple(start, end));
+  return;
+}
+
 static void vf_putrule(unsigned char **start, unsigned char *end, spt_t ptsize)
 {
   SIGNED_QUAD width, height;
@@ -491,6 +497,12 @@
   return;
 }
 
+static void vf_put3(unsigned char **start, unsigned char *end)
+{
+  dvi_put (unsigned_triple(start, end));
+  return;
+}
+
 static void vf_push(void)
 {
   dvi_push();
@@ -851,8 +863,10 @@
 	  vf_set2(&start, end);
 	  break;
 	case SET3:
+	  vf_set3(&start, end);
+	  break;
 	case SET4:
-	  ERROR ("Multibyte (>16 bits) character in VF packet.\nI can't handle this!");
+	  ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
 	  break;
 	case SET_RULE:
 	  vf_setrule(&start, end, ptsize);
@@ -864,8 +878,10 @@
 	  vf_put2(&start, end);
 	  break;
 	case PUT3:
+	  vf_put3(&start, end);
+	  break;
 	case PUT4:
-	  ERROR ("Multibyte (>16 bits) character in VF packet.\nI can't handle this!");
+	  ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
 	  break;
 	case PUT_RULE:
 	  vf_putrule(&start, end, ptsize);
