• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 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)41 hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
42 		     hb_draw_state_t *st HB_UNUSED,
43 		     float to_x HB_UNUSED, float to_y HB_UNUSED,
44 		     void *user_data HB_UNUSED) {}
45 
46 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)47 hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
48 		     hb_draw_state_t *st HB_UNUSED,
49 		     float to_x HB_UNUSED, float to_y HB_UNUSED,
50 		     void *user_data HB_UNUSED) {}
51 
52 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)53 hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
54 			  hb_draw_state_t *st,
55 			  float control_x, float control_y,
56 			  float to_x, float to_y,
57 			  void *user_data HB_UNUSED)
58 {
59 #define HB_ONE_THIRD 0.33333333f
60   dfuncs->emit_cubic_to (draw_data, *st,
61 			 (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
62 			 (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
63 			 (to_x + 2.f * control_x) * HB_ONE_THIRD,
64 			 (to_y + 2.f * control_y) * HB_ONE_THIRD,
65 			 to_x, to_y);
66 #undef HB_ONE_THIRD
67 }
68 
69 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)70 hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
71 		      hb_draw_state_t *st HB_UNUSED,
72 		      float control1_x HB_UNUSED, float control1_y HB_UNUSED,
73 		      float control2_x HB_UNUSED, float control2_y HB_UNUSED,
74 		      float to_x HB_UNUSED, float to_y HB_UNUSED,
75 		      void *user_data HB_UNUSED) {}
76 
77 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)78 hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
79 			hb_draw_state_t *st HB_UNUSED,
80 			void *user_data HB_UNUSED) {}
81 
82 
83 static bool
_hb_draw_funcs_set_preamble(hb_draw_funcs_t * dfuncs,bool func_is_null,void ** user_data,hb_destroy_func_t * destroy)84 _hb_draw_funcs_set_preamble (hb_draw_funcs_t    *dfuncs,
85 			     bool                func_is_null,
86 			     void              **user_data,
87 			     hb_destroy_func_t  *destroy)
88 {
89   if (hb_object_is_immutable (dfuncs))
90   {
91     if (*destroy)
92       (*destroy) (*user_data);
93     return false;
94   }
95 
96   if (func_is_null)
97   {
98     if (*destroy)
99       (*destroy) (*user_data);
100     *destroy = nullptr;
101     *user_data = nullptr;
102   }
103 
104   return true;
105 }
106 
107 static bool
_hb_draw_funcs_set_middle(hb_draw_funcs_t * dfuncs,void * user_data,hb_destroy_func_t destroy)108 _hb_draw_funcs_set_middle (hb_draw_funcs_t   *dfuncs,
109 			   void              *user_data,
110 			   hb_destroy_func_t  destroy)
111 {
112   if (user_data && !dfuncs->user_data)
113   {
114     dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
115     if (unlikely (!dfuncs->user_data))
116       goto fail;
117   }
118   if (destroy && !dfuncs->destroy)
119   {
120     dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
121     if (unlikely (!dfuncs->destroy))
122       goto fail;
123   }
124 
125   return true;
126 
127 fail:
128   if (destroy)
129     (destroy) (user_data);
130   return false;
131 }
132 
133 #define HB_DRAW_FUNC_IMPLEMENT(name)						\
134 										\
135 void										\
136 hb_draw_funcs_set_##name##_func (hb_draw_funcs_t	 *dfuncs,		\
137 				 hb_draw_##name##_func_t  func,			\
138 				 void			 *user_data,		\
139 				 hb_destroy_func_t	  destroy)		\
140 {										\
141   if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
142       return;                                                            \
143 										\
144   if (dfuncs->destroy && dfuncs->destroy->name)					\
145     dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
146 									 \
147   if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy))           \
148       return;                                                            \
149 									\
150   if (func)								\
151     dfuncs->func.name = func;						\
152   else									\
153     dfuncs->func.name = hb_draw_##name##_nil;				\
154 									\
155   if (dfuncs->user_data)						\
156     dfuncs->user_data->name = user_data;				\
157   if (dfuncs->destroy)							\
158     dfuncs->destroy->name = destroy;					\
159 }
160 
161 HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
162 #undef HB_DRAW_FUNC_IMPLEMENT
163 
164 /**
165  * hb_draw_funcs_create:
166  *
167  * Creates a new draw callbacks object.
168  *
169  * Return value: (transfer full):
170  * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
171  * reference count should be released with hb_draw_funcs_destroy when you are
172  * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
173  * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
174  * be returned.
175  *
176  * Since: 4.0.0
177  **/
178 hb_draw_funcs_t *
hb_draw_funcs_create()179 hb_draw_funcs_create ()
180 {
181   hb_draw_funcs_t *dfuncs;
182   if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
183     return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
184 
185   dfuncs->func =  Null (hb_draw_funcs_t).func;
186 
187   return dfuncs;
188 }
189 
190 DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
191 {
192   HB_OBJECT_HEADER_STATIC,
193 
194   {
195 #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
196     HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
197 #undef HB_DRAW_FUNC_IMPLEMENT
198   }
199 };
200 
201 
202 /**
203  * hb_draw_funcs_reference: (skip)
204  * @dfuncs: draw functions
205  *
206  * Increases the reference count on @dfuncs by one. This prevents @buffer from
207  * being destroyed until a matching call to hb_draw_funcs_destroy() is made.
208  *
209  * Return value: (transfer full):
210  * The referenced #hb_draw_funcs_t.
211  *
212  * Since: 4.0.0
213  **/
214 hb_draw_funcs_t *
hb_draw_funcs_reference(hb_draw_funcs_t * dfuncs)215 hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
216 {
217   return hb_object_reference (dfuncs);
218 }
219 
220 /**
221  * hb_draw_funcs_destroy: (skip)
222  * @dfuncs: draw functions
223  *
224  * Deallocate the @dfuncs.
225  * Decreases the reference count on @dfuncs by one. If the result is zero, then
226  * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
227  *
228  * Since: 4.0.0
229  **/
230 void
hb_draw_funcs_destroy(hb_draw_funcs_t * dfuncs)231 hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
232 {
233   if (!hb_object_destroy (dfuncs)) return;
234 
235   if (dfuncs->destroy)
236   {
237 #define HB_DRAW_FUNC_IMPLEMENT(name) \
238     if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
239       HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
240 #undef HB_DRAW_FUNC_IMPLEMENT
241   }
242 
243   hb_free (dfuncs->destroy);
244   hb_free (dfuncs->user_data);
245 
246   hb_free (dfuncs);
247 }
248 
249 /**
250  * hb_draw_funcs_make_immutable:
251  * @dfuncs: draw functions
252  *
253  * Makes @dfuncs object immutable.
254  *
255  * Since: 4.0.0
256  **/
257 void
hb_draw_funcs_make_immutable(hb_draw_funcs_t * dfuncs)258 hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
259 {
260   if (hb_object_is_immutable (dfuncs))
261     return;
262 
263   hb_object_make_immutable (dfuncs);
264 }
265 
266 /**
267  * hb_draw_funcs_is_immutable:
268  * @dfuncs: draw functions
269  *
270  * Checks whether @dfuncs is immutable.
271  *
272  * Return value: `true` if @dfuncs is immutable, `false` otherwise
273  *
274  * Since: 4.0.0
275  **/
276 hb_bool_t
hb_draw_funcs_is_immutable(hb_draw_funcs_t * dfuncs)277 hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
278 {
279   return hb_object_is_immutable (dfuncs);
280 }
281 
282 
283 /**
284  * hb_draw_move_to:
285  * @dfuncs: draw functions
286  * @draw_data: associated draw data passed by the caller
287  * @st: current draw state
288  * @to_x: X component of target point
289  * @to_y: Y component of target point
290  *
291  * Perform a "move-to" draw operation.
292  *
293  * Since: 4.0.0
294  **/
295 void
hb_draw_move_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float to_x,float to_y)296 hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
297 		 hb_draw_state_t *st,
298 		 float to_x, float to_y)
299 {
300   dfuncs->move_to (draw_data, *st,
301 		   to_x, to_y);
302 }
303 
304 /**
305  * hb_draw_line_to:
306  * @dfuncs: draw functions
307  * @draw_data: associated draw data passed by the caller
308  * @st: current draw state
309  * @to_x: X component of target point
310  * @to_y: Y component of target point
311  *
312  * Perform a "line-to" draw operation.
313  *
314  * Since: 4.0.0
315  **/
316 void
hb_draw_line_to(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st,float to_x,float to_y)317 hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
318 		 hb_draw_state_t *st,
319 		 float to_x, float to_y)
320 {
321   dfuncs->line_to (draw_data, *st,
322 		   to_x, to_y);
323 }
324 
325 /**
326  * hb_draw_quadratic_to:
327  * @dfuncs: draw functions
328  * @draw_data: associated draw data passed by the caller
329  * @st: current draw state
330  * @control_x: X component of control point
331  * @control_y: Y component of control point
332  * @to_x: X component of target point
333  * @to_y: Y component of target point
334  *
335  * Perform a "quadratic-to" draw operation.
336  *
337  * Since: 4.0.0
338  **/
339 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)340 hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
341 		      hb_draw_state_t *st,
342 		      float control_x, float control_y,
343 		      float to_x, float to_y)
344 {
345   dfuncs->quadratic_to (draw_data, *st,
346 			control_x, control_y,
347 			to_x, to_y);
348 }
349 
350 /**
351  * hb_draw_cubic_to:
352  * @dfuncs: draw functions
353  * @draw_data: associated draw data passed by the caller
354  * @st: current draw state
355  * @control1_x: X component of first control point
356  * @control1_y: Y component of first control point
357  * @control2_x: X component of second control point
358  * @control2_y: Y component of second control point
359  * @to_x: X component of target point
360  * @to_y: Y component of target point
361  *
362  * Perform a "cubic-to" draw operation.
363  *
364  * Since: 4.0.0
365  **/
366 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)367 hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
368 		  hb_draw_state_t *st,
369 		  float control1_x, float control1_y,
370 		  float control2_x, float control2_y,
371 		  float to_x, float to_y)
372 {
373   dfuncs->cubic_to (draw_data, *st,
374 		    control1_x, control1_y,
375 		    control2_x, control2_y,
376 		    to_x, to_y);
377 }
378 
379 /**
380  * hb_draw_close_path:
381  * @dfuncs: draw functions
382  * @draw_data: associated draw data passed by the caller
383  * @st: current draw state
384  *
385  * Perform a "close-path" draw operation.
386  *
387  * Since: 4.0.0
388  **/
389 void
hb_draw_close_path(hb_draw_funcs_t * dfuncs,void * draw_data,hb_draw_state_t * st)390 hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
391 		    hb_draw_state_t *st)
392 {
393   dfuncs->close_path (draw_data, *st);
394 }
395 
396 
397 #endif
398