diff -ur dvipdfmx-20110311.orig/src/dvi.c dvipdfmx-20110311/src/dvi.c
--- dvipdfmx-20110311.orig/src/dvi.c	2011-11-05 14:58:04.000000000 +0100
+++ dvipdfmx-20110311/src/dvi.c	2012-01-17 19:27:40.000000000 +0100
@@ -654,19 +654,25 @@
 
 void dvi_right (SIGNED_QUAD x)
 {
-  if (!dvi_state.d) {
-    dvi_state.h += x;
-  } else {
-    dvi_state.v += x;
+  switch (dvi_state.d) {
+  case 0:
+    dvi_state.h += x; break;
+  case 1:
+    dvi_state.v += x; break;
+  case 3:
+    dvi_state.v -= x; break;
   }
 }
 
 void dvi_down (SIGNED_QUAD y)
 {
-  if (!dvi_state.d) {
-    dvi_state.v += y;
-  } else {
-    dvi_state.h -= y;
+  switch (dvi_state.d) {
+  case 0:
+    dvi_state.v += y; break;
+  case 1:
+    dvi_state.h -= y; break;
+  case 3:
+    dvi_state.h += y; break;
   }
 }
 
@@ -721,10 +727,13 @@
     }
     dvi_pop();
   }
-  if (!dvi_state.d) {
-    dvi_state.h += width;
-  } else {
-    dvi_state.v += width;
+  switch (dvi_state.d) {
+  case 0:
+    dvi_state.h += width; break;
+  case 1:
+    dvi_state.v += width; break;
+  case 3:
+    dvi_state.v -= width; break;
   }
 }
 
@@ -803,11 +812,13 @@
     vf_set_char(ch, font->font_id); /* push/pop invoked */
     break;
   }
-
-  if (!dvi_state.d) {
-    dvi_state.h += width;
-  } else {
-    dvi_state.v += width;
+  switch (dvi_state.d) {
+  case 0:
+    dvi_state.h += width; break;
+  case 1:
+    dvi_state.v += width; break;
+  case 3:
+    dvi_state.v -= width; break;
   }
 }
 
@@ -890,17 +901,24 @@
 {
   do_moveto(dvi_state.h, dvi_state.v);
 
-  if (!dvi_state.d) {
+  switch (dvi_state.d) {
+  case 0:
     pdf_dev_set_rule(dvi_state.h, -dvi_state.v,  width, height);
-  } else { /* right ? */
+    break;
+  case 1:
     pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width);
+    break;
+  case 3: 
+    pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width);
+    break;
   }
 }
 
 void
-dvi_dir (UNSIGNED_BYTE dir)
+dvi_dir (UNSIGNED_BYTE dir) /* how? */
 {
-  dvi_state.d = dir ? 1 : 0;
+  fprintf(stderr, "  > dvi_dir %d\n", dir);
+  dvi_state.d = dir;
   pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */
 }
 
@@ -1385,7 +1403,7 @@
 static void
 do_dir (void)
 {
-  dvi_state.d = get_unsigned_byte(dvi_file) ? 1 : 0;
+  dvi_state.d = get_unsigned_byte(dvi_file);
   pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */
 }
 
diff -ur dvipdfmx-20110311.orig/src/pdfdev.c dvipdfmx-20110311/src/pdfdev.c
--- dvipdfmx-20110311.orig/src/pdfdev.c	2011-03-06 04:14:14.000000000 +0100
+++ dvipdfmx-20110311/src/pdfdev.c	2012-01-17 19:27:40.000000000 +0100
@@ -332,19 +332,23 @@
  * is vertical font. While ASCII pTeX manages current writing direction
  * and font's WMode separately.
  *
- * 00/11 WMODE_HH/VV  h(v) font, h(v) direction.
- * 01    WMODE_HV    -90 deg. rotated
- * 10    WMODE_VH    +90 deg. rotated
- *
+ * 000/101 WMODE_HH/VV  h(v) font, h(v) direction.
+ * 001    WMODE_HV    -90 deg. rotated  
+ * 100    WMODE_VH    +90 deg. rotated
+ * 011    WMODE_HD    +90 deg. rotated
+ * 111    WMODE_VD    180 deg. rotated
+
  * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode
  * is applied.
  */
 #define TEXT_WMODE_HH 0
 #define TEXT_WMODE_HV 1
-#define TEXT_WMODE_VH 2
-#define TEXT_WMODE_VV 3
+#define TEXT_WMODE_VH 4
+#define TEXT_WMODE_VV 5
+#define TEXT_WMODE_HD 3
+#define TEXT_WMODE_VD 7
 
