Bug 1883518 - Remove a bunch of unused ServoBindings.toml entries. r=firefox-style...
[gecko.git] / gfx / harfbuzz / src / hb-paint-extents.hh
blobf172bd42f932cd7d01b2a0409de2ebbdf72fa557
1 /*
2 * Copyright © 2022 Behdad Esfahbod
4 * This is part of HarfBuzz, a text shaping library.
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.
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.
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.
25 #ifndef HB_PAINT_EXTENTS_HH
26 #define HB_PAINT_EXTENTS_HH
28 #include "hb.hh"
29 #include "hb-paint.h"
32 typedef struct hb_extents_t
34 hb_extents_t () {}
35 hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
36 xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
38 bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
39 bool is_void () const { return xmin > xmax; }
41 void union_ (const hb_extents_t &o)
43 xmin = hb_min (xmin, o.xmin);
44 ymin = hb_min (ymin, o.ymin);
45 xmax = hb_max (xmax, o.xmax);
46 ymax = hb_max (ymax, o.ymax);
49 void intersect (const hb_extents_t &o)
51 xmin = hb_max (xmin, o.xmin);
52 ymin = hb_max (ymin, o.ymin);
53 xmax = hb_min (xmax, o.xmax);
54 ymax = hb_min (ymax, o.ymax);
57 void
58 add_point (float x, float y)
60 if (unlikely (is_void ()))
62 xmin = xmax = x;
63 ymin = ymax = y;
65 else
67 xmin = hb_min (xmin, x);
68 ymin = hb_min (ymin, y);
69 xmax = hb_max (xmax, x);
70 ymax = hb_max (ymax, y);
74 float xmin = 0.f;
75 float ymin = 0.f;
76 float xmax = -1.f;
77 float ymax = -1.f;
78 } hb_extents_t;
80 typedef struct hb_transform_t
82 hb_transform_t () {}
83 hb_transform_t (float xx, float yx,
84 float xy, float yy,
85 float x0, float y0) :
86 xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
88 void multiply (const hb_transform_t &o)
90 /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
91 hb_transform_t r;
93 r.xx = o.xx * xx + o.yx * xy;
94 r.yx = o.xx * yx + o.yx * yy;
96 r.xy = o.xy * xx + o.yy * xy;
97 r.yy = o.xy * yx + o.yy * yy;
99 r.x0 = o.x0 * xx + o.y0 * xy + x0;
100 r.y0 = o.x0 * yx + o.y0 * yy + y0;
102 *this = r;
105 void transform_distance (float &dx, float &dy) const
107 float new_x = xx * dx + xy * dy;
108 float new_y = yx * dx + yy * dy;
109 dx = new_x;
110 dy = new_y;
113 void transform_point (float &x, float &y) const
115 transform_distance (x, y);
116 x += x0;
117 y += y0;
120 void transform_extents (hb_extents_t &extents) const
122 float quad_x[4], quad_y[4];
124 quad_x[0] = extents.xmin;
125 quad_y[0] = extents.ymin;
126 quad_x[1] = extents.xmin;
127 quad_y[1] = extents.ymax;
128 quad_x[2] = extents.xmax;
129 quad_y[2] = extents.ymin;
130 quad_x[3] = extents.xmax;
131 quad_y[3] = extents.ymax;
133 extents = hb_extents_t {};
134 for (unsigned i = 0; i < 4; i++)
136 transform_point (quad_x[i], quad_y[i]);
137 extents.add_point (quad_x[i], quad_y[i]);
141 float xx = 1.f;
142 float yx = 0.f;
143 float xy = 0.f;
144 float yy = 1.f;
145 float x0 = 0.f;
146 float y0 = 0.f;
147 } hb_transform_t;
149 typedef struct hb_bounds_t
151 enum status_t {
152 UNBOUNDED,
153 BOUNDED,
154 EMPTY,
157 hb_bounds_t (status_t status) : status (status) {}
158 hb_bounds_t (const hb_extents_t &extents) :
159 status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
161 void union_ (const hb_bounds_t &o)
163 if (o.status == UNBOUNDED)
164 status = UNBOUNDED;
165 else if (o.status == BOUNDED)
167 if (status == EMPTY)
168 *this = o;
169 else if (status == BOUNDED)
170 extents.union_ (o.extents);
174 void intersect (const hb_bounds_t &o)
176 if (o.status == EMPTY)
177 status = EMPTY;
178 else if (o.status == BOUNDED)
180 if (status == UNBOUNDED)
181 *this = o;
182 else if (status == BOUNDED)
184 extents.intersect (o.extents);
185 if (extents.is_empty ())
186 status = EMPTY;
191 status_t status;
192 hb_extents_t extents;
193 } hb_bounds_t;
195 typedef struct hb_paint_extents_context_t hb_paint_extents_context_t;
197 struct hb_paint_extents_context_t
199 hb_paint_extents_context_t ()
201 transforms.push (hb_transform_t{});
202 clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED});
203 groups.push (hb_bounds_t{hb_bounds_t::EMPTY});
206 hb_extents_t get_extents ()
208 return groups.tail().extents;
211 bool is_bounded ()
213 return groups.tail().status != hb_bounds_t::UNBOUNDED;
216 void push_transform (const hb_transform_t &trans)
218 hb_transform_t t = transforms.tail ();
219 t.multiply (trans);
220 transforms.push (t);
223 void pop_transform ()
225 transforms.pop ();
228 void push_clip (hb_extents_t extents)
230 /* Transform extents and push a new clip. */
231 const hb_transform_t &t = transforms.tail ();
232 t.transform_extents (extents);
234 clips.push (hb_bounds_t {extents});
237 void pop_clip ()
239 clips.pop ();
242 void push_group ()
244 groups.push (hb_bounds_t {hb_bounds_t::EMPTY});
247 void pop_group (hb_paint_composite_mode_t mode)
249 const hb_bounds_t src_bounds = groups.pop ();
250 hb_bounds_t &backdrop_bounds = groups.tail ();
252 // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite
253 switch ((int) mode)
255 case HB_PAINT_COMPOSITE_MODE_CLEAR:
256 backdrop_bounds.status = hb_bounds_t::EMPTY;
257 break;
258 case HB_PAINT_COMPOSITE_MODE_SRC:
259 case HB_PAINT_COMPOSITE_MODE_SRC_OUT:
260 backdrop_bounds = src_bounds;
261 break;
262 case HB_PAINT_COMPOSITE_MODE_DEST:
263 case HB_PAINT_COMPOSITE_MODE_DEST_OUT:
264 break;
265 case HB_PAINT_COMPOSITE_MODE_SRC_IN:
266 case HB_PAINT_COMPOSITE_MODE_DEST_IN:
267 backdrop_bounds.intersect (src_bounds);
268 break;
269 default:
270 backdrop_bounds.union_ (src_bounds);
271 break;
275 void paint ()
277 const hb_bounds_t &clip = clips.tail ();
278 hb_bounds_t &group = groups.tail ();
280 group.union_ (clip);
283 protected:
284 hb_vector_t<hb_transform_t> transforms;
285 hb_vector_t<hb_bounds_t> clips;
286 hb_vector_t<hb_bounds_t> groups;
289 HB_INTERNAL hb_paint_funcs_t *
290 hb_paint_extents_get_funcs ();
293 #endif /* HB_PAINT_EXTENTS_HH */