Coverage Report

Created: 2025-07-18 06:12

/src/harfbuzz/src/hb-paint.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2022 Matthias Clasen
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
#ifndef HB_PAINT_HH
26
#define HB_PAINT_HH
27
28
#include "hb.hh"
29
#include "hb-face.hh"
30
#include "hb-font.hh"
31
#include "hb-geometry.hh"
32
33
#define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \
34
0
  HB_PAINT_FUNC_IMPLEMENT (push_transform) \
35
0
  HB_PAINT_FUNC_IMPLEMENT (pop_transform) \
36
0
  HB_PAINT_FUNC_IMPLEMENT (color_glyph) \
37
0
  HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \
38
0
  HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \
39
0
  HB_PAINT_FUNC_IMPLEMENT (pop_clip) \
40
0
  HB_PAINT_FUNC_IMPLEMENT (color) \
41
0
  HB_PAINT_FUNC_IMPLEMENT (image) \
42
0
  HB_PAINT_FUNC_IMPLEMENT (linear_gradient) \
43
0
  HB_PAINT_FUNC_IMPLEMENT (radial_gradient) \
44
0
  HB_PAINT_FUNC_IMPLEMENT (sweep_gradient) \
45
0
  HB_PAINT_FUNC_IMPLEMENT (push_group) \
46
0
  HB_PAINT_FUNC_IMPLEMENT (pop_group) \
47
0
  HB_PAINT_FUNC_IMPLEMENT (custom_palette_color) \
48
  /* ^--- Add new callbacks here */
