3333#include " ../../../hb-open-type.hh"
3434#include " ../../../hb-ot-var-common.hh"
3535#include " ../../../hb-paint.hh"
36+ #include " ../../../hb-paint-bounded.hh"
3637#include " ../../../hb-paint-extents.hh"
3738
3839#include " ../CPAL/CPAL.hh"
@@ -47,6 +48,12 @@ namespace OT {
4748struct hb_paint_context_t ;
4849}
4950
51+ struct hb_colr_scratch_t
52+ {
53+ hb_paint_bounded_context_t paint_bounded;
54+ hb_paint_extents_context_t paint_extents;
55+ };
56+
5057namespace OT {
5158
5259struct COLR ;
@@ -90,12 +97,27 @@ public:
9097 font (font_),
9198 palette (
9299#ifndef HB_NO_COLOR
93- font->face->table.CPAL->get_palette_colors (palette_)
100+ // https://github.com/harfbuzz/harfbuzz/issues/5116
101+ font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0)
94102#endif
95103 ),
96104 foreground (foreground_),
97105 instancer (instancer_)
98- { }
106+ {
107+ if (font->is_synthetic ())
108+ {
109+ font = hb_font_create_sub_font (font);
110+ hb_font_set_synthetic_bold (font, 0 , 0 , true );
111+ hb_font_set_synthetic_slant (font, 0 );
112+ }
113+ else
114+ hb_font_reference (font);
115+ }
116+
117+ ~hb_paint_context_t ()
118+ {
119+ hb_font_destroy (font);
120+ }
99121
100122 hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
101123 {
@@ -932,9 +954,9 @@ struct PaintGlyph
932954 void paint_glyph (hb_paint_context_t *c) const
933955 {
934956 TRACE_PAINT (this );
935- c->funcs ->push_inverse_root_transform (c->data , c->font );
957+ c->funcs ->push_inverse_font_transform (c->data , c->font );
936958 c->funcs ->push_clip_glyph (c->data , gid, c->font );
937- c->funcs ->push_root_transform (c->data , c->font );
959+ c->funcs ->push_font_transform (c->data , c->font );
938960 c->recurse (this +paint);
939961 c->funcs ->pop_transform (c->data );
940962 c->funcs ->pop_clip (c->data );
@@ -1511,10 +1533,12 @@ struct PaintComposite
15111533 void paint_glyph (hb_paint_context_t *c) const
15121534 {
15131535 TRACE_PAINT (this );
1536+ c->funcs ->push_group (c->data );
15141537 c->recurse (this +backdrop);
15151538 c->funcs ->push_group (c->data );
15161539 c->recurse (this +src);
15171540 c->funcs ->pop_group (c->data , (hb_paint_composite_mode_t ) (int ) mode);
1541+ c->funcs ->pop_group (c->data , HB_PAINT_COMPOSITE_MODE_SRC_OVER);
15181542 }
15191543
15201544 HBUINT8 format; /* format = 32 */
@@ -1612,7 +1636,7 @@ struct ClipBox
16121636 void closurev1 (hb_colrv1_closure_context_t * c) const
16131637 {
16141638 switch (u.format ) {
1615- case 2 : u.format2 .closurev1 (c);
1639+ case 2 : u.format2 .closurev1 (c); return ;
16161640 default :return ;
16171641 }
16181642 }
@@ -2079,6 +2103,8 @@ struct COLR
20792103{
20802104 static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
20812105
2106+ bool has_data () const { return has_v0_data () || version; }
2107+
20822108 bool has_v0_data () const { return numBaseGlyphs; }
20832109 bool has_v1_data () const
20842110 {
@@ -2112,7 +2138,53 @@ struct COLR
21122138 {
21132139 accelerator_t (hb_face_t *face)
21142140 { colr = hb_sanitize_context_t ().reference_table <COLR> (face); }
2115- ~accelerator_t () { this ->colr .destroy (); }
2141+
2142+ ~accelerator_t ()
2143+ {
2144+ auto *scratch = cached_scratch.get_relaxed ();
2145+ if (scratch)
2146+ {
2147+ scratch->~hb_colr_scratch_t ();
2148+ hb_free (scratch);
2149+ }
2150+
2151+ colr.destroy ();
2152+ }
2153+
2154+
2155+ bool has_data () const { return colr->has_data (); }
2156+
2157+ #ifndef HB_NO_PAINT
2158+ bool
2159+ get_extents (hb_font_t *font,
2160+ hb_codepoint_t glyph,
2161+ hb_glyph_extents_t *extents) const
2162+ {
2163+ if (unlikely (!has_data ())) return false ;
2164+
2165+ hb_colr_scratch_t *scratch = acquire_scratch ();
2166+ if (unlikely (!scratch)) return true ;
2167+ bool ret = colr->get_extents (font, glyph, extents, *scratch);
2168+ release_scratch (scratch);
2169+ return ret;
2170+ }
2171+
2172+ bool paint_glyph (hb_font_t *font,
2173+ hb_codepoint_t glyph,
2174+ hb_paint_funcs_t *funcs, void *data,
2175+ unsigned int palette_index,
2176+ hb_color_t foreground,
2177+ bool clip = true ) const
2178+ {
2179+ if (unlikely (!has_data ())) return false ;
2180+
2181+ hb_colr_scratch_t *scratch = acquire_scratch ();
2182+ if (unlikely (!scratch)) return true ;
2183+ bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch);
2184+ release_scratch (scratch);
2185+ return ret;
2186+ }
2187+ #endif
21162188
21172189 bool is_valid () { return colr.get_blob ()->length ; }
21182190
@@ -2148,7 +2220,33 @@ struct COLR
21482220 { return colr->get_delta_set_index_map_ptr (); }
21492221
21502222 private:
2223+
2224+ hb_colr_scratch_t *acquire_scratch () const
2225+ {
2226+ hb_colr_scratch_t *scratch = cached_scratch.get_acquire ();
2227+
2228+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr )))
2229+ {
2230+ scratch = (hb_colr_scratch_t *) hb_calloc (1 , sizeof (hb_colr_scratch_t ));
2231+ if (unlikely (!scratch))
2232+ return nullptr ;
2233+ }
2234+
2235+ return scratch;
2236+ }
2237+ void release_scratch (hb_colr_scratch_t *scratch) const
2238+ {
2239+ if (!cached_scratch.cmpexch (nullptr , scratch))
2240+ {
2241+ scratch->~hb_colr_scratch_t ();
2242+ hb_free (scratch);
2243+ }
2244+ }
2245+
2246+ public:
21512247 hb_blob_ptr_t <COLR> colr;
2248+ private:
2249+ mutable hb_atomic_t <hb_colr_scratch_t *> cached_scratch;
21522250 };
21532251
21542252 void closure_glyphs (hb_codepoint_t glyph,
@@ -2520,7 +2618,10 @@ struct COLR
25202618
25212619#ifndef HB_NO_PAINT
25222620 bool
2523- get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
2621+ get_extents (hb_font_t *font,
2622+ hb_codepoint_t glyph,
2623+ hb_glyph_extents_t *extents,
2624+ hb_colr_scratch_t &scratch) const
25242625 {
25252626
25262627 ItemVarStoreInstancer instancer (get_var_store_ptr (),
@@ -2534,10 +2635,10 @@ struct COLR
25342635 }
25352636
25362637 auto *extents_funcs = hb_paint_extents_get_funcs ();
2537- hb_paint_extents_context_t extents_data ;
2538- bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data , 0 , HB_COLOR (0 ,0 ,0 ,0 ));
2638+ scratch. paint_extents . clear () ;
2639+ bool ret = paint_glyph (font, glyph, extents_funcs, &scratch. paint_extents , 0 , HB_COLOR (0 ,0 ,0 ,0 ), true , scratch );
25392640
2540- hb_extents_t e = extents_data .get_extents ();
2641+ auto e = scratch. paint_extents .get_extents ();
25412642 if (e.is_void ())
25422643 {
25432644 extents->x_bearing = 0 ;
@@ -2583,7 +2684,12 @@ struct COLR
25832684
25842685#ifndef HB_NO_PAINT
25852686 bool
2586- paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true ) const
2687+ paint_glyph (hb_font_t *font,
2688+ hb_codepoint_t glyph,
2689+ hb_paint_funcs_t *funcs, void *data,
2690+ unsigned int palette_index, hb_color_t foreground,
2691+ bool clip,
2692+ hb_colr_scratch_t &scratch) const
25872693 {
25882694 ItemVarStoreInstancer instancer (get_var_store_ptr (),
25892695 get_delta_set_index_map_ptr (),
@@ -2617,26 +2723,26 @@ struct COLR
26172723 }
26182724 else
26192725 {
2620- auto *extents_funcs = hb_paint_extents_get_funcs ();
2621- hb_paint_extents_context_t extents_data;
2726+ clip = false ;
2727+ is_bounded = false ;
2728+ }
2729+
2730+ if (!is_bounded)
2731+ {
2732+ auto *bounded_funcs = hb_paint_bounded_get_funcs ();
2733+ scratch.paint_bounded .clear ();
26222734
26232735 paint_glyph (font, glyph,
2624- extents_funcs , &extents_data ,
2736+ bounded_funcs , &scratch. paint_bounded ,
26252737 palette_index, foreground,
2626- false );
2627-
2628- hb_extents_t extents = extents_data.get_extents ();
2629- is_bounded = extents_data.is_bounded ();
2738+ false ,
2739+ scratch);
26302740
2631- c.funcs ->push_clip_rectangle (c.data ,
2632- extents.xmin ,
2633- extents.ymin ,
2634- extents.xmax ,
2635- extents.ymax );
2741+ is_bounded = scratch.paint_bounded .is_bounded ();
26362742 }
26372743 }
26382744
2639- c.funcs ->push_root_transform (c.data , font);
2745+ c.funcs ->push_font_transform (c.data , font);
26402746
26412747 if (is_bounded)
26422748 c.recurse (*paint);
@@ -2714,9 +2820,7 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
27142820 return ;
27152821
27162822 const Paint &paint = paint_offset_lists.get_paint (i);
2717- c->funcs ->push_group (c->data );
27182823 c->recurse (paint);
2719- c->funcs ->pop_group (c->data , HB_PAINT_COMPOSITE_MODE_SRC_OVER);
27202824 }
27212825}
27222826
@@ -2728,7 +2832,7 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
27282832 if (unlikely (!node.visit (gid)))
27292833 return ;
27302834
2731- c->funcs ->push_inverse_root_transform (c->data , c->font );
2835+ c->funcs ->push_inverse_font_transform (c->data , c->font );
27322836 if (c->funcs ->color_glyph (c->data , gid, c->font ))
27332837 {
27342838 c->funcs ->pop_transform (c->data );
0 commit comments