[ot-glyph] rewrite the API
This commit is contained in:
parent
05443e55bc
commit
017f606c83
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2019 Ebrahim Byagowi
|
* Copyright © 2019-2020 Ebrahim Byagowi
|
||||||
*
|
*
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
|
@ -31,133 +31,15 @@
|
||||||
#include "hb-ot-cff1-table.hh"
|
#include "hb-ot-cff1-table.hh"
|
||||||
#include "hb-ot-cff2-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;
|
hb_vector_t<hb_position_t> coords;
|
||||||
unsigned int coords_count;
|
hb_vector_t<uint8_t> commands;
|
||||||
|
|
||||||
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_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<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;
|
|
||||||
|
|
||||||
if (path->destroy) path->destroy (path->user_data);
|
|
||||||
|
|
||||||
free (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ();
|
|
||||||
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<hb_position_t> &coords = *user_data->coords;
|
|
||||||
hb_vector_t<uint8_t> &commands = *user_data->commands;
|
|
||||||
|
|
||||||
bool ret = false;
|
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);
|
if (!ret) ret = font->face->table.cff2->get_path (font, glyph, &coords, &commands);
|
||||||
#endif
|
#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))
|
/* FIXME: We should do all these memory O(1) without hb_vector_t
|
||||||
{
|
by moving the logic to the tables */
|
||||||
user_data->fini ();
|
unsigned int coords_idx = 0;
|
||||||
free (user_data);
|
for (unsigned int i = 0; i < commands.length; ++i)
|
||||||
return hb_ot_glyph_path_empty ();
|
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,
|
return true;
|
||||||
user_data, (hb_destroy_func_t) _hb_ot_glyph_path_free_vectors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2019 Ebrahim Byagowi
|
* Copyright © 2019-2020 Ebrahim Byagowi
|
||||||
*
|
*
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
|
@ -33,34 +33,39 @@
|
||||||
|
|
||||||
HB_BEGIN_DECLS
|
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,
|
* hb_ot_glyph_decompose_funcs_t:
|
||||||
unsigned int coords_count,
|
*
|
||||||
uint8_t *commands,
|
* Glyph decompose callbacks.
|
||||||
unsigned int commands_count,
|
*
|
||||||
void *user_data,
|
* Since: REPLACEME
|
||||||
hb_destroy_func_t destroy);
|
**/
|
||||||
|
typedef struct hb_ot_glyph_decompose_funcs_t
|
||||||
HB_EXTERN hb_ot_glyph_path_t *
|
{
|
||||||
hb_ot_glyph_path_create_from_font (hb_font_t *font, hb_codepoint_t glyph);
|
hb_ot_glyph_decompose_move_to_func_t move_to;
|
||||||
|
hb_ot_glyph_decompose_line_to_func_t line_to;
|
||||||
HB_EXTERN void
|
hb_ot_glyph_decompose_conic_to_func_t conic_to;
|
||||||
hb_ot_glyph_path_destroy (hb_ot_glyph_path_t *path);
|
hb_ot_glyph_decompose_cubic_to_func_t cubic_to;
|
||||||
|
/*< private >*/
|
||||||
HB_EXTERN hb_ot_glyph_path_t *
|
void *reserved4;
|
||||||
hb_ot_glyph_path_empty (void);
|
void *reserved3;
|
||||||
|
void *reserved2;
|
||||||
HB_EXTERN const uint8_t *
|
void *reserved1;
|
||||||
hb_ot_glyph_path_get_commands (hb_ot_glyph_path_t *path, unsigned int *count);
|
} hb_ot_glyph_decompose_funcs_t;
|
||||||
|
|
||||||
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_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
|
HB_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,48 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
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
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -49,6 +91,12 @@ main (int argc, char **argv)
|
||||||
exit (1);
|
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++)
|
for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++)
|
||||||
{
|
{
|
||||||
hb_face_t *face = hb_face_create (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\"><path d=\"",
|
" viewBox=\"%d %d %d %d\"><path d=\"",
|
||||||
extents.x_bearing, 0,
|
extents.x_bearing, 0,
|
||||||
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender); //-extents.height);
|
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender); //-extents.height);
|
||||||
hb_ot_glyph_path_t *path = hb_ot_glyph_path_create_from_font (font, gid);
|
user_data_t user_data;
|
||||||
unsigned int commands_count;
|
user_data.ascender = font_extents.ascender;
|
||||||
const uint8_t *commands = hb_ot_glyph_path_get_commands (path, &commands_count);
|
user_data.f = f;
|
||||||
unsigned int coords_count;
|
if (!hb_ot_glyph_decompose (font, gid, &funcs, &user_data))
|
||||||
const hb_position_t *coords = hb_ot_glyph_path_get_coords (path, &coords_count);
|
printf ("Failed to decompose gid: %d\n", gid);
|
||||||
unsigned j = 0;
|
|
||||||
for (unsigned i = 0; i < commands_count && j < coords_count; ++i)
|
|
||||||
{
|
|
||||||
fprintf (f, "%c", commands[i]);
|
|
||||||
if (commands[i] == 'Z') continue;
|
|
||||||
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] == '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);
|
|
||||||
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