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.hh155
1 files changed, 106 insertions, 49 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 a807bdcfc5..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);
}
@@ -243,23 +243,25 @@ struct ContextualSubtable
if (buffer->idx == buffer->len && !mark_set)
return;
- const HBGlyphID *replacement;
+ const HBGlyphID16 *replacement;
replacement = nullptr;
if (Types::extended)
{
if (entry.data.markIndex != 0xFFFF)
{
- const Lookup<HBGlyphID> &lookup = subs[entry.data.markIndex];
+ const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex];
replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
- const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
+ 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)
@@ -278,16 +280,18 @@ struct ContextualSubtable
{
if (entry.data.currentIndex != 0xFFFF)
{
- const Lookup<HBGlyphID> &lookup = subs[entry.data.currentIndex];
+ const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex];
replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
- const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
+ 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<HBGlyphID>, 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<HBGlyphID>, 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,16 +529,18 @@ 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))
{
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
- const HBGlyphID &ligatureData = ligature[ligature_idx];
+ 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);
@@ -565,7 +573,7 @@ struct LigatureSubtable
const LigatureSubtable *table;
const UnsizedArrayOf<HBUINT32> &ligAction;
const UnsizedArrayOf<HBUINT16> &component;
- const UnsizedArrayOf<HBGlyphID> &ligature;
+ const UnsizedArrayOf<HBGlyphID16> &ligature;
unsigned int match_length;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
};
@@ -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);
}
@@ -597,7 +606,7 @@ struct LigatureSubtable
ligAction; /* Offset to the ligature action table. */
NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
component; /* Offset to the component table. */
- NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
+ NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
ligature; /* Offset to the actual ligature lists. */
public:
DEFINE_SIZE_STATIC (28);
@@ -618,9 +627,28 @@ 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++)
{
- const HBGlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+ /* 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)
{
info[i].codepoint = *replacement;
@@ -641,7 +669,7 @@ struct NoncontextualSubtable
}
protected:
- Lookup<HBGlyphID> substitute;
+ Lookup<HBGlyphID16> substitute;
public:
DEFINE_SIZE_MIN (2);
};
@@ -744,8 +772,9 @@ struct InsertionSubtable
unsigned int count = (flags & MarkedInsertCount);
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.markedInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+ hb_barrier ();
bool before = flags & MarkedInsertBefore;
@@ -772,8 +801,9 @@ struct InsertionSubtable
unsigned int count = (flags & CurrentInsertCount) >> 5;
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.currentInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+ hb_barrier ();
bool before = flags & CurrentInsertBefore;
@@ -810,7 +840,7 @@ struct InsertionSubtable
private:
hb_aat_apply_context_t *c;
unsigned int mark;
- const UnsizedArrayOf<HBGlyphID> &insertionAction;
+ const UnsizedArrayOf<HBGlyphID16> &insertionAction;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -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,13 +860,14 @@ 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);
}
protected:
StateTable<Types, EntryData>
machine;
- NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
+ NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
@@ -906,11 +937,11 @@ struct ChainSubtable
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...));
- case Contextual: return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
- case Ligature: return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
- case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
- case Insertion: return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
+ case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...));
+ case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...));
+ case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...));
+ case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...));
+ case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...));
default: return_trace (c->default_return_value ());
}
}
@@ -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);
}