diff --git a/src/hb-ot-glyph.cc b/src/hb-ot-glyph.cc index 38bdf3105..77b3a137c 100644 --- a/src/hb-ot-glyph.cc +++ b/src/hb-ot-glyph.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Ebrahim Byagowi + * Copyright © 2019-2020 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -31,133 +31,15 @@ #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" -struct hb_ot_glyph_path_t +hb_bool_t +hb_ot_glyph_decompose (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, + void *user_data) { - hb_object_header_t header; + if (unlikely (!funcs || glyph >= font->face->get_num_glyphs ())) return false; - const hb_position_t *coords; - unsigned int coords_count; - - const uint8_t *commands; - unsigned int commands_count; - - void *user_data; - hb_destroy_func_t destroy; -}; - -hb_ot_glyph_path_t * -hb_ot_glyph_path_empty () -{ - return const_cast (&Null (hb_ot_glyph_path_t)); -} - -hb_ot_glyph_path_t * -hb_ot_glyph_path_create (hb_position_t *coords, - unsigned int coords_count, - uint8_t *commands, - unsigned int commands_count, - void *user_data, - hb_destroy_func_t destroy) -{ - hb_ot_glyph_path_t *path; - - if (!coords_count || !commands_count || - !(path = hb_object_create ())) - { - if (destroy) - destroy (user_data); - return hb_ot_glyph_path_empty (); - } - - path->coords = coords; - path->coords_count = coords_count; - path->commands = commands; - path->commands_count = commands_count; - path->user_data = user_data; - path->destroy = destroy; - - return path; -} - -const hb_position_t * -hb_ot_glyph_path_get_coords (hb_ot_glyph_path_t *path, unsigned int *count) -{ - if (count) *count = path->coords_count; - return path->coords; -} - -const uint8_t * -hb_ot_glyph_path_get_commands (hb_ot_glyph_path_t *path, unsigned int *count) -{ - if (count) *count = path->commands_count; - return path->commands; -} - -hb_ot_glyph_path_t * -hb_ot_glyph_path_reference (hb_ot_glyph_path_t *path) -{ - return hb_object_reference (path); -} - -void -hb_ot_glyph_path_destroy (hb_ot_glyph_path_t *path) -{ - if (!hb_object_destroy (path)) return; - - if (path->destroy) path->destroy (path->user_data); - - free (path); -} - -struct _hb_ot_glyph_path_vectors -{ - hb_vector_t *coords; - hb_vector_t *commands; - - bool init () - { - coords = (hb_vector_t *) malloc (sizeof (hb_vector_t)); - commands = (hb_vector_t *) malloc (sizeof (hb_vector_t)); - if (unlikely (!coords || !commands)) - { - free (coords); - free (commands); - return false; - } - coords->init (); - commands->init (); - return true; - } - - void fini () - { - coords->fini (); - commands->fini (); - free (coords); - free (commands); - } -}; - -static void -_hb_ot_glyph_path_free_vectors (void *user_data) -{ - ((_hb_ot_glyph_path_vectors *) user_data)->fini (); - free (user_data); -} - -hb_ot_glyph_path_t * -hb_ot_glyph_path_create_from_font (hb_font_t *font, hb_codepoint_t glyph) -{ - _hb_ot_glyph_path_vectors *user_data = (_hb_ot_glyph_path_vectors *) - malloc (sizeof (_hb_ot_glyph_path_vectors)); - if (unlikely (!user_data || !user_data->init () || glyph >= font->face->get_num_glyphs ())) - { - free (user_data); - return hb_ot_glyph_path_empty (); - } - - hb_vector_t &coords = *user_data->coords; - hb_vector_t &commands = *user_data->commands; + hb_vector_t coords; + hb_vector_t commands; bool ret = false; @@ -167,17 +49,41 @@ hb_ot_glyph_path_create_from_font (hb_font_t *font, hb_codepoint_t glyph) if (!ret) ret = font->face->table.cff2->get_path (font, glyph, &coords, &commands); #endif - assert (coords.length % 2 == 0); /* coords pairs, should be an even number */ + if (unlikely (!ret || coords.length % 2 != 0)) return false; - if (unlikely (!ret)) - { - user_data->fini (); - free (user_data); - return hb_ot_glyph_path_empty (); - } + /* FIXME: We should do all these memory O(1) without hb_vector_t + by moving the logic to the tables */ + unsigned int coords_idx = 0; + for (unsigned int i = 0; i < commands.length; ++i) + switch (commands[i]) + { + case 'Z': break; + case 'M': + if (unlikely (coords.length < coords_idx + 2)) return false; + funcs->move_to (coords[coords_idx + 0], coords[coords_idx + 1], user_data); + coords_idx += 2; + break; + case 'L': + if (unlikely (coords.length < coords_idx + 2)) return false; + funcs->line_to (coords[coords_idx + 0], coords[coords_idx + 1], user_data); + coords_idx += 2; + break; + case 'Q': + if (unlikely (coords.length < coords_idx + 4)) return false; + funcs->conic_to (coords[coords_idx + 0], coords[coords_idx + 1], + coords[coords_idx + 2], coords[coords_idx + 3], user_data); + coords_idx += 4; + break; + case 'C': + if (unlikely (coords.length >= coords_idx + 6)) return false; + funcs->cubic_to (coords[coords_idx + 0], coords[coords_idx + 1], + coords[coords_idx + 2], coords[coords_idx + 3], + coords[coords_idx + 4], coords[coords_idx + 5], user_data); + coords_idx += 6; + break; + } - return hb_ot_glyph_path_create (coords.arrayZ, coords.length, commands.arrayZ, commands.length, - user_data, (hb_destroy_func_t) _hb_ot_glyph_path_free_vectors); + return true; } #endif diff --git a/src/hb-ot-glyph.h b/src/hb-ot-glyph.h index 2e38c76d2..9c2cb9bc8 100644 --- a/src/hb-ot-glyph.h +++ b/src/hb-ot-glyph.h @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Ebrahim Byagowi + * Copyright © 2019-2020 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -33,34 +33,39 @@ HB_BEGIN_DECLS -typedef struct hb_ot_glyph_path_t hb_ot_glyph_path_t; +typedef void (*hb_ot_glyph_decompose_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); +typedef void (*hb_ot_glyph_decompose_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); +typedef void (*hb_ot_glyph_decompose_conic_to_func_t) (hb_position_t control_x, hb_position_t control_y, + hb_position_t to_x, hb_position_t to_y, + void *user_data); +typedef void (*hb_ot_glyph_decompose_cubic_to_func_t) (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, + void *user_data); -HB_EXTERN hb_ot_glyph_path_t * -hb_ot_glyph_path_create (hb_position_t *coords, - unsigned int coords_count, - uint8_t *commands, - unsigned int commands_count, - void *user_data, - hb_destroy_func_t destroy); - -HB_EXTERN hb_ot_glyph_path_t * -hb_ot_glyph_path_create_from_font (hb_font_t *font, hb_codepoint_t glyph); - -HB_EXTERN void -hb_ot_glyph_path_destroy (hb_ot_glyph_path_t *path); - -HB_EXTERN hb_ot_glyph_path_t * -hb_ot_glyph_path_empty (void); - -HB_EXTERN const uint8_t * -hb_ot_glyph_path_get_commands (hb_ot_glyph_path_t *path, unsigned int *count); - -HB_EXTERN const hb_position_t * -hb_ot_glyph_path_get_coords (hb_ot_glyph_path_t *path, unsigned int *count); - -HB_EXTERN hb_ot_glyph_path_t * -hb_ot_glyph_path_reference (hb_ot_glyph_path_t *path); +/** + * hb_ot_glyph_decompose_funcs_t: + * + * Glyph decompose callbacks. + * + * Since: REPLACEME + **/ +typedef struct hb_ot_glyph_decompose_funcs_t +{ + hb_ot_glyph_decompose_move_to_func_t move_to; + hb_ot_glyph_decompose_line_to_func_t line_to; + hb_ot_glyph_decompose_conic_to_func_t conic_to; + hb_ot_glyph_decompose_cubic_to_func_t cubic_to; + /*< private >*/ + void *reserved4; + void *reserved3; + void *reserved2; + void *reserved1; +} hb_ot_glyph_decompose_funcs_t; +hb_bool_t +hb_ot_glyph_decompose (hb_font_t *font, hb_codepoint_t glyph, + hb_ot_glyph_decompose_funcs_t *funcs, void *user_data); HB_END_DECLS diff --git a/src/test-ot-glyph.cc b/src/test-ot-glyph.cc index 8722f3dc1..a735e6a07 100644 --- a/src/test-ot-glyph.cc +++ b/src/test-ot-glyph.cc @@ -32,6 +32,48 @@ #include #include +struct user_data_t +{ + FILE *f; + hb_position_t ascender; +}; + +static void +move_to (hb_position_t to_x, hb_position_t to_y, void *user_data) +{ + user_data_t u = *((user_data_t *) user_data); + fprintf (u.f, "M%d,%d", to_x, u.ascender - to_y); +} + +static void +line_to (hb_position_t to_x, hb_position_t to_y, void *user_data) +{ + user_data_t u = *((user_data_t *) user_data); + fprintf (u.f, "L%d,%d", to_x, u.ascender - to_y); +} + +static void +conic_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 u = *((user_data_t *) user_data); + fprintf (u.f, "Q%d,%d %d,%d", control_x, u.ascender - control_y, + to_x, u.ascender - to_y); +} + +static void +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, + void *user_data) +{ + user_data_t u = *((user_data_t *) user_data); + fprintf (u.f, "C%d,%d %d,%d %d,%d", control1_x, u.ascender - control1_y, + control2_x, u.ascender - control2_y, + to_x, u.ascender - to_y); +} + int main (int argc, char **argv) { @@ -49,6 +91,12 @@ main (int argc, char **argv) exit (1); } + hb_ot_glyph_decompose_funcs_t funcs; + funcs.move_to = (hb_ot_glyph_decompose_move_to_func_t) move_to; + funcs.line_to = (hb_ot_glyph_decompose_line_to_func_t) line_to; + funcs.conic_to = (hb_ot_glyph_decompose_conic_to_func_t) conic_to; + funcs.cubic_to = (hb_ot_glyph_decompose_cubic_to_func_t) cubic_to; + for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++) { hb_face_t *face = hb_face_create (blob, face_index); @@ -67,38 +115,13 @@ main (int argc, char **argv) " viewBox=\"%d %d %d %d\">= j + 2); - fprintf (f, "%d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y); - j += 2; - if (commands[i] == 'Q') - { - assert (coords_count >= j + 2); - fprintf (f, " %d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y); - j += 2; - } - if (commands[i] == 'C') - { - assert (coords_count >= j + 4); - fprintf (f, " %d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y); - j += 2; - fprintf (f, " %d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y); - j += 2; - } - } - assert (coords_count == j); + user_data_t user_data; + user_data.ascender = font_extents.ascender; + user_data.f = f; + if (!hb_ot_glyph_decompose (font, gid, &funcs, &user_data)) + printf ("Failed to decompose gid: %d\n", gid); fprintf (f, "\"/>"); fclose (f); - hb_ot_glyph_path_destroy (path); } hb_font_destroy (font); hb_face_destroy (face);