struct driver_context_t
{ static constexpr bool in_place = true; enum Flags
{
MarkFirst = 0x8000, /* If set, make the current glyph the first
* glyph to be rearranged. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph *beforegoingtothenewstate.Thismeans *thattheglyphindexdoesn'tchange,even
* if the glyph at that index has changed. */
MarkLast = 0x2000, /* If set, make the current glyph the last
* glyph to be rearranged. */
Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
Verb = 0x000F, /* The type of rearrangement specified. */
};
driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
ret (false),
start (0), end (0) {}
struct EntryData
{
HBUINT16 markIndex; /* Index of the substitution table for the
* marked glyph (use 0xFFFF for none). */
HBUINT16 currentIndex; /* Index of the substitution table for the
* current glyph (use 0xFFFF for none). */ public:
DEFINE_SIZE_STATIC (4);
};
struct driver_context_t
{ static constexpr bool in_place = true; enum Flags
{
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
* going to the new state. */
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
};
driver_context_t (const ContextualSubtable *table_,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
gdef (*c->gdef_table),
mark_set (false),
has_glyph_classes (gdef.has_glyph_classes ()),
mark (0),
table (table_),
subs (table+table->substitutionTables) {}
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
} void transition (hb_buffer_t *buffer,
StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> &entry)
{ /* Looks like CoreText applies neither mark nor current substitution for
* end-of-text if mark was not explicitly set. */ if (buffer->idx == buffer->len && !mark_set) return;
template <> struct LigatureEntry<true>
{ enum Flags
{
SetComponent = 0x8000, /* Push this glyph onto the component stack for
* eventual processing. */
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
next iteration. */
PerformAction = 0x2000, /* Use the ligActionIndex to process a ligature
* group. */
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
};
struct EntryData
{
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry *forprocessingthisgroup,ifindicated
* by the flags. */ public:
DEFINE_SIZE_STATIC (2);
};
staticunsignedint ligActionIndex (const Entry<EntryData> &entry)
{ return entry.data.ligActionIndex; }
}; template <> struct LigatureEntry<false>
{ enum Flags
{
SetComponent = 0x8000, /* Push this glyph onto the component stack for
* eventual processing. */
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
next iteration. */
Offset = 0x3FFF, /* Byte offset from beginning of subtable to the *ligatureactionlist.Thisvaluemustbea
* multiple of 4. */
};
struct driver_context_t
{ static constexpr bool in_place = false; enum
{
DontAdvance = LigatureEntryT::DontAdvance,
}; enum LigActionFlags
{
LigActionLast = 0x80000000, /* This is the last action in the list. This also
* implies storage. */
LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index *intheligaturetableinplaceofthemarked
* (i.e. currently-popped) glyph. */
LigActionOffset = 0x3FFFFFFF, /* A 30-bit value which is sign-extended to 32-bits *andaddedtotheglyphID,resultinginanindex
* into the component table. */
};
bool ret = false; unsignedint num_glyphs = c->face->get_num_glyphs ();
hb_glyph_info_t *info = c->buffer->info; unsignedint 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 (unsignedint 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)
{
info[i].codepoint = *replacement;
c->buffer_digest.add (*replacement); if (has_glyph_classes)
_hb_glyph_info_set_glyph_props (&info[i],
gdef.get_glyph_props (*replacement));
ret = true;
}
}
struct EntryData
{
HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table. *Thenumberofglyphstobeinsertediscontained *inthecurrentInsertCountfieldintheflags. *Avalueof0xFFFFindicatesnoinsertionisto
* be done. */
HBUINT16 markedInsertIndex; /* Zero-based index into the insertion glyph table. *Thenumberofglyphstobeinsertediscontained *inthemarkedInsertCountfieldintheflags. *Avalueof0xFFFFindicatesnoinsertionisto
* be done. */ public:
DEFINE_SIZE_STATIC (4);
};
struct driver_context_t
{ static constexpr bool in_place = false; enum Flags
{
SetMark = 0x8000, /* If set, mark the current glyph. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before *goingtothenewstate.Thisdoesnotmean *thattheglyphpointedtoisthesameoneas *before.Ifyou'vemadeinsertionsimmediately *downstreamofthecurrentglyph,thenextglyph *processedwouldinfactbethefirstone
* inserted. */
CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero, *thenthespecifiedglyphlistwillbeinserted *asakashida-likeinsertion,eitherbeforeor *afterthecurrentglyph(dependingonthestate *ofthecurrentInsertBeforeflag).Ifclear,and *thecurrentInsertListisnonzero,thenthe *specifiedglyphlistwillbeinsertedasa *split-vowel-likeinsertion,eitherbeforeor *afterthecurrentglyph(dependingonthestate
* of the currentInsertBefore flag). */
MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero, *thenthespecifiedglyphlistwillbeinserted *asakashida-likeinsertion,eitherbeforeor *afterthemarkedglyph(dependingonthestate *ofthemarkedInsertBeforeflag).Ifclear,and *themarkedInsertListisnonzero,thenthe *specifiedglyphlistwillbeinsertedasa *split-vowel-likeinsertion,eitherbeforeor *afterthemarkedglyph(dependingonthestate
* of the markedInsertBefore flag). */
CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made *totheleftofthecurrentglyph.Ifclear,
* they're made to the right of the current glyph. */
MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be *madetotheleftofthemarkedglyph.Ifclear,
* they're made to the right of the marked glyph. */
CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the *numberofglyphstoinsertatthecurrent *position.Sincezeromeansnoinsertions,the *largestnumberofinsertionsatanygiven
* current location is 31 glyphs. */
MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the *numberofglyphstoinsertatthemarked *position.Sincezeromeansnoinsertions,the *largestnumberofinsertionsatanygiven
* marked location is 31 glyphs. */
};
driver_context_t (const InsertionSubtable *table,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
mark (0),
insertionAction (table+table->insertionAction) {}
unsignedint end = buffer->out_len; if (unlikely (!buffer->move_to (mark))) return;
if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; for (unsignedint i = 0; i < count; i++)
c->buffer_digest.add (glyphs[i]);
ret = true; if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
if (unlikely (!buffer->move_to (end + count))) return;
if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
/* Humm. Not sure where to move to. There's this wording under *DontAdvanceflag: * *"Ifset,don'tupdatetheglyphindexbeforegoingtothenewstate. *Thisdoesnotmeanthattheglyphpointedtoisthesameoneas *before.Ifyou'vemadeinsertionsimmediatelydownstreamofthe *currentglyph,thenextglyphprocessedwouldinfactbethefirst *oneinserted." * *ThissuggeststhatifDontAdvanceisNOTset,weshouldmoveto *end+count.Ifit*was*,thenmovetoend,suchthatnewlyinserted *glyphsarenowvisible. * *https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
*/ if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return;
}
}
public:
HBUINT16 featureType; /* The type of feature. */
HBUINT16 featureSetting; /* The feature's setting (aka selector). */
HBUINT32 enableFlags; /* Flags for the settings that this feature
* and setting enables. */
HBUINT32 disableFlags; /* Complement of flags for the settings that this
* feature and setting disable. */
/* The following is a calloc because when we are collecting subtables, *someofthemmightbeinvalidandhencenotcollect;asaresult, *wemightnotfillinallthecountentriesofthesubtablesarray. *Zeroingitallowsthesetdigesttogatekeepitwithouthavingto
* initialize it further. */ auto *thiz = (hb_aat_layout_chain_accelerator_t *) hb_calloc (1, size); if (unlikely (!thiz)) return nullptr;
enum Coverage
{
Vertical = 0x80, /* If set, this subtable will only be applied *toverticaltext.Ifclear,thissubtable
* will only be applied to horizontal text. */
Backwards = 0x40, /* If set, this subtable will process glyphs *indescendingorder.Ifclear,itwill
* process the glyphs in ascending order. */
AllDirections = 0x20, /* If set, this subtable will be applied to *bothhorizontalandverticaltext(i.e.
* the state of bit 0x80000000 is ignored). */
Logical = 0x10, /* If set, this subtable will process glyphs *inlogicalorder(orreverselogicalorder,
* depending on the value of bit 0x80000000). */
}; enum Type
{
Rearrangement = 0,
Contextual = 1,
Ligature = 2,
Noncontextual = 4,
Insertion = 5
};
if (!c->check_array (featureZ.arrayZ, featureCount))
return_trace (false);
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); unsignedint count = subtableCount; for (unsignedint i = 0; i < count; i++)
{ if (!subtable->sanitize (c))
return_trace (false);
hb_barrier ();
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
}
if (version >= 3)
{ const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) subtable; if (!coverage->sanitize (c, count))
return_trace (false);
}
return_trace (true);
}
protected:
HBUINT32 defaultFlags; /* The default specification for subtables. */
HBUINT32 length; /* Total byte count, including this header. */
HBUINT featureCount; /* Number of feature subtable entries. */
HBUINT subtableCount; /* The number of subtables in the chain. */
UnsizedArrayOf<Feature> featureZ; /* Features. */ /*ChainSubtable firstSubtable;*//* Subtables. */ /*SubtableGlyphCoverage coverages*//* Only if version >= 3. */
const Chain<Types> *chain = &firstChain; unsignedint count = chainCount; for (unsignedint i = 0; i < count; i++)
{ if (!chain->sanitize (c, version))
return_trace (false);
hb_barrier ();
chain = &StructAfter<Chain<Types>> (*chain);
}
return_trace (true);
}
protected:
HBUINT16 version; /* Version number of the glyph metamorphosis table.
* 1, 2, or 3. */
HBUINT16 unused; /* Set to 0. */
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
* table. */
Chain<Types> firstChain; /* Chains. */
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.