Coverage Report

Created: 2025-07-07 10:01

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