diff --git a/src/hb-draw.hh b/src/hb-draw.hh index 03b518ed6..f0655b7fd 100644 --- a/src/hb-draw.hh +++ b/src/hb-draw.hh @@ -59,6 +59,7 @@ struct draw_helper_t void line_to (hb_position_t x, hb_position_t y) { + if (equal_to_current (x, y)) return; if (!path_open) start_path (); funcs->line_to (x, y, user_data); current_x = x; @@ -69,6 +70,8 @@ struct draw_helper_t quadratic_to (hb_position_t control_x, hb_position_t control_y, hb_position_t to_x, hb_position_t to_y) { + if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y)) + return; if (!path_open) start_path (); if (funcs->is_quadratic_to_set) funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data); @@ -83,14 +86,18 @@ struct draw_helper_t } void - cubic_to (hb_position_t x1, hb_position_t y1, - hb_position_t x2, hb_position_t y2, - hb_position_t x3, hb_position_t y3) + cubic_to (hb_position_t control1_x, hb_position_t control1_y, + hb_position_t control2_x, hb_position_t control2_y, + hb_position_t to_x, hb_position_t to_y) { + if (equal_to_current (control1_x, control1_y) && + equal_to_current (control2_x, control2_y) && + equal_to_current (to_x, to_y)) + return; if (!path_open) start_path (); - funcs->cubic_to (x1, y1, x2, y2, x3, y3, user_data); - current_x = x3; - current_y = y3; + funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data); + current_x = to_x; + current_y = to_y; } void end_path () @@ -106,6 +113,9 @@ struct draw_helper_t } protected: + bool equal_to_current (hb_position_t x, hb_position_t y) + { return current_x == x && current_y == y; } + void start_path () { if (path_open) end_path (); diff --git a/test/api/test-draw.c b/test/api/test-draw.c index 903fd8aeb..df6c27658 100644 --- a/test/api/test-draw.c +++ b/test/api/test-draw.c @@ -769,8 +769,8 @@ test_hb_draw_stroking (void) user_data.consumed = 0; g_assert (hb_font_draw_glyph (font, 6, funcs, &user_data)); - char expected[] = "M1626,1522Q1626,1522 1626,1522Q1626,1522 1626,1522ZM436,1522" - "Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427Q1384,332 1626,332" + /* Skip empty path where all the points of a path are equal */ + char expected[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427Q1384,332 1626,332" "Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522" "Q2816,1764 2722,1985Q2627,2205 2468,2364Q2309,2523 2089,2618Q1868,2712 1626,2712" "Q1384,2712 1164,2618Q943,2523 784,2364Q625,2205 531,1985Q436,1764 436,1522ZM256,1528" @@ -810,8 +810,8 @@ test_hb_draw_stroking (void) user_data.consumed = 0; g_assert (hb_font_draw_glyph (font, 4, funcs, &user_data)); - char expected[] = "M397,372L397,372Z" /* TODO: Do we like to fold this path? */ - "M106,372C106,532 237,662 397,662C557,662 688,532 688,372C688,212 557,81 397,81C237,81 106,212 106,372Z" + /* Skip empty path in CFF */ + char expected[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372C688,212 557,81 397,81C237,81 106,212 106,372Z" "M62,373C62,188 212,39 397,39C582,39 731,188 731,373C731,558 582,708 397,708C212,708 62,558 62,373Z"; g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); diff --git a/test/fuzzing/hb-draw-fuzzer.cc b/test/fuzzing/hb-draw-fuzzer.cc index e35c15e06..25fe66da6 100644 --- a/test/fuzzing/hb-draw-fuzzer.cc +++ b/test/fuzzing/hb-draw-fuzzer.cc @@ -36,17 +36,20 @@ _line_to (hb_position_t to_x, hb_position_t to_y, void *user_data_) { _user_data_t *user_data = (_user_data_t *) user_data_; assert (user_data->is_open); + assert (user_data->path_last_x != to_x || user_data->path_last_y != to_y); ++user_data->path_len; user_data->path_last_x = to_x; user_data->path_last_y = to_y; } static void -_quadratic_to (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED, +_quadratic_to (hb_position_t control_x, hb_position_t control_y, hb_position_t to_x, hb_position_t to_y, void *user_data_) { _user_data_t *user_data = (_user_data_t *) user_data_; assert (user_data->is_open); + assert (user_data->path_last_x != control_x || user_data->path_last_y != control_y || + user_data->path_last_x != to_x || user_data->path_last_y != to_y); ++user_data->path_len; user_data->path_last_x = to_x; user_data->path_last_y = to_y; @@ -59,6 +62,9 @@ _cubic_to (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSE { _user_data_t *user_data = (_user_data_t *) user_data_; assert (user_data->is_open); + assert (user_data->path_last_x != control1_x || user_data->path_last_y != control1_y || + user_data->path_last_x != control2_x || user_data->path_last_y != control2_y || + user_data->path_last_x != to_x || user_data->path_last_y != to_y); ++user_data->path_len; user_data->path_last_x = to_x; user_data->path_last_y = to_y;