Bug 589113 – Some characters rotated incorrectly in vertical text
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2009 17:39:41 +0000 (13:39 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 22 Jul 2009 17:41:57 +0000 (13:41 -0400)
Always show full-width Unicode characters upright.

pango-view/test-mixed.markup
pango-view/test-mixed.txt
pango/pango-context.c

index daac071..894a1b8 100644 (file)
@@ -5,5 +5,5 @@
 Grass is Green. 2006</span>
 <span lang="fa">Arabic is گل‌ها قرمزند،‏
 چمن سبز. ۲۰۰۶</span>
-<span lang="zh-cn">白日依山尽, 2006</span>
+<span lang="zh-cn">ABC 白日依山尽, 2006</span>
 <span lang="ja">「ノートを買った。」</span>
index c04a91b..e23f031 100644 (file)
@@ -5,5 +5,5 @@ Roses are Red,
 Grass is Green. 2006
 Arabic is گل‌ها قرمزند،‏
 چمن سبز. ۲۰۰۶
-白日依山尽, 2006
+ABC 白日依山尽, 2006
 「ノートを買った。」
index c00338e..4057968 100644 (file)
@@ -645,11 +645,27 @@ typedef enum {
   SCRIPT_CHANGED       = 1 << 1,
   LANG_CHANGED         = 1 << 2,
   FONT_CHANGED         = 1 << 3,
-  DERIVED_LANG_CHANGED = 1 << 4
+  DERIVED_LANG_CHANGED = 1 << 4,
+  WIDTH_CHANGED        = 1 << 5
 } ChangedFlags;
 
+
+
+typedef struct _PangoWidthIter PangoWidthIter;
+
+struct _PangoWidthIter
+{
+       const gchar *text_start;
+       const gchar *text_end;
+       const gchar *start;
+       const gchar *end;
+       gboolean wide;
+};
+
 typedef struct _ItemizeState ItemizeState;
 
+
+
 struct _ItemizeState
 {
   PangoContext *context;
@@ -687,6 +703,8 @@ struct _ItemizeState
   const char *script_end;
   PangoScript script;
 
+  PangoWidthIter width_iter;
+
   PangoLanguage *derived_lang;
   PangoEngineLang *lang_engine;
 
@@ -777,6 +795,38 @@ update_end (ItemizeState *state)
     state->run_end = state->attr_end;
   if (state->script_end < state->run_end)
     state->run_end = state->script_end;
+  if (state->width_iter.end < state->run_end)
+    state->run_end = state->width_iter.end;
+}
+
+static void
+width_iter_next(PangoWidthIter* iter)
+{
+  iter->start = iter->end;
+
+  if (iter->end < iter->text_end)
+    {
+      gunichar ch = g_utf8_get_char (iter->end);
+      iter->wide = g_unichar_iswide (ch);
+    }
+
+  while (iter->end < iter->text_end)
+    {
+      gunichar ch = g_utf8_get_char (iter->end);
+      if (g_unichar_iswide (ch) != iter->wide)
+        break;
+      iter->end = g_utf8_next_char (iter->end);
+    }
+}
+
+static void
+width_iter_init (PangoWidthIter* iter, const char* text, int length)
+{
+  iter->text_start = text;
+  iter->text_end = text + length;
+  iter->start = iter->end = text;
+
+  width_iter_next (iter);
 }
 
 static void
@@ -852,6 +902,9 @@ itemize_state_init (ItemizeState      *state,
   pango_script_iter_get_range (&state->script_iter, NULL,
                               &state->script_end, &state->script);
 
+  /* Initialize the width iterator */
+  width_iter_init (&state->width_iter, text + start_index, length);
+
   update_end (state);
 
   if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
@@ -871,7 +924,7 @@ itemize_state_init (ItemizeState      *state,
   state->fallback_engines = NULL;
   state->base_font = NULL;
 
-  state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED;
+  state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED | WIDTH_CHANGED;
 }
 
 static gboolean
@@ -902,6 +955,11 @@ itemize_state_next (ItemizeState *state)
                                   &state->script_end, &state->script);
       state->changed |= SCRIPT_CHANGED;
     }
+  if (state->run_end == state->width_iter.end)
+    {
+      width_iter_next (&state->width_iter);
+      state->changed |= WIDTH_CHANGED;
+    }
 
   update_end (state);
 
@@ -1231,7 +1289,7 @@ itemize_state_update_for_new_run (ItemizeState *state)
 {
   /* This block should be moved to update_attr_iterator, but I'm too lazy to
    * do it right now */
-  if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED))
+  if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED | WIDTH_CHANGED))
     {
       PangoGravity old_gravity = state->resolved_gravity;
 
@@ -1239,6 +1297,11 @@ itemize_state_update_for_new_run (ItemizeState *state)
        {
          state->resolved_gravity = state->font_desc_gravity;
        }
+      else if (state->width_iter.wide)
+        {
+         /* Wide characters are always upright */
+          state->resolved_gravity = state->context->resolved_gravity;
+        }
       else
        {
          PangoGravity gravity = state->gravity;