Implement fallback vertical shaping from Firefox
Fixes https://github.com/harfbuzz/harfbuzz/issues/355
This commit is contained in:
parent
b6d0f1529d
commit
2dc20e632e
@ -102,6 +102,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||
#endif
|
||||
|
||||
plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
|
||||
plan.has_vert = !!plan.map.get_1_mask (HB_TAG ('v','e','r','t'));
|
||||
|
||||
hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
|
||||
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
|
||||
#ifndef HB_NO_OT_KERN
|
||||
@ -573,24 +575,86 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
|
||||
* Substitute
|
||||
*/
|
||||
|
||||
static inline void
|
||||
hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
|
||||
static hb_codepoint_t
|
||||
hb_vert_char_for (hb_codepoint_t u)
|
||||
{
|
||||
if (HB_DIRECTION_IS_FORWARD (c->target_direction))
|
||||
return;
|
||||
switch (u >> 8)
|
||||
{
|
||||
case 0x20: switch (u) {
|
||||
case 0x2013u: return 0xfe32u; // EN DASH
|
||||
case 0x2014u: return 0xfe31u; // EM DASH
|
||||
case 0x2025u: return 0xfe30u; // TWO DOT LEADER
|
||||
case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
|
||||
} break;
|
||||
case 0x30: switch (u) {
|
||||
case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
|
||||
case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
|
||||
case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
|
||||
case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
|
||||
case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
|
||||
case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
|
||||
case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
|
||||
case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
|
||||
case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
|
||||
case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
|
||||
case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
|
||||
case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
|
||||
case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
|
||||
case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
|
||||
case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
|
||||
case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
|
||||
} break;
|
||||
case 0xfe: switch (u) {
|
||||
case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
|
||||
} break;
|
||||
case 0xff: switch (u) {
|
||||
case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
|
||||
case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
|
||||
case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
|
||||
case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
|
||||
case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
|
||||
case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
|
||||
case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
|
||||
case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
|
||||
case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
|
||||
case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
|
||||
case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
|
||||
case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
|
||||
} break;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
hb_unicode_funcs_t *unicode = buffer->unicode;
|
||||
hb_mask_t rtlm_mask = c->plan->rtlm_mask;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
|
||||
if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
|
||||
info[i].mask |= rtlm_mask;
|
||||
else
|
||||
info[i].codepoint = codepoint;
|
||||
|
||||
if (HB_DIRECTION_IS_BACKWARD (c->target_direction))
|
||||
{
|
||||
hb_unicode_funcs_t *unicode = buffer->unicode;
|
||||
hb_mask_t rtlm_mask = c->plan->rtlm_mask;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
|
||||
if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
|
||||
info[i].codepoint = codepoint;
|
||||
else
|
||||
info[i].mask |= rtlm_mask;
|
||||
}
|
||||
}
|
||||
|
||||
if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
hb_codepoint_t codepoint = hb_vert_char_for (info[i].codepoint);
|
||||
if (c->font->has_glyph (codepoint))
|
||||
if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
|
||||
info[i].codepoint = codepoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,7 +831,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
hb_ot_mirror_chars (c);
|
||||
hb_ot_rotate_chars (c);
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
|
||||
|
||||
|
@ -99,6 +99,7 @@ struct hb_ot_shape_plan_t
|
||||
#else
|
||||
static constexpr bool has_frac = false;
|
||||
#endif
|
||||
bool has_vert : 1;
|
||||
bool has_gpos_mark : 1;
|
||||
bool zero_marks : 1;
|
||||
bool fallback_glyph_classes : 1;
|
||||
|
@ -43,6 +43,7 @@ TESTS = \
|
||||
tests/none-directional.tests \
|
||||
tests/positioning-features.tests \
|
||||
tests/rand.tests \
|
||||
tests/rotation.tests \
|
||||
tests/spaces.tests \
|
||||
tests/simple.tests \
|
||||
tests/sinhala.tests \
|
||||
|
Loading…
Reference in New Issue
Block a user