xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-paint-extents.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1 /*
2  * Copyright © 2022 Behdad Esfahbod
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  */
24 
25 #include "hb.hh"
26 
27 #ifndef HB_NO_PAINT
28 
29 #include "hb-paint-extents.hh"
30 
31 #include "hb-draw.h"
32 
33 #include "hb-machinery.hh"
34 
35 
36 /*
37  * This file implements bounds-extraction as well as boundedness
38  * computation of COLRv1 fonts as described in:
39  *
40  * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
41  */
42 
43 static void
hb_paint_extents_push_transform(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,float xx,float yx,float xy,float yy,float dx,float dy,void * user_data HB_UNUSED)44 hb_paint_extents_push_transform (hb_paint_funcs_t *funcs HB_UNUSED,
45 				 void *paint_data,
46 				 float xx, float yx,
47 				 float xy, float yy,
48 				 float dx, float dy,
49 				 void *user_data HB_UNUSED)
50 {
51   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
52 
53   c->push_transform (hb_transform_t {xx, yx, xy, yy, dx, dy});
54 }
55 
56 static void
hb_paint_extents_pop_transform(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)57 hb_paint_extents_pop_transform (hb_paint_funcs_t *funcs HB_UNUSED,
58 			        void *paint_data,
59 				void *user_data HB_UNUSED)
60 {
61   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
62 
63   c->pop_transform ();
64 }
65 
66 static void
hb_draw_extents_move_to(hb_draw_funcs_t * dfuncs HB_UNUSED,void * data,hb_draw_state_t * st,float to_x,float to_y,void * user_data HB_UNUSED)67 hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
68 			 void *data,
69 			 hb_draw_state_t *st,
70 			 float to_x, float to_y,
71 			 void *user_data HB_UNUSED)
72 {
73   hb_extents_t *extents = (hb_extents_t *) data;
74 
75   extents->add_point (to_x, to_y);
76 }
77 
78 static void
hb_draw_extents_line_to(hb_draw_funcs_t * dfuncs HB_UNUSED,void * data,hb_draw_state_t * st,float to_x,float to_y,void * user_data HB_UNUSED)79 hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
80 			 void *data,
81 			 hb_draw_state_t *st,
82 			 float to_x, float to_y,
83 			 void *user_data HB_UNUSED)
84 {
85   hb_extents_t *extents = (hb_extents_t *) data;
86 
87   extents->add_point (to_x, to_y);
88 }
89 
90 static void
hb_draw_extents_quadratic_to(hb_draw_funcs_t * dfuncs HB_UNUSED,void * data,hb_draw_state_t * st,float control_x,float control_y,float to_x,float to_y,void * user_data HB_UNUSED)91 hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
92 			      void *data,
93 			      hb_draw_state_t *st,
94 			      float control_x, float control_y,
95 			      float to_x, float to_y,
96 			      void *user_data HB_UNUSED)
97 {
98   hb_extents_t *extents = (hb_extents_t *) data;
99 
100   extents->add_point (control_x, control_y);
101   extents->add_point (to_x, to_y);
102 }
103 
104 static void
hb_draw_extents_cubic_to(hb_draw_funcs_t * dfuncs HB_UNUSED,void * data,hb_draw_state_t * st,float control1_x,float control1_y,float control2_x,float control2_y,float to_x,float to_y,void * user_data HB_UNUSED)105 hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
106 			  void *data,
107 			  hb_draw_state_t *st,
108 			  float control1_x, float control1_y,
109 			  float control2_x, float control2_y,
110 			  float to_x, float to_y,
111 			  void *user_data HB_UNUSED)
112 {
113   hb_extents_t *extents = (hb_extents_t *) data;
114 
115   extents->add_point (control1_x, control1_y);
116   extents->add_point (control2_x, control2_y);
117   extents->add_point (to_x, to_y);
118 }
119 
120 static inline void free_static_draw_extents_funcs ();
121 
122 static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
123 {
createhb_draw_extents_funcs_lazy_loader_t124   static hb_draw_funcs_t *create ()
125   {
126     hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
127 
128     hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
129     hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
130     hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
131     hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
132 
133     hb_draw_funcs_make_immutable (funcs);
134 
135     hb_atexit (free_static_draw_extents_funcs);
136 
137     return funcs;
138   }
139 } static_draw_extents_funcs;
140 
141 static inline
free_static_draw_extents_funcs()142 void free_static_draw_extents_funcs ()
143 {
144   static_draw_extents_funcs.free_instance ();
145 }
146 
147 static hb_draw_funcs_t *
hb_draw_extents_get_funcs()148 hb_draw_extents_get_funcs ()
149 {
150   return static_draw_extents_funcs.get_unconst ();
151 }
152 
153 static void
hb_paint_extents_push_clip_glyph(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_codepoint_t glyph,hb_font_t * font,void * user_data HB_UNUSED)154 hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
155 				  void *paint_data,
156 				  hb_codepoint_t glyph,
157 				  hb_font_t *font,
158 				  void *user_data HB_UNUSED)
159 {
160   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
161 
162   hb_extents_t extents;
163   hb_draw_funcs_t *draw_extent_funcs = hb_draw_extents_get_funcs ();
164   hb_font_draw_glyph (font, glyph, draw_extent_funcs, &extents);
165   c->push_clip (extents);
166 }
167 
168 static void
hb_paint_extents_push_clip_rectangle(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,float xmin,float ymin,float xmax,float ymax,void * user_data)169 hb_paint_extents_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
170 				      void *paint_data,
171 				      float xmin, float ymin, float xmax, float ymax,
172 				      void *user_data)
173 {
174   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
175 
176   hb_extents_t extents = {xmin, ymin, xmax, ymax};
177   c->push_clip (extents);
178 }
179 
180 static void
hb_paint_extents_pop_clip(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)181 hb_paint_extents_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED,
182 			   void *paint_data,
183 			   void *user_data HB_UNUSED)
184 {
185   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
186 
187   c->pop_clip ();
188 }
189 
190 static void
hb_paint_extents_push_group(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)191 hb_paint_extents_push_group (hb_paint_funcs_t *funcs HB_UNUSED,
192 			     void *paint_data,
193 			     void *user_data HB_UNUSED)
194 {
195   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
196 
197   c->push_group ();
198 }
199 
200 static void
hb_paint_extents_pop_group(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_paint_composite_mode_t mode,void * user_data HB_UNUSED)201 hb_paint_extents_pop_group (hb_paint_funcs_t *funcs HB_UNUSED,
202 			    void *paint_data,
203 			    hb_paint_composite_mode_t mode,
204 			    void *user_data HB_UNUSED)
205 {
206   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
207 
208   c->pop_group (mode);
209 }
210 
211 static hb_bool_t
hb_paint_extents_paint_image(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_blob_t * blob HB_UNUSED,unsigned int width HB_UNUSED,unsigned int height HB_UNUSED,hb_tag_t format HB_UNUSED,float slant HB_UNUSED,hb_glyph_extents_t * glyph_extents,void * user_data HB_UNUSED)212 hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
213 			      void *paint_data,
214 			      hb_blob_t *blob HB_UNUSED,
215 			      unsigned int width HB_UNUSED,
216 			      unsigned int height HB_UNUSED,
217 			      hb_tag_t format HB_UNUSED,
218 			      float slant HB_UNUSED,
219 			      hb_glyph_extents_t *glyph_extents,
220 			      void *user_data HB_UNUSED)
221 {
222   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
223 
224   hb_extents_t extents = {(float) glyph_extents->x_bearing,
225 			  (float) glyph_extents->y_bearing + glyph_extents->height,
226 			  (float) glyph_extents->x_bearing + glyph_extents->width,
227 			  (float) glyph_extents->y_bearing};
228   c->push_clip (extents);
229   c->paint ();
230   c->pop_clip ();
231 
232   return true;
233 }
234 
235 static void
hb_paint_extents_paint_color(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_bool_t use_foreground HB_UNUSED,hb_color_t color HB_UNUSED,void * user_data HB_UNUSED)236 hb_paint_extents_paint_color (hb_paint_funcs_t *funcs HB_UNUSED,
237 			      void *paint_data,
238 			      hb_bool_t use_foreground HB_UNUSED,
239 			      hb_color_t color HB_UNUSED,
240 			      void *user_data HB_UNUSED)
241 {
242   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
243 
244   c->paint ();
245 }
246 
247 static void
hb_paint_extents_paint_linear_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line HB_UNUSED,float x0 HB_UNUSED,float y0 HB_UNUSED,float x1 HB_UNUSED,float y1 HB_UNUSED,float x2 HB_UNUSED,float y2 HB_UNUSED,void * user_data HB_UNUSED)248 hb_paint_extents_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
249 				        void *paint_data,
250 				        hb_color_line_t *color_line HB_UNUSED,
251 				        float x0 HB_UNUSED, float y0 HB_UNUSED,
252 				        float x1 HB_UNUSED, float y1 HB_UNUSED,
253 				        float x2 HB_UNUSED, float y2 HB_UNUSED,
254 				        void *user_data HB_UNUSED)
255 {
256   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
257 
258   c->paint ();
259 }
260 
261 static void
hb_paint_extents_paint_radial_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line HB_UNUSED,float x0 HB_UNUSED,float y0 HB_UNUSED,float r0 HB_UNUSED,float x1 HB_UNUSED,float y1 HB_UNUSED,float r1 HB_UNUSED,void * user_data HB_UNUSED)262 hb_paint_extents_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
263 				        void *paint_data,
264 				        hb_color_line_t *color_line HB_UNUSED,
265 				        float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED,
266 				        float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED,
267 				        void *user_data HB_UNUSED)
268 {
269   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
270 
271   c->paint ();
272 }
273 
274 static void
hb_paint_extents_paint_sweep_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line HB_UNUSED,float cx HB_UNUSED,float cy HB_UNUSED,float start_angle HB_UNUSED,float end_angle HB_UNUSED,void * user_data HB_UNUSED)275 hb_paint_extents_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
276 				       void *paint_data,
277 				       hb_color_line_t *color_line HB_UNUSED,
278 				       float cx HB_UNUSED, float cy HB_UNUSED,
279 				       float start_angle HB_UNUSED,
280 				       float end_angle HB_UNUSED,
281 				       void *user_data HB_UNUSED)
282 {
283   hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
284 
285   c->paint ();
286 }
287 
288 static inline void free_static_paint_extents_funcs ();
289 
290 static struct hb_paint_extents_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_paint_extents_funcs_lazy_loader_t>
291 {
createhb_paint_extents_funcs_lazy_loader_t292   static hb_paint_funcs_t *create ()
293   {
294     hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
295 
296     hb_paint_funcs_set_push_transform_func (funcs, hb_paint_extents_push_transform, nullptr, nullptr);
297     hb_paint_funcs_set_pop_transform_func (funcs, hb_paint_extents_pop_transform, nullptr, nullptr);
298     hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_extents_push_clip_glyph, nullptr, nullptr);
299     hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_extents_push_clip_rectangle, nullptr, nullptr);
300     hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_extents_pop_clip, nullptr, nullptr);
301     hb_paint_funcs_set_push_group_func (funcs, hb_paint_extents_push_group, nullptr, nullptr);
302     hb_paint_funcs_set_pop_group_func (funcs, hb_paint_extents_pop_group, nullptr, nullptr);
303     hb_paint_funcs_set_color_func (funcs, hb_paint_extents_paint_color, nullptr, nullptr);
304     hb_paint_funcs_set_image_func (funcs, hb_paint_extents_paint_image, nullptr, nullptr);
305     hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_extents_paint_linear_gradient, nullptr, nullptr);
306     hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_extents_paint_radial_gradient, nullptr, nullptr);
307     hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_extents_paint_sweep_gradient, nullptr, nullptr);
308 
309     hb_paint_funcs_make_immutable (funcs);
310 
311     hb_atexit (free_static_paint_extents_funcs);
312 
313     return funcs;
314   }
315 } static_paint_extents_funcs;
316 
317 static inline
free_static_paint_extents_funcs()318 void free_static_paint_extents_funcs ()
319 {
320   static_paint_extents_funcs.free_instance ();
321 }
322 
323 hb_paint_funcs_t *
hb_paint_extents_get_funcs()324 hb_paint_extents_get_funcs ()
325 {
326   return static_paint_extents_funcs.get_unconst ();
327 }
328 
329 
330 #endif
331