diff options
author | ONO Yoshio <ohtsuka.yoshio@gmail.com> | 2018-10-17 17:37:19 +0900 |
---|---|---|
committer | ONO Yoshio <ohtsuka.yoshio@gmail.com> | 2018-10-22 23:17:20 +0900 |
commit | d2975902a87d3f4a6ff5806c35686c40af48ae70 (patch) | |
tree | 757d4c631a7f315d3e33026b2ecd426378bb56cd /pango/pango-context.c | |
parent | 9f405de60fbcf3cf52e61add5c8691778d6920cd (diff) | |
download | pango-d2975902a87d3f4a6ff5806c35686c40af48ae70.tar.gz |
Issue #322 - Vertical text doesn't fall back to rotated versions ...
...of horizontal glyphs when necessary
Implemented UAX#50 to determine whether characters rotate or not
in vertical layout.
Diffstat (limited to 'pango/pango-context.c')
-rw-r--r-- | pango/pango-context.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/pango/pango-context.c b/pango/pango-context.c index b48b0eaa..65602bb0 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -706,7 +706,7 @@ struct _PangoWidthIter const gchar *text_end; const gchar *start; const gchar *end; - gboolean wide; + gboolean upright; }; typedef struct _ItemizeState ItemizeState; @@ -853,25 +853,58 @@ update_end (ItemizeState *state) state->run_end = state->emoji_iter.end; } -/* g_unichar_iswide() uses EastAsianWidth, which is broken. - * We should switch to using VerticalTextLayout: - * http://www.unicode.org/reports/tr50/#Data50 - * - * In the mean time, fixup Hangul jamo to be all wide so we - * don't break run in the middle. The EastAsianWidth has - * 'W' for L-jamo, and 'N' for T and V jamo! - * - * https://bugzilla.gnome.org/show_bug.cgi?id=705727 - */ static gboolean -width_iter_iswide (gunichar ch) +width_iter_is_upright (gunichar ch) { - if ((0x1100u <= ch && ch <= 0x11FFu) || - (0xA960u <= ch && ch <= 0xA97Cu) || - (0xD7B0u <= ch && ch <= 0xD7FBu)) - return TRUE; + /* https://www.unicode.org/Public/11.0.0/ucd/VerticalOrientation.txt + * VO=U or Tu table generated by tools/gen-vertical-orientation-U-table.py. + * + * FIXME: In the future, If GLib supports VerticalOrientation, please use it. + */ + static const gunichar upright[][2] = { + {0x00A7, 0x00A7}, {0x00A9, 0x00A9}, {0x00AE, 0x00AE}, {0x00B1, 0x00B1}, + {0x00BC, 0x00BE}, {0x00D7, 0x00D7}, {0x00F7, 0x00F7}, {0x02EA, 0x02EB}, + {0x1100, 0x11FF}, {0x1401, 0x167F}, {0x18B0, 0x18FF}, {0x2016, 0x2016}, + {0x2020, 0x2021}, {0x2030, 0x2031}, {0x203B, 0x203C}, {0x2042, 0x2042}, + {0x2047, 0x2049}, {0x2051, 0x2051}, {0x2065, 0x2065}, {0x20DD, 0x20E0}, + {0x20E2, 0x20E4}, {0x2100, 0x2101}, {0x2103, 0x2109}, {0x210F, 0x210F}, + {0x2113, 0x2114}, {0x2116, 0x2117}, {0x211E, 0x2123}, {0x2125, 0x2125}, + {0x2127, 0x2127}, {0x2129, 0x2129}, {0x212E, 0x212E}, {0x2135, 0x213F}, + {0x2145, 0x214A}, {0x214C, 0x214D}, {0x214F, 0x2189}, {0x218C, 0x218F}, + {0x221E, 0x221E}, {0x2234, 0x2235}, {0x2300, 0x2307}, {0x230C, 0x231F}, + {0x2324, 0x2328}, {0x232B, 0x232B}, {0x237D, 0x239A}, {0x23BE, 0x23CD}, + {0x23CF, 0x23CF}, {0x23D1, 0x23DB}, {0x23E2, 0x2422}, {0x2424, 0x24FF}, + {0x25A0, 0x2619}, {0x2620, 0x2767}, {0x2776, 0x2793}, {0x2B12, 0x2B2F}, + {0x2B50, 0x2B59}, {0x2BB8, 0x2BD1}, {0x2BD3, 0x2BEB}, {0x2BF0, 0x2BFF}, + {0x2E80, 0x3007}, {0x3012, 0x3013}, {0x3020, 0x302F}, {0x3031, 0x309F}, + {0x30A1, 0x30FB}, {0x30FD, 0xA4CF}, {0xA960, 0xA97F}, {0xAC00, 0xD7FF}, + {0xE000, 0xFAFF}, {0xFE10, 0xFE1F}, {0xFE30, 0xFE48}, {0xFE50, 0xFE57}, + {0xFE5F, 0xFE62}, {0xFE67, 0xFE6F}, {0xFF01, 0xFF07}, {0xFF0A, 0xFF0C}, + {0xFF0E, 0xFF19}, {0xFF1F, 0xFF3A}, {0xFF3C, 0xFF3C}, {0xFF3E, 0xFF3E}, + {0xFF40, 0xFF5A}, {0xFFE0, 0xFFE2}, {0xFFE4, 0xFFE7}, {0xFFF0, 0xFFF8}, + {0xFFFC, 0xFFFD}, {0x10980, 0x1099F}, {0x11580, 0x115FF}, {0x11A00, 0x11AAF}, + {0x13000, 0x1342F}, {0x14400, 0x1467F}, {0x16FE0, 0x18AFF}, {0x1B000, 0x1B12F}, + {0x1B170, 0x1B2FF}, {0x1D000, 0x1D1FF}, {0x1D2E0, 0x1D37F}, {0x1D800, 0x1DAAF}, + {0x1F000, 0x1F7FF}, {0x1F900, 0x1FA6F}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, + {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD} + }; + static const int max = sizeof(upright) / sizeof(upright[0]); + int st = 0; + int ed = max; + + while (st <= ed) + { + int mid = (st + ed) / 2; + if (upright[mid][0] <= ch && ch <= upright[mid][1]) + return TRUE; + else + if (upright[mid][0] <= ch) + st = mid + 1; + else + ed = mid - 1; + } - return g_unichar_iswide (ch); + return FALSE; } static void @@ -883,7 +916,7 @@ width_iter_next(PangoWidthIter* iter) if (iter->end < iter->text_end) { gunichar ch = g_utf8_get_char (iter->end); - iter->wide = width_iter_iswide (ch); + iter->upright = width_iter_is_upright (ch); } while (iter->end < iter->text_end) @@ -898,7 +931,7 @@ width_iter_next(PangoWidthIter* iter) continue; } - /* ignore the wide check if met joiner */ + /* ignore the upright check if met joiner */ if (met_joiner) { iter->end = g_utf8_next_char (iter->end); @@ -915,7 +948,7 @@ width_iter_next(PangoWidthIter* iter) continue; } - if (width_iter_iswide (ch) != iter->wide) + if (width_iter_is_upright (ch) != iter->upright) break; iter->end = g_utf8_next_char (iter->end); } @@ -1348,7 +1381,7 @@ itemize_state_update_for_new_run (ItemizeState *state) gravity = state->context->resolved_gravity; state->resolved_gravity = pango_gravity_get_for_script_and_width (state->script, - state->width_iter.wide, + state->width_iter.upright, gravity, gravity_hint); } |