[instancer] store recalculated head/maxp info in subset plan

This commit is contained in:
Qunxin Liu 2023-01-17 15:16:17 -08:00
parent 92122421c9
commit 1f948e7fd5
3 changed files with 72 additions and 7 deletions

View File

@ -142,16 +142,30 @@ struct Glyph
update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points); update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points);
int rounded_xMin = roundf (xMin);
int rounded_xMax = roundf (xMax);
int rounded_yMin = roundf (yMin);
int rounded_yMax = roundf (yMax);
if (type != EMPTY)
{
plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin);
plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, rounded_yMin);
plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, rounded_xMax);
plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, rounded_yMax);
}
/*for empty glyphs: all_points only include phantom points. /*for empty glyphs: all_points only include phantom points.
*just update metrics and then return */ *just update metrics and then return */
if (!glyph_header) if (!glyph_header)
return true; return true;
glyph_header->numberOfContours = header->numberOfContours; glyph_header->numberOfContours = header->numberOfContours;
glyph_header->xMin = roundf (xMin);
glyph_header->yMin = roundf (yMin); glyph_header->xMin = rounded_xMin;
glyph_header->xMax = roundf (xMax); glyph_header->yMin = rounded_yMin;
glyph_header->yMax = roundf (yMax); glyph_header->xMax = rounded_xMax;
glyph_header->yMax = rounded_yMax;
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size); dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
return true; return true;
@ -164,7 +178,8 @@ struct Glyph
hb_bytes_t &dest_end /* OUT */) hb_bytes_t &dest_end /* OUT */)
{ {
contour_point_vector_t all_points, deltas; contour_point_vector_t all_points, deltas;
if (!get_points (font, glyf, all_points, &deltas, false, false)) unsigned composite_contours = 0;
if (!get_points (font, glyf, all_points, &deltas, &plan->head_maxp_info, &composite_contours, false, false))
return false; return false;
// .notdef, set type to empty so we only update metrics and don't compile bytes for // .notdef, set type to empty so we only update metrics and don't compile bytes for
@ -210,6 +225,8 @@ struct Glyph
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
contour_point_vector_t &all_points /* OUT */, contour_point_vector_t &all_points /* OUT */,
contour_point_vector_t *deltas = nullptr, /* OUT */ contour_point_vector_t *deltas = nullptr, /* OUT */
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
unsigned *composite_contours = nullptr, /* OUT */
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,
@ -223,6 +240,11 @@ struct Glyph
if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false; if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
(*edge_count)++; (*edge_count)++;
if (head_maxp_info)
{
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
}
if (!coords) if (!coords)
coords = hb_array (font->coords, font->num_coords); coords = hb_array (font->coords, font->num_coords);
@ -233,6 +255,10 @@ struct Glyph
switch (type) { switch (type) {
case SIMPLE: case SIMPLE:
if (depth == 0 && head_maxp_info)
head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours);
if (depth > 0 && composite_contours)
*composite_contours += (unsigned) header->numberOfContours;
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
return false; return false;
break; break;
@ -308,6 +334,8 @@ struct Glyph
switch (type) { switch (type) {
case SIMPLE: case SIMPLE:
if (depth == 0 && head_maxp_info)
head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4);
if (!inplace) if (!inplace)
all_points.extend (points.as_array ()); all_points.extend (points.as_array ());
break; break;
@ -318,12 +346,13 @@ 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, .get_points (font,
glyf_accelerator, glyf_accelerator,
comp_points, comp_points,
deltas, deltas,
head_maxp_info,
composite_contours,
shift_points_hori, shift_points_hori,
use_my_metrics, use_my_metrics,
phantom_only, phantom_only,
@ -365,6 +394,13 @@ struct Glyph
comp_index++; comp_index++;
} }
if (head_maxp_info && depth == 0)
{
if (composite_contours)
head_maxp_info->maxCompositeContours = hb_max (head_maxp_info->maxCompositeContours, *composite_contours);
head_maxp_info->maxCompositePoints = hb_max (head_maxp_info->maxCompositePoints, all_points.length);
head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
}
all_points.extend (phantoms); all_points.extend (phantoms);
} break; } break;
#ifndef HB_NO_VAR_COMPOSITES #ifndef HB_NO_VAR_COMPOSITES
@ -390,6 +426,8 @@ struct Glyph
glyf_accelerator, glyf_accelerator,
comp_points, comp_points,
deltas, deltas,
head_maxp_info,
nullptr,
shift_points_hori, shift_points_hori,
use_my_metrics, use_my_metrics,
phantom_only, phantom_only,

View File

@ -194,7 +194,7 @@ struct glyf_accelerator_t
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 (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only))) if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
return false; return false;
if (consumer.is_consuming_contour_points ()) if (consumer.is_consuming_contour_points ())

View File

@ -41,6 +41,30 @@ namespace OT {
struct Feature; struct Feature;
} }
struct head_maxp_info_t
{
head_maxp_info_t ()
:xMin (0x7FFF), xMax (-0x7FFF), yMin (0x7FFF), yMax (-0x7FFF),
maxPoints (0), maxContours (0),
maxCompositePoints (0),
maxCompositeContours (0),
maxComponentElements (0),
maxComponentDepth (0) {}
int xMin;
int xMax;
int yMin;
int yMax;
unsigned maxPoints;
unsigned maxContours;
unsigned maxCompositePoints;
unsigned maxCompositeContours;
unsigned maxComponentElements;
unsigned maxComponentDepth;
};
typedef struct head_maxp_info_t head_maxp_info_t;
struct hb_subset_plan_t struct hb_subset_plan_t
{ {
HB_INTERNAL hb_subset_plan_t (hb_face_t *, HB_INTERNAL hb_subset_plan_t (hb_face_t *,
@ -168,6 +192,9 @@ struct hb_subset_plan_t
//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
mutable hb_map_t bounds_height_map; mutable hb_map_t bounds_height_map;
//recalculated head/maxp table info after instancing
mutable head_maxp_info_t head_maxp_info;
#ifdef HB_EXPERIMENTAL_API #ifdef HB_EXPERIMENTAL_API
// name table overrides map: hb_ot_name_record_ids_t-> name string new value or // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
// None to indicate should remove // None to indicate should remove