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