commit
8c641eeefb
|
@ -96,7 +96,10 @@ HB_BASE_sources = \
|
||||||
OT/glyf/Glyph.hh \
|
OT/glyf/Glyph.hh \
|
||||||
OT/glyf/GlyphHeader.hh \
|
OT/glyf/GlyphHeader.hh \
|
||||||
OT/glyf/SimpleGlyph.hh \
|
OT/glyf/SimpleGlyph.hh \
|
||||||
|
OT/glyf/coord-setter.hh \
|
||||||
|
OT/glyf/composite-iter.hh \
|
||||||
OT/glyf/CompositeGlyph.hh \
|
OT/glyf/CompositeGlyph.hh \
|
||||||
|
OT/glyf/VarCompositeGlyph.hh \
|
||||||
OT/glyf/SubsetGlyph.hh \
|
OT/glyf/SubsetGlyph.hh \
|
||||||
OT/Layout/types.hh \
|
OT/Layout/types.hh \
|
||||||
OT/Layout/Common/Coverage.hh \
|
OT/Layout/Common/Coverage.hh \
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "../../hb-open-type.hh"
|
#include "../../hb-open-type.hh"
|
||||||
|
#include "composite-iter.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
@ -252,55 +253,7 @@ struct CompositeGlyphRecord
|
||||||
DEFINE_SIZE_MIN (4);
|
DEFINE_SIZE_MIN (4);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &>
|
using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
|
||||||
{
|
|
||||||
typedef const CompositeGlyphRecord *__item_t__;
|
|
||||||
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
|
|
||||||
glyph (glyph_), current (nullptr), current_size (0)
|
|
||||||
{
|
|
||||||
set_current (current_);
|
|
||||||
}
|
|
||||||
|
|
||||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
|
||||||
|
|
||||||
item_t __item__ () const { return *current; }
|
|
||||||
bool __more__ () const { return current; }
|
|
||||||
void __next__ ()
|
|
||||||
{
|
|
||||||
if (!current->has_more ()) { current = nullptr; return; }
|
|
||||||
|
|
||||||
set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
|
|
||||||
}
|
|
||||||
composite_iter_t __end__ () const { return composite_iter_t (); }
|
|
||||||
bool operator != (const composite_iter_t& o) const
|
|
||||||
{ return current != o.current; }
|
|
||||||
|
|
||||||
|
|
||||||
void set_current (__item_t__ current_)
|
|
||||||
{
|
|
||||||
if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
|
|
||||||
{
|
|
||||||
current = nullptr;
|
|
||||||
current_size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned size = current_->get_size ();
|
|
||||||
if (!glyph.check_range (current_, size))
|
|
||||||
{
|
|
||||||
current = nullptr;
|
|
||||||
current_size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
current = current_;
|
|
||||||
current_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
hb_bytes_t glyph;
|
|
||||||
__item_t__ current;
|
|
||||||
unsigned current_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompositeGlyph
|
struct CompositeGlyph
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "GlyphHeader.hh"
|
#include "GlyphHeader.hh"
|
||||||
#include "SimpleGlyph.hh"
|
#include "SimpleGlyph.hh"
|
||||||
#include "CompositeGlyph.hh"
|
#include "CompositeGlyph.hh"
|
||||||
|
#include "VarCompositeGlyph.hh"
|
||||||
|
#include "coord-setter.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
@ -32,7 +34,7 @@ enum phantom_point_index_t
|
||||||
|
|
||||||
struct Glyph
|
struct Glyph
|
||||||
{
|
{
|
||||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
composite_iter_t get_composite_iterator () const
|
composite_iter_t get_composite_iterator () const
|
||||||
|
@ -40,6 +42,11 @@ struct Glyph
|
||||||
if (type != COMPOSITE) return composite_iter_t ();
|
if (type != COMPOSITE) return composite_iter_t ();
|
||||||
return CompositeGlyph (*header, bytes).iter ();
|
return CompositeGlyph (*header, bytes).iter ();
|
||||||
}
|
}
|
||||||
|
var_composite_iter_t get_var_composite_iterator () const
|
||||||
|
{
|
||||||
|
if (type != VAR_COMPOSITE) return var_composite_iter_t ();
|
||||||
|
return VarCompositeGlyph (*header, bytes).iter ();
|
||||||
|
}
|
||||||
|
|
||||||
const hb_bytes_t trim_padding () const
|
const hb_bytes_t trim_padding () const
|
||||||
{
|
{
|
||||||
|
@ -204,15 +211,24 @@ struct Glyph
|
||||||
bool shift_points_hori = true,
|
bool shift_points_hori = true,
|
||||||
bool use_my_metrics = true,
|
bool use_my_metrics = true,
|
||||||
bool phantom_only = false,
|
bool phantom_only = false,
|
||||||
|
hb_array_t<int> coords = hb_array_t<int> (),
|
||||||
unsigned int depth = 0) const
|
unsigned int depth = 0) const
|
||||||
{
|
{
|
||||||
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
||||||
|
|
||||||
|
if (!coords)
|
||||||
|
coords = hb_array (font->coords, font->num_coords);
|
||||||
|
|
||||||
contour_point_vector_t stack_points;
|
contour_point_vector_t stack_points;
|
||||||
bool inplace = type == SIMPLE && all_points.length == 0;
|
bool inplace = type == SIMPLE && all_points.length == 0;
|
||||||
/* Load into all_points if it's empty, as an optimization. */
|
/* Load into all_points if it's empty, as an optimization. */
|
||||||
contour_point_vector_t &points = inplace ? all_points : stack_points;
|
contour_point_vector_t &points = inplace ? all_points : stack_points;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case SIMPLE:
|
||||||
|
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
{
|
{
|
||||||
/* pseudo component points for each component in composite glyph */
|
/* pseudo component points for each component in composite glyph */
|
||||||
|
@ -220,9 +236,14 @@ struct Glyph
|
||||||
if (unlikely (!points.resize (num_points))) return false;
|
if (unlikely (!points.resize (num_points))) return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIMPLE:
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
case VAR_COMPOSITE:
|
||||||
return false;
|
{
|
||||||
|
for (auto &item : get_var_composite_iterator ())
|
||||||
|
if (unlikely (!item.get_points (points))) return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +283,9 @@ struct Glyph
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
|
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||||
|
coords,
|
||||||
|
points.as_array ());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||||
|
@ -288,9 +311,17 @@ struct Glyph
|
||||||
for (auto &item : get_composite_iterator ())
|
for (auto &item : get_composite_iterator ())
|
||||||
{
|
{
|
||||||
comp_points.reset ();
|
comp_points.reset ();
|
||||||
|
|
||||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||||
.get_points (font, glyf_accelerator, comp_points,
|
.get_points (font,
|
||||||
deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
|
glyf_accelerator,
|
||||||
|
comp_points,
|
||||||
|
deltas,
|
||||||
|
shift_points_hori,
|
||||||
|
use_my_metrics,
|
||||||
|
phantom_only,
|
||||||
|
coords,
|
||||||
|
depth + 1)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Apply component transformation & translation */
|
/* Apply component transformation & translation */
|
||||||
|
@ -328,8 +359,50 @@ struct Glyph
|
||||||
|
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
} break;
|
} break;
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
case VAR_COMPOSITE:
|
||||||
|
{
|
||||||
|
contour_point_vector_t comp_points;
|
||||||
|
hb_array_t<contour_point_t> points_left = points.as_array ();
|
||||||
|
for (auto &item : get_var_composite_iterator ())
|
||||||
|
{
|
||||||
|
hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ());
|
||||||
|
|
||||||
|
comp_points.reset ();
|
||||||
|
|
||||||
|
coord_setter_t coord_setter (coords);
|
||||||
|
item.set_variations (coord_setter, record_points);
|
||||||
|
|
||||||
|
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||||
|
.get_points (font,
|
||||||
|
glyf_accelerator,
|
||||||
|
comp_points,
|
||||||
|
deltas,
|
||||||
|
shift_points_hori,
|
||||||
|
use_my_metrics,
|
||||||
|
phantom_only,
|
||||||
|
coord_setter.get_coords (),
|
||||||
|
depth + 1)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Apply component transformation */
|
||||||
|
item.transform_points (record_points, comp_points);
|
||||||
|
|
||||||
|
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||||
|
if (use_my_metrics && item.is_use_my_metrics ())
|
||||||
|
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||||
|
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||||
|
|
||||||
|
all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||||
|
|
||||||
|
points_left += item.get_num_points ();
|
||||||
|
}
|
||||||
|
all_points.extend (phantoms);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
||||||
|
@ -368,6 +441,7 @@ struct Glyph
|
||||||
int num_contours = header->numberOfContours;
|
int num_contours = header->numberOfContours;
|
||||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||||
else if (num_contours > 0) type = SIMPLE;
|
else if (num_contours > 0) type = SIMPLE;
|
||||||
|
else if (num_contours == -2) type = VAR_COMPOSITE;
|
||||||
else type = COMPOSITE; /* negative numbers */
|
else type = COMPOSITE; /* negative numbers */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,274 @@
|
||||||
|
#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
|
||||||
|
#define OT_GLYF_VARCOMPOSITEGLYPH_HH
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../hb-open-type.hh"
|
||||||
|
#include "coord-setter.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace OT {
|
||||||
|
namespace glyf_impl {
|
||||||
|
|
||||||
|
|
||||||
|
struct VarCompositeGlyphRecord
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
enum var_composite_glyph_flag_t
|
||||||
|
{
|
||||||
|
USE_MY_METRICS = 0x0001,
|
||||||
|
AXIS_INDICES_ARE_SHORT = 0x0002,
|
||||||
|
UNIFORM_SCALE = 0x0004,
|
||||||
|
HAVE_TRANSLATE_X = 0x0008,
|
||||||
|
HAVE_TRANSLATE_Y = 0x0010,
|
||||||
|
HAVE_ROTATION = 0x0020,
|
||||||
|
HAVE_SCALE_X = 0x0040,
|
||||||
|
HAVE_SCALE_Y = 0x0080,
|
||||||
|
HAVE_SKEW_X = 0x0100,
|
||||||
|
HAVE_SKEW_Y = 0x0200,
|
||||||
|
HAVE_TCENTER_X = 0x0400,
|
||||||
|
HAVE_TCENTER_Y = 0x0800,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static constexpr unsigned NUM_TRANSFORM_POINTS = 5;
|
||||||
|
|
||||||
|
unsigned int get_size () const
|
||||||
|
{
|
||||||
|
unsigned int size = min_size;
|
||||||
|
|
||||||
|
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
|
||||||
|
size += num_axes * axis_width;
|
||||||
|
|
||||||
|
if (flags & HAVE_TRANSLATE_X) size += 2;
|
||||||
|
if (flags & HAVE_TRANSLATE_Y) size += 2;
|
||||||
|
if (flags & HAVE_ROTATION) size += 2;
|
||||||
|
if (flags & HAVE_SCALE_X) size += 2;
|
||||||
|
if (flags & HAVE_SCALE_Y) size += 2;
|
||||||
|
if (flags & HAVE_SKEW_X) size += 2;
|
||||||
|
if (flags & HAVE_SKEW_Y) size += 2;
|
||||||
|
if (flags & HAVE_TCENTER_X) size += 2;
|
||||||
|
if (flags & HAVE_TCENTER_Y) size += 2;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_more () const { return true; }
|
||||||
|
|
||||||
|
bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
|
||||||
|
|
||||||
|
hb_codepoint_t get_gid () const
|
||||||
|
{
|
||||||
|
return gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_num_axes () const
|
||||||
|
{
|
||||||
|
return num_axes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_num_points () const
|
||||||
|
{
|
||||||
|
return num_axes + NUM_TRANSFORM_POINTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transform_points (hb_array_t<contour_point_t> transformation_points,
|
||||||
|
contour_point_vector_t &points) const
|
||||||
|
{
|
||||||
|
float matrix[4];
|
||||||
|
contour_point_t trans;
|
||||||
|
|
||||||
|
get_transformation_from_points (transformation_points, matrix, trans);
|
||||||
|
|
||||||
|
points.transform (matrix);
|
||||||
|
points.translate (trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void transform (float (&matrix)[4], contour_point_t &trans,
|
||||||
|
float (other)[6])
|
||||||
|
{
|
||||||
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
|
||||||
|
float xx1 = other[0];
|
||||||
|
float xy1 = other[1];
|
||||||
|
float yx1 = other[2];
|
||||||
|
float yy1 = other[3];
|
||||||
|
float dx1 = other[4];
|
||||||
|
float dy1 = other[5];
|
||||||
|
float xx2 = matrix[0];
|
||||||
|
float xy2 = matrix[1];
|
||||||
|
float yx2 = matrix[2];
|
||||||
|
float yy2 = matrix[3];
|
||||||
|
float dx2 = trans.x;
|
||||||
|
float dy2 = trans.y;
|
||||||
|
|
||||||
|
matrix[0] = xx1*xx2 + xy1*yx2;
|
||||||
|
matrix[1] = xx1*xy2 + xy1*yy2;
|
||||||
|
matrix[2] = yx1*xx2 + yy1*yx2;
|
||||||
|
matrix[3] = yx1*xy2 + yy1*yy2;
|
||||||
|
trans.x = xx2*dx1 + yx2*dy1 + dx2;
|
||||||
|
trans.y = xy2*dx1 + yy2*dy1 + dy2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void translate (float (&matrix)[4], contour_point_t &trans,
|
||||||
|
float translateX, float translateY)
|
||||||
|
{
|
||||||
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213
|
||||||
|
float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY};
|
||||||
|
transform (matrix, trans, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scale (float (&matrix)[4], contour_point_t &trans,
|
||||||
|
float scaleX, float scaleY)
|
||||||
|
{
|
||||||
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224
|
||||||
|
float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f};
|
||||||
|
transform (matrix, trans, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rotate (float (&matrix)[4], contour_point_t &trans,
|
||||||
|
float rotation)
|
||||||
|
{
|
||||||
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
||||||
|
rotation = rotation * float (M_PI);
|
||||||
|
float c = cosf (rotation);
|
||||||
|
float s = sinf (rotation);
|
||||||
|
float other[6] = {c, s, -s, c, 0.f, 0.f};
|
||||||
|
transform (matrix, trans, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void skew (float (&matrix)[4], contour_point_t &trans,
|
||||||
|
float skewX, float skewY)
|
||||||
|
{
|
||||||
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
||||||
|
skewX = skewX * float (M_PI);
|
||||||
|
skewY = skewY * float (M_PI);
|
||||||
|
float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
|
||||||
|
transform (matrix, trans, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_points (contour_point_vector_t &points) const
|
||||||
|
{
|
||||||
|
float translateX = 0.f;
|
||||||
|
float translateY = 0.f;
|
||||||
|
float rotation = 0.f;
|
||||||
|
float scaleX = 1.f * (1 << 12);
|
||||||
|
float scaleY = 1.f * (1 << 12);
|
||||||
|
float skewX = 0.f;
|
||||||
|
float skewY = 0.f;
|
||||||
|
float tCenterX = 0.f;
|
||||||
|
float tCenterY = 0.f;
|
||||||
|
|
||||||
|
if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
|
||||||
|
|
||||||
|
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
||||||
|
unsigned axes_size = num_axes * axis_width;
|
||||||
|
|
||||||
|
const F2DOT14 *q = (const F2DOT14 *) (axes_size +
|
||||||
|
&StructAfter<const HBUINT8> (gid));
|
||||||
|
|
||||||
|
hb_array_t<contour_point_t> axis_points = points.as_array ().sub_array (points.length - get_num_points ());
|
||||||
|
unsigned count = num_axes;
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
axis_points[i].x = *q++;
|
||||||
|
|
||||||
|
const HBUINT16 *p = (const HBUINT16 *) q;
|
||||||
|
|
||||||
|
if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++;
|
||||||
|
if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++;
|
||||||
|
if (flags & HAVE_ROTATION) rotation = * (const F2DOT14 *) p++;
|
||||||
|
if (flags & HAVE_SCALE_X) scaleX = * (const F4DOT12 *) p++;
|
||||||
|
if (flags & HAVE_SCALE_Y) scaleY = * (const F4DOT12 *) p++;
|
||||||
|
if (flags & HAVE_SKEW_X) skewX = * (const F2DOT14 *) p++;
|
||||||
|
if (flags & HAVE_SKEW_Y) skewY = * (const F2DOT14 *) p++;
|
||||||
|
if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++;
|
||||||
|
if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++;
|
||||||
|
|
||||||
|
if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y))
|
||||||
|
scaleY = scaleX;
|
||||||
|
|
||||||
|
hb_array_t<contour_point_t> t = points.as_array ().sub_array (points.length - NUM_TRANSFORM_POINTS);
|
||||||
|
t[0].x = translateX;
|
||||||
|
t[0].y = translateY;
|
||||||
|
t[1].x = rotation;
|
||||||
|
t[2].x = scaleX;
|
||||||
|
t[2].y = scaleY;
|
||||||
|
t[3].x = skewX;
|
||||||
|
t[3].y = skewY;
|
||||||
|
t[4].x = tCenterX;
|
||||||
|
t[4].y = tCenterY;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_transformation_from_points (hb_array_t<contour_point_t> points,
|
||||||
|
float (&matrix)[4], contour_point_t &trans) const
|
||||||
|
{
|
||||||
|
matrix[0] = matrix[3] = 1.f;
|
||||||
|
matrix[1] = matrix[2] = 0.f;
|
||||||
|
trans.init (0.f, 0.f);
|
||||||
|
|
||||||
|
hb_array_t<contour_point_t> t = points.sub_array (points.length - NUM_TRANSFORM_POINTS);
|
||||||
|
|
||||||
|
float translateX = t[0].x;
|
||||||
|
float translateY = t[0].y;
|
||||||
|
float rotation = t[1].x / (1 << 14);
|
||||||
|
float scaleX = t[2].x / (1 << 12);
|
||||||
|
float scaleY = t[2].y / (1 << 12);
|
||||||
|
float skewX = t[3].x / (1 << 14);
|
||||||
|
float skewY = t[3].y / (1 << 14);
|
||||||
|
float tCenterX = t[4].x;
|
||||||
|
float tCenterY = t[4].y;
|
||||||
|
|
||||||
|
translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
|
||||||
|
rotate (matrix, trans, rotation);
|
||||||
|
scale (matrix, trans, scaleX, scaleY);
|
||||||
|
skew (matrix, trans, -skewX, skewY);
|
||||||
|
translate (matrix, trans, -tCenterX, -tCenterY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_variations (coord_setter_t &setter,
|
||||||
|
hb_array_t<contour_point_t> axis_points) const
|
||||||
|
{
|
||||||
|
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
||||||
|
|
||||||
|
const HBUINT8 *p = &StructAfter<const HBUINT8> (gid);
|
||||||
|
const HBUINT16 *q = &StructAfter<const HBUINT16> (gid);
|
||||||
|
|
||||||
|
unsigned count = num_axes;
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
unsigned axis_index = axis_width == 1 ? *p++ : *q++;
|
||||||
|
signed v = axis_points[i].x;
|
||||||
|
v = hb_clamp (v, -(1<<14), (1<<14));
|
||||||
|
setter[axis_index] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HBUINT16 flags;
|
||||||
|
HBUINT8 num_axes;
|
||||||
|
HBGlyphID16 gid;
|
||||||
|
public:
|
||||||
|
DEFINE_SIZE_MIN (5);
|
||||||
|
};
|
||||||
|
|
||||||
|
using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
|
||||||
|
|
||||||
|
struct VarCompositeGlyph
|
||||||
|
{
|
||||||
|
const GlyphHeader &header;
|
||||||
|
hb_bytes_t bytes;
|
||||||
|
VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
|
||||||
|
header (header_), bytes (bytes_) {}
|
||||||
|
|
||||||
|
var_composite_iter_t iter () const
|
||||||
|
{ return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace glyf_impl */
|
||||||
|
} /* namespace OT */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef OT_GLYF_COMPOSITE_ITER_HH
|
||||||
|
#define OT_GLYF_COMPOSITE_ITER_HH
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../hb.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace OT {
|
||||||
|
namespace glyf_impl {
|
||||||
|
|
||||||
|
|
||||||
|
template <typename CompositeGlyphRecord>
|
||||||
|
struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>,
|
||||||
|
const CompositeGlyphRecord &>
|
||||||
|
{
|
||||||
|
typedef const CompositeGlyphRecord *__item_t__;
|
||||||
|
composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) :
|
||||||
|
glyph (glyph_), current (nullptr), current_size (0)
|
||||||
|
{
|
||||||
|
set_current (current_);
|
||||||
|
}
|
||||||
|
|
||||||
|
composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
||||||
|
|
||||||
|
const CompositeGlyphRecord & __item__ () const { return *current; }
|
||||||
|
bool __more__ () const { return current; }
|
||||||
|
void __next__ ()
|
||||||
|
{
|
||||||
|
if (!current->has_more ()) { current = nullptr; return; }
|
||||||
|
|
||||||
|
set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
|
||||||
|
}
|
||||||
|
composite_iter_tmpl __end__ () const { return composite_iter_tmpl (); }
|
||||||
|
bool operator != (const composite_iter_tmpl& o) const
|
||||||
|
{ return current != o.current; }
|
||||||
|
|
||||||
|
|
||||||
|
void set_current (__item_t__ current_)
|
||||||
|
{
|
||||||
|
if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
|
||||||
|
{
|
||||||
|
current = nullptr;
|
||||||
|
current_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned size = current_->get_size ();
|
||||||
|
if (!glyph.check_range (current_, size))
|
||||||
|
{
|
||||||
|
current = nullptr;
|
||||||
|
current_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current_;
|
||||||
|
current_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
hb_bytes_t glyph;
|
||||||
|
__item_t__ current;
|
||||||
|
unsigned current_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace glyf_impl */
|
||||||
|
} /* namespace OT */
|
||||||
|
|
||||||
|
#endif /* OT_GLYF_COMPOSITE_ITER_HH */
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef OT_GLYF_COORD_SETTER_HH
|
||||||
|
#define OT_GLYF_COORD_SETTER_HH
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../hb.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace OT {
|
||||||
|
namespace glyf_impl {
|
||||||
|
|
||||||
|
|
||||||
|
struct coord_setter_t
|
||||||
|
{
|
||||||
|
coord_setter_t (hb_array_t<int> coords) :
|
||||||
|
coords (coords) {}
|
||||||
|
|
||||||
|
int& operator [] (unsigned idx)
|
||||||
|
{
|
||||||
|
if (coords.length < idx + 1)
|
||||||
|
coords.resize (idx + 1);
|
||||||
|
return coords[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_array_t<int> get_coords ()
|
||||||
|
{ return coords.as_array (); }
|
||||||
|
|
||||||
|
hb_vector_t<int> coords;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace glyf_impl */
|
||||||
|
} /* namespace OT */
|
||||||
|
|
||||||
|
#endif /* OT_GLYF_COORD_SETTER_HH */
|
|
@ -35,8 +35,9 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HB_EXPERIMENTAL
|
#ifndef HB_EXPERIMENTAL_API
|
||||||
#define HB_NO_BEYOND_64K
|
#define HB_NO_BEYOND_64K
|
||||||
|
#define HB_NO_VAR_COMPOSITES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HB_TINY
|
#ifdef HB_TINY
|
||||||
|
|
|
@ -157,6 +157,9 @@ struct HBFixed : Type
|
||||||
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||||
using F2DOT14 = HBFixed<HBINT16, 14>;
|
using F2DOT14 = HBFixed<HBINT16, 14>;
|
||||||
|
|
||||||
|
/* 16-bit signed fixed number with the low 12 bits of fraction (4.12). */
|
||||||
|
using F4DOT12 = HBFixed<HBINT16, 12>;
|
||||||
|
|
||||||
/* 32-bit signed fixed-point number (16.16). */
|
/* 32-bit signed fixed-point number (16.16). */
|
||||||
using F16DOT16 = HBFixed<HBINT32, 16>;
|
using F16DOT16 = HBFixed<HBINT32, 16>;
|
||||||
|
|
||||||
|
|
|
@ -548,10 +548,11 @@ struct gvar
|
||||||
{ return (i >= end) ? start : (i + 1); }
|
{ return (i >= end) ? start : (i + 1); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
|
bool apply_deltas_to_points (hb_codepoint_t glyph,
|
||||||
|
hb_array_t<int> coords,
|
||||||
const hb_array_t<contour_point_t> points) const
|
const hb_array_t<contour_point_t> points) const
|
||||||
{
|
{
|
||||||
if (!font->num_coords) return true;
|
if (!coords) return true;
|
||||||
|
|
||||||
if (unlikely (glyph >= table->glyphCount)) return true;
|
if (unlikely (glyph >= table->glyphCount)) return true;
|
||||||
|
|
||||||
|
@ -578,7 +579,6 @@ struct gvar
|
||||||
if (points.arrayZ[i].is_end_point)
|
if (points.arrayZ[i].is_end_point)
|
||||||
end_points.push (i);
|
end_points.push (i);
|
||||||
|
|
||||||
auto coords = hb_array (font->coords, font->num_coords);
|
|
||||||
unsigned num_coords = table->axisCount;
|
unsigned num_coords = table->axisCount;
|
||||||
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
|
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue