summaryrefslogtreecommitdiff
path: root/pango/pango-context.c
diff options
context:
space:
mode:
authorONO Yoshio <ohtsuka.yoshio@gmail.com>2018-10-17 17:37:19 +0900
committerONO Yoshio <ohtsuka.yoshio@gmail.com>2018-10-22 23:17:20 +0900
commitd2975902a87d3f4a6ff5806c35686c40af48ae70 (patch)
tree757d4c631a7f315d3e33026b2ecd426378bb56cd /pango/pango-context.c
parent9f405de60fbcf3cf52e61add5c8691778d6920cd (diff)
downloadpango-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.c75
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);
}