[pango: 1/2] Issue #322 - Vertical text doesn't fall back to rotated versions ...
- From: Khaled Hosny <khaledh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango: 1/2] Issue #322 - Vertical text doesn't fall back to rotated versions ...
- Date: Thu, 13 Dec 2018 12:29:46 +0000 (UTC)
commit d2975902a87d3f4a6ff5806c35686c40af48ae70
Author: ONO Yoshio <ohtsuka yoshio gmail com>
Date: Wed Oct 17 17:37:19 2018 +0900
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.
pango/pango-context.c | 75 ++++++++++++++++++++++---------
tools/gen-vertical-orientation-U-table.py | 54 ++++++++++++++++++++++
2 files changed, 108 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);
}
diff --git a/tools/gen-vertical-orientation-U-table.py b/tools/gen-vertical-orientation-U-table.py
new file mode 100755
index 00000000..4697b319
--- /dev/null
+++ b/tools/gen-vertical-orientation-U-table.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+#coding:utf-8
+import os
+import sys
+
+if len(sys.argv) != 2:
+ print('usage;./' + os.path.basename(__file__) + ' VerticalOrientation.txt')
+ sys.exit(1)
+
+#pick up all data from text
+data = []
+f = open(sys.argv[1], 'r')
+for line in f:
+ line = line.split("#")[0].strip()
+ if len(line) == 0:
+ continue
+
+ coderange, vo = line.split(";")
+ vo = vo.strip()
+
+ codes = coderange.split("..")
+ if len(codes) == 1:
+ st = int(codes[0], 16)
+ ed = st
+ else:
+ st = int(codes[0], 16)
+ ed = int(codes[1], 16)
+
+ data.append([st, ed, vo])
+f.close()
+
+
+#compress all data, replace Tu to U and Tr to R.
+compressed = []
+t = []
+for d in data:
+ if d[2] == 'Tu': d[2] = 'U'
+ if d[2] == 'Tr': d[2] = 'R'
+
+ if t == []:
+ t = d
+ else:
+ if t[2] == d[2] and t[1] + 1 == d[0]:
+ t[1] = d[1]
+ else:
+ compressed.append(t)
+ t = d
+compressed.append(t)
+
+
+#dump vo=U
+for d in compressed:
+ if d[2] == 'U':
+ print('{0x%04X, 0x%04X},' % tuple(d[0:2]))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]