| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641 |
- /*
- * Copyright © 2018 Ebrahim Byagowi
- * Copyright © 2020 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Calder Kitagawa
- */
- #ifndef HB_OT_COLOR_COLR_TABLE_HH
- #define HB_OT_COLOR_COLR_TABLE_HH
- #include "hb-open-type.hh"
- #include "hb-ot-layout-common.hh"
- #include "hb-ot-var-common.hh"
- /*
- * COLR -- Color
- * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
- */
- #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
- #ifndef HB_COLRV1_MAX_NESTING_LEVEL
- #define HB_COLRV1_MAX_NESTING_LEVEL 16
- #endif
- namespace OT {
- struct COLR;
- struct hb_colrv1_closure_context_t :
- hb_dispatch_context_t<hb_colrv1_closure_context_t>
- {
- template <typename T>
- return_t dispatch (const T &obj)
- {
- if (unlikely (nesting_level_left == 0))
- return hb_empty_t ();
- if (paint_visited (&obj))
- return hb_empty_t ();
- nesting_level_left--;
- obj.closurev1 (this);
- nesting_level_left++;
- return hb_empty_t ();
- }
- static return_t default_return_value () { return hb_empty_t (); }
- bool paint_visited (const void *paint)
- {
- hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base);
- if (visited_paint.in_error() || visited_paint.has (delta))
- return true;
- visited_paint.add (delta);
- return false;
- }
- const COLR* get_colr_table () const
- { return reinterpret_cast<const COLR *> (base); }
- void add_glyph (unsigned glyph_id)
- { glyphs->add (glyph_id); }
- void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers)
- { layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); }
- void add_palette_index (unsigned palette_index)
- { palette_indices->add (palette_index); }
- public:
- const void *base;
- hb_set_t visited_paint;
- hb_set_t *glyphs;
- hb_set_t *layer_indices;
- hb_set_t *palette_indices;
- unsigned nesting_level_left;
- hb_colrv1_closure_context_t (const void *base_,
- hb_set_t *glyphs_,
- hb_set_t *layer_indices_,
- hb_set_t *palette_indices_,
- unsigned nesting_level_left_ = HB_COLRV1_MAX_NESTING_LEVEL) :
- base (base_),
- glyphs (glyphs_),
- layer_indices (layer_indices_),
- palette_indices (palette_indices_),
- nesting_level_left (nesting_level_left_)
- {}
- };
- struct LayerRecord
- {
- operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- public:
- HBGlyphID16 glyphId; /* Glyph ID of layer glyph */
- Index colorIdx; /* Index value to use with a
- * selected color palette.
- * An index value of 0xFFFF
- * is a special case indicating
- * that the text foreground
- * color (defined by a
- * higher-level client) should
- * be used and shall not be
- * treated as actual index
- * into CPAL ColorRecord array. */
- public:
- DEFINE_SIZE_STATIC (4);
- };
- struct BaseGlyphRecord
- {
- int cmp (hb_codepoint_t g) const
- { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- public:
- HBGlyphID16 glyphId; /* Glyph ID of reference glyph */
- HBUINT16 firstLayerIdx; /* Index (from beginning of
- * the Layer Records) to the
- * layer record. There will be
- * numLayers consecutive entries
- * for this base glyph. */
- HBUINT16 numLayers; /* Number of color layers
- * associated with this glyph */
- public:
- DEFINE_SIZE_STATIC (6);
- };
- template <typename T>
- struct Variable
- {
- Variable<T>* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed (this));
- }
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { value.closurev1 (c); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- if (!value.subset (c)) return_trace (false);
- return_trace (c->serializer->embed (varIdxBase));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && value.sanitize (c));
- }
- protected:
- T value;
- public:
- VarIdx varIdxBase;
- public:
- DEFINE_SIZE_STATIC (4 + T::static_size);
- };
- template <typename T>
- struct NoVariable
- {
- static constexpr uint32_t varIdxBase = VarIdx::NO_VARIATION;
- NoVariable<T>* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed (this));
- }
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { value.closurev1 (c); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- return_trace (value.subset (c));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && value.sanitize (c));
- }
- T value;
- public:
- DEFINE_SIZE_STATIC (T::static_size);
- };
- // Color structures
- struct ColorStop
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { c->add_palette_index (paletteIndex); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
- HB_SERIALIZE_ERROR_INT_OVERFLOW));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- F2DOT14 stopOffset;
- HBUINT16 paletteIndex;
- F2DOT14 alpha;
- public:
- DEFINE_SIZE_STATIC (2 + 2 * F2DOT14::static_size);
- };
- struct Extend : HBUINT8
- {
- enum {
- EXTEND_PAD = 0,
- EXTEND_REPEAT = 1,
- EXTEND_REFLECT = 2,
- };
- public:
- DEFINE_SIZE_STATIC (1);
- };
- template <template<typename> class Var>
- struct ColorLine
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- {
- for (const auto &stop : stops.iter ())
- stop.closurev1 (c);
- }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!out)) return_trace (false);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
- if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false);
- for (const auto& stop : stops.iter ())
- {
- if (!stop.subset (c)) return_trace (false);
- }
- return_trace (true);
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- stops.sanitize (c));
- }
- Extend extend;
- Array16Of<Var<ColorStop>> stops;
- public:
- DEFINE_SIZE_ARRAY_SIZED (3, stops);
- };
- // Composition modes
- // Compositing modes are taken from https://www.w3.org/TR/compositing-1/
- // NOTE: a brief audit of major implementations suggests most support most
- // or all of the specified modes.
- struct CompositeMode : HBUINT8
- {
- enum {
- // Porter-Duff modes
- // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators
- COMPOSITE_CLEAR = 0, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear
- COMPOSITE_SRC = 1, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src
- COMPOSITE_DEST = 2, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst
- COMPOSITE_SRC_OVER = 3, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover
- COMPOSITE_DEST_OVER = 4, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover
- COMPOSITE_SRC_IN = 5, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin
- COMPOSITE_DEST_IN = 6, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin
- COMPOSITE_SRC_OUT = 7, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout
- COMPOSITE_DEST_OUT = 8, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout
- COMPOSITE_SRC_ATOP = 9, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop
- COMPOSITE_DEST_ATOP = 10, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop
- COMPOSITE_XOR = 11, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor
- COMPOSITE_PLUS = 12, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus
- // Blend modes
- // https://www.w3.org/TR/compositing-1/#blending
- COMPOSITE_SCREEN = 13, // https://www.w3.org/TR/compositing-1/#blendingscreen
- COMPOSITE_OVERLAY = 14, // https://www.w3.org/TR/compositing-1/#blendingoverlay
- COMPOSITE_DARKEN = 15, // https://www.w3.org/TR/compositing-1/#blendingdarken
- COMPOSITE_LIGHTEN = 16, // https://www.w3.org/TR/compositing-1/#blendinglighten
- COMPOSITE_COLOR_DODGE = 17, // https://www.w3.org/TR/compositing-1/#blendingcolordodge
- COMPOSITE_COLOR_BURN = 18, // https://www.w3.org/TR/compositing-1/#blendingcolorburn
- COMPOSITE_HARD_LIGHT = 19, // https://www.w3.org/TR/compositing-1/#blendinghardlight
- COMPOSITE_SOFT_LIGHT = 20, // https://www.w3.org/TR/compositing-1/#blendingsoftlight
- COMPOSITE_DIFFERENCE = 21, // https://www.w3.org/TR/compositing-1/#blendingdifference
- COMPOSITE_EXCLUSION = 22, // https://www.w3.org/TR/compositing-1/#blendingexclusion
- COMPOSITE_MULTIPLY = 23, // https://www.w3.org/TR/compositing-1/#blendingmultiply
- // Modes that, uniquely, do not operate on components
- // https://www.w3.org/TR/compositing-1/#blendingnonseparable
- COMPOSITE_HSL_HUE = 24, // https://www.w3.org/TR/compositing-1/#blendinghue
- COMPOSITE_HSL_SATURATION = 25, // https://www.w3.org/TR/compositing-1/#blendingsaturation
- COMPOSITE_HSL_COLOR = 26, // https://www.w3.org/TR/compositing-1/#blendingcolor
- COMPOSITE_HSL_LUMINOSITY = 27, // https://www.w3.org/TR/compositing-1/#blendingluminosity
- };
- public:
- DEFINE_SIZE_STATIC (1);
- };
- struct Affine2x3
- {
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- F16DOT16 xx;
- F16DOT16 yx;
- F16DOT16 xy;
- F16DOT16 yy;
- F16DOT16 dx;
- F16DOT16 dy;
- public:
- DEFINE_SIZE_STATIC (6 * F16DOT16::static_size);
- };
- struct PaintColrLayers
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex),
- HB_SERIALIZE_ERROR_INT_OVERFLOW));
- return_trace (true);
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- HBUINT8 format; /* format = 1 */
- HBUINT8 numLayers;
- HBUINT32 firstLayerIndex; /* index into COLRv1::layerList */
- public:
- DEFINE_SIZE_STATIC (6);
- };
- struct PaintSolid
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { c->add_palette_index (paletteIndex); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
- HB_SERIALIZE_ERROR_INT_OVERFLOW));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- HBUINT8 format; /* format = 2(noVar) or 3(Var)*/
- HBUINT16 paletteIndex;
- F2DOT14 alpha;
- public:
- DEFINE_SIZE_STATIC (3 + F2DOT14::static_size);
- };
- template <template<typename> class Var>
- struct PaintLinearGradient
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->colorLine.serialize_subset (c, colorLine, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
- }
- HBUINT8 format; /* format = 4(noVar) or 5 (Var) */
- Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient
- * table) to ColorLine subtable. */
- FWORD x0;
- FWORD y0;
- FWORD x1;
- FWORD y1;
- FWORD x2;
- FWORD y2;
- public:
- DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
- };
- template <template<typename> class Var>
- struct PaintRadialGradient
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->colorLine.serialize_subset (c, colorLine, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
- }
- HBUINT8 format; /* format = 6(noVar) or 7 (Var) */
- Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient
- * table) to ColorLine subtable. */
- FWORD x0;
- FWORD y0;
- UFWORD radius0;
- FWORD x1;
- FWORD y1;
- UFWORD radius1;
- public:
- DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
- };
- template <template<typename> class Var>
- struct PaintSweepGradient
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->colorLine.serialize_subset (c, colorLine, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
- }
- HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
- Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient
- * table) to ColorLine subtable. */
- FWORD centerX;
- FWORD centerY;
- F2DOT14 startAngle;
- F2DOT14 endAngle;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size);
- };
- struct Paint;
- // Paint a non-COLR glyph, filled as indicated by paint.
- struct PaintGlyph
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
- HB_SERIALIZE_ERROR_INT_OVERFLOW))
- return_trace (false);
- return_trace (out->paint.serialize_subset (c, paint, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && paint.sanitize (c, this));
- }
- HBUINT8 format; /* format = 10 */
- Offset24To<Paint> paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */
- HBUINT16 gid;
- public:
- DEFINE_SIZE_STATIC (6);
- };
- struct PaintColrGlyph
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
- HB_SERIALIZE_ERROR_INT_OVERFLOW));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- HBUINT8 format; /* format = 11 */
- HBUINT16 gid;
- public:
- DEFINE_SIZE_STATIC (3);
- };
- template <template<typename> class Var>
- struct PaintTransform
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- src.sanitize (c, this) &&
- transform.sanitize (c, this));
- }
- HBUINT8 format; /* format = 12(noVar) or 13 (Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
- Offset24To<Var<Affine2x3>> transform;
- public:
- DEFINE_SIZE_STATIC (7);
- };
- struct PaintTranslate
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 14(noVar) or 15 (Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
- FWORD dx;
- FWORD dy;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size);
- };
- struct PaintScale
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 16 (noVar) or 17(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintScale table) to Paint subtable. */
- F2DOT14 scaleX;
- F2DOT14 scaleY;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
- };
- struct PaintScaleAroundCenter
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 18 (noVar) or 19(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */
- F2DOT14 scaleX;
- F2DOT14 scaleY;
- FWORD centerX;
- FWORD centerY;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
- };
- struct PaintScaleUniform
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 20 (noVar) or 21(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */
- F2DOT14 scale;
- public:
- DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
- };
- struct PaintScaleUniformAroundCenter
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 22 (noVar) or 23(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */
- F2DOT14 scale;
- FWORD centerX;
- FWORD centerY;
- public:
- DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
- };
- struct PaintRotate
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 24 (noVar) or 25(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
- F2DOT14 angle;
- public:
- DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
- };
- struct PaintRotateAroundCenter
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 26 (noVar) or 27(Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */
- F2DOT14 angle;
- FWORD centerX;
- FWORD centerY;
- public:
- DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
- };
- struct PaintSkew
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 28(noVar) or 29 (Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
- F2DOT14 xSkewAngle;
- F2DOT14 ySkewAngle;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
- };
- struct PaintSkewAroundCenter
- {
- HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (out->src.serialize_subset (c, src, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
- }
- HBUINT8 format; /* format = 30(noVar) or 31 (Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */
- F2DOT14 xSkewAngle;
- F2DOT14 ySkewAngle;
- FWORD centerX;
- FWORD centerY;
- public:
- DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
- };
- struct PaintComposite
- {
- void closurev1 (hb_colrv1_closure_context_t* c) const;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- if (!out->src.serialize_subset (c, src, this)) return_trace (false);
- return_trace (out->backdrop.serialize_subset (c, backdrop, this));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- src.sanitize (c, this) &&
- backdrop.sanitize (c, this));
- }
- HBUINT8 format; /* format = 32 */
- Offset24To<Paint> src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
- CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */
- Offset24To<Paint> backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
- public:
- DEFINE_SIZE_STATIC (8);
- };
- struct ClipBoxData
- {
- int xMin, yMin, xMax, yMax;
- };
- struct ClipBoxFormat1
- {
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
- void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
- {
- clip_box.xMin = xMin;
- clip_box.yMin = yMin;
- clip_box.xMax = xMax;
- clip_box.yMax = yMax;
- }
- public:
- HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
- FWORD xMin;
- FWORD yMin;
- FWORD xMax;
- FWORD yMax;
- public:
- DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
- };
- struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
- {
- void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
- {
- value.get_clip_box(clip_box, instancer);
- if (instancer)
- {
- clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0));
- clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1));
- clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2));
- clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3));
- }
- }
- };
- struct ClipBox
- {
- ClipBox* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- switch (u.format) {
- case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1)));
- case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2)));
- default:return_trace (nullptr);
- }
- }
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
- bool get_extents (hb_glyph_extents_t *extents,
- const VarStoreInstancer &instancer) const
- {
- ClipBoxData clip_box;
- switch (u.format) {
- case 1:
- u.format1.get_clip_box (clip_box, instancer);
- break;
- case 2:
- u.format2.get_clip_box (clip_box, instancer);
- break;
- default:
- return false;
- }
- extents->x_bearing = clip_box.xMin;
- extents->y_bearing = clip_box.yMax;
- extents->width = clip_box.xMax - clip_box.xMin;
- extents->height = clip_box.yMin - clip_box.yMax;
- return true;
- }
- protected:
- union {
- HBUINT8 format; /* Format identifier */
- ClipBoxFormat1 format1;
- ClipBoxFormat2 format2;
- } u;
- };
- struct ClipRecord
- {
- int cmp (hb_codepoint_t g) const
- { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
- ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
- if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
- return_trace (out);
- }
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
- }
- bool get_extents (hb_glyph_extents_t *extents,
- const void *base,
- const VarStoreInstancer &instancer) const
- {
- return (base+clipBox).get_extents (extents, instancer);
- }
- public:
- HBUINT16 startGlyphID; // first gid clip applies to
- HBUINT16 endGlyphID; // last gid clip applies to, inclusive
- Offset24To<ClipBox> clipBox; // Box or VarBox
- public:
- DEFINE_SIZE_STATIC (7);
- };
- DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
- struct ClipList
- {
- unsigned serialize_clip_records (hb_serialize_context_t *c,
- const hb_set_t& gids,
- const hb_map_t& gid_offset_map) const
- {
- TRACE_SERIALIZE (this);
- if (gids.is_empty () ||
- gid_offset_map.get_population () != gids.get_population ())
- return_trace (0);
- unsigned count = 0;
- hb_codepoint_t start_gid= gids.get_min ();
- hb_codepoint_t prev_gid = start_gid;
- unsigned offset = gid_offset_map.get (start_gid);
- unsigned prev_offset = offset;
- for (const hb_codepoint_t _ : gids.iter ())
- {
- if (_ == start_gid) continue;
- offset = gid_offset_map.get (_);
- if (_ == prev_gid + 1 && offset == prev_offset)
- {
- prev_gid = _;
- continue;
- }
- ClipRecord record;
- record.startGlyphID = start_gid;
- record.endGlyphID = prev_gid;
- record.clipBox = prev_offset;
- if (!c->copy (record, this)) return_trace (0);
- count++;
- start_gid = _;
- prev_gid = _;
- prev_offset = offset;
- }
- //last one
- {
- ClipRecord record;
- record.startGlyphID = start_gid;
- record.endGlyphID = prev_gid;
- record.clipBox = prev_offset;
- if (!c->copy (record, this)) return_trace (0);
- count++;
- }
- return_trace (count);
- }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
- const hb_set_t& glyphset = *c->plan->_glyphset_colred;
- const hb_map_t &glyph_map = *c->plan->glyph_map;
- hb_map_t new_gid_offset_map;
- hb_set_t new_gids;
- for (const ClipRecord& record : clips.iter ())
- {
- unsigned start_gid = record.startGlyphID;
- unsigned end_gid = record.endGlyphID;
- for (unsigned gid = start_gid; gid <= end_gid; gid++)
- {
- if (!glyphset.has (gid) || !glyph_map.has (gid)) continue;
- unsigned new_gid = glyph_map.get (gid);
- new_gid_offset_map.set (new_gid, record.clipBox);
- new_gids.add (new_gid);
- }
- }
- unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
- if (!count) return_trace (false);
- return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- // TODO Make a formatted struct!
- return_trace (c->check_struct (this) && clips.sanitize (c, this));
- }
- bool
- get_extents (hb_codepoint_t gid,
- hb_glyph_extents_t *extents,
- const VarStoreInstancer &instancer) const
- {
- auto *rec = clips.as_array ().bsearch (gid);
- if (rec)
- {
- rec->get_extents (extents, this, instancer);
- return true;
- }
- return false;
- }
- HBUINT8 format; // Set to 1.
- SortedArray32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
- public:
- DEFINE_SIZE_ARRAY_SIZED (5, clips);
- };
- struct Paint
- {
- template <typename ...Ts>
- bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!c->check_start_recursion (HB_COLRV1_MAX_NESTING_LEVEL)))
- return_trace (c->no_dispatch_return_value ());
- return_trace (c->end_recursion (this->dispatch (c, std::forward<Ts> (ds)...)));
- }
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.paintformat1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.paintformat2, std::forward<Ts> (ds)...));
- case 3: return_trace (c->dispatch (u.paintformat3, std::forward<Ts> (ds)...));
- case 4: return_trace (c->dispatch (u.paintformat4, std::forward<Ts> (ds)...));
- case 5: return_trace (c->dispatch (u.paintformat5, std::forward<Ts> (ds)...));
- case 6: return_trace (c->dispatch (u.paintformat6, std::forward<Ts> (ds)...));
- case 7: return_trace (c->dispatch (u.paintformat7, std::forward<Ts> (ds)...));
- case 8: return_trace (c->dispatch (u.paintformat8, std::forward<Ts> (ds)...));
- case 9: return_trace (c->dispatch (u.paintformat9, std::forward<Ts> (ds)...));
- case 10: return_trace (c->dispatch (u.paintformat10, std::forward<Ts> (ds)...));
- case 11: return_trace (c->dispatch (u.paintformat11, std::forward<Ts> (ds)...));
- case 12: return_trace (c->dispatch (u.paintformat12, std::forward<Ts> (ds)...));
- case 13: return_trace (c->dispatch (u.paintformat13, std::forward<Ts> (ds)...));
- case 14: return_trace (c->dispatch (u.paintformat14, std::forward<Ts> (ds)...));
- case 15: return_trace (c->dispatch (u.paintformat15, std::forward<Ts> (ds)...));
- case 16: return_trace (c->dispatch (u.paintformat16, std::forward<Ts> (ds)...));
- case 17: return_trace (c->dispatch (u.paintformat17, std::forward<Ts> (ds)...));
- case 18: return_trace (c->dispatch (u.paintformat18, std::forward<Ts> (ds)...));
- case 19: return_trace (c->dispatch (u.paintformat19, std::forward<Ts> (ds)...));
- case 20: return_trace (c->dispatch (u.paintformat20, std::forward<Ts> (ds)...));
- case 21: return_trace (c->dispatch (u.paintformat21, std::forward<Ts> (ds)...));
- case 22: return_trace (c->dispatch (u.paintformat22, std::forward<Ts> (ds)...));
- case 23: return_trace (c->dispatch (u.paintformat23, std::forward<Ts> (ds)...));
- case 24: return_trace (c->dispatch (u.paintformat24, std::forward<Ts> (ds)...));
- case 25: return_trace (c->dispatch (u.paintformat25, std::forward<Ts> (ds)...));
- case 26: return_trace (c->dispatch (u.paintformat26, std::forward<Ts> (ds)...));
- case 27: return_trace (c->dispatch (u.paintformat27, std::forward<Ts> (ds)...));
- case 28: return_trace (c->dispatch (u.paintformat28, std::forward<Ts> (ds)...));
- case 29: return_trace (c->dispatch (u.paintformat29, std::forward<Ts> (ds)...));
- case 30: return_trace (c->dispatch (u.paintformat30, std::forward<Ts> (ds)...));
- case 31: return_trace (c->dispatch (u.paintformat31, std::forward<Ts> (ds)...));
- case 32: return_trace (c->dispatch (u.paintformat32, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
- protected:
- union {
- HBUINT8 format;
- PaintColrLayers paintformat1;
- PaintSolid paintformat2;
- Variable<PaintSolid> paintformat3;
- PaintLinearGradient<NoVariable> paintformat4;
- Variable<PaintLinearGradient<Variable>> paintformat5;
- PaintRadialGradient<NoVariable> paintformat6;
- Variable<PaintRadialGradient<Variable>> paintformat7;
- PaintSweepGradient<NoVariable> paintformat8;
- Variable<PaintSweepGradient<Variable>> paintformat9;
- PaintGlyph paintformat10;
- PaintColrGlyph paintformat11;
- PaintTransform<NoVariable> paintformat12;
- PaintTransform<Variable> paintformat13;
- PaintTranslate paintformat14;
- Variable<PaintTranslate> paintformat15;
- PaintScale paintformat16;
- Variable<PaintScale> paintformat17;
- PaintScaleAroundCenter paintformat18;
- Variable<PaintScaleAroundCenter> paintformat19;
- PaintScaleUniform paintformat20;
- Variable<PaintScaleUniform> paintformat21;
- PaintScaleUniformAroundCenter paintformat22;
- Variable<PaintScaleUniformAroundCenter> paintformat23;
- PaintRotate paintformat24;
- Variable<PaintRotate> paintformat25;
- PaintRotateAroundCenter paintformat26;
- Variable<PaintRotateAroundCenter> paintformat27;
- PaintSkew paintformat28;
- Variable<PaintSkew> paintformat29;
- PaintSkewAroundCenter paintformat30;
- Variable<PaintSkewAroundCenter> paintformat31;
- PaintComposite paintformat32;
- } u;
- public:
- DEFINE_SIZE_MIN (2);
- };
- struct BaseGlyphPaintRecord
- {
- int cmp (hb_codepoint_t g) const
- { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
- bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
- const void* src_base, hb_subset_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- auto *out = s->embed (this);
- if (unlikely (!out)) return_trace (false);
- if (!s->check_assign (out->glyphId, glyph_map->get (glyphId),
- HB_SERIALIZE_ERROR_INT_OVERFLOW))
- return_trace (false);
- return_trace (out->paint.serialize_subset (c, paint, src_base));
- }
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) && paint.sanitize (c, base)));
- }
- public:
- HBGlyphID16 glyphId; /* Glyph ID of reference glyph */
- Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphPaintRecord array) to Paint,
- * Typically PaintColrLayers */
- public:
- DEFINE_SIZE_STATIC (6);
- };
- struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
- {
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- const hb_set_t* glyphset = c->plan->_glyphset_colred;
- for (const auto& _ : as_array ())
- {
- unsigned gid = _.glyphId;
- if (!glyphset->has (gid)) continue;
- if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
- else return_trace (false);
- }
- return_trace (out->len != 0);
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (SortedArray32Of<BaseGlyphPaintRecord>::sanitize (c, this));
- }
- };
- struct LayerList : Array32OfOffset32To<Paint>
- {
- const Paint& get_paint (unsigned i) const
- { return this+(*this)[i]; }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- for (const auto& _ : + hb_enumerate (*this)
- | hb_filter (c->plan->colrv1_layers, hb_first))
- {
- auto *o = out->serialize_append (c->serializer);
- if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
- return_trace (false);
- }
- return_trace (true);
- }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (Array32OfOffset32To<Paint>::sanitize (c, this));
- }
- };
- struct COLR
- {
- static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
- bool has_data () const { return numBaseGlyphs; }
- unsigned int get_glyph_layers (hb_codepoint_t glyph,
- unsigned int start_offset,
- unsigned int *count, /* IN/OUT. May be NULL. */
- hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const
- {
- const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
- hb_array_t<const LayerRecord> all_layers = (this+layersZ).as_array (numLayers);
- hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
- record.numLayers);
- if (count)
- {
- + glyph_layers.sub_array (start_offset, count)
- | hb_sink (hb_array (layers, *count))
- ;
- }
- return glyph_layers.length;
- }
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- { colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
- ~accelerator_t () { this->colr.destroy (); }
- bool is_valid () { return colr.get_blob ()->length; }
- void closure_glyphs (hb_codepoint_t glyph,
- hb_set_t *related_ids /* OUT */) const
- { colr->closure_glyphs (glyph, related_ids); }
- void closure_V0palette_indices (const hb_set_t *glyphs,
- hb_set_t *palettes /* OUT */) const
- { colr->closure_V0palette_indices (glyphs, palettes); }
- void closure_forV1 (hb_set_t *glyphset,
- hb_set_t *layer_indices,
- hb_set_t *palette_indices) const
- { colr->closure_forV1 (glyphset, layer_indices, palette_indices); }
- private:
- hb_blob_ptr_t<COLR> colr;
- };
- void closure_glyphs (hb_codepoint_t glyph,
- hb_set_t *related_ids /* OUT */) const
- {
- const BaseGlyphRecord *record = get_base_glyph_record (glyph);
- if (!record) return;
- auto glyph_layers = (this+layersZ).as_array (numLayers).sub_array (record->firstLayerIdx,
- record->numLayers);
- if (!glyph_layers.length) return;
- related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
- }
- void closure_V0palette_indices (const hb_set_t *glyphs,
- hb_set_t *palettes /* OUT */) const
- {
- if (!numBaseGlyphs || !numLayers) return;
- hb_array_t<const BaseGlyphRecord> baseGlyphs = (this+baseGlyphsZ).as_array (numBaseGlyphs);
- hb_array_t<const LayerRecord> all_layers = (this+layersZ).as_array (numLayers);
- for (const BaseGlyphRecord record : baseGlyphs)
- {
- if (!glyphs->has (record.glyphId)) continue;
- hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
- record.numLayers);
- for (const LayerRecord layer : glyph_layers)
- palettes->add (layer.colorIdx);
- }
- }
- void closure_forV1 (hb_set_t *glyphset,
- hb_set_t *layer_indices,
- hb_set_t *palette_indices) const
- {
- if (version != 1) return;
- hb_set_t visited_glyphs;
- hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
- const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
- for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
- {
- unsigned gid = baseglyph_paintrecord.glyphId;
- if (!glyphset->has (gid)) continue;
- const Paint &paint = &baseglyph_paintrecords+baseglyph_paintrecord.paint;
- paint.dispatch (&c);
- }
- hb_set_union (glyphset, &visited_glyphs);
- }
- const LayerList& get_layerList () const
- { return (this+layerList); }
- const BaseGlyphList& get_baseglyphList () const
- { return (this+baseGlyphList); }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
- (this+layersZ).sanitize (c, numLayers) &&
- (version == 0 ||
- (version == 1 &&
- baseGlyphList.sanitize (c, this) &&
- layerList.sanitize (c, this) &&
- clipList.sanitize (c, this) &&
- varIdxMap.sanitize (c, this) &&
- varStore.sanitize (c, this))));
- }
- template<typename BaseIterator, typename LayerIterator,
- hb_requires (hb_is_iterator (BaseIterator)),
- hb_requires (hb_is_iterator (LayerIterator))>
- bool serialize_V0 (hb_serialize_context_t *c,
- unsigned version,
- BaseIterator base_it,
- LayerIterator layer_it)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (base_it.len () != layer_it.len ()))
- return_trace (false);
- this->version = version;
- numLayers = 0;
- numBaseGlyphs = base_it.len ();
- if (numBaseGlyphs == 0)
- {
- baseGlyphsZ = 0;
- layersZ = 0;
- return_trace (true);
- }
- c->push ();
- for (const hb_item_type<BaseIterator> _ : + base_it.iter ())
- {
- auto* record = c->embed (_);
- if (unlikely (!record)) return_trace (false);
- record->firstLayerIdx = numLayers;
- numLayers += record->numLayers;
- }
- c->add_link (baseGlyphsZ, c->pop_pack ());
- c->push ();
- for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ())
- _.as_array ().copy (c);
- c->add_link (layersZ, c->pop_pack ());
- return_trace (true);
- }
- const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const
- {
- const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid);
- if (record == &Null (BaseGlyphRecord) ||
- (record && (hb_codepoint_t) record->glyphId != gid))
- record = nullptr;
- return record;
- }
- const BaseGlyphPaintRecord* get_base_glyph_paintrecord (hb_codepoint_t gid) const
- {
- const BaseGlyphPaintRecord* record = &(this+baseGlyphList).bsearch ((unsigned) gid);
- if ((record && (hb_codepoint_t) record->glyphId != gid))
- record = nullptr;
- return record;
- }
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
- const hb_set_t& glyphset = *c->plan->_glyphset_colred;
- auto base_it =
- + hb_range (c->plan->num_output_glyphs ())
- | hb_filter ([&](hb_codepoint_t new_gid)
- {
- hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
- if (glyphset.has (old_gid)) return true;
- return false;
- })
- | hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
- {
- hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
- const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
- if (unlikely (!old_record))
- return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
- BaseGlyphRecord new_record = {};
- new_record.glyphId = new_gid;
- new_record.numLayers = old_record->numLayers;
- return hb_pair_t<bool, BaseGlyphRecord> (true, new_record);
- })
- | hb_filter (hb_first)
- | hb_map_retains_sorting (hb_second)
- ;
- auto layer_it =
- + hb_range (c->plan->num_output_glyphs ())
- | hb_map (reverse_glyph_map)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
- {
- const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
- hb_vector_t<LayerRecord> out_layers;
- if (unlikely (!old_record ||
- old_record->firstLayerIdx >= numLayers ||
- old_record->firstLayerIdx + old_record->numLayers > numLayers))
- return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
- auto layers = (this+layersZ).as_array (numLayers).sub_array (old_record->firstLayerIdx,
- old_record->numLayers);
- out_layers.resize (layers.length);
- for (unsigned int i = 0; i < layers.length; i++) {
- out_layers[i] = layers[i];
- hb_codepoint_t new_gid = 0;
- if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
- return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
- out_layers[i].glyphId = new_gid;
- out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx);
- }
- return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
- })
- | hb_filter (hb_first)
- | hb_map_retains_sorting (hb_second)
- ;
- if (version == 0 && (!base_it || !layer_it))
- return_trace (false);
- COLR *colr_prime = c->serializer->start_embed<COLR> ();
- if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false);
- if (version == 0)
- return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it));
- auto snap = c->serializer->snapshot ();
- if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
- if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
- {
- if (c->serializer->in_error ()) return_trace (false);
- //no more COLRv1 glyphs: downgrade to version 0
- c->serializer->revert (snap);
- return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
- }
- if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
- colr_prime->layerList.serialize_subset (c, layerList, this);
- colr_prime->clipList.serialize_subset (c, clipList, this);
- colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
- //TODO: subset varStore once it's implemented in fonttools
- return_trace (true);
- }
- bool
- get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
- {
- if (version != 1)
- return false;
- VarStoreInstancer instancer (this+varStore,
- this+varIdxMap,
- hb_array (font->coords, font->num_coords));
- if ((this+clipList).get_extents (glyph,
- extents,
- instancer))
- {
- extents->x_bearing = font->em_scale_x (extents->x_bearing);
- extents->y_bearing = font->em_scale_x (extents->y_bearing);
- extents->width = font->em_scale_x (extents->width);
- extents->height = font->em_scale_x (extents->height);
- return true;
- }
- return false;
- }
- protected:
- HBUINT16 version; /* Table version number (starts at 0). */
- HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
- NNOffset32To<SortedUnsizedArrayOf<BaseGlyphRecord>>
- baseGlyphsZ; /* Offset to Base Glyph records. */
- NNOffset32To<UnsizedArrayOf<LayerRecord>>
- layersZ; /* Offset to Layer Records. */
- HBUINT16 numLayers; /* Number of Layer Records. */
- // Version-1 additions
- Offset32To<BaseGlyphList> baseGlyphList;
- Offset32To<LayerList> layerList;
- Offset32To<ClipList> clipList; // Offset to ClipList table (may be NULL)
- Offset32To<DeltaSetIndexMap> varIdxMap; // Offset to DeltaSetIndexMap table (may be NULL)
- Offset32To<VariationStore> varStore;
- public:
- DEFINE_SIZE_MIN (14);
- };
- struct COLR_accelerator_t : COLR::accelerator_t {
- COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {}
- };
- } /* namespace OT */
- #endif /* HB_OT_COLOR_COLR_TABLE_HH */
|