[draw] Fix invalid rendering of some glyph on Estedad-VF

Basically reverts 11f3fca so I can do the same tested and better later

Fixes #2215
This commit is contained in:
Ebrahim Byagowi 2020-02-29 16:04:03 +03:30 committed by GitHub
parent 86c40b3a1d
commit 44169f3396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 21 deletions

View File

@ -573,7 +573,9 @@ struct glyf
return true;
}
bool get_contour_points (contour_point_vector_t &points_ /* OUT */, bool phantom_only = false) const
bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
hb_vector_t<unsigned int> &end_points_ /* OUT */,
bool phantom_only = false) const
{
const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
int num_contours = header.numberOfContours;
@ -584,8 +586,13 @@ struct glyf
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
if (phantom_only) return true;
end_points_.resize (num_contours);
for (int i = 0; i < num_contours; i++)
{
end_points_[i] = endPtsOfContours[i];
points_[endPtsOfContours[i]].is_end_point = true;
}
/* Skip instructions */
const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
@ -702,6 +709,7 @@ struct glyf
{
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
contour_point_vector_t points;
hb_vector_t<unsigned> end_points;
switch (type) {
case COMPOSITE:
@ -714,7 +722,7 @@ struct glyf
break;
}
case SIMPLE:
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, end_points, phantom_only)))
return false;
break;
default: return false; /* empty glyph */
@ -738,7 +746,8 @@ struct glyf
}
#ifndef HB_NO_VAR
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font->coords, font->num_coords, points.as_array ()))) return false;
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font->coords, font->num_coords,
points.as_array (), end_points.as_array ()))) return false;
#endif
switch (type) {

View File

@ -546,7 +546,8 @@ struct gvar
public:
bool apply_deltas_to_points (hb_codepoint_t glyph,
const int *coords, unsigned int coord_count,
const hb_array_t<contour_point_t> points) const
const hb_array_t<contour_point_t> points,
const hb_array_t<unsigned int> end_points) const
{
coord_count = hb_min (coord_count, gvar_table->axisCount);
if (!coord_count || coord_count != gvar_table->axisCount) return true;
@ -605,27 +606,16 @@ struct gvar
deltas[pt_index].y += y_deltas[i] * scalar;
}
/* find point before phantoms start which is an end point */
unsigned all_contours_end = points.length ? points.length - 1 : 0;
while (all_contours_end > 0)
{
if (points[all_contours_end].is_end_point) break;
--all_contours_end;
}
/* infer deltas for unreferenced points */
for (unsigned start_point = 0; start_point < all_contours_end; ++start_point)
unsigned start_point = 0;
for (unsigned c = 0; c < end_points.length; c++)
{
unsigned end_point = end_points[c];
/* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
unsigned end_point = start_point;
unsigned unref_count = 0;
for (; end_point <= all_contours_end; ++end_point)
{
if (!deltas[end_point].flag)
unref_count++;
if (points[end_point].is_end_point)
break;
}
for (unsigned i = start_point; i <= end_point; i++)
if (!deltas[i].flag) unref_count++;
unsigned j = start_point;
if (unref_count == 0 || unref_count > end_point - start_point)

Binary file not shown.

View File

@ -7,3 +7,5 @@ chromacheck-* fonts are from https://github.com/RoelN/ChromaCheck/tree/master/fo
RanaKufi-Regular.subset.otf is from https://github.com/alif-type/rana-kufi/ but the subset is licensed for us in MIT for the project use.
glyphs.ttf is from https://github.com/RazrFalcon/ttf-parser/blob/337e7d1/tests/fonts/glyphs.ttf
Estedad-VF.ttf, licensed under OFL 1.1, is from https://github.com/aminabedi68/Estedad

View File

@ -751,6 +751,66 @@ test_hb_draw_font_kit_variations_tests (void)
}
}
static void
test_hb_draw_estedad_vf (void)
{
/* https://github.com/harfbuzz/harfbuzz/issues/2215 */
char str[2048];
user_data_t user_data = {
.str = str,
.size = sizeof (str)
};
{
/* See https://github.com/google/skia/blob/d38f00a1/gm/stroketext.cpp#L115-L124 */
hb_face_t *face = hb_test_open_font_file ("fonts/Estedad-VF.ttf");
hb_font_t *font = hb_font_create (face);
hb_face_destroy (face);
hb_variation_t var;
hb_variation_from_string ("wght=100", -1, &var);
hb_font_set_variations (font, &var, 1);
user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 156, funcs, &user_data));
/* Skip empty path where all the points of a path are equal */
char expected[] = "M150,1158L182,1158Q256,1158 317,1170Q377,1182 421,1213L421,430L521,430"
"L521,1490L421,1490L421,1320Q393,1279 344,1262Q294,1244 182,1244L150,1244"
"L150,1158ZM1815,-122L1669,-122L1669,642L1552,642L1055,-117L1055,-206"
"L1569,-206L1569,-458L1669,-458L1669,-206L1815,-206L1815,-122ZM1569,-122"
"L1166,-122L1569,494L1569,-122ZM609,-79L1639,1288L1555,1334L525,-33L609,-79Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 180, funcs, &user_data));
/* Skip empty path where all the points of a path are equal */
char expected2[] = "M120,693Q120,545 177,414Q233,282 333,182Q433,81 567,24Q701,-33 855,-33"
"Q1010,-33 1144,24Q1277,81 1377,182Q1477,282 1534,414Q1590,545 1590,693"
"Q1590,842 1534,973Q1477,1104 1377,1205Q1277,1305 1144,1362Q1010,1419 855,1419"
"Q701,1419 567,1362Q433,1305 333,1205Q233,1104 177,973Q120,842 120,693ZM220,693"
"Q220,828 270,945Q320,1061 409,1148Q497,1235 612,1284Q726,1333 855,1333"
"Q984,1333 1099,1284Q1213,1235 1302,1148Q1390,1061 1440,945Q1490,828 1490,693"
"Q1490,558 1440,442Q1390,325 1302,237Q1213,149 1099,100Q984,51 855,51"
"Q726,51 612,100Q497,149 409,237Q320,325 270,442Q220,558 220,693ZM690,643"
"L690,997L886,997Q970,997 1029,949Q1087,901 1087,819Q1087,737 1028,690"
"Q969,643 886,643L690,643ZM1165,334L973,568Q1065,591 1126,658Q1187,725 1187,819"
"Q1187,896 1147,956Q1106,1015 1038,1049Q969,1083 886,1083L590,1083L590,310"
"L690,310L690,557L860,557L1083,286L1165,334Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 262, funcs, &user_data));
/* Skip empty path where all the points of a path are equal */
char expected3[] = "M422,598Q495,598 545,548Q595,498 595,426Q595,353 545,303Q494,252 422,252"
"Q350,252 300,303Q250,353 250,426Q250,499 300,549Q349,598 422,598ZM422,698"
"Q347,698 285,662Q223,625 187,564Q150,502 150,426Q150,351 187,289"
"Q223,226 285,189Q346,152 422,152Q498,152 560,189Q622,226 659,289"
"Q695,351 695,426Q695,502 658,564Q621,625 560,662Q498,698 422,698Z";
g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1);
hb_font_destroy (font);
}
}
static void
test_hb_draw_stroking (void)
{
@ -866,6 +926,7 @@ main (int argc, char **argv)
hb_test_add (test_hb_draw_ttf_parser_tests);
hb_test_add (test_hb_draw_font_kit_glyphs_tests);
hb_test_add (test_hb_draw_font_kit_variations_tests);
hb_test_add (test_hb_draw_estedad_vf);
hb_test_add (test_hb_draw_stroking);
hb_test_add (test_hb_draw_immutable);
unsigned result = hb_test_run ();