1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2022 Matthias Clasen 3*2d1272b8SAndroid Build Coastguard Worker * 4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library. 5*2d1272b8SAndroid Build Coastguard Worker * 6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without 7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this 8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the 9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in 10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software. 11*2d1272b8SAndroid Build Coastguard Worker * 12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE. 17*2d1272b8SAndroid Build Coastguard Worker * 18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23*2d1272b8SAndroid Build Coastguard Worker */ 24*2d1272b8SAndroid Build Coastguard Worker 25*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_PAINT_HH 26*2d1272b8SAndroid Build Coastguard Worker #define HB_PAINT_HH 27*2d1272b8SAndroid Build Coastguard Worker 28*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh" 29*2d1272b8SAndroid Build Coastguard Worker #include "hb-face.hh" 30*2d1272b8SAndroid Build Coastguard Worker #include "hb-font.hh" 31*2d1272b8SAndroid Build Coastguard Worker 32*2d1272b8SAndroid Build Coastguard Worker #define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \ 33*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (push_transform) \ 34*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (pop_transform) \ 35*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (color_glyph) \ 36*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \ 37*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \ 38*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (pop_clip) \ 39*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (color) \ 40*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (image) \ 41*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (linear_gradient) \ 42*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (radial_gradient) \ 43*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (sweep_gradient) \ 44*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (push_group) \ 45*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (pop_group) \ 46*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNC_IMPLEMENT (custom_palette_color) \ 47*2d1272b8SAndroid Build Coastguard Worker /* ^--- Add new callbacks here */ 48*2d1272b8SAndroid Build Coastguard Worker 49*2d1272b8SAndroid Build Coastguard Worker struct hb_paint_funcs_t 50*2d1272b8SAndroid Build Coastguard Worker { 51*2d1272b8SAndroid Build Coastguard Worker hb_object_header_t header; 52*2d1272b8SAndroid Build Coastguard Worker 53*2d1272b8SAndroid Build Coastguard Worker struct { 54*2d1272b8SAndroid Build Coastguard Worker #define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_func_t name; 55*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS 56*2d1272b8SAndroid Build Coastguard Worker #undef HB_PAINT_FUNC_IMPLEMENT 57*2d1272b8SAndroid Build Coastguard Worker } func; 58*2d1272b8SAndroid Build Coastguard Worker 59*2d1272b8SAndroid Build Coastguard Worker struct { 60*2d1272b8SAndroid Build Coastguard Worker #define HB_PAINT_FUNC_IMPLEMENT(name) void *name; 61*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS 62*2d1272b8SAndroid Build Coastguard Worker #undef HB_PAINT_FUNC_IMPLEMENT 63*2d1272b8SAndroid Build Coastguard Worker } *user_data; 64*2d1272b8SAndroid Build Coastguard Worker 65*2d1272b8SAndroid Build Coastguard Worker struct { 66*2d1272b8SAndroid Build Coastguard Worker #define HB_PAINT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 67*2d1272b8SAndroid Build Coastguard Worker HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS 68*2d1272b8SAndroid Build Coastguard Worker #undef HB_PAINT_FUNC_IMPLEMENT 69*2d1272b8SAndroid Build Coastguard Worker } *destroy; 70*2d1272b8SAndroid Build Coastguard Worker push_transformhb_paint_funcs_t71*2d1272b8SAndroid Build Coastguard Worker void push_transform (void *paint_data, 72*2d1272b8SAndroid Build Coastguard Worker float xx, float yx, 73*2d1272b8SAndroid Build Coastguard Worker float xy, float yy, 74*2d1272b8SAndroid Build Coastguard Worker float dx, float dy) 75*2d1272b8SAndroid Build Coastguard Worker { func.push_transform (this, paint_data, 76*2d1272b8SAndroid Build Coastguard Worker xx, yx, xy, yy, dx, dy, 77*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->push_transform); } pop_transformhb_paint_funcs_t78*2d1272b8SAndroid Build Coastguard Worker void pop_transform (void *paint_data) 79*2d1272b8SAndroid Build Coastguard Worker { func.pop_transform (this, paint_data, 80*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->pop_transform); } color_glyphhb_paint_funcs_t81*2d1272b8SAndroid Build Coastguard Worker bool color_glyph (void *paint_data, 82*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph, 83*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font) 84*2d1272b8SAndroid Build Coastguard Worker { return func.color_glyph (this, paint_data, 85*2d1272b8SAndroid Build Coastguard Worker glyph, 86*2d1272b8SAndroid Build Coastguard Worker font, 87*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->push_clip_glyph); } push_clip_glyphhb_paint_funcs_t88*2d1272b8SAndroid Build Coastguard Worker void push_clip_glyph (void *paint_data, 89*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph, 90*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font) 91*2d1272b8SAndroid Build Coastguard Worker { func.push_clip_glyph (this, paint_data, 92*2d1272b8SAndroid Build Coastguard Worker glyph, 93*2d1272b8SAndroid Build Coastguard Worker font, 94*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->push_clip_glyph); } push_clip_rectanglehb_paint_funcs_t95*2d1272b8SAndroid Build Coastguard Worker void push_clip_rectangle (void *paint_data, 96*2d1272b8SAndroid Build Coastguard Worker float xmin, float ymin, float xmax, float ymax) 97*2d1272b8SAndroid Build Coastguard Worker { func.push_clip_rectangle (this, paint_data, 98*2d1272b8SAndroid Build Coastguard Worker xmin, ymin, xmax, ymax, 99*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->push_clip_rectangle); } pop_cliphb_paint_funcs_t100*2d1272b8SAndroid Build Coastguard Worker void pop_clip (void *paint_data) 101*2d1272b8SAndroid Build Coastguard Worker { func.pop_clip (this, paint_data, 102*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->pop_clip); } colorhb_paint_funcs_t103*2d1272b8SAndroid Build Coastguard Worker void color (void *paint_data, 104*2d1272b8SAndroid Build Coastguard Worker hb_bool_t is_foreground, 105*2d1272b8SAndroid Build Coastguard Worker hb_color_t color) 106*2d1272b8SAndroid Build Coastguard Worker { func.color (this, paint_data, 107*2d1272b8SAndroid Build Coastguard Worker is_foreground, color, 108*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->color); } imagehb_paint_funcs_t109*2d1272b8SAndroid Build Coastguard Worker bool image (void *paint_data, 110*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *image, 111*2d1272b8SAndroid Build Coastguard Worker unsigned width, unsigned height, 112*2d1272b8SAndroid Build Coastguard Worker hb_tag_t format, 113*2d1272b8SAndroid Build Coastguard Worker float slant, 114*2d1272b8SAndroid Build Coastguard Worker hb_glyph_extents_t *extents) 115*2d1272b8SAndroid Build Coastguard Worker { return func.image (this, paint_data, 116*2d1272b8SAndroid Build Coastguard Worker image, width, height, format, slant, extents, 117*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->image); } linear_gradienthb_paint_funcs_t118*2d1272b8SAndroid Build Coastguard Worker void linear_gradient (void *paint_data, 119*2d1272b8SAndroid Build Coastguard Worker hb_color_line_t *color_line, 120*2d1272b8SAndroid Build Coastguard Worker float x0, float y0, 121*2d1272b8SAndroid Build Coastguard Worker float x1, float y1, 122*2d1272b8SAndroid Build Coastguard Worker float x2, float y2) 123*2d1272b8SAndroid Build Coastguard Worker { func.linear_gradient (this, paint_data, 124*2d1272b8SAndroid Build Coastguard Worker color_line, x0, y0, x1, y1, x2, y2, 125*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->linear_gradient); } radial_gradienthb_paint_funcs_t126*2d1272b8SAndroid Build Coastguard Worker void radial_gradient (void *paint_data, 127*2d1272b8SAndroid Build Coastguard Worker hb_color_line_t *color_line, 128*2d1272b8SAndroid Build Coastguard Worker float x0, float y0, float r0, 129*2d1272b8SAndroid Build Coastguard Worker float x1, float y1, float r1) 130*2d1272b8SAndroid Build Coastguard Worker { func.radial_gradient (this, paint_data, 131*2d1272b8SAndroid Build Coastguard Worker color_line, x0, y0, r0, x1, y1, r1, 132*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->radial_gradient); } sweep_gradienthb_paint_funcs_t133*2d1272b8SAndroid Build Coastguard Worker void sweep_gradient (void *paint_data, 134*2d1272b8SAndroid Build Coastguard Worker hb_color_line_t *color_line, 135*2d1272b8SAndroid Build Coastguard Worker float x0, float y0, 136*2d1272b8SAndroid Build Coastguard Worker float start_angle, 137*2d1272b8SAndroid Build Coastguard Worker float end_angle) 138*2d1272b8SAndroid Build Coastguard Worker { func.sweep_gradient (this, paint_data, 139*2d1272b8SAndroid Build Coastguard Worker color_line, x0, y0, start_angle, end_angle, 140*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->sweep_gradient); } push_grouphb_paint_funcs_t141*2d1272b8SAndroid Build Coastguard Worker void push_group (void *paint_data) 142*2d1272b8SAndroid Build Coastguard Worker { func.push_group (this, paint_data, 143*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->push_group); } pop_grouphb_paint_funcs_t144*2d1272b8SAndroid Build Coastguard Worker void pop_group (void *paint_data, 145*2d1272b8SAndroid Build Coastguard Worker hb_paint_composite_mode_t mode) 146*2d1272b8SAndroid Build Coastguard Worker { func.pop_group (this, paint_data, 147*2d1272b8SAndroid Build Coastguard Worker mode, 148*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->pop_group); } custom_palette_colorhb_paint_funcs_t149*2d1272b8SAndroid Build Coastguard Worker bool custom_palette_color (void *paint_data, 150*2d1272b8SAndroid Build Coastguard Worker unsigned int color_index, 151*2d1272b8SAndroid Build Coastguard Worker hb_color_t *color) 152*2d1272b8SAndroid Build Coastguard Worker { return func.custom_palette_color (this, paint_data, 153*2d1272b8SAndroid Build Coastguard Worker color_index, 154*2d1272b8SAndroid Build Coastguard Worker color, 155*2d1272b8SAndroid Build Coastguard Worker !user_data ? nullptr : user_data->custom_palette_color); } 156*2d1272b8SAndroid Build Coastguard Worker 157*2d1272b8SAndroid Build Coastguard Worker 158*2d1272b8SAndroid Build Coastguard Worker /* Internal specializations. */ 159*2d1272b8SAndroid Build Coastguard Worker push_root_transformhb_paint_funcs_t160*2d1272b8SAndroid Build Coastguard Worker void push_root_transform (void *paint_data, 161*2d1272b8SAndroid Build Coastguard Worker const hb_font_t *font) 162*2d1272b8SAndroid Build Coastguard Worker { 163*2d1272b8SAndroid Build Coastguard Worker float upem = font->face->get_upem (); 164*2d1272b8SAndroid Build Coastguard Worker int xscale = font->x_scale, yscale = font->y_scale; 165*2d1272b8SAndroid Build Coastguard Worker float slant = font->slant_xy; 166*2d1272b8SAndroid Build Coastguard Worker 167*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, 168*2d1272b8SAndroid Build Coastguard Worker xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0); 169*2d1272b8SAndroid Build Coastguard Worker } 170*2d1272b8SAndroid Build Coastguard Worker push_inverse_root_transformhb_paint_funcs_t171*2d1272b8SAndroid Build Coastguard Worker void push_inverse_root_transform (void *paint_data, 172*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font) 173*2d1272b8SAndroid Build Coastguard Worker { 174*2d1272b8SAndroid Build Coastguard Worker float upem = font->face->get_upem (); 175*2d1272b8SAndroid Build Coastguard Worker int xscale = font->x_scale ? font->x_scale : upem; 176*2d1272b8SAndroid Build Coastguard Worker int yscale = font->y_scale ? font->y_scale : upem; 177*2d1272b8SAndroid Build Coastguard Worker float slant = font->slant_xy; 178*2d1272b8SAndroid Build Coastguard Worker 179*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, 180*2d1272b8SAndroid Build Coastguard Worker upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0); 181*2d1272b8SAndroid Build Coastguard Worker } 182*2d1272b8SAndroid Build Coastguard Worker 183*2d1272b8SAndroid Build Coastguard Worker HB_NODISCARD push_translatehb_paint_funcs_t184*2d1272b8SAndroid Build Coastguard Worker bool push_translate (void *paint_data, 185*2d1272b8SAndroid Build Coastguard Worker float dx, float dy) 186*2d1272b8SAndroid Build Coastguard Worker { 187*2d1272b8SAndroid Build Coastguard Worker if (!dx && !dy) 188*2d1272b8SAndroid Build Coastguard Worker return false; 189*2d1272b8SAndroid Build Coastguard Worker 190*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, 191*2d1272b8SAndroid Build Coastguard Worker 1.f, 0.f, 0.f, 1.f, dx, dy); 192*2d1272b8SAndroid Build Coastguard Worker return true; 193*2d1272b8SAndroid Build Coastguard Worker } 194*2d1272b8SAndroid Build Coastguard Worker 195*2d1272b8SAndroid Build Coastguard Worker HB_NODISCARD push_scalehb_paint_funcs_t196*2d1272b8SAndroid Build Coastguard Worker bool push_scale (void *paint_data, 197*2d1272b8SAndroid Build Coastguard Worker float sx, float sy) 198*2d1272b8SAndroid Build Coastguard Worker { 199*2d1272b8SAndroid Build Coastguard Worker if (sx == 1.f && sy == 1.f) 200*2d1272b8SAndroid Build Coastguard Worker return false; 201*2d1272b8SAndroid Build Coastguard Worker 202*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, 203*2d1272b8SAndroid Build Coastguard Worker sx, 0.f, 0.f, sy, 0.f, 0.f); 204*2d1272b8SAndroid Build Coastguard Worker return true; 205*2d1272b8SAndroid Build Coastguard Worker } 206*2d1272b8SAndroid Build Coastguard Worker 207*2d1272b8SAndroid Build Coastguard Worker HB_NODISCARD push_rotatehb_paint_funcs_t208*2d1272b8SAndroid Build Coastguard Worker bool push_rotate (void *paint_data, 209*2d1272b8SAndroid Build Coastguard Worker float a) 210*2d1272b8SAndroid Build Coastguard Worker { 211*2d1272b8SAndroid Build Coastguard Worker if (!a) 212*2d1272b8SAndroid Build Coastguard Worker return false; 213*2d1272b8SAndroid Build Coastguard Worker 214*2d1272b8SAndroid Build Coastguard Worker float cc = cosf (a * HB_PI); 215*2d1272b8SAndroid Build Coastguard Worker float ss = sinf (a * HB_PI); 216*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f); 217*2d1272b8SAndroid Build Coastguard Worker return true; 218*2d1272b8SAndroid Build Coastguard Worker } 219*2d1272b8SAndroid Build Coastguard Worker 220*2d1272b8SAndroid Build Coastguard Worker HB_NODISCARD push_skewhb_paint_funcs_t221*2d1272b8SAndroid Build Coastguard Worker bool push_skew (void *paint_data, 222*2d1272b8SAndroid Build Coastguard Worker float sx, float sy) 223*2d1272b8SAndroid Build Coastguard Worker { 224*2d1272b8SAndroid Build Coastguard Worker if (!sx && !sy) 225*2d1272b8SAndroid Build Coastguard Worker return false; 226*2d1272b8SAndroid Build Coastguard Worker 227*2d1272b8SAndroid Build Coastguard Worker float x = tanf (-sx * HB_PI); 228*2d1272b8SAndroid Build Coastguard Worker float y = tanf (+sy * HB_PI); 229*2d1272b8SAndroid Build Coastguard Worker push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f); 230*2d1272b8SAndroid Build Coastguard Worker return true; 231*2d1272b8SAndroid Build Coastguard Worker } 232*2d1272b8SAndroid Build Coastguard Worker }; 233*2d1272b8SAndroid Build Coastguard Worker DECLARE_NULL_INSTANCE (hb_paint_funcs_t); 234*2d1272b8SAndroid Build Coastguard Worker 235*2d1272b8SAndroid Build Coastguard Worker 236*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_PAINT_HH */ 237