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 push_transformhb_paint_funcs_t71 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); } pop_transformhb_paint_funcs_t78 void pop_transform (void *paint_data) 79 { func.pop_transform (this, paint_data, 80 !user_data ? nullptr : user_data->pop_transform); } color_glyphhb_paint_funcs_t81 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); } push_clip_glyphhb_paint_funcs_t88 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); } push_clip_rectanglehb_paint_funcs_t95 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); } pop_cliphb_paint_funcs_t100 void pop_clip (void *paint_data) 101 { func.pop_clip (this, paint_data, 102 !user_data ? nullptr : user_data->pop_clip); } colorhb_paint_funcs_t103 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); } imagehb_paint_funcs_t109 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); } linear_gradienthb_paint_funcs_t118 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); } radial_gradienthb_paint_funcs_t126 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); } sweep_gradienthb_paint_funcs_t133 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); } push_grouphb_paint_funcs_t141 void push_group (void *paint_data) 142 { func.push_group (this, paint_data, 143 !user_data ? nullptr : user_data->push_group); } pop_grouphb_paint_funcs_t144 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); } custom_palette_colorhb_paint_funcs_t149 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 push_root_transformhb_paint_funcs_t160 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 push_inverse_root_transformhb_paint_funcs_t171 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 push_translatehb_paint_funcs_t184 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 push_scalehb_paint_funcs_t196 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 push_rotatehb_paint_funcs_t208 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 push_skewhb_paint_funcs_t221 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 */ 237