--- pango-1.24.5/pango/pango-context.c.orig	2009-10-05 15:14:13.000000000 +0900
+++ pango-1.24.5/pango/pango-context.c	2009-10-13 19:17:34.000000000 +0900
@@ -56,6 +56,8 @@ struct _PangoContextClass
 };
 
 static void pango_context_finalize    (GObject           *object);
+static PangoLanguage * compute_derived_language (PangoLanguage *lang,
+                                                 PangoScript    script);
 
 G_DEFINE_TYPE (PangoContext, pango_context, G_TYPE_OBJECT)
 
@@ -650,6 +652,11 @@ typedef enum {
 } ChangedFlags;
 
 
+typedef enum {
+  WIDTH_NOWIDE         = 0,
+  WIDTH_WIDE           = 1 << 1,
+  WIDTH_VERTICAL_ALNUM = 1 << 2
+} WideFlags;
 
 typedef struct _PangoWidthIter PangoWidthIter;
 
@@ -659,7 +666,7 @@ struct _PangoWidthIter
 	const gchar *text_end;
 	const gchar *start;
 	const gchar *end;
-	gboolean wide;
+	WideFlags wide;
 };
 
 typedef struct _ItemizeState ItemizeState;
@@ -799,34 +806,102 @@ update_end (ItemizeState *state)
     state->run_end = state->width_iter.end;
 }
 
-static void
-width_iter_next(PangoWidthIter* iter)
+static gboolean
+width_iter_next(PangoWidthIter* iter, gboolean vertical_alnum)
 {
+  gint digit = 0;
+  const gchar *first_digit_c = NULL;
+  const gchar *p;
+  gboolean iswide;
+
   iter->start = iter->end;
 
+  if (iter->wide & WIDTH_VERTICAL_ALNUM)
+    iter->wide ^= WIDTH_VERTICAL_ALNUM;
+
   if (iter->end < iter->text_end)
     {
       gunichar ch = g_utf8_get_char (iter->end);
-      iter->wide = g_unichar_iswide (ch);
+      iter->wide = g_unichar_iswide (ch) ? WIDTH_WIDE : WIDTH_NOWIDE;
     }
 
   while (iter->end < iter->text_end)
     {
       gunichar ch = g_utf8_get_char (iter->end);
-      if (g_unichar_iswide (ch) != iter->wide)
+      iswide = g_unichar_iswide (ch);
+
+      if (iswide == FALSE && g_unichar_isalnum (ch))
+        {
+          if (digit == 0)
+            first_digit_c = iter->end;
+          digit++;
+        }
+      else
+        {
+          /* If the digit is one or two on CJK, the gravity is vertical.
+           */
+          if (digit == 1 || digit == 2)
+            {
+              if (first_digit_c > iter->start)
+                iter->end = first_digit_c;
+              break;
+            }
+          digit = 0;
+        }
+
+      if (iswide != (iter->wide == WIDTH_WIDE))
         break;
       iter->end = g_utf8_next_char (iter->end);
     }
+
+  if (iter->end == iter->text_end)
+    {
+      if (digit == 1 || digit == 2)
+        {
+          if (first_digit_c > iter->start)
+            iter->end = first_digit_c;
+        }
+    }
+
+  digit = 0;
+  for (p = iter->start;
+       vertical_alnum && p < iter->end;
+       p = g_utf8_next_char (p))
+    {
+      gunichar ch = g_utf8_get_char (p);
+
+      if (g_unichar_isalnum (ch) && !g_unichar_iswide(ch))
+        digit++;
+      else
+        break;
+    }
+
+  if (iter->wide == WIDTH_NOWIDE && (digit == 1 || digit == 2))
+    {
+      iter->wide |= WIDTH_VERTICAL_ALNUM;
+      return TRUE;
+    }
+
+  return FALSE;
 }
 
 static void
-width_iter_init (PangoWidthIter* iter, const char* text, int length)
+width_iter_init (PangoWidthIter* iter, const char* text, int length, ItemizeState *state)
 {
+  PangoLanguage *lang;
+  gboolean vertical_alnum;
+
   iter->text_start = text;
   iter->text_end = text + length;
   iter->start = iter->end = text;
 
-  width_iter_next (iter);
+  lang = compute_derived_language (state->lang, state->script);
+  vertical_alnum = pango_language_matches (lang, "ja;ko;zh");
+
+  if (width_iter_next (iter, vertical_alnum))
+    {
+      state->script = PANGO_SCRIPT_HAN;
+    }
 }
 
 static void
