[glyf] Switch to ttf-parser's glyf to path algorithm

It consumes each point at a time and doesn't need to know contour size before hand
This commit is contained in:
Ebrahim Byagowi 2020-02-17 10:11:49 +03:30
parent 3c792c2aa5
commit 60f8f384f9
2 changed files with 254 additions and 206 deletions

View File

@ -1059,6 +1059,19 @@ struct glyf
user_data); user_data);
} }
struct optional_point_t
{
optional_point_t () { is_null = true; }
optional_point_t (float x_, float y_) { x = x_; y = y_; is_null = false; }
bool is_null;
float x;
float y;
optional_point_t lerp (optional_point_t p, float t)
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
};
bool bool
get_path (hb_font_t *font, hb_codepoint_t gid, get_path (hb_font_t *font, hb_codepoint_t gid,
const hb_draw_funcs_t *funcs, void *user_data) const const hb_draw_funcs_t *funcs, void *user_data) const
@ -1075,69 +1088,115 @@ struct glyf
float, float, float, float, float, float, float, float, float, float, float, float,
void *) = funcs->quadratic_to ? _normal_quadratic_to_call : _translate_quadratic_to_cubic; void *) = funcs->quadratic_to ? _normal_quadratic_to_call : _translate_quadratic_to_cubic;
unsigned contour_start = 0; /* based on https://github.com/RazrFalcon/ttf-parser/blob/master/src/glyf.rs#L292 which is base on font-rs */
/* Learnt from https://github.com/opentypejs/opentype.js/blob/4e0bb99/src/tables/glyf.js#L222 */ unsigned point_index = 0;
while (contour_start < points.length) while (point_index < points.length)
{ {
float prev_x = 0; float prev_y = 0; /* Skip empty contours */
unsigned contour_length = 0; if (points[point_index].is_end_point)
for (unsigned i = contour_start; i < points.length; ++i)
{ {
contour_length++; ++point_index;
if (points[i].is_end_point)
break;
}
/* Skip contours with less than 2 points */
if (contour_length < 2)
{
contour_start += contour_length;
continue; continue;
} }
optional_point_t first_oncurve = optional_point_t ();
contour_point_t *curr = &points[contour_start + contour_length - 1]; optional_point_t first_offcurve = optional_point_t ();
contour_point_t *next = &points[contour_start]; optional_point_t last_offcurve = optional_point_t ();
float last_x = 0, last_y = 0;
if (curr->flag & Glyph::FLAG_ON_CURVE) do
{ {
prev_x = curr->x; prev_y = curr->y; bool is_on_curve = points[point_index].flag & Glyph::FLAG_ON_CURVE;
funcs->move_to (font->em_scalef_x (prev_x), font->em_scalef_y (prev_y), user_data); optional_point_t p (points[point_index].x, points[point_index].y);
} if (first_oncurve.is_null)
else
{
if (next->flag & Glyph::FLAG_ON_CURVE)
{ {
prev_x = next->x; prev_y = next->y; if (is_on_curve)
funcs->move_to (font->em_scalef_x (prev_x), font->em_scalef_y (prev_y), user_data); {
first_oncurve = p;
last_x = p.x; last_y = p.y;
funcs->move_to (font->em_scalef_x (last_x), font->em_scalef_y (last_y),
user_data);
}
else
{
if (!first_offcurve.is_null)
{
optional_point_t mid = first_offcurve.lerp (p, .5f);
first_oncurve = mid;
last_offcurve = p;
last_x = mid.x; last_y = mid.y;
funcs->move_to (font->em_scalef_x (last_x), font->em_scalef_y (last_y),
user_data);
}
else
first_offcurve = p;
}
} }
else else
{ {
prev_x = (curr->x + next->x) / 2.f; prev_y = (curr->y + next->y) / 2.f; if (!last_offcurve.is_null)
/* If both first and last points are off-curve, start at their middle. */ {
funcs->move_to (font->em_scalef_x (prev_x), font->em_scalef_y (prev_y), user_data); if (is_on_curve)
{
quad_to (font, funcs, last_x, last_y, last_offcurve.x, last_offcurve.y, p.x, p.y, user_data);
last_x = p.x;
last_y = p.y;
last_offcurve = optional_point_t ();
}
else
{
optional_point_t mid = last_offcurve.lerp (p, .5f);
quad_to (font, funcs, last_x, last_y, last_offcurve.x, last_offcurve.y, mid.x, mid.y, user_data);
last_x = mid.x;
last_y = mid.y;
last_offcurve = p;
}
}
else
{
if (is_on_curve)
{
last_x = p.x;
last_y = p.y;
funcs->line_to (font->em_scalef_x (last_x), font->em_scalef_y (last_y),
user_data);
}
else
{
last_offcurve = p;
}
}
} }
} } while (!points[point_index++].is_end_point);
for (unsigned i = 0; i < contour_length; ++i) while (true)
{ {
curr = next; if (!first_offcurve.is_null && !last_offcurve.is_null)
next = &points[contour_start + ((i + 1) % contour_length)];
if (curr->flag & Glyph::FLAG_ON_CURVE)
{ {
prev_x = curr->x; prev_y = curr->y; optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
funcs->line_to (font->em_scalef_x (curr->x), font->em_scalef_y (curr->y), user_data); quad_to (font, funcs, last_x, last_y, last_offcurve.x, last_offcurve.y, mid.x, mid.y, user_data);
last_x = mid.x;
last_y = mid.y;
last_offcurve = optional_point_t ();
} }
else else if (!first_offcurve.is_null && last_offcurve.is_null)
{ {
float to_x, to_y; if (!first_oncurve.is_null)
if (next->flag & Glyph::FLAG_ON_CURVE) { to_x = next->x; to_y = next->y; } quad_to (font, funcs, last_x, last_y, first_offcurve.x, first_offcurve.y, first_oncurve.x, first_oncurve.y, user_data);
else { to_x = (curr->x + next->x) / 2.f; to_y = (curr->y + next->y) / 2.f; } break;
quad_to (font, funcs, prev_x, prev_y, curr->x, curr->y, to_x, to_y, user_data); }
prev_x = to_x; prev_y = to_y; else if (first_offcurve.is_null && !last_offcurve.is_null)
{
if (!first_oncurve.is_null)
quad_to (font, funcs, last_x, last_y, last_offcurve.x, last_offcurve.y, first_oncurve.x, first_oncurve.y, user_data);
break;
}
else /* first_offcurve.is_null && last_offcurve.is_null */
{
if (!first_oncurve.is_null)
funcs->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y),
user_data);
break;
} }
} }
contour_start += contour_length;
funcs->close_path (user_data); funcs->close_path (user_data);
} }
return true; return true;

