Commit eb2c647f authored by Khaled Hosny's avatar Khaled Hosny

Merge branch 'issue-322' into 'master'

Issue #322 - Vertical text doesn't fall back to rotated versions of horizontal glyphs when necessary

Closes #322

See merge request !28
parents 8b8d0e84 d2975902
Pipeline #45783 passed with stage
in 2 minutes and 12 seconds
......@@ -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);
}
......
#!/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]))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment