Bug 1862332 [wpt PR 42877] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / gfx / harfbuzz / src / hb-paint.cc
blob8eb24eb28b2ea66afc31f47bddba52671b1d52aa
1 /*
2 * Copyright © 2022 Matthias Clasen
4 * This is part of HarfBuzz, a text shaping library.
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.
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.
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.
25 #include "hb.hh"
27 #ifndef HB_NO_PAINT
29 #include "hb-paint.hh"
31 /**
32 * SECTION: hb-paint
33 * @title: hb-paint
34 * @short_description: Glyph painting
35 * @include: hb.h
37 * Functions for painting glyphs.
39 * The main purpose of these functions is to paint (extract) color glyph layers
40 * from the COLRv1 table, but the API works for drawing ordinary outlines and
41 * images as well.
43 * The #hb_paint_funcs_t struct can be used with hb_font_paint_glyph().
44 **/
46 static void
47 hb_paint_push_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
48 float xx, float yx,
49 float xy, float yy,
50 float dx, float dy,
51 void *user_data) {}
53 static void
54 hb_paint_pop_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
55 void *user_data) {}
57 static hb_bool_t
58 hb_paint_color_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
59 hb_codepoint_t glyph,
60 hb_font_t *font,
61 void *user_data) { return false; }
63 static void
64 hb_paint_push_clip_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
65 hb_codepoint_t glyph,
66 hb_font_t *font,
67 void *user_data) {}
69 static void
70 hb_paint_push_clip_rectangle_nil (hb_paint_funcs_t *funcs, void *paint_data,
71 float xmin, float ymin, float xmax, float ymax,
72 void *user_data) {}
74 static void
75 hb_paint_pop_clip_nil (hb_paint_funcs_t *funcs, void *paint_data,
76 void *user_data) {}
78 static void
79 hb_paint_color_nil (hb_paint_funcs_t *funcs, void *paint_data,
80 hb_bool_t is_foreground,
81 hb_color_t color,
82 void *user_data) {}
84 static hb_bool_t
85 hb_paint_image_nil (hb_paint_funcs_t *funcs, void *paint_data,
86 hb_blob_t *image,
87 unsigned int width,
88 unsigned int height,
89 hb_tag_t format,
90 float slant_xy,
91 hb_glyph_extents_t *extents,
92 void *user_data) { return false; }
94 static void
95 hb_paint_linear_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
96 hb_color_line_t *color_line,
97 float x0, float y0,
98 float x1, float y1,
99 float x2, float y2,
100 void *user_data) {}
102 static void
103 hb_paint_radial_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
104 hb_color_line_t *color_line,
105 float x0, float y0, float r0,
106 float x1, float y1, float r1,
107 void *user_data) {}
109 static void
110 hb_paint_sweep_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
111 hb_color_line_t *color_line,
112 float x0, float y0,
113 float start_angle,
114 float end_angle,
115 void *user_data) {}
117 static void
118 hb_paint_push_group_nil (hb_paint_funcs_t *funcs, void *paint_data,
119 void *user_data) {}
121 static void
122 hb_paint_pop_group_nil (hb_paint_funcs_t *funcs, void *paint_data,
123 hb_paint_composite_mode_t mode,
124 void *user_data) {}
126 static hb_bool_t
127 hb_paint_custom_palette_color_nil (hb_paint_funcs_t *funcs, void *paint_data,
128 unsigned int color_index,
129 hb_color_t *color,
130 void *user_data) { return false; }
132 static bool
133 _hb_paint_funcs_set_preamble (hb_paint_funcs_t *funcs,
134 bool func_is_null,
135 void **user_data,
136 hb_destroy_func_t *destroy)
138 if (hb_object_is_immutable (funcs))
140 if (*destroy)
141 (*destroy) (*user_data);
142 return false;
145 if (func_is_null)
147 if (*destroy)
148 (*destroy) (*user_data);
149 *destroy = nullptr;
150 *user_data = nullptr;
153 return true;
156 static bool
157 _hb_paint_funcs_set_middle (hb_paint_funcs_t *funcs,
158 void *user_data,
159 hb_destroy_func_t destroy)
161 if (user_data && !funcs->user_data)
163 funcs->user_data = (decltype (funcs->user_data)) hb_calloc (1, sizeof (*funcs->user_data));
164 if (unlikely (!funcs->user_data))
165 goto fail;
167 if (destroy && !funcs->destroy)
169 funcs->destroy = (decltype (funcs->destroy)) hb_calloc (1, sizeof (*funcs->destroy));
170 if (unlikely (!funcs->destroy))
171 goto fail;
174 return true;
176 fail:
177 if (destroy)
178 (destroy) (user_data);
179 return false;
182 #define HB_PAINT_FUNC_IMPLEMENT(name) \
184 void \
185 hb_paint_funcs_set_##name##_func (hb_paint_funcs_t *funcs, \
186 hb_paint_##name##_func_t func, \
187 void *user_data, \
188 hb_destroy_func_t destroy) \
190 if (!_hb_paint_funcs_set_preamble (funcs, !func, &user_data, &destroy)) \
191 return; \
193 if (funcs->destroy && funcs->destroy->name) \
194 funcs->destroy->name (!funcs->user_data ? nullptr : funcs->user_data->name);\
196 if (!_hb_paint_funcs_set_middle (funcs, user_data, destroy)) \
197 return; \
199 if (func) \
200 funcs->func.name = func; \
201 else \
202 funcs->func.name = hb_paint_##name##_nil; \
204 if (funcs->user_data) \
205 funcs->user_data->name = user_data; \
206 if (funcs->destroy) \
207 funcs->destroy->name = destroy; \
210 HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
211 #undef HB_PAINT_FUNC_IMPLEMENT
214 * hb_paint_funcs_create:
216 * Creates a new #hb_paint_funcs_t structure of paint functions.
218 * The initial reference count of 1 should be released with hb_paint_funcs_destroy()
219 * when you are done using the #hb_paint_funcs_t. This function never returns
220 * `NULL`. If memory cannot be allocated, a special singleton #hb_paint_funcs_t
221 * object will be returned.
223 * Returns value: (transfer full): the paint-functions structure
225 * Since: 7.0.0
227 hb_paint_funcs_t *
228 hb_paint_funcs_create ()
230 hb_paint_funcs_t *funcs;
231 if (unlikely (!(funcs = hb_object_create<hb_paint_funcs_t> ())))
232 return const_cast<hb_paint_funcs_t *> (&Null (hb_paint_funcs_t));
234 funcs->func = Null (hb_paint_funcs_t).func;
236 return funcs;
239 DEFINE_NULL_INSTANCE (hb_paint_funcs_t) =
241 HB_OBJECT_HEADER_STATIC,
244 #define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_nil,
245 HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
246 #undef HB_PAINT_FUNC_IMPLEMENT
251 * hb_paint_funcs_get_empty:
253 * Fetches the singleton empty paint-functions structure.
255 * Return value: (transfer full): The empty paint-functions structure
257 * Since: 7.0.0
259 hb_paint_funcs_t *
260 hb_paint_funcs_get_empty ()
262 return const_cast<hb_paint_funcs_t *> (&Null (hb_paint_funcs_t));
266 * hb_paint_funcs_reference: (skip)
267 * @funcs: The paint-functions structure
269 * Increases the reference count on a paint-functions structure.
271 * This prevents @funcs from being destroyed until a matching
272 * call to hb_paint_funcs_destroy() is made.
274 * Return value: The paint-functions structure
276 * Since: 7.0.0
278 hb_paint_funcs_t *
279 hb_paint_funcs_reference (hb_paint_funcs_t *funcs)
281 return hb_object_reference (funcs);
285 * hb_paint_funcs_destroy: (skip)
286 * @funcs: The paint-functions structure
288 * Decreases the reference count on a paint-functions structure.
290 * When the reference count reaches zero, the structure
291 * is destroyed, freeing all memory.
293 * Since: 7.0.0
295 void
296 hb_paint_funcs_destroy (hb_paint_funcs_t *funcs)
298 if (!hb_object_destroy (funcs)) return;
300 if (funcs->destroy)
302 #define HB_PAINT_FUNC_IMPLEMENT(name) \
303 if (funcs->destroy->name) funcs->destroy->name (!funcs->user_data ? nullptr : funcs->user_data->name);
304 HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
305 #undef HB_PAINT_FUNC_IMPLEMENT
308 hb_free (funcs->destroy);
309 hb_free (funcs->user_data);
310 hb_free (funcs);
314 * hb_paint_funcs_set_user_data: (skip)
315 * @funcs: The paint-functions structure
316 * @key: The user-data key
317 * @data: A pointer to the user data
318 * @destroy: (nullable): A callback to call when @data is not needed anymore
319 * @replace: Whether to replace an existing data with the same key
321 * Attaches a user-data key/data pair to the specified paint-functions structure.
323 * Return value: `true` if success, `false` otherwise
325 * Since: 7.0.0
327 hb_bool_t
328 hb_paint_funcs_set_user_data (hb_paint_funcs_t *funcs,
329 hb_user_data_key_t *key,
330 void * data,
331 hb_destroy_func_t destroy,
332 hb_bool_t replace)
334 return hb_object_set_user_data (funcs, key, data, destroy, replace);
338 * hb_paint_funcs_get_user_data: (skip)
339 * @funcs: The paint-functions structure
340 * @key: The user-data key to query
342 * Fetches the user-data associated with the specified key,
343 * attached to the specified paint-functions structure.
345 * Return value: (transfer none): A pointer to the user data
347 * Since: 7.0.0
349 void *
350 hb_paint_funcs_get_user_data (const hb_paint_funcs_t *funcs,
351 hb_user_data_key_t *key)
353 return hb_object_get_user_data (funcs, key);
357 * hb_paint_funcs_make_immutable:
358 * @funcs: The paint-functions structure
360 * Makes a paint-functions structure immutable.
362 * After this call, all attempts to set one of the callbacks
363 * on @funcs will fail.
365 * Since: 7.0.0
367 void
368 hb_paint_funcs_make_immutable (hb_paint_funcs_t *funcs)
370 if (hb_object_is_immutable (funcs))
371 return;
373 hb_object_make_immutable (funcs);
377 * hb_paint_funcs_is_immutable:
378 * @funcs: The paint-functions structure
380 * Tests whether a paint-functions structure is immutable.
382 * Return value: `true` if @funcs is immutable, `false` otherwise
384 * Since: 7.0.0
386 hb_bool_t
387 hb_paint_funcs_is_immutable (hb_paint_funcs_t *funcs)
389 return hb_object_is_immutable (funcs);
394 * hb_color_line_get_color_stops:
395 * @color_line: a #hb_color_line_t object
396 * @start: the index of the first color stop to return
397 * @count: (inout) (optional): Input = the maximum number of feature tags to return;
398 * Output = the actual number of feature tags returned (may be zero)
399 * @color_stops: (out) (array length=count) (optional): Array of #hb_color_stop_t to populate
401 * Fetches a list of color stops from the given color line object.
403 * Note that due to variations being applied, the returned color stops
404 * may be out of order. It is the callers responsibility to ensure that
405 * color stops are sorted by their offset before they are used.
407 * Return value: the total number of color stops in @color_line
409 * Since: 7.0.0
411 unsigned int
412 hb_color_line_get_color_stops (hb_color_line_t *color_line,
413 unsigned int start,
414 unsigned int *count,
415 hb_color_stop_t *color_stops)
417 return color_line->get_color_stops (color_line,
418 color_line->data,
419 start, count,
420 color_stops,
421 color_line->get_color_stops_user_data);
425 * hb_color_line_get_extend:
426 * @color_line: a #hb_color_line_t object
428 * Fetches the extend mode of the color line object.
430 * Return value: the extend mode of @color_line
432 * Since: 7.0.0
434 hb_paint_extend_t
435 hb_color_line_get_extend (hb_color_line_t *color_line)
437 return color_line->get_extend (color_line,
438 color_line->data,
439 color_line->get_extend_user_data);
444 * hb_paint_push_transform:
445 * @funcs: paint functions
446 * @paint_data: associated data passed by the caller
447 * @xx: xx component of the transform matrix
448 * @yx: yx component of the transform matrix
449 * @xy: xy component of the transform matrix
450 * @yy: yy component of the transform matrix
451 * @dx: dx component of the transform matrix
452 * @dy: dy component of the transform matrix
454 * Perform a "push-transform" paint operation.
456 * Since: 7.0.0
458 void
459 hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
460 float xx, float yx,
461 float xy, float yy,
462 float dx, float dy)
464 funcs->push_transform (paint_data, xx, yx, xy, yy, dx, dy);
468 * hb_paint_pop_transform:
469 * @funcs: paint functions
470 * @paint_data: associated data passed by the caller
472 * Perform a "pop-transform" paint operation.
474 * Since: 7.0.0
476 void
477 hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data)
479 funcs->pop_transform (paint_data);
483 * hb_paint_color_glyph:
484 * @funcs: paint functions
485 * @paint_data: associated data passed by the caller
486 * @glyph: the glyph ID
487 * @font: the font
489 * Perform a "color-glyph" paint operation.
491 * Since: 8.2.0
493 hb_bool_t
494 hb_paint_color_glyph (hb_paint_funcs_t *funcs, void *paint_data,
495 hb_codepoint_t glyph,
496 hb_font_t *font)
498 return funcs->color_glyph (paint_data, glyph, font);
502 * hb_paint_push_clip_glyph:
503 * @funcs: paint functions
504 * @paint_data: associated data passed by the caller
505 * @glyph: the glyph ID
506 * @font: the font
508 * Perform a "push-clip-glyph" paint operation.
510 * Since: 7.0.0
512 void
513 hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
514 hb_codepoint_t glyph,
515 hb_font_t *font)
517 funcs->push_clip_glyph (paint_data, glyph, font);
521 * hb_paint_push_clip_rectangle:
522 * @funcs: paint functions
523 * @paint_data: associated data passed by the caller
524 * @xmin: min X for the rectangle
525 * @ymin: min Y for the rectangle
526 * @xmax: max X for the rectangle
527 * @ymax: max Y for the rectangle
529 * Perform a "push-clip-rect" paint operation.
531 * Since: 7.0.0
533 void
534 hb_paint_push_clip_rectangle (hb_paint_funcs_t *funcs, void *paint_data,
535 float xmin, float ymin, float xmax, float ymax)
537 funcs->push_clip_rectangle (paint_data, xmin, ymin, xmax, ymax);
541 * hb_paint_pop_clip:
542 * @funcs: paint functions
543 * @paint_data: associated data passed by the caller
545 * Perform a "pop-clip" paint operation.
547 * Since: 7.0.0
549 void
550 hb_paint_pop_clip (hb_paint_funcs_t *funcs, void *paint_data)
552 funcs->pop_clip (paint_data);
556 * hb_paint_color:
557 * @funcs: paint functions
558 * @paint_data: associated data passed by the caller
559 * @is_foreground: whether the color is the foreground
560 * @color: The color to use
562 * Perform a "color" paint operation.
564 * Since: 7.0.0
566 void
567 hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
568 hb_bool_t is_foreground,
569 hb_color_t color)
571 funcs->color (paint_data, is_foreground, color);
575 * hb_paint_image:
576 * @funcs: paint functions
577 * @paint_data: associated data passed by the caller
578 * @image: image data
579 * @width: width of the raster image in pixels, or 0
580 * @height: height of the raster image in pixels, or 0
581 * @format: the image format as a tag
582 * @slant: the synthetic slant ratio to be applied to the image during rendering
583 * @extents: (nullable): the extents of the glyph
585 * Perform a "image" paint operation.
587 * Since: 7.0.0
589 void
590 hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
591 hb_blob_t *image,
592 unsigned int width,
593 unsigned int height,
594 hb_tag_t format,
595 float slant,
596 hb_glyph_extents_t *extents)
598 funcs->image (paint_data, image, width, height, format, slant, extents);
602 * hb_paint_linear_gradient:
603 * @funcs: paint functions
604 * @paint_data: associated data passed by the caller
605 * @color_line: Color information for the gradient
606 * @x0: X coordinate of the first point
607 * @y0: Y coordinate of the first point
608 * @x1: X coordinate of the second point
609 * @y1: Y coordinate of the second point
610 * @x2: X coordinate of the third point
611 * @y2: Y coordinate of the third point
613 * Perform a "linear-gradient" paint operation.
615 * Since: 7.0.0
617 void
618 hb_paint_linear_gradient (hb_paint_funcs_t *funcs, void *paint_data,
619 hb_color_line_t *color_line,
620 float x0, float y0,
621 float x1, float y1,
622 float x2, float y2)
624 funcs->linear_gradient (paint_data, color_line, x0, y0, x1, y1, x2, y2);
628 * hb_paint_radial_gradient:
629 * @funcs: paint functions
630 * @paint_data: associated data passed by the caller
631 * @color_line: Color information for the gradient
632 * @x0: X coordinate of the first circle's center
633 * @y0: Y coordinate of the first circle's center
634 * @r0: radius of the first circle
635 * @x1: X coordinate of the second circle's center
636 * @y1: Y coordinate of the second circle's center
637 * @r1: radius of the second circle
639 * Perform a "radial-gradient" paint operation.
641 * Since: 7.0.0
643 void
644 hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
645 hb_color_line_t *color_line,
646 float x0, float y0, float r0,
647 float x1, float y1, float r1)
649 funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1);
653 * hb_paint_sweep_gradient:
654 * @funcs: paint functions
655 * @paint_data: associated data passed by the caller
656 * @color_line: Color information for the gradient
657 * @x0: X coordinate of the circle's center
658 * @y0: Y coordinate of the circle's center
659 * @start_angle: the start angle
660 * @end_angle: the end angle
662 * Perform a "sweep-gradient" paint operation.
664 * Since: 7.0.0
666 void
667 hb_paint_sweep_gradient (hb_paint_funcs_t *funcs, void *paint_data,
668 hb_color_line_t *color_line,
669 float x0, float y0,
670 float start_angle, float end_angle)
672 funcs->sweep_gradient (paint_data, color_line, x0, y0, start_angle, end_angle);
676 * hb_paint_push_group:
677 * @funcs: paint functions
678 * @paint_data: associated data passed by the caller
680 * Perform a "push-group" paint operation.
682 * Since: 7.0.0
684 void
685 hb_paint_push_group (hb_paint_funcs_t *funcs, void *paint_data)
687 funcs->push_group (paint_data);
691 * hb_paint_pop_group:
692 * @funcs: paint functions
693 * @paint_data: associated data passed by the caller
694 * @mode: the compositing mode to use
696 * Perform a "pop-group" paint operation.
698 * Since: 7.0.0
700 void
701 hb_paint_pop_group (hb_paint_funcs_t *funcs, void *paint_data,
702 hb_paint_composite_mode_t mode)
704 funcs->pop_group (paint_data, mode);
708 * hb_paint_custom_palette_color:
709 * @funcs: paint functions
710 * @paint_data: associated data passed by the caller
711 * @color_index: color index
712 * @color: (out): fetched color
714 * Gets the custom palette color for @color_index.
716 * Return value: `true` if found, `false` otherwise
718 * Since: 7.0.0
720 hb_bool_t
721 hb_paint_custom_palette_color (hb_paint_funcs_t *funcs, void *paint_data,
722 unsigned int color_index,
723 hb_color_t *color)
725 return funcs->custom_palette_color (paint_data, color_index, color);
728 #endif