View File

@ -187,26 +187,27 @@ test_hb_draw_glyf (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 3, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 3, funcs, &user_data));
char expected[] = "M275,442L275,442Q232,442 198,420Q164,397 145,353Q126,309 126,245L126,245" char expected[] = "M275,442Q232,442 198,420Q164,397 145,353Q126,309 126,245"
"Q126,182 147,139Q167,95 204,73Q240,50 287,50L287,50Q330,50 367,70" "Q126,182 147,139Q167,95 204,73Q240,50 287,50Q330,50 367,70"
"Q404,90 427,128L427,128L451,116Q431,54 384,21Q336,-13 266,-13L266,-13Q198,-13 148,18" "Q404,90 427,128L451,116Q431,54 384,21Q336,-13 266,-13"
"Q97,48 70,104Q43,160 43,236L43,236Q43,314 76,371Q108,427 160,457Q212,487 272,487L272,487" "Q198,-13 148,18Q97,48 70,104Q43,160 43,236Q43,314 76,371"
"Q316,487 354,470Q392,453 417,424Q442,395 448,358L448,358Q441,321 403,321L403,321" "Q108,427 160,457Q212,487 272,487Q316,487 354,470Q392,453 417,424"
"Q378,321 367,334Q355,347 350,366L350,366L325,454L371,417Q346,430 321,436Q296,442 275,442Z"; "Q442,395 448,358Q441,321 403,321Q378,321 367,334"
"Q355,347 350,366L325,454L371,417Q346,430 321,436Q296,442 275,442Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
/* Test translating quadratic calls to cubic by a _draw_funcs_t that doesn't set the callback */ /* Test translating quadratic calls to cubic by a _draw_funcs_t that doesn't set the callback */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 3, funcs2, &user_data)); g_assert (hb_font_draw_glyph (font, 3, funcs2, &user_data));
char expected2[] = "M275,442L275,442C246,442 221,435 198,420C175,405 158,382 145,353C132,324 126,288 126,245" char expected2[] = "M275,442C246,442 221,435 198,420C175,405 158,382 145,353"
"L126,245C126,203 133,168 147,139C160,110 179,88 204,73C228,58 256,50 287,50L287,50" "C132,324 126,288 126,245C126,203 133,168 147,139C160,110 179,88 204,73"
"C316,50 342,57 367,70C392,83 412,103 427,128L427,128L451,116C438,75 415,43 384,21" "C228,58 256,50 287,50C316,50 342,57 367,70C392,83 412,103 427,128"
"C352,-2 313,-13 266,-13L266,-13C221,-13 181,-3 148,18C114,38 88,67 70,104" "L451,116C438,75 415,43 384,21C352,-2 313,-13 266,-13C221,-13 181,-3 148,18"
"C52,141 43,185 43,236L43,236C43,288 54,333 76,371C97,408 125,437 160,457" "C114,38 88,67 70,104C52,141 43,185 43,236C43,288 54,333 76,371"
"C195,477 232,487 272,487L272,487C301,487 329,481 354,470C379,459 400,443 417,424" "C97,408 125,437 160,457C195,477 232,487 272,487C301,487 329,481 354,470"
"C434,405 444,383 448,358L448,358C443,333 428,321 403,321L403,321" "C379,459 400,443 417,424C434,405 444,383 448,358C443,333 428,321 403,321"
"C386,321 374,325 367,334C359,343 353,353 350,366L350,366L325,454" "C386,321 374,325 367,334C359,343 353,353 350,366L325,454L371,417"
"L371,417C354,426 338,432 321,436C304,440 289,442 275,442Z"; "C354,426 338,432 321,436C304,440 289,442 275,442Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
hb_variation_t var; hb_variation_t var;
@ -216,12 +217,13 @@ test_hb_draw_glyf (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 3, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 3, funcs, &user_data));
char expected3[] = "M323,448L323,448Q297,448 271,430Q244,412 227,371" char expected3[] = "M323,448Q297,448 271,430Q244,412 227,371Q209,330 209,261"
"Q209,330 209,261L209,261Q209,204 226,166Q242,127 273,107Q303,86 344,86L344,86Q378,86 404,101" "Q209,204 226,166Q242,127 273,107Q303,86 344,86Q378,86 404,101"
"Q430,115 451,137L451,137L488,103Q458,42 404,13Q350,-16 279,-16L279,-16Q211,-16 153,13Q95,41 60,99" "Q430,115 451,137L488,103Q458,42 404,13Q350,-16 279,-16"
"Q25,156 25,241L25,241Q25,323 62,382Q99,440 163,471Q226,501 303,501L303,501Q357,501 399,481" "Q211,-16 153,13Q95,41 60,99Q25,156 25,241Q25,323 62,382"
"Q440,460 464,426Q488,392 492,352L492,352Q475,297 420,297L420,297Q390,297 366,320" "Q99,440 163,471Q226,501 303,501Q357,501 399,481Q440,460 464,426"
"Q342,342 339,401L339,401L333,469L411,427Q387,438 368,443Q348,448 323,448Z"; "Q488,392 492,352Q475,297 420,297Q390,297 366,320Q342,342 339,401"
"L333,469L411,427Q387,438 368,443Q348,448 323,448Z";
g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1); g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -317,7 +319,7 @@ static void
test_hb_draw_ttf_parser_tests (void) test_hb_draw_ttf_parser_tests (void)
{ {
/* https://github.com/RazrFalcon/ttf-parser/blob/337e7d1c/tests/tests.rs#L50-L133 */ /* https://github.com/RazrFalcon/ttf-parser/blob/337e7d1c/tests/tests.rs#L50-L133 */
char str[1024] = {0}; char str[1024];
user_data_t user_data = { user_data_t user_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
@ -327,28 +329,27 @@ test_hb_draw_ttf_parser_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
{ {
/* We aren't identical on paths points for glyf with ttf-parser but visually, investigate */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 0, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 0, funcs, &user_data));
char expected[] = "M450,0L50,0L50,750L450,750L450,0Z"; char expected[] = "M50,0L50,750L450,750L450,0L50,0Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 1, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 1, funcs, &user_data));
char expected[] = "M514,416L56,416L56,487L514,487L514,416ZM514,217L56,217L56,288L514,288L514,217Z"; char expected[] = "M56,416L56,487L514,487L514,416L56,416ZM56,217L56,288L514,288L514,217L56,217Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 4, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 4, funcs, &user_data));
char expected[] = "M332,536L332,468L197,468L197,0L109,0L109,468L15,468L15,509L109,539L109,570" char expected[] = "M332,468L197,468L197,0L109,0L109,468L15,468L15,509L109,539"
"Q109,674 155,720Q201,765 283,765L283,765Q315,765 342,760Q368,754 387,747" "L109,570Q109,674 155,720Q201,765 283,765Q315,765 342,760"
"L387,747L364,678Q348,683 327,688Q306,693 284,693L284,693Q240,693 219,664" "Q368,754 387,747L364,678Q348,683 327,688Q306,693 284,693"
"Q197,634 197,571L197,571L197,536L332,536ZM474,737L474,737Q494,737 510,724" "Q240,693 219,664Q197,634 197,571L197,536L332,536L332,468Z"
"Q525,710 525,681L525,681Q525,653 510,639Q494,625 474,625L474,625" "M474,737Q494,737 510,724Q525,710 525,681Q525,653 510,639"
"Q452,625 437,639Q422,653 422,681L422,681Q422,710 437,724Q452,737 474,737Z" "Q494,625 474,625Q452,625 437,639Q422,653 422,681"
"M429,536L517,536L517,0L429,0L429,536Z"; "Q422,710 437,724Q452,737 474,737ZM517,536L517,0L429,0L429,536L517,536Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
@ -360,11 +361,10 @@ test_hb_draw_ttf_parser_tests (void)
{ {
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data));
char expected[] = "M346,536L346,468L211,468L211,0L123,0L123,468L29,468" char expected[] = "M346,468L211,468L211,0L123,0L123,468L29,468L29,509L123,539"
"L29,509L123,539L123,570Q123,674 169,720Q215,765 297,765" "L123,570Q123,674 169,720Q215,765 297,765Q329,765 356,760"
"L297,765Q329,765 356,760Q382,754 401,747L401,747L378,678" "Q382,754 401,747L378,678Q362,683 341,688Q320,693 298,693"
"Q362,683 341,688Q320,693 298,693L298,693Q254,693 233,664" "Q254,693 233,664Q211,634 211,571L211,536L346,536L346,468Z";
"Q211,634 211,571L211,571L211,536L346,536Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
} }
@ -420,27 +420,25 @@ test_hb_draw_font_kit_glyphs_tests (void)
/* should get a path for the glyph */ /* should get a path for the glyph */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 37, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 37, funcs, &user_data));
char expected[] = "M201,0L201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100" char expected[] = "M201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100"
"L1165,1100Q1165,970 1093,886Q1020,801 881,776L881,776L881,766" "Q1165,970 1093,886Q1020,801 881,776L881,766Q1214,709 1214,416"
"Q1214,709 1214,416L1214,416Q1214,220 1082,110Q949,0 711,0L711,0L201,0Z" "Q1214,220 1082,110Q949,0 711,0L201,0L201,1462ZM371,836L651,836"
"M371,1315L371,836L651,836Q831,836 910,893Q989,949 989,1083L989,1083" "Q831,836 910,893Q989,949 989,1083Q989,1206 901,1261"
"Q989,1206 901,1261Q813,1315 621,1315L621,1315L371,1315ZM662,692L371,692" "Q813,1315 621,1315L371,1315L371,836ZM371,692L371,145L676,145"
"L371,145L676,145Q853,145 943,214Q1032,282 1032,428L1032,428" "Q853,145 943,214Q1032,282 1032,428Q1032,564 941,628Q849,692 662,692L371,692Z";
"Q1032,564 941,628Q849,692 662,692L662,692Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
/* should get a path for the glyph */ /* should get a path for the glyph */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 171, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 171, funcs, &user_data));
char expected2[] = "M639,-20L639,-20Q396,-20 256,128Q115,276 115,539L115,539" char expected2[] = "M639,-20Q396,-20 256,128Q115,276 115,539Q115,804 246,960"
"Q115,804 246,960Q376,1116 596,1116L596,1116Q802,1116 922,981" "Q376,1116 596,1116Q802,1116 922,981Q1042,845 1042,623"
"Q1042,845 1042,623L1042,623L1042,518L287,518Q292,325 385,225" "L1042,518L287,518Q292,325 385,225Q477,125 645,125"
"Q477,125 645,125L645,125Q822,125 995,199L995,199L995,51" "Q822,125 995,199L995,51Q907,13 829,-4Q750,-20 639,-20Z"
"Q907,13 829,-4Q750,-20 639,-20ZM594,977L594,977" "M594,977Q462,977 384,891Q305,805 291,653L864,653"
"Q462,977 384,891Q305,805 291,653L291,653L864,653" "Q864,810 794,894Q724,977 594,977ZM471,1266Q519,1328 575,1416"
"Q864,810 794,894Q724,977 594,977ZM471,1241L471,1266" "Q630,1504 662,1569L864,1569L864,1548Q820,1483 733,1388"
"Q519,1328 575,1416Q630,1504 662,1569L662,1569L864,1569" "Q646,1293 582,1241L471,1241L471,1266Z";
"L864,1548Q820,1483 733,1388Q646,1293 582,1241L582,1241L471,1241Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -461,27 +459,27 @@ test_hb_draw_font_kit_glyphs_tests (void)
/* should resolve composite glyphs recursively */ /* should resolve composite glyphs recursively */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
char expected[] = "M581,170L581,274L443,274Q409,274 384,259Q359,243 348,219" char expected[] = "M581,274L443,274Q409,274 384,259Q359,243 348,219Q336,194 340,166"
"Q336,194 340,166Q343,138 365,111L365,111L468,-13Q470,-10 473,-7" "Q343,138 365,111L468,-13Q470,-10 473,-7Q475,-3 477,0L253,0"
"Q475,-3 477,0L477,0L253,0Q225,0 203,8Q180,15 168,32Q155,48 155,73" "Q225,0 203,8Q180,15 168,32Q155,48 155,73L155,269L50,269L50,73"
"L155,73L155,269L50,269L50,73Q50,24 69,-10Q88,-44 118,-65" "Q50,24 69,-10Q88,-44 118,-65Q147,-85 181,-95Q214,-104 243,-104"
"Q147,-85 181,-95Q214,-104 243,-104L243,-104L473,-104" "L473,-104Q501,-104 525,-91Q549,-78 564,-56Q578,-34 578,-8"
"Q501,-104 525,-91Q549,-78 564,-56Q578,-34 578,-8Q578,18 557,43" "Q578,18 557,43L442,182Q439,179 437,176Q435,173 432,170"
"L557,43L442,182Q439,179 437,176Q435,173 432,170L432,170L581,170Z" "L581,170L581,274ZM184,-194Q184,-216 199,-231Q214,-246 236,-246"
"M184,-194L184,-194Q184,-216 199,-231Q214,-246 236,-246L236,-246" "Q258,-246 273,-231Q288,-216 288,-194Q288,-172 273,-157"
"Q258,-246 273,-231Q288,-216 288,-194L288,-194Q288,-172 273,-157" "Q258,-142 236,-142Q214,-142 199,-157Q184,-172 184,-194Z"
"Q258,-142 236,-142L236,-142Q214,-142 199,-157Q184,-172 184,-194Z" "M360,-194Q360,-216 375,-231Q390,-246 412,-246"
"M360,-194L360,-194Q360,-216 375,-231Q390,-246 412,-246L412,-246" "Q434,-246 449,-231Q464,-216 464,-194Q464,-172 449,-157"
"Q434,-246 449,-231Q464,-216 464,-194L464,-194Q464,-172 449,-157" "Q434,-142 412,-142Q390,-142 375,-157Q360,-172 360,-194Z";
"Q434,-142 412,-142L412,-142Q390,-142 375,-157Q360,-172 360,-194Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
/* should transform points of a composite glyph */ /* should transform points of a composite glyph */
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 2, funcs, &user_data)); /* 2 == arAlef.fina */ g_assert (hb_font_draw_glyph (font, 2, funcs, &user_data)); /* 2 == arAlef.fina */
char expected2[] = "M50,624L155,624L155,84Q150,90 146,95Q141,99 136,105L136,105" char expected2[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105"
"L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51Q50,74 50,104" "L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51"
"L50,104L50,624ZM282,0L282,105L312,105L312,0L282,0Z"; "Q50,74 50,104L50,624L155,624ZM282,105L312,105"
"L312,0L282,0L282,105Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -554,27 +552,25 @@ test_hb_draw_font_kit_variations_tests (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
char expected[] = "M414,-102L371,-102L371,539L914,539L914,-27Q914,-102 840,-102L840,-102Q796,-102 755,-98" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
"L755,-98L742,-59Q790,-66 836,-66L836,-66Q871,-66 871,-31L871,-31L871,504L414,504L414,-102Z" "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
"M203,-94L203,-94Q138,-94 86,-90L86,-90L74,-52Q137,-59 188,-59L188,-59Q211,-59 222,-47" "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-47"
"Q233,-34 236,12Q238,58 240,135Q242,211 242,262L242,262L74,262L94,527L242,527L242,719" "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527"
"L63,719L63,754L285,754L285,492L133,492L117,297L285,297Q285,241 284,185L284,185" "L242,719L63,719L63,754L285,754L285,492L133,492L117,297L285,297"
"Q284,104 281,46L281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94ZM461,12L461,12" "Q285,241 284,185Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86"
"L434,43Q473,73 503,115L503,115Q478,150 441,188L441,188L469,211Q501,179 525,147" "Q223,-94 203,-94ZM461,12L434,43Q473,73 503,115Q478,150 441,188L469,211"
"L525,147Q538,172 559,230L559,230L594,211Q571,152 551,117L551,117Q577,84 602,43L602,43" "Q501,179 525,147Q538,172 559,230L594,211Q571,152 551,117Q577,84 602,43"
"L566,20Q544,64 528,86L528,86Q500,44 461,12ZM465,258L465,258L438,285Q474,316 501,351L501,351" "L566,20Q544,64 528,86Q500,44 461,12ZM465,258L438,285Q474,316 501,351"
"Q474,388 445,418L445,418L473,441Q500,414 523,381L523,381Q546,413 563,453L563,453" "Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453L598,434"
"L598,434Q571,382 549,352L549,352Q576,320 598,285L598,285L563,262Q546,294 525,322" "Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322Q491,280 465,258Z"
"L525,322Q491,280 465,258ZM707,12L707,12L680,43Q717,68 753,115L753,115Q731,147 691,188" "M707,12L680,43Q717,68 753,115Q731,147 691,188L719,211Q739,190 754,172"
"L691,188L719,211Q739,190 754,172Q769,154 774,147L774,147Q793,185 809,230L809,230" "Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117Q828,82 852,43"
"L844,211Q822,155 801,117L801,117Q828,82 852,43L852,43L820,20Q798,58 778,87" "L820,20Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730L664,-94"
"L778,87Q747,43 707,12ZM664,-94L621,-94L621,730L664,730L664,-94ZM348,570L348,570" "L621,-94ZM348,570L324,605Q425,629 527,688L555,656Q491,621 439,601"
"L324,605Q425,629 527,688L527,688L555,656Q491,621 439,601Q386,581 348,570ZM715,258" "Q386,581 348,570ZM715,258L688,285Q727,318 753,351Q733,378 695,418L723,441"
"L715,258L688,285Q727,318 753,351L753,351Q733,378 695,418L695,418L723,441Q754,410 775,381" "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
"L775,381Q794,407 813,453L813,453L848,434Q826,387 801,352L801,352Q823,321 848,281" "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
"L848,281L813,262Q791,301 775,323L775,323Q749,288 715,258ZM941,719L348,719L348,754" "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
"L941,754L941,719ZM957,605L936,570Q870,602 817,622Q764,641 727,652L727,652L749,688"
"Q852,655 957,605L957,605Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -600,27 +596,25 @@ test_hb_draw_font_kit_variations_tests (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
char expected[] = "M414,-102L371,-102L371,539L914,539L914,-27Q914,-102 840,-102L840,-102Q796,-102 755,-98" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
"L755,-98L742,-59Q790,-66 836,-66L836,-66Q871,-66 871,-31L871,-31L871,504L414,504" "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
"L414,-102ZM203,-94L203,-94Q138,-94 86,-90L86,-90L74,-52Q137,-59 188,-59L188,-59" "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-47"
"Q211,-59 222,-47Q233,-34 236,12Q238,58 240,135Q242,211 242,262L242,262L74,262" "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527"
"L94,527L242,527L242,719L63,719L63,754L285,754L285,492L133,492L117,297" "L242,719L63,719L63,754L285,754L285,492L133,492L117,297L285,297"
"L285,297Q285,241 284,185L284,185Q284,104 281,46L281,46Q278,-20 269,-49Q260,-78 242,-86" "Q285,241 284,185Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86"
"Q223,-94 203,-94ZM461,12L461,12L434,43Q473,73 503,115L503,115Q478,150 441,188L441,188" "Q223,-94 203,-94ZM461,12L434,43Q473,73 503,115Q478,150 441,188"
"L469,211Q501,179 525,147L525,147Q538,172 559,230L559,230L594,211Q571,152 551,117" "L469,211Q501,179 525,147Q538,172 559,230L594,211Q571,152 551,117"
"L551,117Q577,84 602,43L602,43L566,20Q544,64 528,86L528,86Q500,44 461,12ZM465,258" "Q577,84 602,43L566,20Q544,64 528,86Q500,44 461,12ZM465,258L438,285"
"L465,258L438,285Q474,316 501,351L501,351Q474,388 445,418L445,418L473,441" "Q474,316 501,351Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453"
"Q500,414 523,381L523,381Q546,413 563,453L563,453L598,434Q571,382 549,352L549,352" "L598,434Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322"
"Q576,320 598,285L598,285L563,262Q546,294 525,322L525,322Q491,280 465,258ZM707,12" "Q491,280 465,258ZM707,12L680,43Q717,68 753,115Q731,147 691,188L719,211"
"L707,12L680,43Q717,68 753,115L753,115Q731,147 691,188L691,188L719,211Q739,190 754,172" "Q739,190 754,172Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117"
"Q769,154 774,147L774,147Q793,185 809,230L809,230L844,211Q822,155 801,117L801,117" "Q828,82 852,43L820,20Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730"
"Q828,82 852,43L852,43L820,20Q798,58 778,87L778,87Q747,43 707,12ZM664,-94L621,-94L621,730" "L664,-94L621,-94ZM348,570L324,605Q425,629 527,688L555,656Q491,621 439,601"
"L664,730L664,-94ZM348,570L348,570L324,605Q425,629 527,688L527,688L555,656Q491,621 439,601" "Q386,581 348,570ZM715,258L688,285Q727,318 753,351Q733,378 695,418L723,441"
"Q386,581 348,570ZM715,258L715,258L688,285Q727,318 753,351L753,351Q733,378 695,418" "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
"L695,418L723,441Q754,410 775,381L775,381Q794,407 813,453L813,453L848,434Q826,387 801,352" "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
"L801,352Q823,321 848,281L848,281L813,262Q791,301 775,323L775,323Q749,288 715,258ZM941,719" "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
"L348,719L348,754L941,754L941,719ZM957,605L936,570Q870,602 817,622Q764,641 727,652L727,652"
"L749,688Q852,655 957,605L957,605Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -646,28 +640,25 @@ test_hb_draw_font_kit_variations_tests (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, codepoint, funcs, &user_data));
char expected[] = "M414,-102L371,-102L371,539L914,539L914,-27Q914,-102 840,-102L840,-102" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
"Q796,-102 755,-98L755,-98L742,-59Q790,-66 836,-66L836,-66Q871,-66 871,-31" "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
"L871,-31L871,504L414,504L414,-102ZM203,-94L203,-94Q138,-94 86,-90" "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-47"
"L86,-90L74,-52Q137,-59 188,-59L188,-59Q211,-59 222,-47Q233,-34 236,12" "Q233,-34 236,12Q238,58 240,135Q242,211 242,262L74,262L94,527L242,527"
"Q238,58 240,135Q242,211 242,262L242,262L74,262L94,527L242,527L242,719" "L242,719L63,719L63,754L285,754L285,492L133,492L117,297L285,297"
"L63,719L63,754L285,754L285,492L133,492L117,297L285,297Q285,241 284,185" "Q285,241 284,185Q284,104 281,46Q278,-20 269,-49Q260,-78 242,-86"
"L284,185Q284,104 281,46L281,46Q278,-20 269,-49Q260,-78 242,-86Q223,-94 203,-94Z" "Q223,-94 203,-94ZM461,12L434,43Q473,73 503,115Q478,150 441,188"
"M461,12L461,12L434,43Q473,73 503,115L503,115Q478,150 441,188L441,188L469,211" "L469,211Q501,179 525,147Q538,172 559,230L594,211Q571,152 551,117"
"Q501,179 525,147L525,147Q538,172 559,230L559,230L594,211Q571,152 551,117L551,117" "Q577,84 602,43L566,20Q544,64 528,86Q500,44 461,12ZM465,258L438,285"
"Q577,84 602,43L602,43L566,20Q544,64 528,86L528,86Q500,44 461,12ZM465,258L465,258L438,285" "Q474,316 501,351Q474,388 445,418L473,441Q500,414 523,381Q546,413 563,453"
"Q474,316 501,351L501,351Q474,388 445,418L445,418L473,441Q500,414 523,381L523,381" "L598,434Q571,382 549,352Q576,320 598,285L563,262Q546,294 525,322"
"Q546,413 563,453L563,453L598,434Q571,382 549,352L549,352Q576,320 598,285L598,285" "Q491,280 465,258ZM707,12L680,43Q717,68 753,115Q731,147 691,188L719,211"
"L563,262Q546,294 525,322L525,322Q491,280 465,258ZM707,12L707,12L680,43Q717,68 753,115" "Q739,190 754,172Q769,154 774,147Q793,185 809,230L844,211Q822,155 801,117"
"L753,115Q731,147 691,188L691,188L719,211Q739,190 754,172Q769,154 774,147L774,147" "Q828,82 852,43L820,20Q798,58 778,87Q747,43 707,12ZM621,-94L621,730L664,730"
"Q793,185 809,230L809,230L844,211Q822,155 801,117L801,117Q828,82 852,43L852,43L820,20" "L664,-94L621,-94ZM348,570L324,605Q425,629 527,688L555,656Q491,621 439,601"
"Q798,58 778,87L778,87Q747,43 707,12ZM664,-94L621,-94L621,730L664,730L664,-94Z" "Q386,581 348,570ZM715,258L688,285Q727,318 753,351Q733,378 695,418L723,441"
"M348,570L348,570L324,605Q425,629 527,688L527,688L555,656Q491,621 439,601" "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
"Q386,581 348,570ZM715,258L715,258L688,285Q727,318 753,351L753,351Q733,378 695,418" "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
"L695,418L723,441Q754,410 775,381L775,381Q794,407 813,453L813,453L848,434" "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
"Q826,387 801,352L801,352Q823,321 848,281L848,281L813,262Q791,301 775,323L775,323"
"Q749,288 715,258ZM941,719L348,719L348,754L941,754L941,719ZM957,605L936,570"
"Q870,602 817,622Q764,641 727,652L727,652L749,688Q852,655 957,605L957,605Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
@ -776,37 +767,35 @@ test_hb_draw_stroking (void)
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data));
char expected[] = "M1626,1522Q1626,1522 1626,1522Q1626,1522 1626,1522ZM531,1985" char expected[] = "M1626,1522Q1626,1522 1626,1522Q1626,1522 1626,1522ZM436,1522"
"Q436,1764 436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427" "Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427Q1384,332 1626,332"
"Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060" "Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522"
"Q2816,1280 2816,1522Q2816,1764 2722,1985Q2627,2205 2468,2364" "Q2816,1764 2722,1985Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
"Q2309,2523 2089,2618Q1868,2712 1626,2712Q1384,2712 1164,2618" "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985Q436,1764 436,1522ZM256,1528"
"Q943,2523 784,2364Q625,2205 531,1985ZM306,1165Q256,1342 256,1528" "Q256,1714 306,1892Q355,2069 443,2220Q531,2370 658,2497Q784,2623 935,2711"
"Q256,1714 306,1892Q355,2069 443,2220Q531,2370 658,2497" "Q1085,2799 1263,2849Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
"Q784,2623 935,2711Q1085,2799 1263,2849Q1440,2898 1626,2898" "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892Q2996,1714 2996,1528"
"Q1812,2898 1990,2849Q2167,2799 2318,2711Q2468,2623 2595,2497" "Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345"
"Q2721,2370 2809,2220Q2897,2069 2947,1892Q2996,1714 2996,1528" "Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
"Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560" "Q784,433 658,560Q531,686 443,837Q355,987 306,1165Q256,1342 256,1528Z";
"Q2468,433 2318,345Q2167,257 1990,208Q1812,158 1626,158"
"Q1440,158 1263,208Q1085,257 935,345Q784,433 658,560"
"Q531,686 443,837Q355,987 306,1165Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1);
user_data.consumed = 0; user_data.consumed = 0;
g_assert (hb_font_draw_glyph (font, 7, funcs, &user_data)); g_assert (hb_font_draw_glyph (font, 7, funcs, &user_data));
char expected2[] = "M531,1985Q436,1764 436,1522Q436,1280 531,1060Q625,839 784,680" char expected2[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427"
"Q943,521 1164,427Q1384,332 1626,332Q1868,332 2089,427" "Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680"
"Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522" "Q2627,839 2722,1060Q2816,1280 2816,1522Q2816,1764 2722,1985"
"Q2816,1764 2722,1985Q2627,2205 2468,2364Q2309,2523 2089,2618" "Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712"
"Q1868,2712 1626,2712Q1384,2712 1164,2618Q943,2523 784,2364" "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985"
"Q625,2205 531,1985ZM306,1165Q256,1342 256,1528Q256,1714 306,1892" "Q436,1764 436,1522ZM256,1528Q256,1714 306,1892Q355,2069 443,2220"
"Q355,2069 443,2220Q531,2370 658,2497Q784,2623 935,2711" "Q531,2370 658,2497Q784,2623 935,2711Q1085,2799 1263,2849"
"Q1085,2799 1263,2849Q1440,2898 1626,2898Q1812,2898 1990,2849" "Q1440,2898 1626,2898Q1812,2898 1990,2849Q2167,2799 2318,2711"
"Q2167,2799 2318,2711Q2468,2623 2595,2497Q2721,2370 2809,2220" "Q2468,2623 2595,2497Q2721,2370 2809,2220Q2897,2069 2947,1892"
"Q2897,2069 2947,1892Q2996,1714 2996,1528Q2996,1342 2947,1165" "Q2996,1714 2996,1528Q2996,1342 2947,1165Q2897,987 2809,837"
"Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345" "Q2721,686 2595,560Q2468,433 2318,345Q2167,257 1990,208"
"Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208" "Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
"Q1085,257 935,345Q784,433 658,560Q531,686 443,837Q355,987 306,1165Z"; "Q784,433 658,560Q531,686 443,837Q355,987 306,1165"
"Q256,1342 256,1528Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);