49
50
struct hb_paint_funcs_t
51
{
52
  hb_object_header_t header;
53
54
  struct {
55
#define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_func_t name;
56
    HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
57
#undef HB_PAINT_FUNC_IMPLEMENT
58
  } func;
59
60
  struct {
61
#define HB_PAINT_FUNC_IMPLEMENT(name) void *name;
62
    HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
63
#undef HB_PAINT_FUNC_IMPLEMENT
64
  } *user_data;
65
66
  struct {
67
#define HB_PAINT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
68
    HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
69
#undef HB_PAINT_FUNC_IMPLEMENT
70
  } *destroy;
71
72
  void push_transform (void *paint_data,
73
                       float xx, float yx,
74
                       float xy, float yy,
75
                       float dx, float dy)
76
0
  {
77
    // Handle -0.f to avoid -0.f == 0.f in the transform matrix.
78
0
    if (dx == -0.f) dx = 0.f;
79
0
    if (dy == -0.f) dy = 0.f;
80
0
    func.push_transform (this, paint_data,
81
0
                         xx, yx, xy, yy, dx, dy,
82
0
                         !user_data ? nullptr : user_data->push_transform); }
83
  void pop_transform (void *paint_data)
84
0
  { func.pop_transform (this, paint_data,
85
0
                        !user_data ? nullptr : user_data->pop_transform); }
86
  bool color_glyph (void *paint_data,
87
                    hb_codepoint_t glyph,
88
                    hb_font_t *font)
89
0
  { return func.color_glyph (this, paint_data,
90
0
                             glyph,
91
0
                             font,
92
0
                             !user_data ? nullptr : user_data->push_clip_glyph); }
93
  void push_clip_glyph (void *paint_data,
94
                        hb_codepoint_t glyph,
95
                        hb_font_t *font)
96
0
  { func.push_clip_glyph (this, paint_data,
97
0
                          glyph,
98
0
                          font,
99
0
                          !user_data ? nullptr : user_data->push_clip_glyph); }
100
  void push_clip_rectangle (void *paint_data,
101
                           float xmin, float ymin, float xmax, float ymax)
102
0
  { func.push_clip_rectangle (this, paint_data,
103
0
                              xmin, ymin, xmax, ymax,
104
0
                              !user_data ? nullptr : user_data->push_clip_rectangle); }
105
  void pop_clip (void *paint_data)
106
0
  { func.pop_clip (this, paint_data,
107
0
                   !user_data ? nullptr : user_data->pop_clip); }
108
  void color (void *paint_data,
109
              hb_bool_t is_foreground,
110
              hb_color_t color)
111
0
  { func.color (this, paint_data,
112
0
                is_foreground, color,
113
0
                !user_data ? nullptr : user_data->color); }
114
  bool image (void *paint_data,
115
              hb_blob_t *image,
116
              unsigned width, unsigned height,
117
              hb_tag_t format,
118
              float slant,
119
              hb_glyph_extents_t *extents)
120
0
  { return func.image (this, paint_data,
121
0
                       image, width, height, format, slant, extents,
122
0
                       !user_data ? nullptr : user_data->image); }
123
  void linear_gradient (void *paint_data,
124
                        hb_color_line_t *color_line,
125
                        float x0, float y0,
126
                        float x1, float y1,
127
                        float x2, float y2)
128
0
  { func.linear_gradient (this, paint_data,
129
0
                          color_line, x0, y0, x1, y1, x2, y2,
130
0
                          !user_data ? nullptr : user_data->linear_gradient); }
131
  void radial_gradient (void *paint_data,
132
                        hb_color_line_t *color_line,
133
                        float x0, float y0, float r0,
134
                        float x1, float y1, float r1)
135
0
  { func.radial_gradient (this, paint_data,
136
0
                          color_line, x0, y0, r0, x1, y1, r1,
137
0
                          !user_data ? nullptr : user_data->radial_gradient); }
138
  void sweep_gradient (void *paint_data,
139
                       hb_color_line_t *color_line,
140
                       float x0, float y0,
141
                       float start_angle,
142
                       float end_angle)
143
0
  { func.sweep_gradient (this, paint_data,
144
0
                         color_line, x0, y0, start_angle, end_angle,
145
0
                         !user_data ? nullptr : user_data->sweep_gradient); }
146
  void push_group (void *paint_data)
147
0
  { func.push_group (this, paint_data,
148
0
                     !user_data ? nullptr : user_data->push_group); }
149
  void pop_group (void *paint_data,
150
                  hb_paint_composite_mode_t mode)
151
0
  { func.pop_group (this, paint_data,
152
0
                    mode,
153
0
                    !user_data ? nullptr : user_data->pop_group); }
154
  bool custom_palette_color (void *paint_data,
155
                             unsigned int color_index,
156
                             hb_color_t *color)
157
0
  { return func.custom_palette_color (this, paint_data,
158
0
                                      color_index,
159
0
                                      color,
160
0
                                      !user_data ? nullptr : user_data->custom_palette_color); }
161
162
163
  /* Internal specializations. */
164
165
  void push_font_transform (void *paint_data,
166
                            const hb_font_t *font)
167
0
  {
168
0
    float upem = font->face->get_upem ();
169
0
    int xscale = font->x_scale, yscale = font->y_scale;
170
171
0
    push_transform (paint_data,
172
0
        xscale/upem, 0,
173
0
        0, yscale/upem,
174
0
        0, 0);
175
0
  }
176
177
  void push_inverse_font_transform (void *paint_data,
178
                                    const hb_font_t *font)
179
0
  {
180
0
    float upem = font->face->get_upem ();
181
0
    int xscale = font->x_scale ? font->x_scale : upem;
182
0
    int yscale = font->y_scale ? font->y_scale : upem;
183
184
0
    push_transform (paint_data,
185
0
        upem/xscale, 0,
186
0
        0, upem/yscale,
187
0
        0, 0);
188
0
  }
189
190
  void push_transform (void *paint_data, hb_transform_t<float> t)
191
0
  {
192
0
    push_transform (paint_data, t.xx, t.yx, t.xy, t.yy, t.x0, t.y0);
193
0
  }
194
195
  void push_translate (void *paint_data,
196
                       float dx, float dy)
197
0
  {
198
0
    push_transform (paint_data,
199
0
        hb_transform_t<float>::translation (dx, dy));
200
0
  }
201
202
  void push_scale (void *paint_data,
203
                   float sx, float sy)
204
0
  {
205
0
    push_transform (paint_data,
206
0
        hb_transform_t<float>::scaling (sx, sy));
207
0
  }
208
  void push_scale_around_center (void *paint_data,
209
         float sx, float sy,
210
         float cx, float cy)
211
0
  {
212
0
    push_transform (paint_data,
213
0
        hb_transform_t<float>::scaling_around_center (sx, sy, cx, cy));
214
0
  }
215
216
  void push_rotate (void *paint_data,
217
                    float a)
218
0
  {
219
0
    push_transform (paint_data,
220
0
        hb_transform_t<float>::rotation (a * HB_PI));
221
0
  }
222
223
  void push_rotate_around_center (void *paint_data,
224
          float a,
225
          float cx, float cy)
226
0
  {
227
0
    push_transform (paint_data,
228
0
        hb_transform_t<float>::rotation_around_center (a * HB_PI, cx, cy));
229
0
  }
230
231
  void push_skew (void *paint_data,
232
                  float sx, float sy)
233
0
  {
234
0
    push_transform (paint_data,
235
0
        hb_transform_t<float>::skewing (-sx * HB_PI, sy * HB_PI));
236
0
  }
237
  void push_skew_around_center (void *paint_data,
238
        float sx, float sy,
239
        float cx, float cy)
240
0
  {
241
0
    push_transform (paint_data,
242
0
        hb_transform_t<float>::skewing_around_center (-sx * HB_PI, sy * HB_PI, cx, cy));
243
0
  }
244
};
245
DECLARE_NULL_INSTANCE (hb_paint_funcs_t);
246
247
248
#endif /* HB_PAINT_HH */