[glyf] Flesh out VarCompositeGlyph

This commit is contained in:
Behdad Esfahbod 2022-10-13 13:12:26 -06:00
parent 21f671bc45
commit 575d99406a
2 changed files with 131 additions and 88 deletions

View File

@ -14,42 +14,37 @@ struct VarCompositeGlyphRecord
protected: protected:
enum var_composite_glyph_flag_t enum var_composite_glyph_flag_t
{ {
ARG_1_AND_2_ARE_WORDS = 0x0001, USE_MY_METRICS = 0x0001,
ARGS_ARE_XY_VALUES = 0x0002, AXIS_INDICES_ARE_SHORT = 0x0002,
ROUND_XY_TO_GRID = 0x0004, UNIFORM_SCALE = 0x0004,
WE_HAVE_A_SCALE = 0x0008, HAVE_TRANSLATE_X = 0x0008,
MORE_COMPONENTS = 0x0020, HAVE_TRANSLATE_Y = 0x0010,
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040, HAVE_ROTATION = 0x0020,
WE_HAVE_A_TWO_BY_TWO = 0x0080, HAVE_SCALE_X = 0x0040,
WE_HAVE_INSTRUCTIONS = 0x0100, HAVE_SCALE_Y = 0x0080,
USE_MY_METRICS = 0x0200, HAVE_SKEW_X = 0x0100,
OVERLAP_COMPOUND = 0x0400, HAVE_SKEW_Y = 0x0200,
SCALED_COMPONENT_OFFSET = 0x0800, HAVE_TCENTER_X = 0x0400,
UNSCALED_COMPONENT_OFFSET = 0x1000, HAVE_TCENTER_Y = 0x0800,
#ifndef HB_NO_BEYOND_64K
GID_IS_24BIT = 0x2000
#endif
}; };
public: public:
unsigned int get_size () const unsigned int get_size () const
{ {
unsigned int size = min_size; unsigned int size = min_size;
/* glyphIndex is 24bit instead of 16bit */
#ifndef HB_NO_BEYOND_64K
if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
#endif
/* arg1 and 2 are int16 */
if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
/* arg1 and 2 are int8 */
else size += 2;
/* One x 16 bit (scale) */ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
if (flags & WE_HAVE_A_SCALE) size += 2; size += num_axes * axis_width;
/* Two x 16 bit (xscale, yscale) */
else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4; if (flags & HAVE_TRANSLATE_X) size += 2;
/* Four x 16 bit (xscale, scale01, scale10, yscale) */ if (flags & HAVE_TRANSLATE_Y) size += 2;
else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8; 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; return size;
} }
@ -58,81 +53,126 @@ struct VarCompositeGlyphRecord
{ {
float matrix[4]; float matrix[4];
contour_point_t trans; contour_point_t trans;
if (get_transformation (matrix, trans))
{ points.transform (matrix);
points.transform (matrix); points.translate (trans);
points.translate (trans);
}
} }
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const 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), 0.f, 0.f};
transform (matrix, trans, other);
}
void get_transformation (float (&matrix)[4], contour_point_t &trans) const
{
float translateX = 0.f;
float translateY = 0.f;
float rotation = 0.f;
float scaleX = 1.f;
float scaleY = 1.f;
float skewX = 0.f;
float skewY = 0.f;
float tCenterX = 0.f;
float tCenterY = 0.f;
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
unsigned axes_size = num_axes * axis_width;
const HBUINT16 *p = (const HBUINT16 *) (axes_size +
&StructAfter<const HBUINT8> (num_axes));
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++).to_float ();
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++).to_float ();
if (flags & HAVE_SKEW_Y) skewY = (* (const F2DOT14 *) p++).to_float ();
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;
matrix[0] = matrix[3] = 1.f; matrix[0] = matrix[3] = 1.f;
matrix[1] = matrix[2] = 0.f; matrix[1] = matrix[2] = 0.f;
trans.init (0.f, 0.f);
const auto *p = &StructAfter<const HBINT8> (flags); translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
#ifndef HB_NO_BEYOND_64K rotate (matrix, trans, rotation);
if (flags & GID_IS_24BIT) scale (matrix, trans, scaleX, scaleY);
p += HBGlyphID24::static_size; skew (matrix, trans, -skewX, skewY);
else translate (matrix, trans, -tCenterX, -tCenterY);
#endif
p += HBGlyphID16::static_size;
int tx, ty;
if (flags & ARG_1_AND_2_ARE_WORDS)
{
tx = *(const HBINT16 *) p;
p += HBINT16::static_size;
ty = *(const HBINT16 *) p;
p += HBINT16::static_size;
}
else
{
tx = *p++;
ty = *p++;
}
trans.init ((float) tx, (float) ty);
{
const F2DOT14 *points = (const F2DOT14 *) p;
if (flags & WE_HAVE_A_SCALE)
{
matrix[0] = matrix[3] = points[0].to_float ();
return true;
}
else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
{
matrix[0] = points[0].to_float ();
matrix[3] = points[1].to_float ();
return true;
}
else if (flags & WE_HAVE_A_TWO_BY_TWO)
{
matrix[0] = points[0].to_float ();
matrix[1] = points[1].to_float ();
matrix[2] = points[2].to_float ();
matrix[3] = points[3].to_float ();
return true;
}
}
return tx || ty;
} }
public: public:
hb_codepoint_t get_gid () const hb_codepoint_t get_gid () const
{ {
#ifndef HB_NO_BEYOND_64K return gid;
if (flags & GID_IS_24BIT)
return StructAfter<const HBGlyphID24> (flags);
else
#endif
return StructAfter<const HBGlyphID16> (flags);
} }
protected: protected:
HBUINT16 flags; HBUINT16 flags;
HBUINT24 pad; HBGlyphID16 gid;
HBUINT8 num_axes;
public: public:
DEFINE_SIZE_MIN (4); DEFINE_SIZE_MIN (5);
}; };
using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>; using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;

View File

@ -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>;