hb-paint.hh (8957B)
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 HB_PAINT_FUNC_IMPLEMENT (push_transform) \ 35 HB_PAINT_FUNC_IMPLEMENT (pop_transform) \ 36 HB_PAINT_FUNC_IMPLEMENT (color_glyph) \ 37 HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \ 38 HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \ 39 HB_PAINT_FUNC_IMPLEMENT (pop_clip) \ 40 HB_PAINT_FUNC_IMPLEMENT (color) \ 41 HB_PAINT_FUNC_IMPLEMENT (image) \ 42 HB_PAINT_FUNC_IMPLEMENT (linear_gradient) \ 43 HB_PAINT_FUNC_IMPLEMENT (radial_gradient) \ 44 HB_PAINT_FUNC_IMPLEMENT (sweep_gradient) \ 45 HB_PAINT_FUNC_IMPLEMENT (push_group) \ 46 HB_PAINT_FUNC_IMPLEMENT (pop_group) \ 47 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 { 77 // Handle -0.f to avoid -0.f == 0.f in the transform matrix. 78 if (dx == -0.f) dx = 0.f; 79 if (dy == -0.f) dy = 0.f; 80 func.push_transform (this, paint_data, 81 xx, yx, xy, yy, dx, dy, 82 !user_data ? nullptr : user_data->push_transform); } 83 void pop_transform (void *paint_data) 84 { func.pop_transform (this, paint_data, 85 !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 { return func.color_glyph (this, paint_data, 90 glyph, 91 font, 92 !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 { func.push_clip_glyph (this, paint_data, 97 glyph, 98 font, 99 !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 { func.push_clip_rectangle (this, paint_data, 103 xmin, ymin, xmax, ymax, 104 !user_data ? nullptr : user_data->push_clip_rectangle); } 105 void pop_clip (void *paint_data) 106 { func.pop_clip (this, paint_data, 107 !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 { func.color (this, paint_data, 112 is_foreground, color, 113 !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 { return func.image (this, paint_data, 121 image, width, height, format, slant, extents, 122 !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 { func.linear_gradient (this, paint_data, 129 color_line, x0, y0, x1, y1, x2, y2, 130 !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 { func.radial_gradient (this, paint_data, 136 color_line, x0, y0, r0, x1, y1, r1, 137 !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 { func.sweep_gradient (this, paint_data, 144 color_line, x0, y0, start_angle, end_angle, 145 !user_data ? nullptr : user_data->sweep_gradient); } 146 void push_group (void *paint_data) 147 { func.push_group (this, paint_data, 148 !user_data ? nullptr : user_data->push_group); } 149 void pop_group (void *paint_data, 150 hb_paint_composite_mode_t mode) 151 { func.pop_group (this, paint_data, 152 mode, 153 !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 { return func.custom_palette_color (this, paint_data, 158 color_index, 159 color, 160 !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 { 168 float upem = font->face->get_upem (); 169 int xscale = font->x_scale, yscale = font->y_scale; 170 171 push_transform (paint_data, 172 xscale/upem, 0, 173 0, yscale/upem, 174 0, 0); 175 } 176 177 void push_inverse_font_transform (void *paint_data, 178 const hb_font_t *font) 179 { 180 float upem = font->face->get_upem (); 181 int xscale = font->x_scale ? font->x_scale : upem; 182 int yscale = font->y_scale ? font->y_scale : upem; 183 184 push_transform (paint_data, 185 upem/xscale, 0, 186 0, upem/yscale, 187 0, 0); 188 } 189 190 void push_transform (void *paint_data, hb_transform_t<float> t) 191 { 192 push_transform (paint_data, t.xx, t.yx, t.xy, t.yy, t.x0, t.y0); 193 } 194 195 void push_translate (void *paint_data, 196 float dx, float dy) 197 { 198 push_transform (paint_data, 199 hb_transform_t<float>::translation (dx, dy)); 200 } 201 202 void push_scale (void *paint_data, 203 float sx, float sy) 204 { 205 push_transform (paint_data, 206 hb_transform_t<float>::scaling (sx, sy)); 207 } 208 void push_scale_around_center (void *paint_data, 209 float sx, float sy, 210 float cx, float cy) 211 { 212 push_transform (paint_data, 213 hb_transform_t<float>::scaling_around_center (sx, sy, cx, cy)); 214 } 215 216 void push_rotate (void *paint_data, 217 float a) 218 { 219 push_transform (paint_data, 220 hb_transform_t<float>::rotation (a * HB_PI)); 221 } 222 223 void push_rotate_around_center (void *paint_data, 224 float a, 225 float cx, float cy) 226 { 227 push_transform (paint_data, 228 hb_transform_t<float>::rotation_around_center (a * HB_PI, cx, cy)); 229 } 230 231 void push_skew (void *paint_data, 232 float sx, float sy) 233 { 234 push_transform (paint_data, 235 hb_transform_t<float>::skewing (-sx * HB_PI, sy * HB_PI)); 236 } 237 void push_skew_around_center (void *paint_data, 238 float sx, float sy, 239 float cx, float cy) 240 { 241 push_transform (paint_data, 242 hb_transform_t<float>::skewing_around_center (-sx * HB_PI, sy * HB_PI, cx, cy)); 243 } 244 }; 245 DECLARE_NULL_INSTANCE (hb_paint_funcs_t); 246 247 248 #endif /* HB_PAINT_HH */