33
33
#include " ../../../hb-open-type.hh"
34
34
#include " ../../../hb-ot-var-common.hh"
35
35
#include " ../../../hb-paint.hh"
36
+ #include " ../../../hb-paint-bounded.hh"
36
37
#include " ../../../hb-paint-extents.hh"
37
38
38
39
#include " ../CPAL/CPAL.hh"
@@ -47,6 +48,12 @@ namespace OT {
47
48
struct hb_paint_context_t ;
48
49
}
49
50
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
+
50
57
namespace OT {
51
58
52
59
struct COLR ;
@@ -90,12 +97,27 @@ public:
90
97
font (font_),
91
98
palette (
92
99
#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)
94
102
#endif
95
103
),
96
104
foreground (foreground_),
97
105
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
+ }
99
121
100
122
hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
101
123
{
@@ -932,9 +954,9 @@ struct PaintGlyph
932
954
void paint_glyph (hb_paint_context_t *c) const
933
955
{
934
956
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 );
936
958
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 );
938
960
c->recurse (this +paint);
939
961
c->funcs ->pop_transform (c->data );
940
962
c->funcs ->pop_clip (c->data );
@@ -1511,10 +1533,12 @@ struct PaintComposite
1511
1533
void paint_glyph (hb_paint_context_t *c) const
1512
1534
{
1513
1535
TRACE_PAINT (this );
1536
+ c->funcs ->push_group (c->data );
1514
1537
c->recurse (this +backdrop);
1515
1538
c->funcs ->push_group (c->data );
1516
1539
c->recurse (this +src);
1517
1540
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);
1518
1542
}
1519
1543
1520
1544
HBUINT8 format; /* format = 32 */
@@ -1612,7 +1636,7 @@ struct ClipBox
1612
1636
void closurev1 (hb_colrv1_closure_context_t * c) const
1613
1637
{
1614
1638
switch (u.format ) {
1615
- case 2 : u.format2 .closurev1 (c);
1639
+ case 2 : u.format2 .closurev1 (c); return ;
1616
1640
default :return ;
1617
1641
}
1618
1642
}
@@ -2079,6 +2103,8 @@ struct COLR
2079
2103
{
2080
2104
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
2081
2105
2106
+ bool has_data () const { return has_v0_data () || version; }
2107
+
2082
2108
bool has_v0_data () const { return numBaseGlyphs; }
2083
2109
bool has_v1_data () const
2084
2110
{
@@ -2112,7 +2138,53 @@ struct COLR
2112
2138
{
2113
2139
accelerator_t (hb_face_t *face)
2114
2140
{ 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
2116
2188
2117
2189
bool is_valid () { return colr.get_blob ()->length ; }
2118
2190
@@ -2148,7 +2220,33 @@ struct COLR
2148
2220
{ return colr->get_delta_set_index_map_ptr (); }
2149
2221
2150
2222
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:
2151
2247
hb_blob_ptr_t <COLR> colr;
2248
+ private:
2249
+ mutable hb_atomic_t <hb_colr_scratch_t *> cached_scratch;
2152
2250
};
2153
2251
2154
2252
void closure_glyphs (hb_codepoint_t glyph,
@@ -2520,7 +2618,10 @@ struct COLR
2520
2618
2521
2619
#ifndef HB_NO_PAINT
2522
2620
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
2524
2625
{
2525
2626
2526
2627
ItemVarStoreInstancer instancer (get_var_store_ptr (),
@@ -2534,10 +2635,10 @@ struct COLR
2534
2635
}
2535
2636
2536
2637
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 );
2539
2640
2540
- hb_extents_t e = extents_data .get_extents ();
2641
+ auto e = scratch. paint_extents .get_extents ();
2541
2642
if (e.is_void ())
2542
2643
{
2543
2644
extents->x_bearing = 0 ;
@@ -2583,7 +2684,12 @@ struct COLR
2583
2684
2584
2685
#ifndef HB_NO_PAINT
2585
2686
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
2587
2693
{
2588
2694
ItemVarStoreInstancer instancer (get_var_store_ptr (),
2589
2695
get_delta_set_index_map_ptr (),
@@ -2617,26 +2723,26 @@ struct COLR
2617
2723
}
2618
2724
else
2619
2725
{
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 ();
2622
2734
2623
2735
paint_glyph (font, glyph,
2624
- extents_funcs , &extents_data ,
2736
+ bounded_funcs , &scratch. paint_bounded ,
2625
2737
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);
2630
2740
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 ();
2636
2742
}
2637
2743
}
2638
2744
2639
- c.funcs ->push_root_transform (c.data , font);
2745
+ c.funcs ->push_font_transform (c.data , font);
2640
2746
2641
2747
if (is_bounded)
2642
2748
c.recurse (*paint);
@@ -2714,9 +2820,7 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
2714
2820
return ;
2715
2821
2716
2822
const Paint &paint = paint_offset_lists.get_paint (i);
2717
- c->funcs ->push_group (c->data );
2718
2823
c->recurse (paint);
2719
- c->funcs ->pop_group (c->data , HB_PAINT_COMPOSITE_MODE_SRC_OVER);
2720
2824
}
2721
2825
}
2722
2826
@@ -2728,7 +2832,7 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
2728
2832
if (unlikely (!node.visit (gid)))
2729
2833
return ;
2730
2834
2731
- c->funcs ->push_inverse_root_transform (c->data , c->font );
2835
+ c->funcs ->push_inverse_font_transform (c->data , c->font );
2732
2836
if (c->funcs ->color_glyph (c->data , gid, c->font ))
2733
2837
{
2734
2838
c->funcs ->pop_transform (c->data );
0 commit comments