-#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 3) == 0 ? 0 : 1)
+#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1)
 #define ROTATE_TEXT(m)       ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV)
 
 static struct {
@@ -526,6 +530,16 @@
     tm.a =  1.0; tm.b =  -slant;
     tm.c =  0.0; tm.d =   extend;
     break;
+  case TEXT_WMODE_HD:
+    /* Horizontal font */
+    tm.a =  0.0;    tm.b = extend;
+    tm.c = -1.0;    tm.d = slant ;
+    break;
+  case TEXT_WMODE_VD:
+    /* Vertical font */
+    tm.a = -1.0; tm.b =   slant;
+    tm.c =  0.0; tm.d =  -extend;
+    break;
   }
   tm.e = xpos * dev_unit.dvi2pts;
   tm.f = ypos * dev_unit.dvi2pts;
@@ -730,6 +744,39 @@
     format_buffer[len++] = ' ';
     len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely);
     break;
+  case TEXT_WMODE_HD:
+    /* Horizontal font in down-to-up mode: rot = +90
+     *
+     *                          | s/e  -1|
+     * d_user = d x -I_hv = d x |        |
+     *                          | 1/e   0|
+     */
+    desired_delx = -(spt_t)(-(dely + delx*slant)/extend);
+    desired_dely = -delx;
+
+    format_buffer[len++] = ' ';
+    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely);
+    format_buffer[len++] = ' ';
+    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx);
+    error_delx = -error_delx;
+    error_dely = -error_dely;
+   break;
+  case TEXT_WMODE_VD:
+    /* Vertical font in down-to-up mode: rot = 180
+     *                          |-1 -s/e|
+     * d_user = d x -I_vv = d x |       |
+     *                          | 0 -1/e|
+     */
+    desired_delx = -delx;
+    desired_dely = -(spt_t)((dely + delx*slant)/extend);
+
+    format_buffer[len++] = ' ';
+    len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx);
+    format_buffer[len++] = ' ';
+    len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely);
+    error_delx = -error_delx;
+    error_dely = -error_dely;
+    break;
   }
   pdf_doc_add_page_content(format_buffer, len);  /* op: */
   /*
@@ -798,11 +845,11 @@
 
   vert_font  = font->wmode ? 1 : 0;
   if (dev_param.autorotate) {
-    vert_dir = text_state.dir_mode ? 1 : 0;
+    vert_dir = text_state.dir_mode;
   } else {
     vert_dir = vert_font;
   }
-  text_rotate = (vert_font << 1)|vert_dir;
+  text_rotate = (vert_font << 2)|vert_dir;
 
   if (font->slant  != text_state.matrix.slant  ||
       font->extend != text_state.matrix.extend ||
@@ -1085,14 +1132,18 @@
    * (in 1000 units per em) but dvipdfmx does not take into account of this...
    */
 
-  if (text_state.dir_mode) {
+  if (text_state.dir_mode==0) {
+    /* Left-to-right */
+    delh = text_xorigin + text_state.offset - xpos;
+    delv = ypos - text_yorigin;
+  } else if (text_state.dir_mode==1) {
     /* Top-to-bottom */
     delh = ypos - text_yorigin + text_state.offset;
     delv = xpos - text_xorigin;
   } else {
-    /* Left-to-right */
-    delh = text_xorigin + text_state.offset - xpos;
-    delv = ypos - text_yorigin;
+    /* Bottom-to-top */
+    delh = ypos + text_yorigin + text_state.offset;
+    delv = xpos + text_xorigin;
   }
 
   /* White-space more than 3em is not considered as a part of single text.
@@ -1615,11 +1666,11 @@
 
   vert_font = (font && font->wmode) ? 1 : 0;
   if (dev_param.autorotate) {
-    vert_dir = text_dir ? 1 : 0;
+    vert_dir = text_dir;
   } else {
     vert_dir = vert_font;
   }
-  text_rotate = (vert_font << 1)|vert_dir;
+  text_rotate = (vert_font << 2)|vert_dir;
 
   if (font &&
       ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) {
@@ -1640,11 +1691,11 @@
 
   vert_font = (font && font->wmode) ? 1 : 0;
   if (auto_rotate) {
-    vert_dir = text_state.dir_mode ? 1 : 0;
+    vert_dir = text_state.dir_mode;
   } else {
     vert_dir = vert_font;
   }
-  text_rotate = (vert_font << 1)|vert_dir;
+  text_rotate = (vert_font << 2)|vert_dir;
 
   if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) {
     text_state.force_reset = 1;
