From 430a67ceaba5896c850c0a0da80f1bc211c022d8 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Thu, 1 Apr 2021 12:01:19 -0700 Subject: [PATCH] [subset] COLRv1 struct definitions --- src/hb-ot-color-colr-table.hh | 479 +++++++++++++++++++++++++++++++++- 1 file changed, 474 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index 2f78e64df..c79214709 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -29,6 +29,7 @@ #define HB_OT_COLOR_COLR_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" /* * COLR -- Color @@ -39,7 +40,6 @@ namespace OT { - struct LayerRecord { operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; } @@ -90,6 +90,467 @@ struct BaseGlyphRecord DEFINE_SIZE_STATIC (6); }; +template +struct Variable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + T value; + VarIdx varIdx; + public: + DEFINE_SIZE_STATIC (4 + T::static_size); +}; + +template +struct NoVariable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + T value; + public: + DEFINE_SIZE_STATIC (T::static_size); +}; + +// Color structures + +template class Var> +struct ColorIndex +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT16 paletteIndex; + Var alpha; + public: + DEFINE_SIZE_STATIC (2 + Var::static_size); +}; + +template class Var> +struct ColorStop +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var stopOffset; + ColorIndex color; + public: + DEFINE_SIZE_STATIC (Var::static_size + ColorIndex::static_size); +}; + +struct Extend : HBUINT8 +{ + enum { + EXTEND_PAD = 0, + EXTEND_REPEAT = 1, + EXTEND_REFLECT = 2, + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template class Var> +struct ColorLine +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + stops.sanitize (c)); + } + + Extend extend; + Array16Of> 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); +}; + +template class Var> +struct Affine2x3 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var xx; + Var yx; + Var xy; + Var yy; + Var dx; + Var dy; + public: + DEFINE_SIZE_STATIC (6 * Var::static_size); +}; + +struct PaintColrLayers +{ + 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::layersV1 */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template class Var> +struct PaintSolid +{ + 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)*/ + ColorIndex color; + public: + DEFINE_SIZE_STATIC (1 + ColorIndex::static_size); +}; + +template class Var> +struct PaintLinearGradient +{ + 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; /* Offset (from beginning of PaintLinearGradient + * table) to ColorLine subtable. */ + Var x0; + Var y0; + Var x1; + Var y1; + Var x2; + Var y2; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var::static_size); +}; + +template class Var> +struct PaintRadialGradient +{ + 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; /* Offset (from beginning of PaintRadialGradient + * table) to ColorLine subtable. */ + Var x0; + Var y0; + Var radius0; + Var x1; + Var y1; + Var radius1; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var::static_size); +}; + +template class Var> +struct PaintSweepGradient +{ + 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; /* Offset (from beginning of PaintSweepGradient + * table) to ColorLine subtable. */ + Var centerX; + Var centerY; + Var startAngle; + Var endAngle; + public: + DEFINE_SIZE_STATIC (2 * Var::static_size + 2 * Var::static_size); +}; + +struct Paint; +// Paint a non-COLR glyph, filled as indicated by paint. +struct PaintGlyph +{ + 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; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct PaintColrGlyph +{ + 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 class Var> +struct PaintTransform +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ + Offset24To src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ + Affine2x3 transform; + public: + DEFINE_SIZE_STATIC (4 + Affine2x3::static_size); +}; + +template class Var> +struct PaintTranslate +{ + 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 src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */ + Var dx; + Var dy; + public: + DEFINE_SIZE_STATIC (4 + Var::static_size); +}; + +template class Var> +struct PaintRotate +{ + 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 src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */ + Var angle; + Var centerX; + Var centerY; + public: + DEFINE_SIZE_STATIC (4 + 3 * Var::static_size); +}; + +template class Var> +struct PaintSkew +{ + 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 src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */ + Var xSkewAngle; + Var ySkewAngle; + Var centerX; + Var centerY; + public: + DEFINE_SIZE_STATIC (4 + 4 * Var::static_size); +}; + +struct PaintComposite +{ + 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 = 20 */ + Offset24To src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */ + CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */ + Offset24To backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Paint +{ + template + 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, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.paintformat2, hb_forward (ds)...)); + case 3: return_trace (c->dispatch (u.paintformat3, hb_forward (ds)...)); + case 4: return_trace (c->dispatch (u.paintformat4, hb_forward (ds)...)); + case 5: return_trace (c->dispatch (u.paintformat5, hb_forward (ds)...)); + case 6: return_trace (c->dispatch (u.paintformat6, hb_forward (ds)...)); + case 7: return_trace (c->dispatch (u.paintformat7, hb_forward (ds)...)); + case 8: return_trace (c->dispatch (u.paintformat8, hb_forward (ds)...)); + case 9: return_trace (c->dispatch (u.paintformat9, hb_forward (ds)...)); + case 10: return_trace (c->dispatch (u.paintformat10, hb_forward (ds)...)); + case 11: return_trace (c->dispatch (u.paintformat11, hb_forward (ds)...)); + case 12: return_trace (c->dispatch (u.paintformat12, hb_forward (ds)...)); + case 13: return_trace (c->dispatch (u.paintformat13, hb_forward (ds)...)); + case 14: return_trace (c->dispatch (u.paintformat14, hb_forward (ds)...)); + case 15: return_trace (c->dispatch (u.paintformat15, hb_forward (ds)...)); + case 16: return_trace (c->dispatch (u.paintformat16, hb_forward (ds)...)); + case 17: return_trace (c->dispatch (u.paintformat17, hb_forward (ds)...)); + case 18: return_trace (c->dispatch (u.paintformat18, hb_forward (ds)...)); + case 19: return_trace (c->dispatch (u.paintformat19, hb_forward (ds)...)); + case 20: return_trace (c->dispatch (u.paintformat20, hb_forward (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; + PaintColrLayers paintformat1; + PaintSolid paintformat2; + PaintSolid paintformat3; + PaintLinearGradient paintformat4; + PaintLinearGradient paintformat5; + PaintRadialGradient paintformat6; + PaintRadialGradient paintformat7; + PaintSweepGradient paintformat8; + PaintSweepGradient paintformat9; + PaintGlyph paintformat10; + PaintColrGlyph paintformat11; + PaintTransform paintformat12; + PaintTransform paintformat13; + PaintTranslate paintformat14; + PaintTranslate paintformat15; + PaintRotate paintformat16; + PaintRotate paintformat17; + PaintSkew paintformat18; + PaintSkew paintformat19; + PaintComposite paintformat20; + } u; +}; + +struct BaseGlyphV1Record +{ + 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 (likely (c->check_struct (this) && paint.sanitize (c, this))); + } + + public: + HBGlyphID glyphId; /* Glyph ID of reference glyph */ + Offset32To paint; /* Offset (from beginning of BaseGlyphV1Record) to Paint, + * Typically PaintColrLayers */ + public: + DEFINE_SIZE_STATIC (6); +}; + +typedef SortedArray32Of BaseGlyphV1List; + +struct LayerV1List : Array32OfOffset32To +{ + const Paint& get_paint (unsigned i) const + { return this+(*this)[i]; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (Array32OfOffset32To::sanitize (c, this)); + } +}; + struct COLR { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; @@ -150,9 +611,13 @@ struct COLR bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && - (this+layersZ).sanitize (c, numLayers))); + return_trace (c->check_struct (this) && + (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && + (this+layersZ).sanitize (c, numLayers) && + (version == 0 || (version == 1 && + baseGlyphsV1List.sanitize (c, this) && + layersV1.sanitize (c, this) && + varStore.sanitize (c, this)))); } template> layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ + // Version-1 additions + Offset32To baseGlyphsV1List; + Offset32To layersV1; + Offset32To varStore; public: - DEFINE_SIZE_STATIC (14); + DEFINE_SIZE_MIN (14); }; } /* namespace OT */