[ot-glyph] Redesign the API
This commit is contained in:
parent
b8b3ff1a02
commit
3dcba9f215
|
@ -29,29 +29,134 @@
|
||||||
#include "hb-ot.h"
|
#include "hb-ot.h"
|
||||||
#include "hb-ot-glyf-table.hh"
|
#include "hb-ot-glyf-table.hh"
|
||||||
|
|
||||||
unsigned int
|
struct hb_ot_glyph_path_t
|
||||||
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. */)
|
|
||||||
{
|
{
|
||||||
unsigned int points_to_write = likely (points && points_count) ? *points_count : 0;
|
hb_object_header_t header;
|
||||||
if (likely (points_count)) *points_count = 0;
|
|
||||||
unsigned int all_points_count = 0;
|
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<hb_ot_glyph_path_t *> (&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<hb_ot_glyph_path_t> ()))
|
||||||
|
{
|
||||||
|
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<hb_position_t> *coords;
|
||||||
|
hb_vector_t<uint8_t> *commands;
|
||||||
|
|
||||||
|
bool init ()
|
||||||
|
{
|
||||||
|
coords = (hb_vector_t<hb_position_t> *) malloc (sizeof (hb_vector_t<hb_position_t>));
|
||||||
|
commands = (hb_vector_t<uint8_t> *) malloc (sizeof (hb_vector_t<uint8_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<hb_position_t> &coords = *user_data->coords;
|
||||||
|
hb_vector_t<uint8_t> &commands = *user_data->commands;
|
||||||
font->face->table.glyf->get_path (font, glyph,
|
font->face->table.glyf->get_path (font, glyph,
|
||||||
[&] (char cmd, float x, float y)
|
[&] (char cmd, float x, float y)
|
||||||
{
|
{
|
||||||
all_points_count++;
|
if (cmd != ' ') commands.push (cmd);
|
||||||
if (start_offset) { start_offset--; return; }
|
if (cmd == 'Z') return;
|
||||||
if (points_to_write)
|
coords.push (font->em_scalef_x (x));
|
||||||
{
|
coords.push (font->em_scalef_y (y));
|
||||||
points[*points_count] = {cmd, font->em_scalef_x (x), font->em_scalef_y (y)};
|
|
||||||
*points_count += 1;
|
|
||||||
points_to_write--;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
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
|
#endif
|
||||||
|
|
|
@ -33,19 +33,33 @@
|
||||||
|
|
||||||
HB_BEGIN_DECLS
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct hb_ot_glyph_path_point_t
|
typedef struct hb_ot_glyph_path_t hb_ot_glyph_path_t;
|
||||||
{
|
|
||||||
char cmd;
|
|
||||||
hb_position_t x;
|
|
||||||
hb_position_t y;
|
|
||||||
} hb_ot_glyph_path_point_t;
|
|
||||||
|
|
||||||
HB_EXTERN unsigned int
|
HB_EXTERN hb_ot_glyph_path_t *
|
||||||
hb_ot_glyph_get_outline_path (hb_font_t *font,
|
hb_ot_glyph_path_empty ();
|
||||||
hb_codepoint_t glyph,
|
|
||||||
unsigned int start_offset,
|
HB_EXTERN hb_ot_glyph_path_t *
|
||||||
unsigned int *points_count /* IN/OUT. May be NULL. */,
|
hb_ot_glyph_create_path (hb_position_t *coords,
|
||||||
hb_ot_glyph_path_point_t *points /* OUT. May be NULL. */);
|
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
|
HB_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -55,26 +55,44 @@ main (int argc, char **argv)
|
||||||
unsigned int glyph_count = hb_face_get_glyph_count (face);
|
unsigned int glyph_count = hb_face_get_glyph_count (face);
|
||||||
for (unsigned int gid = 0; gid < glyph_count; ++gid)
|
for (unsigned int gid = 0; gid < glyph_count; ++gid)
|
||||||
{
|
{
|
||||||
hb_ot_glyph_path_point_t points[200];
|
hb_font_extents_t font_extents;
|
||||||
unsigned int points_len = 200;
|
hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
|
||||||
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_glyph_extents_t extents = {0};
|
hb_glyph_extents_t extents = {0};
|
||||||
hb_font_get_glyph_extents (font, gid, &extents);
|
hb_font_get_glyph_extents (font, gid, &extents);
|
||||||
char name[100];
|
char name[100];
|
||||||
sprintf (name, "%d.svg", gid);
|
sprintf (name, "%d.svg", gid);
|
||||||
FILE *f = fopen (name, "wb");
|
FILE *f = fopen (name, "wb");
|
||||||
int factor = 1;
|
|
||||||
if (extents.height < 0) factor = -1;
|
|
||||||
fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
|
fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
|
||||||
" viewBox=\"0 0 %d %d\"><path d=\"", extents.width, extents.height * factor);
|
" viewBox=\"%d %d %d %d\"><path d=\"",
|
||||||
for (unsigned i = 0; i < points_len; ++i)
|
extents.x_bearing, 0,
|
||||||
|
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender); //-extents.height);
|
||||||
|
hb_ot_glyph_path_t *path = hb_ot_glyph_create_path_from_font (font, gid);
|
||||||
|
unsigned int commands_count;
|
||||||
|
const uint8_t *commands = hb_ot_glyph_path_get_commands (path, &commands_count);
|
||||||
|
unsigned int coords_count;
|
||||||
|
const hb_position_t *coords = hb_ot_glyph_path_get_coords (path, &coords_count);
|
||||||
|
for (unsigned i = 0, j = 0; i < commands_count && j < coords_count; ++i)
|
||||||
{
|
{
|
||||||
if (points[i].cmd == 'Z') fprintf (f, "Z");
|
fprintf (f, "%c", commands[i]);
|
||||||
else fprintf (f, "%c%d,%d", points[i].cmd, points[i].x, (points[i].y + extents.height) * factor);
|
if (commands[i] == 'Z') continue;
|
||||||
|
fprintf (f, "%d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y);
|
||||||
|
j += 2;
|
||||||
|
if (commands[i] == 'Q')
|
||||||
|
{
|
||||||
|
fprintf (f, " %d,%d", coords[j], font_extents.ascender - coords[j + 1]); //extents.y_bearing - points[i].y);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
if (commands[i] == 'C')
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf (f, "\"/></svg>");
|
fprintf (f, "\"/></svg>");
|
||||||
fclose (f);
|
fclose (f);
|
||||||
|
hb_ot_glyph_path_destroy (path);
|
||||||
}
|
}
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
hb_face_destroy (face);
|
hb_face_destroy (face);
|
||||||
|
|
Loading…
Reference in New Issue