xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-draw.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1 /*
2  * Copyright © 2019-2020  Ebrahim Byagowi
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_DRAW
28 
29 #include "hb-draw.hh"
30 
31 /**
32  * SECTION:hb-draw
33  * @title: hb-draw
34  * @short_description: Glyph drawing
35  * @include: hb.h
36  *
37  * Functions for drawing (extracting) glyph shapes.
38  *
39  * The #hb_draw_funcs_t struct can be used with hb_font_draw_glyph().
40  **/
41 
42 static void
hb_draw_move_to_nil(hb_draw_funcs_t * dfuncs HB_UNUSED,void * draw_data HB_UNUSED,hb_draw_state_t * st HB_UNUSED,float to_x HB_UNUSED,float to_y HB_UNUSED,void * user_data HB_UNUSED)43 hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
44 		     hb_draw_state_t *st HB_UNUSED,
45 		     float to_x HB_UNUSED, float to_y HB_UNUSED,
46 		     void *user_data HB_UNUSED) {}
47 
48 static void
hb_draw_line_to_nil(hb_draw_funcs_t * dfuncs HB_UNUSED,void * draw_data HB_UNUSED,hb_draw_state_t * st HB_UNUSED,float to_x HB_UNUSED,float to_y HB_UNUSED,void * user_data HB_UNUSED)49 hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
50 		     hb_draw_state_t *st HB_UNUSED,
51 		     float to_x HB_UNUSED, float to_y HB_UNUSED,
52 		     void *user_data HB_UNUSED) {}
53 
54 static void
hb_draw_quadratic_to_nil(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float control_x,float control_y,float to_x,float to_y,void * user_data HB_UNUSED)55 hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
56 			  hb_draw_state_t *st,
57 			  float control_x, float control_y,
58 			  float to_x, float to_y,
59 			  void *user_data HB_UNUSED)
60 {
61 #define HB_ONE_THIRD 0.33333333f
62   dfuncs->emit_cubic_to (draw_data, *st,
63 			 (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
64 			 (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
65 			 (to_x + 2.f * control_x) * HB_ONE_THIRD,
66 			 (to_y + 2.f * control_y) * HB_ONE_THIRD,
67 			 to_x, to_y);
68 #undef HB_ONE_THIRD
69 }
70 
71 static void
hb_draw_cubic_to_nil(hb_draw_funcs_t * dfuncs HB_UNUSED,void * draw_data HB_UNUSED,hb_draw_state_t * st HB_UNUSED,float control1_x HB_UNUSED,float control1_y HB_UNUSED,float control2_x HB_UNUSED,float control2_y HB_UNUSED,float to_x HB_UNUSED,float to_y HB_UNUSED,void * user_data HB_UNUSED)72 hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
73 		      hb_draw_state_t *st HB_UNUSED,
74 		      float control1_x HB_UNUSED, float control1_y HB_UNUSED,
75 		      float control2_x HB_UNUSED, float control2_y HB_UNUSED,
76 		      float to_x HB_UNUSED, float to_y HB_UNUSED,
77 		      void *user_data HB_UNUSED) {}
78 
79 static void
hb_draw_close_path_nil(hb_draw_funcs_t * dfuncs HB_UNUSED,void * draw_data HB_UNUSED,hb_draw_state_t * st HB_UNUSED,void * user_data HB_UNUSED)80 hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
81 			hb_draw_state_t *st HB_UNUSED,
82 			void *user_data HB_UNUSED) {}
83 
84 
85 static bool
_hb_draw_funcs_set_preamble(hb_draw_funcs_t * dfuncs,bool func_is_null,void ** user_data,hb_destroy_func_t * destroy)86 _hb_draw_funcs_set_preamble (hb_draw_funcs_t    *dfuncs,
87 			     bool                func_is_null,
88 			     void              **user_data,
89 			     hb_destroy_func_t  *destroy)
90 {
91   if (hb_object_is_immutable (dfuncs))
92   {
93     if (*destroy)
94       (*destroy) (*user_data);
95     return false;
96   }
97 
98   if (func_is_null)
99   {
100     if (*destroy)
101       (*destroy) (*user_data);
102     *destroy = nullptr;
103     *user_data = nullptr;
104   }
105 
106   return true;
107 }
108 
109 static bool
_hb_draw_funcs_set_middle(hb_draw_funcs_t * dfuncs,void * user_data,hb_destroy_func_t destroy)110 _hb_draw_funcs_set_middle (hb_draw_funcs_t   *dfuncs,
111 			   void              *user_data,
112 			   hb_destroy_func_t  destroy)
113 {
114   if (user_data && !dfuncs->user_data)
115   {
116     dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
117     if (unlikely (!dfuncs->user_data))
118       goto fail;
119   }
120   if (destroy && !dfuncs->destroy)
121   {
122     dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
123     if (unlikely (!dfuncs->destroy))
124       goto fail;
125   }
126 
127   return true;
128 
129 fail:
130   if (destroy)
131     (destroy) (user_data);
132   return false;
133 }
134 
135 #define HB_DRAW_FUNC_IMPLEMENT(name)						\
136 										\
137 void										\
138 hb_draw_funcs_set_##name##_func (hb_draw_funcs_t	 *dfuncs,		\
139 				 hb_draw_##name##_func_t  func,			\
140 				 void			 *user_data,		\
141 				 hb_destroy_func_t	  destroy)		\
142 {										\
143   if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
144       return;                                                            \
145 										\
146   if (dfuncs->destroy && dfuncs->destroy->name)					\
147     dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
148 									 \
149   if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy))           \
150       return;                                                            \
151 									\
152   if (func)								\
153     dfuncs->func.name = func;						\
154   else									\
155     dfuncs->func.name = hb_draw_##name##_nil;				\
156 									\
157   if (dfuncs->user_data)						\
158     dfuncs->user_data->name = user_data;				\
159   if (dfuncs->destroy)							\
160     dfuncs->destroy->name = destroy;					\
161 }
162 
163 HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
164 #undef HB_DRAW_FUNC_IMPLEMENT
165 
166 /**
167  * hb_draw_funcs_create:
168  *
169  * Creates a new draw callbacks object.
170  *
171  * Return value: (transfer full):
172  * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
173  * reference count should be released with hb_draw_funcs_destroy when you are
174  * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
175  * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
176  * be returned.
177  *
178  * Since: 4.0.0
179  **/
180 hb_draw_funcs_t *
hb_draw_funcs_create()181 hb_draw_funcs_create ()
182 {
183   hb_draw_funcs_t *dfuncs;
184   if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
185     return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
186 
187   dfuncs->func =  Null (hb_draw_funcs_t).func;
188 
189   return dfuncs;
190 }
191 
192 DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
193 {
194   HB_OBJECT_HEADER_STATIC,
195 
196   {
197 #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
198     HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
199 #undef HB_DRAW_FUNC_IMPLEMENT
200   }
201 };
202 
203 /**
204  * hb_draw_funcs_get_empty:
205  *
206  * Fetches the singleton empty draw-functions structure.
207  *
208  * Return value: (transfer full): The empty draw-functions structure
209  *
210  * Since: 7.0.0
211  **/
212 hb_draw_funcs_t *
hb_draw_funcs_get_empty()213 hb_draw_funcs_get_empty ()
214 {
215   return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
216 }
217 
218 /**
219  * hb_draw_funcs_reference: (skip)
220  * @dfuncs: draw functions
221  *
222  * Increases the reference count on @dfuncs by one.
223  *
224  * This prevents @dfuncs from being destroyed until a matching
225  * call to hb_draw_funcs_destroy() is made.
226  *
227  * Return value: (transfer full):
228  * The referenced #hb_draw_funcs_t.
229  *
230  * Since: 4.0.0
231  **/
232 hb_draw_funcs_t *
hb_draw_funcs_reference(hb_draw_funcs_t * dfuncs)233 hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
234 {
235   return hb_object_reference (dfuncs);
236 }
237 
238 /**
239  * hb_draw_funcs_destroy: (skip)
240  * @dfuncs: draw functions
241  *
242  * Deallocate the @dfuncs.
243  * Decreases the reference count on @dfuncs by one. If the result is zero, then
244  * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
245  *
246  * Since: 4.0.0
247  **/
248 void
hb_draw_funcs_destroy(hb_draw_funcs_t * dfuncs)249 hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
250 {
251   if (!hb_object_destroy (dfuncs)) return;
252 
253   if (dfuncs->destroy)
254   {
255 #define HB_DRAW_FUNC_IMPLEMENT(name) \
256     if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
257       HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
258 #undef HB_DRAW_FUNC_IMPLEMENT
259   }
260 
261   hb_free (dfuncs->destroy);
262   hb_free (dfuncs->user_data);
263 
264   hb_free (dfuncs);
265 }
266 
267 /**
268  * hb_draw_funcs_set_user_data: (skip)
269  * @dfuncs: The draw-functions structure
270  * @key: The user-data key
271  * @data: A pointer to the user data
272  * @destroy: (nullable): A callback to call when @data is not needed anymore
273  * @replace: Whether to replace an existing data with the same key
274  *
275  * Attaches a user-data key/data pair to the specified draw-functions structure.
276  *
277  * Return value: `true` if success, `false` otherwise
278  *
279  * Since: 7.0.0
280  **/
281 hb_bool_t
hb_draw_funcs_set_user_data(hb_draw_funcs_t * dfuncs,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)282 hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
283 			     hb_user_data_key_t *key,
284 			     void *              data,
285 			     hb_destroy_func_t   destroy,
286 			     hb_bool_t           replace)
287 {
288   return hb_object_set_user_data (dfuncs, key, data, destroy, replace);
289 }
290 
291 /**
292  * hb_draw_funcs_get_user_data: (skip)
293  * @dfuncs: The draw-functions structure
294  * @key: The user-data key to query
295  *
296  * Fetches the user-data associated with the specified key,
297  * attached to the specified draw-functions structure.
298  *
299  * Return value: (transfer none): A pointer to the user data
300  *
301  * Since: 7.0.0
302  **/
303 void *
hb_draw_funcs_get_user_data(const hb_draw_funcs_t * dfuncs,hb_user_data_key_t * key)304 hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
305 			     hb_user_data_key_t       *key)
306 {
307   return hb_object_get_user_data (dfuncs, key);
308 }
309 
310 /**
311  * hb_draw_funcs_make_immutable:
312  * @dfuncs: draw functions
313  *
314  * Makes @dfuncs object immutable.
315  *
316  * Since: 4.0.0
317  **/
318 void
hb_draw_funcs_make_immutable(hb_draw_funcs_t * dfuncs)319 hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
320 {
321   if (hb_object_is_immutable (dfuncs))
322     return;
323 
324   hb_object_make_immutable (dfuncs);
325 }
326 
327 /**
328  * hb_draw_funcs_is_immutable:
329  * @dfuncs: draw functions
330  *
331  * Checks whether @dfuncs is immutable.
332  *
333  * Return value: `true` if @dfuncs is immutable, `false` otherwise
334  *
335  * Since: 4.0.0
336  **/
337 hb_bool_t
hb_draw_funcs_is_immutable(hb_draw_funcs_t * dfuncs)338 hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
339 {
340   return hb_object_is_immutable (dfuncs);
341 }
342 
343 
344 /**
345  * hb_draw_move_to:
346  * @dfuncs: draw functions
347  * @draw_data: associated draw data passed by the caller
348  * @st: current draw state
349  * @to_x: X component of target point
350  * @to_y: Y component of target point
351  *
352  * Perform a "move-to" draw operation.
353  *
354  * Since: 4.0.0
355  **/
356 void
hb_draw_move_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float to_x,float to_y)357 hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
358 		 hb_draw_state_t *st,
359 		 float to_x, float to_y)
360 {
361   dfuncs->move_to (draw_data, *st,
362 		   to_x, to_y);
363 }
364 
365 /**
366  * hb_draw_line_to:
367  * @dfuncs: draw functions
368  * @draw_data: associated draw data passed by the caller
369  * @st: current draw state
370  * @to_x: X component of target point
371  * @to_y: Y component of target point
372  *
373  * Perform a "line-to" draw operation.
374  *
375  * Since: 4.0.0
376  **/
377 void
hb_draw_line_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float to_x,float to_y)378 hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
379 		 hb_draw_state_t *st,
380 		 float to_x, float to_y)
381 {
382   dfuncs->line_to (draw_data, *st,
383 		   to_x, to_y);
384 }
385 
386 /**
387  * hb_draw_quadratic_to:
388  * @dfuncs: draw functions
389  * @draw_data: associated draw data passed by the caller
390  * @st: current draw state
391  * @control_x: X component of control point
392  * @control_y: Y component of control point
393  * @to_x: X component of target point
394  * @to_y: Y component of target point
395  *
396  * Perform a "quadratic-to" draw operation.
397  *
398  * Since: 4.0.0
399  **/
400 void
hb_draw_quadratic_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float control_x,float control_y,float to_x,float to_y)401 hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
402 		      hb_draw_state_t *st,
403 		      float control_x, float control_y,
404 		      float to_x, float to_y)
405 {
406   dfuncs->quadratic_to (draw_data, *st,
407 			control_x, control_y,
408 			to_x, to_y);
409 }
410 
411 /**
412  * hb_draw_cubic_to:
413  * @dfuncs: draw functions
414  * @draw_data: associated draw data passed by the caller
415  * @st: current draw state
416  * @control1_x: X component of first control point
417  * @control1_y: Y component of first control point
418  * @control2_x: X component of second control point
419  * @control2_y: Y component of second control point
420  * @to_x: X component of target point
421  * @to_y: Y component of target point
422  *
423  * Perform a "cubic-to" draw operation.
424  *
425  * Since: 4.0.0
426  **/
427 void
hb_draw_cubic_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float control1_x,float control1_y,float control2_x,float control2_y,float to_x,float to_y)428 hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
429 		  hb_draw_state_t *st,
430 		  float control1_x, float control1_y,
431 		  float control2_x, float control2_y,
432 		  float to_x, float to_y)
433 {
434   dfuncs->cubic_to (draw_data, *st,
435 		    control1_x, control1_y,
436 		    control2_x, control2_y,
437 		    to_x, to_y);
438 }
439 
440 /**
441  * hb_draw_close_path:
442  * @dfuncs: draw functions
443  * @draw_data: associated draw data passed by the caller
444  * @st: current draw state
445  *
446  * Perform a "close-path" draw operation.
447  *
448  * Since: 4.0.0
449  **/
450 void
hb_draw_close_path(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st)451 hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
452 		    hb_draw_state_t *st)
453 {
454   dfuncs->close_path (draw_data, *st);
455 }
456 
457 
458 #endif
459