#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;
/* Currently we always apply trak. */
plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); #endif
}
#ifndef HB_NO_AAT_SHAPE /* Tracking. We enable dummy feature here just to allow disabling *AAT'trak'tableusingfeatures.
* https://github.com/harfbuzz/harfbuzz/issues/1303 */
map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); #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);
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]);
} /* 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]);
} #ifndef HB_NO_EMOJI_SEQUENCES elseif (unlikely (_hb_glyph_info_is_zwj (&info[i])))
{
_hb_glyph_info_set_continuation (&info[i]); 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]);
}
} #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]);
}
}
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 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].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])); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsignedint i = 0; i < count; i++)
c->font->subtract_glyph_h_origin (info[i].codepoint,
&pos[i].x_offset,
&pos[i].y_offset);
} else
{
c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
&pos[0].y_advance, sizeof(pos[0])); for (unsignedint i = 0; i < count; i++)
{
c->font->subtract_glyph_v_origin (info[i].codepoint,
&pos[i].x_offset,
&pos[i].y_offset);
}
} if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
_hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
}
/* 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. */
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsignedint i = 0; i < count; i++)
c->font->add_glyph_h_origin (info[i].codepoint,
&pos[i].x_offset,
&pos[i].y_offset);
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); #ifndef HB_NO_AAT_SHAPE if (c->plan->apply_morx)
hb_aat_layout_zero_width_deleted_glyphs (c->buffer); #endif
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */ if (c->font->has_glyph_h_origin_func ()) for (unsignedint i = 0; i < count; i++)
c->font->subtract_glyph_h_origin (info[i].codepoint,
&pos[i].x_offset,
&pos[i].y_offset);
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. */
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS)) 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.Ithastobedonehere.
*/ bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
foreach_cluster (buffer, start, end)
{ unsignedint mask = 0; for (unsignedint i = start; i < end; i++)
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
if (flip_tatweel)
{ 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;
}
if (clear_concat)
mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
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.