@@ -903,7 +978,7 @@ itemize_state_init (ItemizeState      *s
 			       &state->script_end, &state->script);
 
   /* Initialize the width iterator */
-  width_iter_init (&state->width_iter, text + start_index, length);
+  width_iter_init (&state->width_iter, text + start_index, length, state);
 
   update_end (state);
 
@@ -930,6 +1005,9 @@ itemize_state_init (ItemizeState      *s
 static gboolean
 itemize_state_next (ItemizeState *state)
 {
+  PangoLanguage *lang;
+  gboolean vertical_alnum;
+
   if (state->run_end == state->end)
     return FALSE;
 
@@ -957,7 +1035,13 @@ itemize_state_next (ItemizeState *state)
     }
   if (state->run_end == state->width_iter.end)
     {
-      width_iter_next (&state->width_iter);
+      lang = compute_derived_language (state->lang, state->script);
+      vertical_alnum = pango_language_matches (lang, "ja;ko;zh");
+
+      if (width_iter_next (&state->width_iter, vertical_alnum))
+        {
+          state->script = PANGO_SCRIPT_HAN;
+        }
       state->changed |= WIDTH_CHANGED;
     }
 
@@ -1075,6 +1159,12 @@ itemize_state_add_character (ItemizeStat
     }
 
   state->item->analysis.flags = state->centered_baseline ? PANGO_ANALYSIS_FLAG_CENTERED_BASELINE : 0;
+  if (PANGO_GRAVITY_IS_VERTICAL (state->resolved_gravity) &&
+      state->width_iter.wide & WIDTH_VERTICAL_ALNUM)
+    {
+      state->item->analysis.flags |= PANGO_ANALYSIS_FLAG_VERTICAL_ROTATE;
+    }
+
 
   state->item->analysis.script = state->script;
   state->item->analysis.language = state->derived_lang;
@@ -1307,7 +1397,7 @@ itemize_state_update_for_new_run (Itemiz
 	    gravity = state->context->resolved_gravity;
 
 	  state->resolved_gravity = pango_gravity_get_for_script_and_width (state->script,
-									    state->width_iter.wide,
+									    state->width_iter.wide != WIDTH_NOWIDE,
 									    gravity,
 									    gravity_hint);
 	}
--- pango-1.24.5/pango/pango-gravity.c.orig	2009-10-05 15:40:50.000000000 +0900
+++ pango-1.24.5/pango/pango-gravity.c	2009-10-05 15:54:48.000000000 +0900
@@ -330,6 +330,10 @@ pango_gravity_get_for_script_and_width (
       if ((base_gravity   == PANGO_GRAVITY_EAST) ^
 	  (props.vert_dir == PANGO_VERTICAL_DIRECTION_BTT))
 	return PANGO_GRAVITY_SOUTH;
+      if ((base_gravity   == PANGO_GRAVITY_WEST) &&
+	  (props.preferred_gravity == PANGO_GRAVITY_EAST) &&
+	  (props.vert_dir == PANGO_VERTICAL_DIRECTION_TTB))
+	return PANGO_GRAVITY_SOUTH;
       else
 	return PANGO_GRAVITY_NORTH;
 
--- pango-1.24.5/pango/pango-item.h.orig	2009-10-13 11:59:36.000000000 +0900
+++ pango-1.24.5/pango/pango-item.h	2009-10-13 12:01:31.000000000 +0900
@@ -31,6 +31,7 @@ typedef struct _PangoItem PangoItem;
 
 /* TODO: if more flags are needed, turn this into a real PangoAnalysisFlags enum */
 #define PANGO_ANALYSIS_FLAG_CENTERED_BASELINE (1 << 0)
+#define PANGO_ANALYSIS_FLAG_VERTICAL_ROTATE (1 << 1)
 
 struct _PangoAnalysis
 {
--- pango-1.24.5/pango/pangocairo-render.c.orig	2009-10-13 12:24:45.000000000 +0900
+++ pango-1.24.5/pango/pangocairo-render.c	2009-10-13 19:21:42.000000000 +0900
@@ -294,6 +294,8 @@ pango_cairo_renderer_show_text_glyphs (P
 
   int i, count;
   int x_position = 0;
+  int y_position = 0;
+  PangoGlyphUnit x_offset, y_offset;
   cairo_glyph_t *cairo_glyphs;
   cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
   double base_x = crenderer->x_offset + (double)x / PANGO_SCALE;
@@ -309,16 +311,36 @@ pango_cairo_renderer_show_text_glyphs (P
 	{
 	  PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
+	  if (gi->geometry.x_offset == 0 && gi->geometry.y_offset)
+	    {
+	      x_offset = (gi->geometry.y_offset > 0) ? gi->geometry.y_offset : 0;
+	      y_offset = gi->geometry.x_offset;
+	      if (i == 0)
+	        {
+	          base_y = 0;
+	          y_offset += gi->geometry.width;
+	        }
+	    }
+	  else
+	    {
+	      x_offset = gi->geometry.x_offset;
+	      y_offset = gi->geometry.y_offset;
+	    }
+
 	  if (gi->glyph != PANGO_GLYPH_EMPTY)
 	    {
-	      double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+	      double cx = base_x + (double)(x_position + x_offset) / PANGO_SCALE;
 	      double cy = gi->geometry.y_offset == 0 ?
 			  base_y :
-			  base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+			  base_y + (double)(y_position + y_offset) / PANGO_SCALE;
 
 	      _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
 	    }
-	  x_position += gi->geometry.width;
+
+	  if (gi->geometry.x_offset == 0 && gi->geometry.y_offset)
+	    y_position -= (gi->geometry.width + 2 * PANGO_SCALE);
+	  else
+	    x_position += gi->geometry.width;
 	}
 
       goto done;
@@ -334,12 +356,28 @@ pango_cairo_renderer_show_text_glyphs (P
     {
       PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
+      if (gi->geometry.x_offset == 0 && gi->geometry.y_offset)
+        {
+          x_offset = (gi->geometry.y_offset > 0) ? gi->geometry.y_offset : 0;
+          y_offset = gi->geometry.x_offset;
+          if (i == 0)
+            {
+              base_y = 0;
+              y_offset += gi->geometry.width;
+            }
+        }
+      else
+        {
+          x_offset = gi->geometry.x_offset;
+          y_offset = gi->geometry.y_offset;
+        }
+
       if (gi->glyph != PANGO_GLYPH_EMPTY)
 	{
-	  double cx = base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+	  double cx = base_x + (double)(x_position + x_offset) / PANGO_SCALE;
 	  double cy = gi->geometry.y_offset == 0 ?
 		      base_y :
-		      base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+		      base_y + (double)(y_position + y_offset) / PANGO_SCALE;
 
 	  if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
 	    _pango_cairo_renderer_draw_unknown_glyph (crenderer, font, gi, cx, cy);
@@ -351,7 +389,11 @@ pango_cairo_renderer_show_text_glyphs (P
 	      count++;
 	    }
 	}
-      x_position += gi->geometry.width;
+
+      if (gi->geometry.x_offset == 0 && gi->geometry.y_offset)
+        y_position -= (gi->geometry.width + 2 * PANGO_SCALE);
+      else
+        x_position += gi->geometry.width;
     }
 
   if (G_UNLIKELY (crenderer->do_path))
--- pango-1.24.5/pango/shape.c.orig	2009-10-13 12:27:42.000000000 +0900
+++ pango-1.24.5/pango/shape.c	2009-10-13 19:23:14.000000000 +0900
@@ -138,7 +138,15 @@ pango_shape (const gchar      *text,
       if (glyphs->glyphs[i].geometry.width < 0)
 	{
 	  glyphs->glyphs[i].geometry.width = -glyphs->glyphs[i].geometry.width;
-	  glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
+	  if (analysis->flags & PANGO_ANALYSIS_FLAG_VERTICAL_ROTATE)
+	    glyphs->glyphs[i].geometry.y_offset += glyphs->glyphs[i].geometry.width;
+	  else
+	    glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
+	}
+      else if (analysis->flags & PANGO_ANALYSIS_FLAG_VERTICAL_ROTATE)
+	{
+	  if (glyphs->glyphs[i].geometry.y_offset == 0)
+	    glyphs->glyphs[i].geometry.y_offset = -1;
 	}
     }
 }
