/* * Copyright © 2022 Matthias Clasen * * This is part of HarfBuzz, a text shaping library. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #ifndef HB_PAINT_HH #define HB_PAINT_HH #include "hb.hh" #include "hb-face.hh" #include "hb-font.hh" #define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \ HB_PAINT_FUNC_IMPLEMENT (push_transform) \ HB_PAINT_FUNC_IMPLEMENT (pop_transform) \ HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \ HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \ HB_PAINT_FUNC_IMPLEMENT (pop_clip) \ HB_PAINT_FUNC_IMPLEMENT (color) \ HB_PAINT_FUNC_IMPLEMENT (image) \ HB_PAINT_FUNC_IMPLEMENT (linear_gradient) \ HB_PAINT_FUNC_IMPLEMENT (radial_gradient) \ HB_PAINT_FUNC_IMPLEMENT (sweep_gradient) \ HB_PAINT_FUNC_IMPLEMENT (push_group) \ HB_PAINT_FUNC_IMPLEMENT (pop_group) \ HB_PAINT_FUNC_IMPLEMENT (custom_palette_color) \ /* ^--- Add new callbacks here */ struct hb_paint_funcs_t { hb_object_header_t header; struct { #define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_func_t name; HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_PAINT_FUNC_IMPLEMENT } func; struct { #define HB_PAINT_FUNC_IMPLEMENT(name) void *name; HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_PAINT_FUNC_IMPLEMENT } *user_data; struct { #define HB_PAINT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_PAINT_FUNC_IMPLEMENT } *destroy; void push_transform (void *paint_data, float xx, float yx, float xy, float yy, float dx, float dy) { func.push_transform (this, paint_data, xx, yx, xy, yy, dx, dy, !user_data ? nullptr : user_data->push_transform); } void pop_transform (void *paint_data) { func.pop_transform (this, paint_data, !user_data ? nullptr : user_data->pop_transform); } void push_clip_glyph (void *paint_data, hb_codepoint_t glyph, hb_font_t *font) { func.push_clip_glyph (this, paint_data, glyph, font, !user_data ? nullptr : user_data->push_clip_glyph); } void push_clip_rectangle (void *paint_data, float xmin, float ymin, float xmax, float ymax) { func.push_clip_rectangle (this, paint_data, xmin, ymin, xmax, ymax, !user_data ? nullptr : user_data->push_clip_rectangle); } void pop_clip (void *paint_data) { func.pop_clip (this, paint_data, !user_data ? nullptr : user_data->pop_clip); } void color (void *paint_data, hb_bool_t is_foreground, hb_color_t color) { func.color (this, paint_data, is_foreground, color, !user_data ? nullptr : user_data->color); } bool image (void *paint_data, hb_blob_t *image, unsigned width, unsigned height, hb_tag_t format, float slant, hb_glyph_extents_t *extents) { return func.image (this, paint_data, image, width, height, format, slant, extents, !user_data ? nullptr : user_data->image); } void linear_gradient (void *paint_data, hb_color_line_t *color_line, float x0, float y0, float x1, float y1, float x2, float y2) { func.linear_gradient (this, paint_data, color_line, x0, y0, x1, y1, x2, y2, !user_data ? nullptr : user_data->linear_gradient); } void radial_gradient (void *paint_data, hb_color_line_t *color_line, float x0, float y0, float r0, float x1, float y1, float r1) { func.radial_gradient (this, paint_data, color_line, x0, y0, r0, x1, y1, r1, !user_data ? nullptr : user_data->radial_gradient); } void sweep_gradient (void *paint_data, hb_color_line_t *color_line, float x0, float y0, float start_angle, float end_angle) { func.sweep_gradient (this, paint_data, color_line, x0, y0, start_angle, end_angle, !user_data ? nullptr : user_data->sweep_gradient); } void push_group (void *paint_data) { func.push_group (this, paint_data, !user_data ? nullptr : user_data->push_group); } void pop_group (void *paint_data, hb_paint_composite_mode_t mode) { func.pop_group (this, paint_data, mode, !user_data ? nullptr : user_data->pop_group); } bool custom_palette_color (void *paint_data, unsigned int color_index, hb_color_t *color) { return func.custom_palette_color (this, paint_data, color_index, color, !user_data ? nullptr : user_data->custom_palette_color); } /* Internal specializations. */ void push_root_transform (void *paint_data, const hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale, yscale = font->y_scale; float slant = font->slant_xy; push_transform (paint_data, xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0); } void push_inverse_root_transform (void *paint_data, hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale ? font->x_scale : upem; int yscale = font->y_scale ? font->y_scale : upem; float slant = font->slant_xy; push_transform (paint_data, upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0); } HB_NODISCARD bool push_translate (void *paint_data, float dx, float dy) { if (!dx && !dy) return false; push_transform (paint_data, 1.f, 0.f, 0.f, 1.f, dx, dy); return true; } HB_NODISCARD bool push_scale (void *paint_data, float sx, float sy) { if (sx == 1.f && sy == 1.f) return false; push_transform (paint_data, sx, 0.f, 0.f, sy, 0.f, 0.f); return true; } HB_NODISCARD bool push_rotate (void *paint_data, float a) { if (!a) return false; float cc = cosf (a * HB_PI); float ss = sinf (a * HB_PI); push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f); return true; } HB_NODISCARD bool push_skew (void *paint_data, float sx, float sy) { if (!sx && !sy) return false; float x = tanf (-sx * HB_PI); float y = tanf (+sy * HB_PI); push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f); return true; } }; DECLARE_NULL_INSTANCE (hb_paint_funcs_t); #endif /* HB_PAINT_HH */