From a9a416de60ce42fea78e8283253d07a018bf2778 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 22 Jul 2009 13:39:41 -0400 Subject: [PATCH] =?utf8?q?Bug=20589113=20=E2=80=93=20Some=20characters=20r?= =?utf8?q?otated=20incorrectly=20in=20vertical=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Always show full-width Unicode characters upright. --- pango-view/test-mixed.markup | 2 +- pango-view/test-mixed.txt | 2 +- pango/pango-context.c | 69 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/pango-view/test-mixed.markup b/pango-view/test-mixed.markup index daac071..894a1b8 100644 --- a/pango-view/test-mixed.markup +++ b/pango-view/test-mixed.markup @@ -5,5 +5,5 @@ Grass is Green. 2006 Arabic is گل‌ها قرمزند،‏ چمن سبز. ۲۰۰۶ -白日依山尽, 2006 +ABC 白日依山尽, 2006 「ノートを買った。」 diff --git a/pango-view/test-mixed.txt b/pango-view/test-mixed.txt index c04a91b..e23f031 100644 --- a/pango-view/test-mixed.txt +++ b/pango-view/test-mixed.txt @@ -5,5 +5,5 @@ Roses are Red, Grass is Green. 2006 Arabic is گل‌ها قرمزند،‏ چمن سبز. ۲۰۰۶ -白日依山尽, 2006 +ABC 白日依山尽, 2006 「ノートを買った。」 diff --git a/pango/pango-context.c b/pango/pango-context.c index c00338e..4057968 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -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; -- 2.7.4