#ifndef HB_NO_AAT_SHAPE /* If we're using morx shaping, we cancel mark position adjustment because AppleColorEmojiassumesthiswillNOTbedonewhenformingemojisequences; https://github.com/harfbuzz/harfbuzz/issues/2967. */ if (plan.apply_morx)
plan.adjust_mark_positioning_when_zeroing = false;
/* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ #ifndef HB_NO_STYLE
plan.apply_trak = hb_aat_layout_has_tracking (face) && face->table.STAT->has_data (); #else
plan.apply_trak = false; #endif
map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
if (planner->shaper->collect_features)
{
map->is_simple = false;
planner->shaper->collect_features (planner);
}
map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
for (unsignedint i = 0; i < ARRAY_LENGTH (common_features); i++)
map->add_feature (common_features[i]);
if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction)) for (unsignedint i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
map->add_feature (horizontal_features[i]); else
{ /* We only apply `vert` feature. See: *https://github.com/harfbuzz/harfbuzz/commit/d71c0df2d17f4590d5611239577a6cb532c26528
* https://lists.freedesktop.org/archives/harfbuzz/2013-August/003490.html */
/* We really want to find a 'vert' feature if there's any in the font, no *matterwhichscript/langsysitislisted(ornot)under. *Seevariousbugsreferencedfrom:
* https://github.com/harfbuzz/harfbuzz/issues/63 */
map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
}
if (num_user_features)
map->is_simple = false; for (unsignedint i = 0; i < num_user_features; i++)
{ const hb_feature_t *feature = &user_features[i];
map->add_feature (feature->tag,
(feature->start == HB_FEATURE_GLOBAL_START &&
feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
feature->value);
}
if (planner->shaper->override_features)
planner->shaper->override_features (planner);
}
staticvoid
hb_set_unicode_props (hb_buffer_t *buffer)
{ /* Implement enough of Unicode Graphemes here that shaping *inreverse-directionwouldn'tbreakgraphemes.Namely, *wemarkallmarksandZWJandZWJ,Extended_Pictographic *sequencesascontinuations.Theforeach_grapheme() *macrousesthisbit. * *https://www.unicode.org/reports/tr29/#Regex_Definitions
*/ unsignedint count = buffer->len;
hb_glyph_info_t *info = buffer->info; for (unsignedint i = 0; i < count; i++)
{
_hb_glyph_info_set_unicode_props (&info[i], buffer);
if (info[i].codepoint < 0x80) continue;
unsigned gen_cat = _hb_glyph_info_get_general_category (&info[i]); if (FLAG_UNSAFE (gen_cat) &
(FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR))) continue;
/* Marks are already set as continuation by the above line.
* Handle Emoji_Modifier and ZWJ-continuation. */ if (unlikely (gen_cat == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
{
_hb_glyph_info_set_continuation (&info[i], buffer);
} /* Regional_Indicators are hairy as hell...
* https://github.com/harfbuzz/harfbuzz/issues/2265 */ elseif (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint)))
{ if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) &&
!_hb_glyph_info_is_continuation (&info[i - 1]))
_hb_glyph_info_set_continuation (&info[i], buffer);
} #ifndef HB_NO_EMOJI_SEQUENCES elseif (unlikely (_hb_glyph_info_is_zwj (&info[i])))
{
_hb_glyph_info_set_continuation (&info[i], buffer); if (i + 1 < count &&
_hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
{
i++;
_hb_glyph_info_set_unicode_props (&info[i], buffer);
_hb_glyph_info_set_continuation (&info[i], buffer);
}
} #endif /* Or part of the Other_Grapheme_Extend that is not marks. *AsofUnicode15thatisjust: * *200C;Other_Grapheme_Extend#CfZEROWIDTHNON-JOINER *FF9E..FF9F;Other_Grapheme_Extend#Lm[2]HALFWIDTHKATAKANAVOICEDSOUNDMARK..HALFWIDTHKATAKANASEMI-VOICEDSOUNDMARK *E0020..E007F;Other_Grapheme_Extend#Cf[96]TAGSPACE..CANCELTAG * *ZWNJisspecial,wedon'twanttomergeitasthere'snoneed,andkeeping *itseparateresultsinmoregranularclusters. *TagsareusedforEmojisub-regionflagsequences: *https://github.com/harfbuzz/harfbuzz/issues/1556 *Katakanaoneswererequested: *https://github.com/harfbuzz/harfbuzz/issues/3844
*/ elseif (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu)))
_hb_glyph_info_set_continuation (&info[i], buffer); elseif (unlikely (info[i].codepoint == 0x2044u /* FRACTION SLASH */))
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_FRACTION_SLASH;
}
}
hb_codepoint_t invisible = buffer->invisible; if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
(invisible || font->get_nominal_glyph (' ', &invisible)))
{ /* Replace default-ignorables with a zero-advance invisible glyph. */ for (unsignedint i = 0; i < count; i++)
{ if (_hb_glyph_info_is_default_ignorable (&info[i]))
info[i].codepoint = invisible;
}
} else
buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable);
}
staticinlinevoid
hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
{ /* Normalization process sets up normalizer_glyph_index(), we just copy it. */ unsignedint count = buffer->len;
hb_glyph_info_t *info = buffer->info; for (unsignedint i = 0; i < count; i++)
info[i].codepoint = info[i].normalizer_glyph_index();
/* This is unfortunate to go here, but necessary... */ if (c->plan->fallback_mark_positioning)
_hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer);
if (HB_DIRECTION_IS_HORIZONTAL (direction))
{
c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
&pos[0].x_advance, sizeof(pos[0])); // h_origin defaults to zero; only apply it if the font has it. if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
c->font->subtract_glyph_h_origins (c->buffer);
} else
{
c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
&pos[0].y_advance, sizeof(pos[0])); // v_origin defaults to non-zero; apply even if only fallback is there.
c->font->subtract_glyph_v_origins (c->buffer);
} if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
_hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
}
staticinlinevoid
hb_ot_position_plan (const hb_ot_shape_context_t *c)
{ /* If the font has no GPOS and direction is forward, then when *zeroingmarkwidths,weshiftthemarkwithit,suchthatthe *markispositionedhangingoverthepreviousglyph.When *directionisbackwardwedon'tshiftanditwillendup *hangingoverthenextglyphafterthefinalreordering. * *Note:Iffallbackpositioninghappens,wedon'tcareabout *thisasitwillbeoverridden.
*/ bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
/* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
// h_origin defaults to zero; only apply it if the font has it. if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
c->font->add_glyph_h_origins (c->buffer);
hb_ot_layout_position_start (c->font, c->buffer);
if (c->plan->zero_marks) switch (c->plan->shaper->zero_width_marks)
{ case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); break;
default: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: break;
}
c->plan->position (c->font, c->buffer);
if (c->plan->zero_marks) switch (c->plan->shaper->zero_width_marks)
{ case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); break;
default: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: break;
}
/* Finish off. Has to follow a certain order. */
hb_ot_layout_position_finish_advances (c->font, c->buffer);
hb_ot_zero_width_default_ignorables (c->buffer);
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
// h_origin defaults to zero; only apply it if the font has it. if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
c->font->subtract_glyph_h_origins (c->buffer);
if (c->plan->fallback_mark_positioning)
_hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
adjust_offsets_when_zeroing);
}
staticinlinevoid
hb_propagate_flags (hb_buffer_t *buffer)
{ /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
* Simplifies using them. */
unsignedint mask = 0; for (unsignedint i = start; i < end; i++)
mask |= info[i].mask;
mask &= and_mask;
for (unsignedint i = start; i < end; i++)
info[i].mask = mask;
} return;
}
/* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things: * *-IftheplacesthattheArabicshapermarkedasSAFE_TO_INSERT_TATWEEL, *areUNSAFE_TO_BREAK,thencleartheSAFE_TO_INSERT_TATWEEL, *-AnyplacethatisSAFE_TO_INSERT_TATWEEL,isalsonowUNSAFE_TO_BREAK. * *Wecouldn'tmakethisinteractionearlier.Ithastobedonethisway.
*/
foreach_cluster (buffer, start, end)
{ unsignedint mask = 0; for (unsignedint i = start; i < end; i++)
mask |= info[i].mask;
if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL; if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
mask &= and_mask;
for (unsignedint i = start; i < end; i++)
info[i].mask = mask;
}
}
/* Pull it all together! */
staticvoid
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{ /* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */ staticvoid
add_char (hb_font_t *font,
hb_unicode_funcs_t *unicode,
hb_bool_t mirror,
hb_codepoint_t u,
hb_set_t *glyphs)
{
hb_codepoint_t glyph; if (font->get_nominal_glyph (u, &glyph))
glyphs->add (glyph); if (mirror)
{
hb_codepoint_t m = unicode->mirroring (u); if (m != u && font->get_nominal_glyph (m, &glyph))
glyphs->add (glyph);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.