summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh117
1 files changed, 87 insertions, 30 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
index b77c1f4d44..06c9334b37 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
@@ -123,7 +123,7 @@ struct RearrangementSubtable
bool reverse_l = 3 == (m >> 4);
bool reverse_r = 3 == (m & 0x0F);
- if (end - start >= l + r)
+ if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH)
{
buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
buffer->merge_clusters (start, end);
@@ -131,14 +131,14 @@ struct RearrangementSubtable
hb_glyph_info_t *info = buffer->info;
hb_glyph_info_t buf[4];
- memcpy (buf, info + start, l * sizeof (buf[0]));
- memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+ hb_memcpy (buf, info + start, l * sizeof (buf[0]));
+ hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
if (l != r)
memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
- memcpy (info + start, buf + 2, r * sizeof (buf[0]));
- memcpy (info + end - l, buf, l * sizeof (buf[0]));
+ hb_memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+ hb_memcpy (info + end - l, buf, l * sizeof (buf[0]));
if (reverse_l)
{
buf[0] = info[end - 1];
@@ -169,7 +169,7 @@ struct RearrangementSubtable
driver_context_t dc (this);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -259,7 +259,9 @@ struct ContextualSubtable
unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
- if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+ if (!(replacement->sanitize (&c->sanitizer) &&
+ hb_barrier () &&
+ *replacement))
replacement = nullptr;
}
if (replacement)
@@ -287,7 +289,9 @@ struct ContextualSubtable
unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
- if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+ if (!(replacement->sanitize (&c->sanitizer) &&
+ hb_barrier () &&
+ *replacement))
replacement = nullptr;
}
if (replacement)
@@ -315,7 +319,7 @@ struct ContextualSubtable
bool has_glyph_classes;
unsigned int mark;
const ContextualSubtable *table;
- const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs;
+ const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -325,7 +329,7 @@ struct ContextualSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -336,6 +340,7 @@ struct ContextualSubtable
unsigned int num_entries = 0;
if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
+ hb_barrier ();
if (!Types::extended)
return_trace (substitutionTables.sanitize (c, this, 0));
@@ -359,7 +364,7 @@ struct ContextualSubtable
protected:
StateTable<Types, EntryData>
machine;
- NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false>, HBUINT>
+ NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false>, HBUINT>
substitutionTables;
public:
DEFINE_SIZE_STATIC (20);
@@ -513,6 +518,7 @@ struct LigatureSubtable
if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
+ hb_barrier ();
action = *actionData;
uint32_t uoffset = action & LigActionOffset;
@@ -523,9 +529,10 @@ struct LigatureSubtable
component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
const HBUINT16 &componentData = component[component_idx];
if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
+ hb_barrier ();
ligature_idx += componentData;
- DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
+ DEBUG_MSG (APPLY, nullptr, "Action store %d last %d",
bool (action & LigActionStore),
bool (action & LigActionLast));
if (action & (LigActionStore | LigActionLast))
@@ -533,6 +540,7 @@ struct LigatureSubtable
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
const HBGlyphID16 &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
+ hb_barrier ();
hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
@@ -577,7 +585,7 @@ struct LigatureSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -587,6 +595,7 @@ struct LigatureSubtable
TRACE_SANITIZE (this);
/* The rest of array sanitizations are done at run-time. */
return_trace (c->check_struct (this) && machine.sanitize (c) &&
+ hb_barrier () &&
ligAction && component && ligature);
}
@@ -618,8 +627,27 @@ struct NoncontextualSubtable
hb_glyph_info_t *info = c->buffer->info;
unsigned int count = c->buffer->len;
+ // If there's only one range, we already checked the flag.
+ auto *last_range = c->range_flags && (c->range_flags->length > 1) ? &(*c->range_flags)[0] : nullptr;
for (unsigned int i = 0; i < count; i++)
{
+ /* This block copied from StateTableDriver::drive. Keep in sync. */
+ if (last_range)
+ {
+ auto *range = last_range;
+ {
+ unsigned cluster = info[i].cluster;
+ while (cluster < range->cluster_first)
+ range--;
+ while (cluster > range->cluster_last)
+ range++;
+
+ last_range = range;
+ }
+ if (!(range->flags & c->subtable_flags))
+ continue;
+ }
+
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
@@ -746,6 +774,7 @@ struct InsertionSubtable
unsigned int start = entry.data.markedInsertIndex;
const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+ hb_barrier ();
bool before = flags & MarkedInsertBefore;
@@ -774,6 +803,7 @@ struct InsertionSubtable
unsigned int start = entry.data.currentInsertIndex;
const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+ hb_barrier ();
bool before = flags & CurrentInsertBefore;
@@ -820,7 +850,7 @@ struct InsertionSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -830,6 +860,7 @@ struct InsertionSubtable
TRACE_SANITIZE (this);
/* The rest of array sanitizations are done at run-time. */
return_trace (c->check_struct (this) && machine.sanitize (c) &&
+ hb_barrier () &&
insertionAction);
}
@@ -925,9 +956,10 @@ struct ChainSubtable
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!length.sanitize (c) ||
- length <= min_size ||
- !c->check_range (this, length))
+ if (!(length.sanitize (c) &&
+ hb_barrier () &&
+ length >= min_size &&
+ c->check_range (this, length)))
return_trace (false);
hb_sanitize_with_object_t with (c, this);
@@ -968,7 +1000,7 @@ struct Chain
// Check whether this type/setting pair was requested in the map, and if so, apply its flags.
// (The search here only looks at the type and setting fields of feature_info_t.)
hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
- if (map->features.bsearch (info))
+ if (map->current_features.bsearch (info))
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
@@ -980,13 +1012,21 @@ struct Chain
setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
goto retry;
}
+#ifndef HB_NO_AAT
+ else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting &&
+ /* TODO: Rudimentary language matching. */
+ hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language))
+ {
+ flags &= feature.disableFlags;
+ flags |= feature.enableFlags;
+ }
+#endif
}
}
return flags;
}
- void apply (hb_aat_apply_context_t *c,
- hb_mask_t flags) const
+ void apply (hb_aat_apply_context_t *c) const
{
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
unsigned int count = subtableCount;
@@ -994,8 +1034,10 @@ struct Chain
{
bool reverse;
- if (!(subtable->subFeatureFlags & flags))
+ if (hb_none (hb_iter (c->range_flags) |
+ hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
goto skip;
+ c->subtable_flags = subtable->subFeatureFlags;
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
@@ -1034,7 +1076,7 @@ struct Chain
bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
- if (!c->buffer->message (c->font, "start chainsubtable %d", c->lookup_index))
+ if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
goto skip;
if (reverse)
@@ -1045,7 +1087,7 @@ struct Chain
if (reverse)
c->buffer->reverse ();
- (void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index);
+ (void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index);
if (unlikely (!c->buffer->successful)) return;
@@ -1060,9 +1102,10 @@ struct Chain
bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
{
TRACE_SANITIZE (this);
- if (!length.sanitize (c) ||
- length < min_size ||
- !c->check_range (this, length))
+ if (!(length.sanitize (c) &&
+ hb_barrier () &&
+ length >= min_size &&
+ c->check_range (this, length)))
return_trace (false);
if (!c->check_array (featureZ.arrayZ, featureCount))
@@ -1074,6 +1117,7 @@ struct Chain
{
if (!subtable->sanitize (c))
return_trace (false);
+ hb_barrier ();
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
}
@@ -1111,22 +1155,31 @@ struct mortmorx
{
const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
+ if (unlikely (!map->chain_flags.resize (count)))
+ return;
for (unsigned int i = 0; i < count; i++)
{
- map->chain_flags.push (chain->compile_flags (mapper));
+ map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper),
+ mapper->range_first,
+ mapper->range_last});
chain = &StructAfter<Chain<Types>> (*chain);
}
}
- void apply (hb_aat_apply_context_t *c) const
+ void apply (hb_aat_apply_context_t *c,
+ const hb_aat_map_t &map) const
{
if (unlikely (!c->buffer->successful)) return;
+
+ c->buffer->unsafe_to_concat ();
+
c->set_lookup_index (0);
const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
- chain->apply (c, c->plan->aat_map.chain_flags[i]);
+ c->range_flags = &map.chain_flags[i];
+ chain->apply (c);
if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain<Types>> (*chain);
}
@@ -1135,7 +1188,10 @@ struct mortmorx
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
+ if (!(version.sanitize (c) &&
+ hb_barrier () &&
+ version &&
+ chainCount.sanitize (c)))
return_trace (false);
const Chain<Types> *chain = &firstChain;
@@ -1144,6 +1200,7 @@ struct mortmorx
{
if (!chain->sanitize (c, version))
return_trace (false);
+ hb_barrier ();
chain = &StructAfter<Chain<Types>> (*chain);
}