diff --git a/src/Makefile.sources b/src/Makefile.sources index d49e6a716..e009dce80 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -91,6 +91,7 @@ HB_BASE_sources = \ hb-ot-layout-gpos-table.hh \ hb-paint.cc \ hb-paint.hh \ + hb-paint-extents.cc \ hb-paint-extents.hh \ hb-ot-layout-gsub-table.hh \ OT/glyf/glyf.hh \ diff --git a/src/harfbuzz-subset.cc b/src/harfbuzz-subset.cc index c5c66747a..0d8571712 100644 --- a/src/harfbuzz-subset.cc +++ b/src/harfbuzz-subset.cc @@ -41,6 +41,7 @@ #include "hb-ot-shaper-vowel-constraints.cc" #include "hb-ot-tag.cc" #include "hb-ot-var.cc" +#include "hb-paint-extents.cc" #include "hb-paint.cc" #include "hb-set.cc" #include "hb-shape-plan.cc" diff --git a/src/harfbuzz.cc b/src/harfbuzz.cc index 03196eaa6..3b80c2059 100644 --- a/src/harfbuzz.cc +++ b/src/harfbuzz.cc @@ -46,6 +46,7 @@ #include "hb-ot-shaper-vowel-constraints.cc" #include "hb-ot-tag.cc" #include "hb-ot-var.cc" +#include "hb-paint-extents.cc" #include "hb-paint.cc" #include "hb-set.cc" #include "hb-shape-plan.cc" diff --git a/src/hb-paint-extents.hh b/src/hb-paint-extents.cc similarity index 61% rename from src/hb-paint-extents.hh rename to src/hb-paint-extents.cc index 39028f1b4..a74e50937 100644 --- a/src/hb-paint-extents.hh +++ b/src/hb-paint-extents.cc @@ -22,11 +22,8 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_PAINT_EXTENTS_HH -#define HB_PAINT_EXTENTS_HH - #include "hb.hh" -#include "hb-paint.hh" +#include "hb-paint-extents.hh" #include "hb-draw.h" /* @@ -36,252 +33,6 @@ * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness */ -typedef struct hb_extents_t -{ - hb_extents_t () {} - hb_extents_t (float xmin, float ymin, float xmax, float ymax) : - xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} - - bool is_empty () const { return xmin >= xmax || ymin >= ymax; } - - void union_ (const hb_extents_t &o) - { - xmin = hb_min (xmin, o.xmin); - ymin = hb_min (ymin, o.ymin); - xmax = hb_max (xmax, o.xmax); - ymax = hb_max (ymax, o.ymax); - } - - void intersect (const hb_extents_t &o) - { - xmin = hb_max (xmin, o.xmin); - ymin = hb_max (ymin, o.ymin); - xmax = hb_min (xmax, o.xmax); - ymax = hb_min (ymax, o.ymax); - } - - float xmin = 0.f; - float ymin = 0.f; - float xmax = -1.f; - float ymax = -1.f; -} hb_extents_t; - -typedef struct hb_transform_t -{ - hb_transform_t () {} - hb_transform_t (float xx, float yx, - float xy, float yy, - float x0, float y0) : - xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {} - - void multiply (const hb_transform_t &o) - { - /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */ - hb_transform_t r; - - r.xx = o.xx * xx + o.yx * xy; - r.yx = o.xx * yx + o.yx * yy; - - r.xy = o.xy * xx + o.yy * xy; - r.yy = o.xy * yx + o.yy * yy; - - r.x0 = o.x0 * xx + o.y0 * xy + x0; - r.y0 = o.x0 * yx + o.y0 * yy + y0; - - *this = r; - } - - void transform_distance (float &dx, float &dy) - { - float new_x = xx * dx + xy * dy; - float new_y = yx * dx + yy * dy; - dx = new_x; - dy = new_y; - } - - void transform_point (float &x, float &y) - { - transform_distance (x, y); - x += x0; - y += y0; - } - - void transform_extents (hb_extents_t extents) - { - float quad_x[4], quad_y[4]; - - quad_x[0] = extents.xmin; - quad_y[0] = extents.ymin; - quad_x[1] = extents.xmin; - quad_y[1] = extents.ymax; - quad_x[2] = extents.xmax; - quad_y[2] = extents.ymin; - quad_x[3] = extents.xmax; - quad_y[3] = extents.ymax; - - for (unsigned i = 0; i < 4; i++) - transform_point (quad_x[i], quad_y[i]); - - extents.xmin = extents.xmax = quad_x[0]; - extents.ymin = extents.ymax = quad_y[0]; - - for (unsigned i = 1; i < 4; i++) - { - extents.xmin = hb_min (extents.xmin, quad_x[i]); - extents.ymin = hb_min (extents.ymin, quad_y[i]); - extents.xmax = hb_max (extents.xmax, quad_x[i]); - extents.ymax = hb_max (extents.ymax, quad_y[i]); - } - } - - float xx = 1.f; - float yx = 0.f; - float xy = 0.f; - float yy = 1.f; - float x0 = 0.f; - float y0 = 0.f; -} hb_transform_t; - -typedef struct hb_bounds_t -{ - enum status_t { - EMPTY, - BOUNDED, - UNBOUNDED, - }; - - hb_bounds_t (status_t status) : status (status) {} - hb_bounds_t (const hb_extents_t &extents) : - status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {} - - void union_ (const hb_bounds_t &o) - { - if (o.status == UNBOUNDED) - status = UNBOUNDED; - else if (o.status == BOUNDED) - { - if (status == EMPTY) - *this = o; - else if (status == BOUNDED) - extents.union_ (o.extents); - } - } - - void intersect (const hb_bounds_t &o) - { - if (o.status == EMPTY) - status = EMPTY; - else if (o.status == BOUNDED) - { - if (status == UNBOUNDED) - *this = o; - else if (status == BOUNDED) - { - extents.intersect (o.extents); - if (extents.is_empty ()) - status = EMPTY; - } - } - } - - status_t status; - hb_extents_t extents; -} hb_bounds_t; - -typedef struct hb_paint_extents_context_t hb_paint_extents_context_t; - -struct hb_paint_extents_context_t { - - hb_paint_extents_context_t () - { - clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED}); - groups.push (hb_bounds_t{hb_bounds_t::EMPTY}); - transforms.push (hb_transform_t{}); - } - - hb_extents_t get_extents () - { - return groups.tail().extents; - } - - bool is_bounded () - { - return groups.tail().status != hb_bounds_t::UNBOUNDED; - } - - void push_transform (const hb_transform_t &trans) - { - hb_transform_t r = transforms.tail (); - r.multiply (trans); - transforms.push (r); - } - - void pop_transform () - { - transforms.pop (); - } - - void push_clip (hb_extents_t extents) - { - /* Transform extents and push a new clip. */ - hb_transform_t &r = transforms.tail (); - r.transform_extents (extents); - - hb_bounds_t b {extents}; - clips.push (b); - } - - void pop_clip () - { - clips.pop (); - } - - void push_group () - { - groups.push (hb_bounds_t{hb_bounds_t::EMPTY}); - } - - void pop_group (hb_paint_composite_mode_t mode) - { - const hb_bounds_t src_bounds = groups.pop (); - hb_bounds_t &backdrop_bounds = groups.tail (); - - // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite - switch ((int) mode) - { - case HB_PAINT_COMPOSITE_MODE_CLEAR: - backdrop_bounds.status = hb_bounds_t::EMPTY; - break; - case HB_PAINT_COMPOSITE_MODE_SRC: - case HB_PAINT_COMPOSITE_MODE_SRC_OUT: - backdrop_bounds = src_bounds; - break; - case HB_PAINT_COMPOSITE_MODE_DEST: - case HB_PAINT_COMPOSITE_MODE_DEST_OUT: - break; - case HB_PAINT_COMPOSITE_MODE_SRC_IN: - case HB_PAINT_COMPOSITE_MODE_DEST_IN: - backdrop_bounds.intersect (src_bounds); - break; - default: - backdrop_bounds.union_ (src_bounds); - break; - } - } - - void paint () - { - const hb_bounds_t &clip = clips.tail (); - hb_bounds_t &group = groups.tail (); - - group.union_ (clip); - } - - hb_vector_t clips; - hb_vector_t groups; - hb_vector_t transforms; -}; - static void hb_paint_extents_push_transform (hb_paint_funcs_t *funcs HB_UNUSED, void *paint_data, @@ -509,7 +260,7 @@ hb_paint_extents_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED, c->paint (); } -static inline hb_paint_funcs_t * +hb_paint_funcs_t * hb_paint_extents_get_funcs () { hb_paint_funcs_t *funcs = hb_paint_funcs_create (); @@ -529,5 +280,3 @@ hb_paint_extents_get_funcs () return funcs; } - -#endif /* HB_PAINT_EXTENTS_HH */ diff --git a/src/meson.build b/src/meson.build index 3b09a3441..e015e0525 100644 --- a/src/meson.build +++ b/src/meson.build @@ -46,6 +46,7 @@ hb_base_sources = files( 'hb-draw.hh', 'hb-paint.cc', 'hb-paint.hh', + 'hb-paint-extents.cc', 'hb-paint-extents.hh', 'hb-face.cc', 'hb-face.hh',