hb-paint-extents.cc (7911B)
1 /* 2 * Copyright © 2022 Behdad Esfahbod 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 #include "hb.hh" 26 27 #ifndef HB_NO_PAINT 28 29 #include "hb-paint-extents.hh" 30 31 #include "hb-draw.hh" 32 33 #include "hb-machinery.hh" 34 35 36 /* 37 * This file implements bounds-extraction computation of COLRv1 fonts as described in: 38 * 39 * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness 40 */ 41 42 static void 43 hb_paint_extents_push_transform (hb_paint_funcs_t *funcs HB_UNUSED, 44 void *paint_data, 45 float xx, float yx, 46 float xy, float yy, 47 float dx, float dy, 48 void *user_data HB_UNUSED) 49 { 50 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 51 52 c->push_transform (hb_transform_t<> {xx, yx, xy, yy, dx, dy}); 53 } 54 55 static void 56 hb_paint_extents_pop_transform (hb_paint_funcs_t *funcs HB_UNUSED, 57 void *paint_data, 58 void *user_data HB_UNUSED) 59 { 60 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 61 62 c->pop_transform (); 63 } 64 65 static void 66 hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, 67 void *paint_data, 68 hb_codepoint_t glyph, 69 hb_font_t *font, 70 void *user_data HB_UNUSED) 71 { 72 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 73 74 hb_extents_t<> extents; 75 hb_draw_funcs_t *draw_extent_funcs = hb_draw_extents_get_funcs (); 76 hb_font_draw_glyph (font, glyph, draw_extent_funcs, &extents); 77 c->push_clip (extents); 78 } 79 80 static void 81 hb_paint_extents_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED, 82 void *paint_data, 83 float xmin, float ymin, float xmax, float ymax, 84 void *user_data) 85 { 86 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 87 88 hb_extents_t<> extents = {xmin, ymin, xmax, ymax}; 89 c->push_clip (extents); 90 } 91 92 static void 93 hb_paint_extents_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED, 94 void *paint_data, 95 void *user_data HB_UNUSED) 96 { 97 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 98 99 c->pop_clip (); 100 } 101 102 static void 103 hb_paint_extents_push_group (hb_paint_funcs_t *funcs HB_UNUSED, 104 void *paint_data, 105 void *user_data HB_UNUSED) 106 { 107 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 108 109 c->push_group (); 110 } 111 112 static void 113 hb_paint_extents_pop_group (hb_paint_funcs_t *funcs HB_UNUSED, 114 void *paint_data, 115 hb_paint_composite_mode_t mode, 116 void *user_data HB_UNUSED) 117 { 118 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 119 120 c->pop_group (mode); 121 } 122 123 static hb_bool_t 124 hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED, 125 void *paint_data, 126 hb_blob_t *blob HB_UNUSED, 127 unsigned int width HB_UNUSED, 128 unsigned int height HB_UNUSED, 129 hb_tag_t format HB_UNUSED, 130 float slant HB_UNUSED, 131 hb_glyph_extents_t *glyph_extents, 132 void *user_data HB_UNUSED) 133 { 134 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 135 136 if (!glyph_extents) 137 return false; // Happens with SVG images. 138 139 hb_extents_t<> extents = {(float) glyph_extents->x_bearing, 140 (float) glyph_extents->y_bearing + glyph_extents->height, 141 (float) glyph_extents->x_bearing + glyph_extents->width, 142 (float) glyph_extents->y_bearing}; 143 c->push_clip (extents); 144 c->paint (); 145 c->pop_clip (); 146 147 return true; 148 } 149 150 static void 151 hb_paint_extents_paint_color (hb_paint_funcs_t *funcs HB_UNUSED, 152 void *paint_data, 153 hb_bool_t use_foreground HB_UNUSED, 154 hb_color_t color HB_UNUSED, 155 void *user_data HB_UNUSED) 156 { 157 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 158 159 c->paint (); 160 } 161 162 static void 163 hb_paint_extents_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED, 164 void *paint_data, 165 hb_color_line_t *color_line HB_UNUSED, 166 float x0 HB_UNUSED, float y0 HB_UNUSED, 167 float x1 HB_UNUSED, float y1 HB_UNUSED, 168 float x2 HB_UNUSED, float y2 HB_UNUSED, 169 void *user_data HB_UNUSED) 170 { 171 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 172 173 c->paint (); 174 } 175 176 static void 177 hb_paint_extents_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED, 178 void *paint_data, 179 hb_color_line_t *color_line HB_UNUSED, 180 float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED, 181 float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED, 182 void *user_data HB_UNUSED) 183 { 184 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 185 186 c->paint (); 187 } 188 189 static void 190 hb_paint_extents_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED, 191 void *paint_data, 192 hb_color_line_t *color_line HB_UNUSED, 193 float cx HB_UNUSED, float cy HB_UNUSED, 194 float start_angle HB_UNUSED, 195 float end_angle HB_UNUSED, 196 void *user_data HB_UNUSED) 197 { 198 hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; 199 200 c->paint (); 201 } 202 203 static inline void free_static_paint_extents_funcs (); 204 205 static struct hb_paint_extents_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_paint_extents_funcs_lazy_loader_t> 206 { 207 static hb_paint_funcs_t *create () 208 { 209 hb_paint_funcs_t *funcs = hb_paint_funcs_create (); 210 211 hb_paint_funcs_set_push_transform_func (funcs, hb_paint_extents_push_transform, nullptr, nullptr); 212 hb_paint_funcs_set_pop_transform_func (funcs, hb_paint_extents_pop_transform, nullptr, nullptr); 213 hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_extents_push_clip_glyph, nullptr, nullptr); 214 hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_extents_push_clip_rectangle, nullptr, nullptr); 215 hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_extents_pop_clip, nullptr, nullptr); 216 hb_paint_funcs_set_push_group_func (funcs, hb_paint_extents_push_group, nullptr, nullptr); 217 hb_paint_funcs_set_pop_group_func (funcs, hb_paint_extents_pop_group, nullptr, nullptr); 218 hb_paint_funcs_set_color_func (funcs, hb_paint_extents_paint_color, nullptr, nullptr); 219 hb_paint_funcs_set_image_func (funcs, hb_paint_extents_paint_image, nullptr, nullptr); 220 hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_extents_paint_linear_gradient, nullptr, nullptr); 221 hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_extents_paint_radial_gradient, nullptr, nullptr); 222 hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_extents_paint_sweep_gradient, nullptr, nullptr); 223 224 hb_paint_funcs_make_immutable (funcs); 225 226 hb_atexit (free_static_paint_extents_funcs); 227 228 return funcs; 229 } 230 } static_paint_extents_funcs; 231 232 static inline 233 void free_static_paint_extents_funcs () 234 { 235 static_paint_extents_funcs.free_instance (); 236 } 237 238 hb_paint_funcs_t * 239 hb_paint_extents_get_funcs () 240 { 241 return static_paint_extents_funcs.get_unconst (); 242 } 243 244 245 #endif