initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
390
thirdparty/harfbuzz/src/hb-geometry.hh
vendored
Normal file
390
thirdparty/harfbuzz/src/hb-geometry.hh
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright © 2022 Behdad Esfahbod
|
||||
*
|
||||
* 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_GEOMETRY_HH
|
||||
#define HB_GEOMETRY_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-algs.hh"
|
||||
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_extents_t
|
||||
{
|
||||
hb_extents_t () {}
|
||||
hb_extents_t (const hb_glyph_extents_t &extents) :
|
||||
xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)),
|
||||
ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
|
||||
xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
|
||||
ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
|
||||
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; }
|
||||
bool is_void () const { return xmin > xmax; }
|
||||
|
||||
void union_ (const hb_extents_t &o)
|
||||
{
|
||||
if (o.is_empty ()) return;
|
||||
if (is_empty ())
|
||||
{
|
||||
*this = o;
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (o.is_empty () || is_empty ())
|
||||
{
|
||||
*this = hb_extents_t {};
|
||||
return;
|
||||
}
|
||||
xmin = hb_max (xmin, o.xmin);
|
||||
ymin = hb_max (ymin, o.ymin);
|
||||
xmax = hb_min (xmax, o.xmax);
|
||||
ymax = hb_min (ymax, o.ymax);
|
||||
}
|
||||
|
||||
void
|
||||
add_point (Float x, Float y)
|
||||
{
|
||||
if (unlikely (is_void ()))
|
||||
{
|
||||
xmin = xmax = x;
|
||||
ymin = ymax = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xmin = hb_min (xmin, x);
|
||||
ymin = hb_min (ymin, y);
|
||||
xmax = hb_max (xmax, x);
|
||||
ymax = hb_max (ymax, y);
|
||||
}
|
||||
}
|
||||
|
||||
hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const
|
||||
{
|
||||
hb_position_t x0 = (hb_position_t) roundf (xmin);
|
||||
hb_position_t y0 = (hb_position_t) roundf (ymin);
|
||||
hb_position_t x1 = (hb_position_t) roundf (xmax);
|
||||
hb_position_t y1 = (hb_position_t) roundf (ymax);
|
||||
return hb_glyph_extents_t {xneg ? x1 : x0,
|
||||
yneg ? y0 : y1,
|
||||
xneg ? x0 - x1 : x1 - x0,
|
||||
yneg ? y1 - y0 : y0 - y1};
|
||||
}
|
||||
|
||||
Float xmin = 0;
|
||||
Float ymin = 0;
|
||||
Float xmax = -1;
|
||||
Float ymax = -1;
|
||||
};
|
||||
|
||||
template <typename Float = float>
|
||||
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) {}
|
||||
|
||||
bool is_identity () const
|
||||
{
|
||||
return xx == 1 && yx == 0 &&
|
||||
xy == 0 && yy == 1 &&
|
||||
x0 == 0 && y0 == 0;
|
||||
}
|
||||
bool is_translation () const
|
||||
{
|
||||
return xx == 1 && yx == 0 &&
|
||||
xy == 0 && yy == 1;
|
||||
}
|
||||
|
||||
void multiply (const hb_transform_t &o, bool before=false)
|
||||
{
|
||||
// Copied from cairo-matrix.c
|
||||
const hb_transform_t &a = before ? o : *this;
|
||||
const hb_transform_t &b = before ? *this : o;
|
||||
*this = {
|
||||
a.xx * b.xx + a.xy * b.yx,
|
||||
a.yx * b.xx + a.yy * b.yx,
|
||||
a.xx * b.xy + a.xy * b.yy,
|
||||
a.yx * b.xy + a.yy * b.yy,
|
||||
a.xx * b.x0 + a.xy * b.y0 + a.x0,
|
||||
a.yx * b.x0 + a.yy * b.y0 + a.y0
|
||||
};
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
void transform_distance (Float &dx, Float &dy) const
|
||||
{
|
||||
Float new_x = xx * dx + xy * dy;
|
||||
Float new_y = yx * dx + yy * dy;
|
||||
dx = new_x;
|
||||
dy = new_y;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
void transform_point (Float &x, Float &y) const
|
||||
{
|
||||
Float new_x = x0 + xx * x + xy * y;
|
||||
Float new_y = y0 + yx * x + yy * y;
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
}
|
||||
|
||||
void transform_extents (hb_extents_t<Float> &extents) const
|
||||
{
|
||||
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;
|
||||
|
||||
extents = hb_extents_t<Float> {};
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
transform_point (quad_x[i], quad_y[i]);
|
||||
extents.add_point (quad_x[i], quad_y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void transform (const hb_transform_t &o, bool before=false) { multiply (o, before); }
|
||||
|
||||
static hb_transform_t translation (Float x, Float y)
|
||||
{
|
||||
return {1, 0, 0, 1, x, y};
|
||||
}
|
||||
void translate (Float x, Float y, bool before=false)
|
||||
{
|
||||
if (before)
|
||||
{
|
||||
x0 += x;
|
||||
y0 += y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
return;
|
||||
|
||||
x0 += xx * x + xy * y;
|
||||
y0 += yx * x + yy * y;
|
||||
}
|
||||
}
|
||||
|
||||
static hb_transform_t scaling (Float scaleX, Float scaleY)
|
||||
{
|
||||
return {scaleX, 0, 0, scaleY, 0, 0};
|
||||
}
|
||||
void scale (Float scaleX, Float scaleY)
|
||||
{
|
||||
if (scaleX == 1 && scaleY == 1)
|
||||
return;
|
||||
|
||||
xx *= scaleX;
|
||||
yx *= scaleX;
|
||||
xy *= scaleY;
|
||||
yy *= scaleY;
|
||||
}
|
||||
static hb_transform_t scaling_around_center (Float scaleX, Float scaleY, Float center_x, Float center_y)
|
||||
{
|
||||
return {scaleX, 0, 0, scaleY,
|
||||
center_x ? (1 - scaleX) * center_x : 0,
|
||||
center_y ? (1 - scaleY) * center_y : 0};
|
||||
}
|
||||
void scale_around_center (Float scaleX, Float scaleY, Float center_x, Float center_y)
|
||||
{
|
||||
if (scaleX == 1 && scaleY == 1)
|
||||
return;
|
||||
|
||||
transform (scaling_around_center (scaleX, scaleY, center_x, center_y));
|
||||
}
|
||||
|
||||
static hb_transform_t rotation (Float radians)
|
||||
{
|
||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
||||
Float c;
|
||||
Float s;
|
||||
hb_sincos (radians, s, c);
|
||||
return {c, s, -s, c, 0, 0};
|
||||
}
|
||||
void rotate (Float radians, bool before=false)
|
||||
{
|
||||
if (radians == 0)
|
||||
return;
|
||||
|
||||
transform (rotation (radians), before);
|
||||
}
|
||||
|
||||
static hb_transform_t rotation_around_center (Float radians, Float center_x, Float center_y)
|
||||
{
|
||||
Float s, c;
|
||||
hb_sincos (radians, s, c);
|
||||
return {
|
||||
c, s, -s, c,
|
||||
(1 - c) * center_x + s * center_y,
|
||||
-s * center_x + (1 - c) * center_y
|
||||
};
|
||||
}
|
||||
void rotate_around_center (Float radians, Float center_x, Float center_y, bool before=false)
|
||||
{
|
||||
if (radians == 0)
|
||||
return;
|
||||
|
||||
transform (rotation_around_center (radians, center_x, center_y), before);
|
||||
}
|
||||
|
||||
static hb_transform_t skewing (Float skewX, Float skewY)
|
||||
{
|
||||
return {1, skewY ? tanf (skewY) : 0, skewX ? tanf (skewX) : 0, 1, 0, 0};
|
||||
}
|
||||
void skew (Float skewX, Float skewY)
|
||||
{
|
||||
if (skewX == 0 && skewY == 0)
|
||||
return;
|
||||
|
||||
transform (skewing (skewX, skewY));
|
||||
}
|
||||
static hb_transform_t skewing_around_center (Float skewX, Float skewY, Float center_x, Float center_y)
|
||||
{
|
||||
skewX = skewX ? tanf (skewX) : 0;
|
||||
skewY = skewY ? tanf (skewY) : 0;
|
||||
return {
|
||||
1, skewY, skewX, 1,
|
||||
center_y ? -skewX * center_y : 0,
|
||||
center_x ? -skewY * center_x : 0
|
||||
};
|
||||
}
|
||||
void skew_around_center (Float skewX, Float skewY, Float center_x, Float center_y)
|
||||
{
|
||||
if (skewX == 0 && skewY == 0)
|
||||
return;
|
||||
|
||||
transform (skewing_around_center (skewX, skewY, center_x, center_y));
|
||||
}
|
||||
|
||||
Float xx = 1;
|
||||
Float yx = 0;
|
||||
Float xy = 0;
|
||||
Float yy = 1;
|
||||
Float x0 = 0;
|
||||
Float y0 = 0;
|
||||
};
|
||||
|
||||
#define HB_TRANSFORM_IDENTITY {1, 0, 0, 1, 0, 0}
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_bounds_t
|
||||
{
|
||||
enum status_t {
|
||||
UNBOUNDED,
|
||||
BOUNDED,
|
||||
EMPTY,
|
||||
};
|
||||
|
||||
hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
|
||||
hb_bounds_t (const hb_extents_t<Float> &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<Float> extents;
|
||||
};
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_transform_decomposed_t
|
||||
{
|
||||
Float translateX = 0;
|
||||
Float translateY = 0;
|
||||
Float rotation = 0; // in radians, counter-clockwise
|
||||
Float scaleX = 1;
|
||||
Float scaleY = 1;
|
||||
Float skewX = 0; // in radians, counter-clockwise
|
||||
Float skewY = 0; // in radians, counter-clockwise
|
||||
Float tCenterX = 0;
|
||||
Float tCenterY = 0;
|
||||
|
||||
operator bool () const
|
||||
{
|
||||
return translateX || translateY ||
|
||||
rotation ||
|
||||
scaleX != 1 || scaleY != 1 ||
|
||||
skewX || skewY ||
|
||||
tCenterX || tCenterY;
|
||||
}
|
||||
|
||||
hb_transform_t<Float> to_transform () const
|
||||
{
|
||||
hb_transform_t<Float> t;
|
||||
t.translate (translateX + tCenterX, translateY + tCenterY);
|
||||
t.rotate (rotation);
|
||||
t.scale (scaleX, scaleY);
|
||||
t.skew (-skewX, skewY);
|
||||
t.translate (-tCenterX, -tCenterY);
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_GEOMETRY_HH */
|
Reference in New Issue
Block a user