[subset] COLRv1 layer/palette indices closure

This commit is contained in:
Qunxin Liu 2021-04-01 12:01:19 -07:00 committed by Garret Rieger
parent a08900b721
commit e59ffe5482
4 changed files with 251 additions and 0 deletions

View File

@ -40,6 +40,63 @@
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 (paint_visited (&obj))
return hb_empty_t ();
obj.closurev1 (this);
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->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[1];
hb_set_t *glyphs;
hb_set_t *layer_indices;
hb_set_t *palette_indices;
hb_colrv1_closure_context_t (const void *base_,
hb_set_t *glyphs_,
hb_set_t *layer_indices_,
hb_set_t *palette_indices_) :
base (base_),
glyphs (glyphs_),
layer_indices (layer_indices_),
palette_indices (palette_indices_)
{}
~hb_colrv1_closure_context_t () { hb_set_clear (visited_paint); }
};
struct LayerRecord
{
operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; }
@ -249,6 +306,8 @@ struct Affine2x3
struct PaintColrLayers
{
void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -265,6 +324,9 @@ struct PaintColrLayers
template <template<typename> class Var>
struct PaintSolid
{
void closurev1 (hb_colrv1_closure_context_t* c) const
{ c->add_palette_index (color.paletteIndex); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -280,6 +342,12 @@ struct PaintSolid
template <template<typename> class Var>
struct PaintLinearGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
{
for (const auto &stop : (this+colorLine).stops.iter ())
c->add_palette_index (stop.color.paletteIndex);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -302,6 +370,12 @@ struct PaintLinearGradient
template <template<typename> class Var>
struct PaintRadialGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
{
for (const auto &stop : (this+colorLine).stops.iter ())
c->add_palette_index (stop.color.paletteIndex);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -324,6 +398,12 @@ struct PaintRadialGradient
template <template<typename> class Var>
struct PaintSweepGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
{
for (const auto &stop : (this+colorLine).stops.iter ())
c->add_palette_index (stop.color.paletteIndex);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -345,6 +425,8 @@ struct Paint;
// Paint a non-COLR glyph, filled as indicated by paint.
struct PaintGlyph
{
void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -360,6 +442,8 @@ struct PaintGlyph
struct PaintColrGlyph
{
void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -375,6 +459,8 @@ struct PaintColrGlyph
template <template<typename> class Var>
struct PaintTransform
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -391,6 +477,8 @@ struct PaintTransform
template <template<typename> class Var>
struct PaintTranslate
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -408,6 +496,8 @@ struct PaintTranslate
template <template<typename> class Var>
struct PaintRotate
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -426,6 +516,8 @@ struct PaintRotate
template <template<typename> class Var>
struct PaintSkew
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -444,6 +536,8 @@ struct PaintSkew
struct PaintComposite
{
void closurev1 (hb_colrv1_closure_context_t* c) const;
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -592,6 +686,11 @@ struct COLR
hb_set_t *related_ids /* OUT */) const
{ colr->closure_glyphs (glyph, related_ids); }
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;
};
@ -608,6 +707,33 @@ struct COLR
related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
}
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 BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List;
for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ())
{
unsigned gid = baseglyphV1record.glyphId;
if (!glyphset->has (gid)) continue;
const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint;
paint.dispatch (&c);
}
hb_set_union (glyphset, &visited_glyphs);
}
const LayerV1List& get_layerV1List () const
{ return (this+layersV1); }
const BaseGlyphV1List& get_baseglyphV1List () const
{ return (this+baseGlyphsV1List); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -663,6 +789,14 @@ struct COLR
return record;
}
const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const
{
const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).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);

View File

@ -0,0 +1,101 @@
/*
* 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.
*
*/
#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH
#define HB_OT_COLR_COLRV1_CLOSURE_HH
#include "hb-open-type.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-color-colr-table.hh"
/*
* COLR -- Color
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
*/
namespace OT {
HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
{
c->add_layer_indices (firstLayerIndex, numLayers);
const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List ();
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
{
const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
paint.dispatch (c);
}
}
HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
{
c->add_glyph (gid);
(this+paint).dispatch (c);
}
HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
{
const COLR *colr_table = c->get_colr_table ();
const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid);
if (!baseglyphV1_record) return;
c->add_glyph (gid);
const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List ();
(&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c);
}
template <template<typename> typename Var>
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
}
template <template<typename> typename Var>
HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
}
template <template<typename> typename Var>
HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
}
template <template<typename> typename Var>
HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
}
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
{
(this+src).dispatch (c);
(this+backdrop).dispatch (c);
}
} /* namespace OT */
#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */

View File

@ -35,6 +35,7 @@
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-cff1-table.hh"
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-colrv1-closure.hh"
#include "hb-ot-var-fvar-table.hh"
#include "hb-ot-stat-table.hh"
@ -277,6 +278,13 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
}
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
hb_set_t layer_indices, palette_indices;
colr.closure_forV1 (plan->_glyphset, &layer_indices, &palette_indices);
_remap_indexes (&layer_indices, plan->colrv1_layers);
_remap_indexes (&palette_indices, plan->colrv1_palettes);
colr.fini ();
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
#ifndef HB_NO_VAR
if (close_over_gdef)
@ -388,6 +396,8 @@ hb_subset_plan_create (hb_face_t *face,
plan->gsub_features = hb_map_create ();
plan->gpos_features = hb_map_create ();
plan->colrv1_layers = hb_map_create ();
plan->colrv1_palettes = hb_map_create ();
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
@ -438,6 +448,8 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_map_destroy (plan->gpos_lookups);
hb_map_destroy (plan->gsub_features);
hb_map_destroy (plan->gpos_features);
hb_map_destroy (plan->colrv1_layers);
hb_map_destroy (plan->colrv1_palettes);
hb_set_destroy (plan->layout_variation_indices);
hb_map_destroy (plan->layout_variation_idx_map);

View File

@ -87,6 +87,10 @@ struct hb_subset_plan_t
hb_map_t *gsub_features;
hb_map_t *gpos_features;
//active layers/palettes we'd like to retain
hb_map_t *colrv1_layers;
hb_map_t *colrv1_palettes;
//The set of layout item variation store delta set indices to be retained
hb_set_t *layout_variation_indices;
//Old -> New layout item variation store delta set index mapping