[glyf] Refactor, move get_points inside Glyph
This commit is contained in:
parent
96b71e802f
commit
b59eb54f70
|
@ -402,6 +402,15 @@ struct glyf
|
||||||
__item_t__ current;
|
__item_t__ current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum phantom_point_index_t
|
||||||
|
{
|
||||||
|
PHANTOM_LEFT = 0,
|
||||||
|
PHANTOM_RIGHT = 1,
|
||||||
|
PHANTOM_TOP = 2,
|
||||||
|
PHANTOM_BOTTOM = 3,
|
||||||
|
PHANTOM_COUNT = 4
|
||||||
|
};
|
||||||
|
|
||||||
struct Glyph
|
struct Glyph
|
||||||
{
|
{
|
||||||
enum simple_glyph_flag_t
|
enum simple_glyph_flag_t
|
||||||
|
@ -539,7 +548,7 @@ struct glyf
|
||||||
const simple_glyph_flag_t same_flag)
|
const simple_glyph_flag_t same_flag)
|
||||||
{
|
{
|
||||||
float v = 0;
|
float v = 0;
|
||||||
for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++)
|
for (unsigned i = 0; i < points_.length; i++)
|
||||||
{
|
{
|
||||||
uint8_t flag = points_[i].flag;
|
uint8_t flag = points_[i].flag;
|
||||||
if (flag & short_flag)
|
if (flag & short_flag)
|
||||||
|
@ -571,7 +580,7 @@ struct glyf
|
||||||
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
|
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
|
||||||
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
||||||
|
|
||||||
points_.resize (num_points + PHANTOM_COUNT);
|
points_.resize (num_points);
|
||||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
||||||
if (phantom_only) return true;
|
if (phantom_only) return true;
|
||||||
|
|
||||||
|
@ -644,28 +653,10 @@ struct glyf
|
||||||
/* Chop instructions off the end */
|
/* Chop instructions off the end */
|
||||||
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
||||||
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
||||||
|
|
||||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */) const
|
|
||||||
{
|
|
||||||
/* add one pseudo point for each component in composite glyph */
|
|
||||||
unsigned int num_points = hb_len (get_iterator ());
|
|
||||||
points_.resize (num_points + PHANTOM_COUNT);
|
|
||||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
||||||
|
|
||||||
enum phantom_point_index_t
|
|
||||||
{
|
|
||||||
PHANTOM_LEFT = 0,
|
|
||||||
PHANTOM_RIGHT = 1,
|
|
||||||
PHANTOM_TOP = 2,
|
|
||||||
PHANTOM_BOTTOM = 3,
|
|
||||||
PHANTOM_COUNT = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
composite_iter_t get_composite_iterator () const
|
composite_iter_t get_composite_iterator () const
|
||||||
{
|
{
|
||||||
|
@ -700,132 +691,67 @@ struct glyf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for a simple glyph, return contour end points, flags, along with coordinate points
|
/* Note: Recursively calls itself.
|
||||||
* for a composite glyph, return pseudo component points
|
* all_points includes phantom points
|
||||||
* in both cases points trailed with four phantom points
|
|
||||||
*/
|
*/
|
||||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */, bool phantom_only = false) const
|
template<typename T>
|
||||||
|
bool get_points (T glyph_for_gid, hb_font_t *font,
|
||||||
|
contour_point_vector_t &all_points /* OUT */,
|
||||||
|
bool phantom_only = false,
|
||||||
|
unsigned int depth = 0) const
|
||||||
{
|
{
|
||||||
|
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
||||||
|
contour_point_vector_t points;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_);
|
case COMPOSITE:
|
||||||
case SIMPLE: return SimpleGlyph (*header, bytes).get_contour_points (points_, phantom_only);
|
{
|
||||||
default:
|
/* pseudo component points for each component in composite glyph */
|
||||||
/* empty glyph */
|
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
|
||||||
points_.resize (PHANTOM_COUNT);
|
if (unlikely (!points.resize (num_points))) return false;
|
||||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
for (unsigned i = 0; i < points.length; i++)
|
||||||
return true;
|
points[i].init ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case SIMPLE:
|
||||||
|
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default: return false; /* empty glyph */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_simple_glyph () const { return type == SIMPLE; }
|
hb_face_t *face = font->face;
|
||||||
bool is_composite_glyph () const { return type == COMPOSITE; }
|
|
||||||
|
|
||||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
/* Init phantom points */
|
||||||
|
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
|
||||||
|
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||||
{
|
{
|
||||||
if (type == EMPTY) return true; /* Empty glyph; zero extents. */
|
for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
|
||||||
return header->get_extents (font, gid, extents);
|
int h_delta = (int) header->xMin - face->table.hmtx->get_side_bearing (gid);
|
||||||
}
|
int v_orig = (int) header->yMax + face->table.vmtx->get_side_bearing (gid);
|
||||||
|
unsigned h_adv = face->table.hmtx->get_advance (gid);
|
||||||
hb_bytes_t get_bytes () const { return bytes; }
|
unsigned v_adv = face->table.vmtx->get_advance (gid);
|
||||||
const GlyphHeader &get_header () const { return *header; }
|
|
||||||
|
|
||||||
Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) :
|
|
||||||
bytes (bytes_), header (bytes.as<GlyphHeader> ())
|
|
||||||
{
|
|
||||||
int num_contours = header->numberOfContours;
|
|
||||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
|
||||||
else if (num_contours > 0) type = SIMPLE;
|
|
||||||
else type = COMPOSITE; /* negative numbers */
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
hb_bytes_t bytes;
|
|
||||||
const GlyphHeader *header;
|
|
||||||
unsigned type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct accelerator_t
|
|
||||||
{
|
|
||||||
void init (hb_face_t *face_)
|
|
||||||
{
|
|
||||||
short_offset = false;
|
|
||||||
num_glyphs = 0;
|
|
||||||
loca_table = nullptr;
|
|
||||||
glyf_table = nullptr;
|
|
||||||
face = face_;
|
|
||||||
const OT::head &head = *face->table.head;
|
|
||||||
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
|
||||||
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
|
||||||
return;
|
|
||||||
short_offset = 0 == head.indexToLocFormat;
|
|
||||||
|
|
||||||
loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
|
|
||||||
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
|
|
||||||
|
|
||||||
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fini ()
|
|
||||||
{
|
|
||||||
loca_table.destroy ();
|
|
||||||
glyf_table.destroy ();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum phantom_point_index_t
|
|
||||||
{
|
|
||||||
PHANTOM_LEFT = 0,
|
|
||||||
PHANTOM_RIGHT = 1,
|
|
||||||
PHANTOM_TOP = 2,
|
|
||||||
PHANTOM_BOTTOM = 3,
|
|
||||||
PHANTOM_COUNT = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void init_phantom_points (hb_codepoint_t gid, hb_array_t<contour_point_t> &phantoms /* IN/OUT */) const
|
|
||||||
{
|
|
||||||
const Glyph &glyph = glyph_for_gid (gid);
|
|
||||||
int h_delta = (int) glyph.get_header ().xMin - face->table.hmtx->get_side_bearing (gid);
|
|
||||||
int v_orig = (int) glyph.get_header ().yMax + face->table.vmtx->get_side_bearing (gid);
|
|
||||||
unsigned int h_adv = face->table.hmtx->get_advance (gid);
|
|
||||||
unsigned int v_adv = face->table.vmtx->get_advance (gid);
|
|
||||||
|
|
||||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||||
phantoms[PHANTOM_TOP].y = v_orig;
|
phantoms[PHANTOM_TOP].y = v_orig;
|
||||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: Recursively calls itself.
|
|
||||||
* all_points includes phantom points
|
|
||||||
*/
|
|
||||||
bool _get_points (hb_codepoint_t gid,
|
|
||||||
const int *coords, unsigned int coord_count,
|
|
||||||
contour_point_vector_t &all_points /* OUT */,
|
|
||||||
bool phantom_only = false,
|
|
||||||
unsigned int depth = 0) const
|
|
||||||
{
|
|
||||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
|
|
||||||
contour_point_vector_t points;
|
|
||||||
const Glyph &glyph = glyph_for_gid (gid);
|
|
||||||
if (unlikely (!glyph.get_contour_points (points, phantom_only))) return false;
|
|
||||||
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
|
||||||
init_phantom_points (gid, phantoms);
|
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array ()))) return false;
|
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font->coords, font->num_coords, points.as_array ()))) return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (glyph.is_simple_glyph ())
|
switch (type) {
|
||||||
|
case SIMPLE:
|
||||||
all_points.extend (points.as_array ());
|
all_points.extend (points.as_array ());
|
||||||
else if (glyph.is_composite_glyph ())
|
break;
|
||||||
|
case COMPOSITE:
|
||||||
{
|
{
|
||||||
unsigned int comp_index = 0;
|
unsigned int comp_index = 0;
|
||||||
for (auto &item : glyph.get_composite_iterator ())
|
for (auto &item : get_composite_iterator ())
|
||||||
{
|
{
|
||||||
contour_point_vector_t comp_points;
|
contour_point_vector_t comp_points;
|
||||||
if (unlikely (!_get_points (item.glyphIndex, coords, coord_count,
|
if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, comp_points, phantom_only, depth + 1))
|
||||||
comp_points, phantom_only, depth))
|
|
||||||
|| comp_points.length < PHANTOM_COUNT)
|
|| comp_points.length < PHANTOM_COUNT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -860,12 +786,76 @@ struct glyf
|
||||||
}
|
}
|
||||||
|
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
|
} break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == 0) /* Apply at top level */
|
||||||
|
{
|
||||||
|
/* Undocumented rasterizer behavior:
|
||||||
|
* Shift points horizontally by the updated left side bearing
|
||||||
|
*/
|
||||||
|
contour_point_t delta;
|
||||||
|
delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
|
||||||
|
if (delta.x) all_points.translate (delta);
|
||||||
}
|
}
|
||||||
else return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
|
||||||
|
{
|
||||||
|
if (type == EMPTY) return true; /* Empty glyph; zero extents. */
|
||||||
|
return header->get_extents (font, gid, extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_bytes_t get_bytes () const { return bytes; }
|
||||||
|
|
||||||
|
Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
|
||||||
|
hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
|
||||||
|
header (bytes.as<GlyphHeader> ())
|
||||||
|
{
|
||||||
|
int num_contours = header->numberOfContours;
|
||||||
|
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||||
|
else if (num_contours > 0) type = SIMPLE;
|
||||||
|
else type = COMPOSITE; /* negative numbers */
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
hb_bytes_t bytes;
|
||||||
|
hb_codepoint_t gid;
|
||||||
|
const GlyphHeader *header;
|
||||||
|
unsigned type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct accelerator_t
|
||||||
|
{
|
||||||
|
void init (hb_face_t *face_)
|
||||||
|
{
|
||||||
|
short_offset = false;
|
||||||
|
num_glyphs = 0;
|
||||||
|
loca_table = nullptr;
|
||||||
|
glyf_table = nullptr;
|
||||||
|
face = face_;
|
||||||
|
const OT::head &head = *face->table.head;
|
||||||
|
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
||||||
|
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||||
|
return;
|
||||||
|
short_offset = 0 == head.indexToLocFormat;
|
||||||
|
|
||||||
|
loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
|
||||||
|
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
|
||||||
|
|
||||||
|
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fini ()
|
||||||
|
{
|
||||||
|
loca_table.destroy ();
|
||||||
|
glyf_table.destroy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
|
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
|
||||||
{
|
{
|
||||||
|
@ -876,17 +866,10 @@ struct glyf
|
||||||
contour_point_vector_t all_points;
|
contour_point_vector_t all_points;
|
||||||
|
|
||||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||||
if (unlikely (!_get_points (gid, font->coords, font->num_coords, all_points, phantom_only) ||
|
if (unlikely (!glyph_for_gid (gid).get_points ([this] (hb_codepoint_t gid) -> const Glyph { return this->glyph_for_gid (gid); },
|
||||||
all_points.length < PHANTOM_COUNT))
|
font, all_points, phantom_only)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Undocumented rasterizer behavior:
|
|
||||||
* Shift points horizontally by the updated left side bearing
|
|
||||||
*/
|
|
||||||
contour_point_t delta;
|
|
||||||
delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
|
|
||||||
if (delta.x) all_points.translate (delta);
|
|
||||||
|
|
||||||
if (consumer.is_consuming_contour_points ())
|
if (consumer.is_consuming_contour_points ())
|
||||||
{
|
{
|
||||||
for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
|
for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
|
||||||
|
@ -1002,7 +985,7 @@ struct glyf
|
||||||
if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
|
if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
|
||||||
return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
|
return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
|
||||||
#endif
|
#endif
|
||||||
return glyph_for_gid (gid).get_extents (font, gid, extents);
|
return glyph_for_gid (gid).get_extents (font, extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Glyph
|
const Glyph
|
||||||
|
@ -1028,7 +1011,7 @@ struct glyf
|
||||||
return Glyph ();
|
return Glyph ();
|
||||||
|
|
||||||
Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
|
Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
|
||||||
end_offset - start_offset));
|
end_offset - start_offset), gid);
|
||||||
return needs_padding_removal ? glyph.trim_padding () : glyph;
|
return needs_padding_removal ? glyph.trim_padding () : glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue