diff --git a/src/hb-ot-glyph.cc b/src/hb-ot-glyph.cc index 2b5beaadd..b63a64990 100644 --- a/src/hb-ot-glyph.cc +++ b/src/hb-ot-glyph.cc @@ -29,29 +29,134 @@ #include "hb-ot.h" #include "hb-ot-glyf-table.hh" -unsigned int -hb_ot_glyph_get_outline_path (hb_font_t *font, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *points_count /* IN/OUT. May be NULL. */, - hb_ot_glyph_path_point_t *points /* OUT. May be NULL. */) +struct hb_ot_glyph_path_t { - unsigned int points_to_write = likely (points && points_count) ? *points_count : 0; - if (likely (points_count)) *points_count = 0; - unsigned int all_points_count = 0; + hb_object_header_t header; + + 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_create_path (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; +} + +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 (); + } +}; + +static void +_hb_ot_glyph_free_path_vectors (void *user_data) +{ + ((_hb_ot_glyph_path_vectors *) user_data)->fini (); + free (user_data); +} + +hb_ot_glyph_path_t * +hb_ot_glyph_create_path_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->init ())) return hb_ot_glyph_path_empty (); + + hb_vector_t &coords = *user_data->coords; + hb_vector_t &commands = *user_data->commands; font->face->table.glyf->get_path (font, glyph, [&] (char cmd, float x, float y) { - all_points_count++; - if (start_offset) { start_offset--; return; } - if (points_to_write) - { - points[*points_count] = {cmd, font->em_scalef_x (x), font->em_scalef_y (y)}; - *points_count += 1; - points_to_write--; - } + if (cmd != ' ') commands.push (cmd); + if (cmd == 'Z') return; + coords.push (font->em_scalef_x (x)); + coords.push (font->em_scalef_y (y)); }); - return all_points_count; + + return hb_ot_glyph_create_path (coords.arrayZ, coords.length, commands.arrayZ, commands.length, + user_data, (hb_destroy_func_t) _hb_ot_glyph_free_path_vectors); } #endif diff --git a/src/hb-ot-glyph.h b/src/hb-ot-glyph.h index 22d983dca..72b59e456 100644 --- a/src/hb-ot-glyph.h +++ b/src/hb-ot-glyph.h @@ -33,19 +33,33 @@ HB_BEGIN_DECLS -typedef struct hb_ot_glyph_path_point_t -{ - char cmd; - hb_position_t x; - hb_position_t y; -} hb_ot_glyph_path_point_t; +typedef struct hb_ot_glyph_path_t hb_ot_glyph_path_t; -HB_EXTERN unsigned int -hb_ot_glyph_get_outline_path (hb_font_t *font, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *points_count /* IN/OUT. May be NULL. */, - hb_ot_glyph_path_point_t *points /* OUT. May be NULL. */); +HB_EXTERN hb_ot_glyph_path_t * +hb_ot_glyph_path_empty (); + +HB_EXTERN hb_ot_glyph_path_t * +hb_ot_glyph_create_path (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 const hb_position_t * +hb_ot_glyph_path_get_coords (hb_ot_glyph_path_t *path, unsigned int *count); + +HB_EXTERN const uint8_t * +hb_ot_glyph_path_get_commands (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_EXTERN void +hb_ot_glyph_path_destroy (hb_ot_glyph_path_t *path); + +HB_EXTERN hb_ot_glyph_path_t * +hb_ot_glyph_create_path_from_font (hb_font_t *font, hb_codepoint_t glyph); HB_END_DECLS diff --git a/src/test-ot-glyph.cc b/src/test-ot-glyph.cc index a9b752c36..a241c39f7 100644 --- a/src/test-ot-glyph.cc +++ b/src/test-ot-glyph.cc @@ -55,26 +55,44 @@ main (int argc, char **argv) unsigned int glyph_count = hb_face_get_glyph_count (face); for (unsigned int gid = 0; gid < glyph_count; ++gid) { - hb_ot_glyph_path_point_t points[200]; - unsigned int points_len = 200; - hb_ot_glyph_get_outline_path (font, gid, 0, nullptr, nullptr); /* just to test it */ - printf ("gid %d, points count: %d\n", gid, hb_ot_glyph_get_outline_path (font, gid, 0, &points_len, points)); + hb_font_extents_t font_extents; + hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); hb_glyph_extents_t extents = {0}; hb_font_get_glyph_extents (font, gid, &extents); char name[100]; sprintf (name, "%d.svg", gid); FILE *f = fopen (name, "wb"); - int factor = 1; - if (extents.height < 0) factor = -1; fprintf (f, ""); fclose (f); + hb_ot_glyph_path_destroy (path); } hb_font_destroy (font); hb_face_destroy (face);