[draw] Fix draw signatures

This commit is contained in:
Behdad Esfahbod 2022-02-02 21:42:48 -06:00
parent 08e1096609
commit 2bed4f46fb
8 changed files with 448 additions and 345 deletions

View File

@ -45,7 +45,7 @@
void void
hb_font_draw_glyph (hb_font_t *font, hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,
const hb_draw_funcs_t *funcs, hb_draw_funcs_t *funcs,
void *user_data) void *user_data)
{ {
if (unlikely (funcs == &Null (hb_draw_funcs_t) || if (unlikely (funcs == &Null (hb_draw_funcs_t) ||

View File

@ -28,6 +28,63 @@
#include "hb-draw.hh" #include "hb-draw.hh"
static void
hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
float control_x HB_UNUSED, float control_y HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
float control1_x HB_UNUSED, float control1_y HB_UNUSED,
float control2_x HB_UNUSED, float control2_y HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
void *user_data HB_UNUSED) {}
#define HB_DRAW_FUNC_IMPLEMENT(name) \
\
void \
hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
hb_draw_##name##_func_t func, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (dfuncs)) \
return; \
\
if (dfuncs->destroy.name) \
dfuncs->destroy.name (dfuncs->user_data.name); \
\
if (func) { \
dfuncs->func.name = func; \
dfuncs->user_data.name = user_data; \
dfuncs->destroy.name = destroy; \
} else { \
dfuncs->func.name = hb_draw_##name##_nil; \
dfuncs->user_data.name = nullptr; \
dfuncs->destroy.name = nullptr; \
} \
}
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
/** /**
* hb_draw_funcs_set_move_to_func: * hb_draw_funcs_set_move_to_func:
* @funcs: draw functions object * @funcs: draw functions object
@ -37,13 +94,6 @@
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
void
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
hb_draw_move_to_func_t move_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->move_to = move_to;
}
/** /**
* hb_draw_funcs_set_line_to_func: * hb_draw_funcs_set_line_to_func:
@ -54,13 +104,6 @@ hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
hb_draw_line_to_func_t line_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->line_to = line_to;
}
/** /**
* hb_draw_funcs_set_quadratic_to_func: * hb_draw_funcs_set_quadratic_to_func:
@ -71,14 +114,6 @@ hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
hb_draw_quadratic_to_func_t quadratic_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->quadratic_to = quadratic_to;
funcs->is_quadratic_to_set = true;
}
/** /**
* hb_draw_funcs_set_cubic_to_func: * hb_draw_funcs_set_cubic_to_func:
@ -89,13 +124,6 @@ hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
hb_draw_cubic_to_func_t cubic_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->cubic_to = cubic_to;
}
/** /**
* hb_draw_funcs_set_close_path_func: * hb_draw_funcs_set_close_path_func:
@ -106,33 +134,6 @@ hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
hb_draw_close_path_func_t close_path)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->close_path = close_path;
}
static void
_move_to_nil (float to_x HB_UNUSED, float to_y HB_UNUSED, void *user_data HB_UNUSED) {}
static void
_line_to_nil (float to_x HB_UNUSED, float to_y HB_UNUSED, void *user_data HB_UNUSED) {}
static void
_quadratic_to_nil (float control_x HB_UNUSED, float control_y HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_cubic_to_nil (float control1_x HB_UNUSED, float control1_y HB_UNUSED,
float control2_x HB_UNUSED, float control2_y HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_close_path_nil (void *user_data HB_UNUSED) {}
/** /**
* hb_draw_funcs_create: * hb_draw_funcs_create:
@ -148,15 +149,31 @@ hb_draw_funcs_create ()
if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ()))) if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t)); return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil; /* XXX Clean up. Use nil object. */
funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil; funcs->func.move_to = hb_draw_move_to_nil;
funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil; funcs->func.line_to = hb_draw_line_to_nil;
funcs->is_quadratic_to_set = false; funcs->func.quadratic_to = hb_draw_quadratic_to_nil;
funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil; funcs->func.cubic_to = hb_draw_cubic_to_nil;
funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil; funcs->func.close_path = hb_draw_close_path_nil;
return funcs; return funcs;
} }
DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
{
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
}
};
/* XXX Remove. */
bool
hb_draw_funcs_t::quadratic_to_is_set () { return func.quadratic_to != hb_draw_quadratic_to_nil; }
/** /**
* hb_draw_funcs_reference: * hb_draw_funcs_reference:
* @funcs: draw functions * @funcs: draw functions

View File

@ -33,26 +33,6 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
typedef void (*hb_draw_move_to_func_t) (float to_x,
float to_y,
void *user_data);
typedef void (*hb_draw_line_to_func_t) (float to_x,
float to_y,
void *user_data);
typedef void (*hb_draw_quadratic_to_func_t) (float control_x,
float control_y,
float to_x,
float to_y,
void *user_data);
typedef void (*hb_draw_cubic_to_func_t) (float control1_x,
float control1_y,
float control2_x,
float control2_y,
float to_x,
float to_y,
void *user_data);
typedef void (*hb_draw_close_path_func_t) (void *user_data);
/** /**
* hb_draw_funcs_t: * hb_draw_funcs_t:
* *
@ -63,27 +43,51 @@ typedef void (*hb_draw_close_path_func_t) (void *user_data);
* *
* Since: REPLACEME * Since: REPLACEME
**/ **/
typedef struct hb_draw_funcs_t hb_draw_funcs_t; typedef struct hb_draw_funcs_t hb_draw_funcs_t;
typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
float to_x, float to_y,
void *user_data);
typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
float to_x, float to_y,
void *user_data);
typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
float control_x, float control_y,
float to_x, float to_y,
void *user_data);
typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *user_data);
typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
void *user_data);
HB_EXTERN void HB_EXTERN void
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs, hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
hb_draw_move_to_func_t move_to); hb_draw_move_to_func_t move_to,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN void HB_EXTERN void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs, hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
hb_draw_line_to_func_t line_to); hb_draw_line_to_func_t line_to,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN void HB_EXTERN void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs, hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
hb_draw_quadratic_to_func_t quadratic_to); hb_draw_quadratic_to_func_t quadratic_to,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN void HB_EXTERN void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs, hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
hb_draw_cubic_to_func_t cubic_to); hb_draw_cubic_to_func_t cubic_to,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN void HB_EXTERN void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs, hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
hb_draw_close_path_func_t close_path); hb_draw_close_path_func_t close_path,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN hb_draw_funcs_t * HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void); hb_draw_funcs_create (void);

View File

@ -27,24 +27,82 @@
#include "hb.hh" #include "hb.hh"
/*
* hb_draw_funcs_t
*/
#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
HB_DRAW_FUNC_IMPLEMENT (move_to) \
HB_DRAW_FUNC_IMPLEMENT (line_to) \
HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
HB_DRAW_FUNC_IMPLEMENT (close_path) \
/* ^--- Add new callbacks here */
struct hb_draw_funcs_t struct hb_draw_funcs_t
{ {
hb_object_header_t header; hb_object_header_t header;
hb_draw_move_to_func_t move_to; struct {
hb_draw_line_to_func_t line_to; #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
hb_draw_quadratic_to_func_t quadratic_to; HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
bool is_quadratic_to_set; #undef HB_DRAW_FUNC_IMPLEMENT
hb_draw_cubic_to_func_t cubic_to; } func;
hb_draw_close_path_func_t close_path;
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
} user_data;
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
} destroy;
void move_to (void *draw_data,
float to_x, float to_y)
{ func.move_to (this, draw_data,
to_x, to_y,
user_data.move_to); }
void line_to (void *draw_data,
float to_x, float to_y)
{ func.line_to (this, draw_data,
to_x, to_y,
user_data.line_to); }
void quadratic_to (void *draw_data,
float control_x, float control_y,
float to_x, float to_y)
{ func.quadratic_to (this, draw_data,
control_x, control_y,
to_x, to_y,
user_data.quadratic_to); }
void cubic_to (void *draw_data,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{ func.cubic_to (this, draw_data,
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y,
user_data.cubic_to); }
void close_path (void *draw_data)
{ func.close_path (this, draw_data,
user_data.close_path); }
/* XXX Remove */
HB_INTERNAL bool quadratic_to_is_set ();
}; };
DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
struct draw_helper_t struct draw_helper_t
{ {
draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_) draw_helper_t (hb_draw_funcs_t *funcs_, void *draw_data_)
{ {
funcs = funcs_; funcs = funcs_;
user_data = user_data_; draw_data = draw_data_;
path_open = false; path_open = false;
path_start_x = current_x = path_start_y = current_y = 0; path_start_x = current_x = path_start_y = current_y = 0;
} }
@ -61,7 +119,7 @@ struct draw_helper_t
{ {
if (equal_to_current (x, y)) return; if (equal_to_current (x, y)) return;
if (!path_open) start_path (); if (!path_open) start_path ();
funcs->line_to (x, y, user_data); funcs->line_to (draw_data, x, y);
current_x = x; current_x = x;
current_y = y; current_y = y;
} }
@ -73,14 +131,15 @@ struct draw_helper_t
if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y)) if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
return; return;
if (!path_open) start_path (); if (!path_open) start_path ();
if (funcs->is_quadratic_to_set) if (funcs->quadratic_to_is_set ())
funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data); funcs->quadratic_to (draw_data, control_x, control_y, to_x, to_y);
else else
funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f), funcs->cubic_to (draw_data,
roundf ((current_x + 2.f * control_x) / 3.f),
roundf ((current_y + 2.f * control_y) / 3.f), roundf ((current_y + 2.f * control_y) / 3.f),
roundf ((to_x + 2.f * control_x) / 3.f), roundf ((to_x + 2.f * control_x) / 3.f),
roundf ((to_y + 2.f * control_y) / 3.f), roundf ((to_y + 2.f * control_y) / 3.f),
to_x, to_y, user_data); to_x, to_y);
current_x = to_x; current_x = to_x;
current_y = to_y; current_y = to_y;
} }
@ -95,7 +154,7 @@ struct draw_helper_t
equal_to_current (to_x, to_y)) equal_to_current (to_x, to_y))
return; return;
if (!path_open) start_path (); if (!path_open) start_path ();
funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data); funcs->cubic_to (draw_data, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
current_x = to_x; current_x = to_x;
current_y = to_y; current_y = to_y;
} }
@ -105,8 +164,8 @@ struct draw_helper_t
if (path_open) if (path_open)
{ {
if ((path_start_x != current_x) || (path_start_y != current_y)) if ((path_start_x != current_x) || (path_start_y != current_y))
funcs->line_to (path_start_x, path_start_y, user_data); funcs->line_to (draw_data, path_start_x, path_start_y);
funcs->close_path (user_data); funcs->close_path (draw_data);
} }
path_open = false; path_open = false;
path_start_x = current_x = path_start_y = current_y = 0; path_start_x = current_x = path_start_y = current_y = 0;
@ -120,7 +179,7 @@ struct draw_helper_t
{ {
if (path_open) end_path (); if (path_open) end_path ();
path_open = true; path_open = true;
funcs->move_to (path_start_x, path_start_y, user_data); funcs->move_to (draw_data, path_start_x, path_start_y);
} }
float path_start_x; float path_start_x;
@ -130,8 +189,8 @@ struct draw_helper_t
float current_y; float current_y;
bool path_open; bool path_open;
const hb_draw_funcs_t *funcs; hb_draw_funcs_t *funcs;
void *user_data; void *draw_data;
}; };
#endif /* HB_DRAW_HH */ #endif /* HB_DRAW_HH */

View File

@ -1059,7 +1059,7 @@ hb_font_set_var_named_instance (hb_font_t *font,
HB_EXTERN void HB_EXTERN void
hb_font_draw_glyph (hb_font_t *font, hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph, hb_codepoint_t glyph,
const hb_draw_funcs_t *funcs, hb_draw_funcs_t *funcs,
void *user_data); void *user_data);
HB_END_DECLS HB_END_DECLS

View File

@ -129,48 +129,55 @@ png_dump (hb_face_t *face, unsigned face_index)
hb_font_destroy (font); hb_font_destroy (font);
} }
struct user_data_t struct draw_data_t
{ {
FILE *f; FILE *f;
hb_position_t ascender; hb_position_t ascender;
}; };
static void static void
move_to (float to_x, float to_y, user_data_t *user_data) move_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
{
fprintf (user_data->f, "M%g,%g", to_x, user_data->ascender - to_y);
}
static void
line_to (float to_x, float to_y, user_data_t *user_data)
{
fprintf (user_data->f, "L%g,%g", to_x, user_data->ascender - to_y);
}
static void
quadratic_to (float control_x, float control_y,
float to_x, float to_y, float to_x, float to_y,
user_data_t *user_data) void *)
{ {
fprintf (user_data->f, "Q%g,%g %g,%g", control_x, user_data->ascender - control_y, fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y);
to_x, user_data->ascender - to_y);
} }
static void static void
cubic_to (float control1_x, float control1_y, line_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float to_x, float to_y,
void *)
{
fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y);
}
static void
quadratic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float control_x, float control_y,
float to_x, float to_y,
void *)
{
fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y,
to_x, draw_data->ascender - to_y);
}
static void
cubic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float control1_x, float control1_y,
float control2_x, float control2_y, float control2_x, float control2_y,
float to_x, float to_y, float to_x, float to_y,
user_data_t *user_data) void *)
{ {
fprintf (user_data->f, "C%g,%g %g,%g %g,%g", control1_x, user_data->ascender - control1_y, fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y,
control2_x, user_data->ascender - control2_y, control2_x, draw_data->ascender - control2_y,
to_x, user_data->ascender - to_y); to_x, draw_data->ascender - to_y);
} }
static void static void
close_path (user_data_t *user_data) close_path (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
void *)
{ {
fprintf (user_data->f, "Z"); fprintf (draw_data->f, "Z");
} }
static void static void
@ -218,9 +225,9 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
" viewBox=\"%d %d %d %d\">\n", " viewBox=\"%d %d %d %d\">\n",
extents.x_bearing, 0, extents.x_bearing, 0,
extents.x_bearing + extents.width, -extents.height); extents.x_bearing + extents.width, -extents.height);
user_data_t user_data; draw_data_t draw_data;
user_data.ascender = extents.y_bearing; draw_data.ascender = extents.y_bearing;
user_data.f = f; draw_data.f = f;
for (unsigned layer = 0; layer < num_layers; ++layer) for (unsigned layer = 0; layer < num_layers; ++layer)
{ {
@ -232,7 +239,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
if (hb_color_get_alpha (color) != 255) if (hb_color_get_alpha (color) != 255)
fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.); fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
fprintf (f, "d=\""); fprintf (f, "d=\"");
hb_font_draw_glyph (font, layers[layer].glyph, funcs, &user_data); hb_font_draw_glyph (font, layers[layer].glyph, funcs, &draw_data);
fprintf (f, "\"/>\n"); fprintf (f, "\"/>\n");
} }
@ -268,10 +275,10 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
" 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.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
user_data_t user_data; draw_data_t draw_data;
user_data.ascender = font_extents.ascender; draw_data.ascender = font_extents.ascender;
user_data.f = f; draw_data.f = f;
hb_font_draw_glyph (font, gid, funcs, &user_data); hb_font_draw_glyph (font, gid, funcs, &draw_data);
fprintf (f, "\"/></svg>"); fprintf (f, "\"/></svg>");
fclose (f); fclose (f);
} }
@ -298,11 +305,11 @@ dump_glyphs (hb_blob_t *blob, const char *font_name)
fclose (font_name_file); fclose (font_name_file);
hb_draw_funcs_t *funcs = hb_draw_funcs_create (); hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to); hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to); hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to); hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to); hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path); hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
unsigned num_faces = hb_face_count (blob); unsigned num_faces = hb_face_count (blob);
for (unsigned face_index = 0; face_index < num_faces; ++face_index) for (unsigned face_index = 0; face_index < num_faces; ++face_index)

View File

@ -27,12 +27,12 @@
#include <hb.h> #include <hb.h>
typedef struct user_data_t typedef struct draw_data_t
{ {
char *str; char *str;
unsigned size; unsigned size;
unsigned consumed; unsigned consumed;
} user_data_t; } draw_data_t;
/* Our modified itoa, why not using libc's? it is going to be used /* Our modified itoa, why not using libc's? it is going to be used
in harfbuzzjs where libc isn't available */ in harfbuzzjs where libc isn't available */
@ -96,69 +96,76 @@ test_itoa (void)
} }
static void static void
move_to (float to_x, float to_y, user_data_t *user_data) move_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float to_x, float to_y,
void *user_data)
{ {
/* 4 = command character space + comma + array starts with 0 index + nul character space */ /* 4 = command character space + comma + array starts with 0 index + nul character space */
if (user_data->consumed + 2 * ITOA_BUF_SIZE + 4 > user_data->size) return; if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
user_data->str[user_data->consumed++] = 'M'; draw_data->str[draw_data->consumed++] = 'M';
user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ','; draw_data->str[draw_data->consumed++] = ',';
user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
} }
static void static void
line_to (float to_x, float to_y, user_data_t *user_data) line_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
{
if (user_data->consumed + 2 * ITOA_BUF_SIZE + 4 > user_data->size) return;
user_data->str[user_data->consumed++] = 'L';
user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
user_data->str[user_data->consumed++] = ',';
user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
}
static void
quadratic_to (float control_x, float control_y,
float to_x, float to_y, float to_x, float to_y,
user_data_t *user_data) void *user_data)
{ {
if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
if (user_data->consumed + 4 * ITOA_BUF_SIZE + 6 > user_data->size) return; draw_data->str[draw_data->consumed++] = 'L';
user_data->str[user_data->consumed++] = 'Q'; draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
user_data->consumed += _hb_itoa (control_x, user_data->str + user_data->consumed); draw_data->str[draw_data->consumed++] = ',';
user_data->str[user_data->consumed++] = ','; draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
user_data->consumed += _hb_itoa (control_y, user_data->str + user_data->consumed);
user_data->str[user_data->consumed++] = ' ';
user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
user_data->str[user_data->consumed++] = ',';
user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
} }
static void static void
cubic_to (float control1_x, float control1_y, quadratic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float control_x, float control_y,
float to_x, float to_y,
void *user_data)
{
if (draw_data->consumed + 4 * ITOA_BUF_SIZE + 6 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'Q';
draw_data->consumed += _hb_itoa (control_x, draw_data->str + draw_data->consumed);
draw_data->str[draw_data->consumed++] = ',';
draw_data->consumed += _hb_itoa (control_y, draw_data->str + draw_data->consumed);
draw_data->str[draw_data->consumed++] = ' ';
draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
draw_data->str[draw_data->consumed++] = ',';
draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
}
static void
cubic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
float control1_x, float control1_y,
float control2_x, float control2_y, float control2_x, float control2_y,
float to_x, float to_y, float to_x, float to_y,
user_data_t *user_data) void *user_data)
{ {
if (user_data->consumed + 6 * ITOA_BUF_SIZE + 8 > user_data->size) return; if (draw_data->consumed + 6 * ITOA_BUF_SIZE + 8 > draw_data->size) return;
user_data->str[user_data->consumed++] = 'C'; draw_data->str[draw_data->consumed++] = 'C';
user_data->consumed += _hb_itoa (control1_x, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (control1_x, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ','; draw_data->str[draw_data->consumed++] = ',';
user_data->consumed += _hb_itoa (control1_y, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (control1_y, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ' '; draw_data->str[draw_data->consumed++] = ' ';
user_data->consumed += _hb_itoa (control2_x, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (control2_x, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ','; draw_data->str[draw_data->consumed++] = ',';
user_data->consumed += _hb_itoa (control2_y, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (control2_y, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ' '; draw_data->str[draw_data->consumed++] = ' ';
user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
user_data->str[user_data->consumed++] = ','; draw_data->str[draw_data->consumed++] = ',';
user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed); draw_data->consumed += _hb_itoa (to_y, draw_data->str + draw_data->consumed);
} }
static void static void
close_path (user_data_t *user_data) close_path (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
void *user_data)
{ {
if (user_data->consumed + 2 > user_data->size) return; if (draw_data->consumed + 2 > draw_data->size) return;
user_data->str[user_data->consumed++] = 'Z'; draw_data->str[draw_data->consumed++] = 'Z';
} }
static hb_draw_funcs_t *funcs; static hb_draw_funcs_t *funcs;
@ -178,17 +185,17 @@ test_hb_draw_glyf (void)
hb_face_destroy (face); hb_face_destroy (face);
char str[1024]; char str[1024];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str), .size = sizeof (str),
.consumed = 0 .consumed = 0
}; };
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 4, funcs, &user_data); hb_font_draw_glyph (font, 4, funcs, &draw_data);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 3, funcs, &user_data); hb_font_draw_glyph (font, 3, funcs, &draw_data);
char expected[] = "M275,442Q232,442 198,420Q164,397 145,353Q126,309 126,245" char expected[] = "M275,442Q232,442 198,420Q164,397 145,353Q126,309 126,245"
"Q126,182 147,139Q167,95 204,73Q240,50 287,50Q330,50 367,70" "Q126,182 147,139Q167,95 204,73Q240,50 287,50Q330,50 367,70"
"Q404,90 427,128L451,116Q431,54 384,21Q336,-13 266,-13" "Q404,90 427,128L451,116Q431,54 384,21Q336,-13 266,-13"
@ -196,11 +203,11 @@ test_hb_draw_glyf (void)
"Q108,427 160,457Q212,487 272,487Q316,487 354,470Q392,453 417,424" "Q108,427 160,457Q212,487 272,487Q316,487 354,470Q392,453 417,424"
"Q442,395 448,358Q441,321 403,321Q378,321 367,334" "Q442,395 448,358Q441,321 403,321Q378,321 367,334"
"Q355,347 350,366L325,454L371,417Q346,430 321,436Q296,442 275,442Z"; "Q355,347 350,366L325,454L371,417Q346,430 321,436Q296,442 275,442Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
/* Test translating quadratic calls to cubic by a _draw_funcs_t that doesn't set the callback */ /* Test translating quadratic calls to cubic by a _draw_funcs_t that doesn't set the callback */
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 3, funcs2, &user_data); hb_font_draw_glyph (font, 3, funcs2, &draw_data);
char expected2[] = "M275,442C246,442 221,435 198,420C175,405 158,382 145,353" char expected2[] = "M275,442C246,442 221,435 198,420C175,405 158,382 145,353"
"C132,324 126,288 126,245C126,203 133,168 147,139C160,110 179,88 204,73" "C132,324 126,288 126,245C126,203 133,168 147,139C160,110 179,88 204,73"
"C228,58 256,50 287,50C316,50 342,57 367,70C392,83 412,103 427,128" "C228,58 256,50 287,50C316,50 342,57 367,70C392,83 412,103 427,128"
@ -210,15 +217,15 @@ test_hb_draw_glyf (void)
"C379,459 400,443 417,424C434,405 444,383 448,358C443,333 428,321 403,321" "C379,459 400,443 417,424C434,405 444,383 448,358C443,333 428,321 403,321"
"C386,321 374,325 367,334C359,343 353,353 350,366L325,454L371,417" "C386,321 374,325 367,334C359,343 353,353 350,366L325,454L371,417"
"C354,426 338,432 321,436C304,440 289,442 275,442Z"; "C354,426 338,432 321,436C304,440 289,442 275,442Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_variation_t var; hb_variation_t var;
var.tag = HB_TAG ('w','g','h','t'); var.tag = HB_TAG ('w','g','h','t');
var.value = 800; var.value = 800;
hb_font_set_variations (font, &var, 1); hb_font_set_variations (font, &var, 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 3, funcs, &user_data); hb_font_draw_glyph (font, 3, funcs, &draw_data);
char expected3[] = "M323,448Q297,448 271,430Q244,412 226,371Q209,330 209,261" char expected3[] = "M323,448Q297,448 271,430Q244,412 226,371Q209,330 209,261"
"Q209,204 225,166Q242,127 272,107Q303,86 344,86Q378,86 404,101" "Q209,204 225,166Q242,127 272,107Q303,86 344,86Q378,86 404,101"
"Q430,115 451,137L488,103Q458,42 404,13Q350,-16 279,-16" "Q430,115 451,137L488,103Q458,42 404,13Q350,-16 279,-16"
@ -226,7 +233,7 @@ test_hb_draw_glyf (void)
"Q99,440 163,470Q226,501 303,501Q357,501 399,480Q440,460 464,426" "Q99,440 163,470Q226,501 303,501Q357,501 399,480Q440,460 464,426"
"Q488,392 492,352Q475,297 420,297Q390,297 366,319Q342,342 339,401" "Q488,392 492,352Q475,297 420,297Q390,297 366,319Q342,342 339,401"
"L333,469L411,427Q387,438 367,443Q348,448 323,448Z"; "L333,469L411,427Q387,438 367,443Q348,448 323,448Z";
g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1); g_assert_cmpmem (str, draw_data.consumed, expected3, sizeof (expected3) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -239,16 +246,16 @@ test_hb_draw_cff1 (void)
hb_face_destroy (face); hb_face_destroy (face);
char str[1024]; char str[1024];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str), .size = sizeof (str),
.consumed = 0 .consumed = 0
}; };
hb_font_draw_glyph (font, 3, funcs, &user_data); hb_font_draw_glyph (font, 3, funcs, &draw_data);
char expected[] = "M203,367C227,440 248,512 268,588L272,588C293,512 314,440 338,367L369,267L172,267L203,367Z" char expected[] = "M203,367C227,440 248,512 268,588L272,588C293,512 314,440 338,367L369,267L172,267L203,367Z"
"M3,0L88,0L151,200L390,200L452,0L541,0L319,656L225,656L3,0Z" "M3,0L88,0L151,200L390,200L452,0L541,0L319,656L225,656L3,0Z"
"M300,653L342,694L201,861L143,806L300,653Z"; "M300,653L342,694L201,861L143,806L300,653Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -262,18 +269,18 @@ test_hb_draw_cff1_rline (void)
hb_face_destroy (face); hb_face_destroy (face);
char str[1024]; char str[1024];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str), .size = sizeof (str),
.consumed = 0 .consumed = 0
}; };
hb_font_draw_glyph (font, 1, funcs, &user_data); hb_font_draw_glyph (font, 1, funcs, &draw_data);
char expected[] = "M775,400C705,400 650,343 650,274L650,250L391,250L713,572L392,893" char expected[] = "M775,400C705,400 650,343 650,274L650,250L391,250L713,572L392,893"
"L287,1000C311,942 296,869 250,823C250,823 286,858 321,823L571,572" "L287,1000C311,942 296,869 250,823C250,823 286,858 321,823L571,572"
"L150,150L750,150L750,276C750,289 761,300 775,300C789,300 800,289 800,276" "L150,150L750,150L750,276C750,289 761,300 775,300C789,300 800,289 800,276"
"L800,100L150,100C100,100 100,150 100,150C100,85 58,23 0,0L900,0L900,274" "L800,100L150,100C100,100 100,150 100,150C100,85 58,23 0,0L900,0L900,274"
"C900,343 844,400 775,400Z"; "C900,343 844,400 775,400Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -286,33 +293,33 @@ test_hb_draw_cff2 (void)
hb_face_destroy (face); hb_face_destroy (face);
char str[1024]; char str[1024];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 3, funcs, &user_data); hb_font_draw_glyph (font, 3, funcs, &draw_data);
char expected[] = "M275,442C303,442 337,435 371,417L325,454L350,366" char expected[] = "M275,442C303,442 337,435 371,417L325,454L350,366"
"C357,341 370,321 403,321C428,321 443,333 448,358" "C357,341 370,321 403,321C428,321 443,333 448,358"
"C435,432 361,487 272,487C153,487 43,393 43,236" "C435,432 361,487 272,487C153,487 43,393 43,236"
"C43,83 129,-13 266,-13C360,-13 424,33 451,116L427,128" "C43,83 129,-13 266,-13C360,-13 424,33 451,116L427,128"
"C396,78 345,50 287,50C193,50 126,119 126,245C126,373 188,442 275,442Z"; "C396,78 345,50 287,50C193,50 126,119 126,245C126,373 188,442 275,442Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_variation_t var; hb_variation_t var;
var.tag = HB_TAG ('w','g','h','t'); var.tag = HB_TAG ('w','g','h','t');
var.value = 800; var.value = 800;
hb_font_set_variations (font, &var, 1); hb_font_set_variations (font, &var, 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 3, funcs, &user_data); hb_font_draw_glyph (font, 3, funcs, &draw_data);
char expected2[] = "M323,448C356,448 380,441 411,427L333,469L339,401" char expected2[] = "M323,448C356,448 380,441 411,427L333,469L339,401"
"C343,322 379,297 420,297C458,297 480,314 492,352" "C343,322 379,297 420,297C458,297 480,314 492,352"
"C486,433 412,501 303,501C148,501 25,406 25,241" "C486,433 412,501 303,501C148,501 25,406 25,241"
"C25,70 143,-16 279,-16C374,-16 447,22 488,103L451,137" "C25,70 143,-16 279,-16C374,-16 447,22 488,103L451,137"
"C423,107 390,86 344,86C262,86 209,148 209,261C209,398 271,448 323,448Z"; "C423,107 390,86 344,86C262,86 209,148 209,261C209,398 271,448 323,448Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -322,7 +329,7 @@ test_hb_draw_ttf_parser_tests (void)
{ {
/* https://github.com/RazrFalcon/ttf-parser/blob/337e7d1c/tests/tests.rs#L50-L133 */ /* https://github.com/RazrFalcon/ttf-parser/blob/337e7d1c/tests/tests.rs#L50-L133 */
char str[1024]; char str[1024];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
@ -331,20 +338,20 @@ test_hb_draw_ttf_parser_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
{ {
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 0, funcs, &user_data); hb_font_draw_glyph (font, 0, funcs, &draw_data);
char expected[] = "M50,0L50,750L450,750L450,0L50,0Z"; char expected[] = "M50,0L50,750L450,750L450,0L50,0Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 1, funcs, &user_data); hb_font_draw_glyph (font, 1, funcs, &draw_data);
char expected[] = "M56,416L56,487L514,487L514,416L56,416ZM56,217L56,288L514,288L514,217L56,217Z"; char expected[] = "M56,416L56,487L514,487L514,416L56,416ZM56,217L56,288L514,288L514,217L56,217Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 4, funcs, &user_data); hb_font_draw_glyph (font, 4, funcs, &draw_data);
char expected[] = "M332,468L197,468L197,0L109,0L109,468L15,468L15,509L109,539" char expected[] = "M332,468L197,468L197,0L109,0L109,468L15,468L15,509L109,539"
"L109,570Q109,674 155,720Q201,765 283,765Q315,765 342,760" "L109,570Q109,674 155,720Q201,765 283,765Q315,765 342,760"
"Q368,754 387,747L364,678Q348,683 327,688Q306,693 284,693" "Q368,754 387,747L364,678Q348,683 327,688Q306,693 284,693"
@ -352,22 +359,22 @@ test_hb_draw_ttf_parser_tests (void)
"M474,737Q494,737 510,724Q525,710 525,681Q525,653 510,639" "M474,737Q494,737 510,724Q525,710 525,681Q525,653 510,639"
"Q494,625 474,625Q452,625 437,639Q422,653 422,681" "Q494,625 474,625Q452,625 437,639Q422,653 422,681"
"Q422,710 437,724Q452,737 474,737ZM517,536L517,0L429,0L429,536L517,536Z"; "Q422,710 437,724Q452,737 474,737ZM517,536L517,0L429,0L429,536L517,536Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 5, funcs, &user_data); hb_font_draw_glyph (font, 5, funcs, &draw_data);
char expected[] = ""; char expected[] = "";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 6, funcs, &user_data); hb_font_draw_glyph (font, 6, funcs, &draw_data);
char expected[] = "M346,468L211,468L211,0L123,0L123,468L29,468L29,509L123,539" char expected[] = "M346,468L211,468L211,0L123,0L123,468L29,468L29,509L123,539"
"L123,570Q123,674 169,720Q215,765 297,765Q329,765 356,760" "L123,570Q123,674 169,720Q215,765 297,765Q329,765 356,760"
"Q382,754 401,747L378,678Q362,683 341,688Q320,693 298,693" "Q382,754 401,747L378,678Q362,683 341,688Q320,693 298,693"
"Q254,693 233,664Q211,634 211,571L211,536L346,536L346,468Z"; "Q254,693 233,664Q211,634 211,571L211,536L346,536L346,468Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
hb_font_destroy (font); hb_font_destroy (font);
@ -377,15 +384,15 @@ test_hb_draw_ttf_parser_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 1, funcs, &user_data); hb_font_draw_glyph (font, 1, funcs, &draw_data);
char expected[] = "M0,0C100,0 150,-20 250,-20C350,-20 400,0 500,0C500,100 520,150 520,250" char expected[] = "M0,0C100,0 150,-20 250,-20C350,-20 400,0 500,0C500,100 520,150 520,250"
"C520,350 500,400 500,500C400,500 350,520 250,520C150,520 100,500 0,500" "C520,350 500,400 500,500C400,500 350,520 250,520C150,520 100,500 0,500"
"C0,400 -20,350 -20,250C-20,150 0,100 0,0ZM50,50C50,130 34,170 34,250" "C0,400 -20,350 -20,250C-20,150 0,100 0,0ZM50,50C50,130 34,170 34,250"
"C34,330 50,370 50,450C130,450 170,466 250,466C330,466 370,450 450,450" "C34,330 50,370 50,450C130,450 170,466 250,466C330,466 370,450 450,450"
"C450,370 466,330 466,250C466,170 450,130 450,50C370,50 330,34 250,34" "C450,370 466,330 466,250C466,170 450,130 450,50C370,50 330,34 250,34"
"C170,34 130,50 50,50Z"; "C170,34 130,50 50,50Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -394,12 +401,12 @@ test_hb_draw_ttf_parser_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 1, funcs, &user_data); hb_font_draw_glyph (font, 1, funcs, &draw_data);
char expected[] = "M82,0L164,0L164,486L82,486L82,0Z" char expected[] = "M82,0L164,0L164,486L82,486L82,0Z"
"M124,586C156,586 181,608 181,639C181,671 156,692 124,692" "M124,586C156,586 181,608 181,639C181,671 156,692 124,692"
"C92,692 67,671 67,639C67,608 92,586 124,586Z"; "C92,692 67,671 67,639C67,608 92,586 124,586Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -410,7 +417,7 @@ test_hb_draw_font_kit_glyphs_tests (void)
{ {
/* https://github.com/foliojs/fontkit/blob/master/test/glyphs.js */ /* https://github.com/foliojs/fontkit/blob/master/test/glyphs.js */
char str[2048]; char str[2048];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
@ -421,26 +428,26 @@ test_hb_draw_font_kit_glyphs_tests (void)
hb_face_destroy (face); hb_face_destroy (face);
/* should get a path for the glyph */ /* should get a path for the glyph */
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 37, funcs, &user_data); hb_font_draw_glyph (font, 37, funcs, &draw_data);
char expected[] = "M201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100" char expected[] = "M201,1462L614,1462Q905,1462 1035,1375Q1165,1288 1165,1100"
"Q1165,970 1093,886Q1020,801 881,776L881,766Q1214,709 1214,416" "Q1165,970 1093,886Q1020,801 881,776L881,766Q1214,709 1214,416"
"Q1214,220 1082,110Q949,0 711,0L201,0L201,1462ZM371,836L651,836" "Q1214,220 1082,110Q949,0 711,0L201,0L201,1462ZM371,836L651,836"
"Q831,836 910,893Q989,949 989,1083Q989,1206 901,1261" "Q831,836 910,893Q989,949 989,1083Q989,1206 901,1261"
"Q813,1315 621,1315L371,1315L371,836ZM371,692L371,145L676,145" "Q813,1315 621,1315L371,1315L371,836ZM371,692L371,145L676,145"
"Q853,145 943,214Q1032,282 1032,428Q1032,564 941,628Q849,692 662,692L371,692Z"; "Q853,145 943,214Q1032,282 1032,428Q1032,564 941,628Q849,692 662,692L371,692Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
/* should get a path for the glyph */ /* should get a path for the glyph */
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 171, funcs, &user_data); hb_font_draw_glyph (font, 171, funcs, &draw_data);
char expected2[] = "M639,-20Q396,-20 256,128Q115,276 115,539Q115,804 246,960Q376,1116 596,1116" char expected2[] = "M639,-20Q396,-20 256,128Q115,276 115,539Q115,804 246,960Q376,1116 596,1116"
"Q802,1116 922,981Q1042,845 1042,623L1042,518L287,518Q292,325 385,225" "Q802,1116 922,981Q1042,845 1042,623L1042,518L287,518Q292,325 385,225"
"Q477,125 645,125Q822,125 995,199L995,51Q907,13 829,-3Q750,-20 639,-20Z" "Q477,125 645,125Q822,125 995,199L995,51Q907,13 829,-3Q750,-20 639,-20Z"
"M594,977Q462,977 384,891Q305,805 291,653L864,653Q864,810 794,894" "M594,977Q462,977 384,891Q305,805 291,653L864,653Q864,810 794,894"
"Q724,977 594,977ZM471,1266Q519,1328 575,1416Q630,1504 662,1569" "Q724,977 594,977ZM471,1266Q519,1328 575,1416Q630,1504 662,1569"
"L864,1569L864,1548Q820,1483 733,1388Q646,1293 582,1241L471,1241L471,1266Z"; "L864,1569L864,1548Q820,1483 733,1388Q646,1293 582,1241L471,1241L471,1266Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -458,8 +465,8 @@ test_hb_draw_font_kit_glyphs_tests (void)
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
/* should resolve composite glyphs recursively */ /* should resolve composite glyphs recursively */
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M581,274L443,274Q409,274 384,259Q359,243 348,219Q336,194 340,166" char expected[] = "M581,274L443,274Q409,274 384,259Q359,243 348,219Q336,194 340,166"
"Q343,138 365,111L468,-13Q470,-10 473,-6Q475,-3 477,0L253,0Q225,0 203,8" "Q343,138 365,111L468,-13Q470,-10 473,-6Q475,-3 477,0L253,0Q225,0 203,8"
"Q180,15 168,32Q155,48 155,73L155,269L50,269L50,73Q50,24 69,-10" "Q180,15 168,32Q155,48 155,73L155,269L50,269L50,73Q50,24 69,-10"
@ -471,16 +478,16 @@ test_hb_draw_font_kit_glyphs_tests (void)
"M360,-194Q360,-216 375,-231Q390,-246 412,-246Q434,-246 449,-231" "M360,-194Q360,-216 375,-231Q390,-246 412,-246Q434,-246 449,-231"
"Q464,-216 464,-194Q464,-172 449,-157Q434,-142 412,-142" "Q464,-216 464,-194Q464,-172 449,-157Q434,-142 412,-142"
"Q390,-142 375,-157Q360,-172 360,-194Z"; "Q390,-142 375,-157Q360,-172 360,-194Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
/* should transform points of a composite glyph */ /* should transform points of a composite glyph */
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 2, funcs, &user_data); /* 2 == arAlef.fina */ hb_font_draw_glyph (font, 2, funcs, &draw_data); /* 2 == arAlef.fina */
char expected2[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105" char expected2[] = "M155,624L155,84Q150,90 146,95Q141,99 136,105"
"L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51" "L292,105L292,0L156,0Q128,0 104,14Q79,27 65,51"
"Q50,74 50,104L50,624L155,624ZM282,105L312,105" "Q50,74 50,104L50,624L155,624ZM282,105L312,105"
"L312,0L282,0L282,105Z"; "L312,0L282,0L282,105Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -490,11 +497,11 @@ test_hb_draw_font_kit_glyphs_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 5, funcs, &user_data); hb_font_draw_glyph (font, 5, funcs, &draw_data);
char expected[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z" char expected[] = "M90,0L258,0C456,0 564,122 564,331C564,539 456,656 254,656L90,656L90,0Z"
"M173,68L173,588L248,588C401,588 478,496 478,331C478,165 401,68 248,68L173,68Z"; "M173,68L173,588L248,588C401,588 478,496 478,331C478,165 401,68 248,68L173,68Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -505,12 +512,12 @@ test_hb_draw_font_kit_glyphs_tests (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 1, funcs, &user_data); hb_font_draw_glyph (font, 1, funcs, &draw_data);
char expected[] = "M139,390C175,390 205,419 205,459C205,501 175,530 139,530C103,530 73,501 73,459" char expected[] = "M139,390C175,390 205,419 205,459C205,501 175,530 139,530C103,530 73,501 73,459"
"C73,419 103,390 139,390ZM139,-13C175,-13 205,15 205,56C205,97 175,127 139,127" "C73,419 103,390 139,390ZM139,-13C175,-13 205,15 205,56C205,97 175,127 139,127"
"C103,127 73,97 73,56C73,15 103,-13 139,-13Z"; "C103,127 73,97 73,56C73,15 103,-13 139,-13Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -522,7 +529,7 @@ test_hb_draw_font_kit_variations_tests (void)
{ {
/* https://github.com/foliojs/fontkit/blob/b310db5/test/variations.js */ /* https://github.com/foliojs/fontkit/blob/b310db5/test/variations.js */
char str[2048]; char str[2048];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
@ -550,8 +557,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102"
"Q796,-102 755,-98L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504" "Q796,-102 755,-98L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504"
"L414,504L414,-102L371,-102ZM203,-94Q138,-94 86,-90L74,-52" "L414,504L414,-102L371,-102ZM203,-94Q138,-94 86,-90L74,-52"
@ -572,7 +579,7 @@ test_hb_draw_font_kit_variations_tests (void)
"Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281" "Q754,410 775,381Q794,407 813,453L848,434Q826,387 801,352Q823,321 848,281"
"L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719" "L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754L941,754L941,719"
"L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z"; "L348,719ZM936,570Q870,602 817,622Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -595,8 +602,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
"L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102" "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
"L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46" "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
@ -616,7 +623,7 @@ test_hb_draw_font_kit_variations_tests (void)
"L848,434Q826,387 801,352Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258Z" "L848,434Q826,387 801,352Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258Z"
"M348,719L348,754L941,754L941,719L348,719ZM936,570Q870,602 817,622" "M348,719L348,754L941,754L941,719L348,719ZM936,570Q870,602 817,622"
"Q764,641 727,652L749,688Q852,655 957,605L936,570Z"; "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -639,8 +646,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98" char expected[] = "M371,-102L371,539L914,539L914,-27Q914,-102 840,-102Q796,-102 755,-98"
"L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102" "L742,-59Q790,-66 836,-66Q871,-66 871,-31L871,504L414,504L414,-102"
"L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46" "L371,-102ZM203,-94Q138,-94 86,-90L74,-52Q137,-59 188,-59Q211,-59 222,-46"
@ -660,7 +667,7 @@ test_hb_draw_font_kit_variations_tests (void)
"Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754" "Q823,321 848,281L813,262Q791,301 775,323Q749,288 715,258ZM348,719L348,754"
"L941,754L941,719L348,719ZM936,570Q870,602 817,622" "L941,754L941,719L348,719ZM936,570Q870,602 817,622"
"Q764,641 727,652L749,688Q852,655 957,605L936,570Z"; "Q764,641 727,652L749,688Q852,655 957,605L936,570Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -686,8 +693,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M246,15C188,15 147,27 101,68L142,23L117,117C111,143 96,149 81,149" char expected[] = "M246,15C188,15 147,27 101,68L142,23L117,117C111,143 96,149 81,149"
"C65,149 56,141 52,126C71,40 137,-13 244,-13C348,-13 436,46 436,156" "C65,149 56,141 52,126C71,40 137,-13 244,-13C348,-13 436,46 436,156"
"C436,229 405,295 271,349L247,359C160,393 119,439 119,506" "C436,229 405,295 271,349L247,359C160,393 119,439 119,506"
@ -696,7 +703,7 @@ test_hb_draw_font_kit_variations_tests (void)
"C161,665 78,606 78,500C78,414 128,361 224,321L261,305C367,259 395,217 395,152" "C161,665 78,606 78,500C78,414 128,361 224,321L261,305C367,259 395,217 395,152"
"C395,65 334,15 246,15ZM267,331L267,759L240,759L240,331L267,331ZM240,-115" "C395,65 334,15 246,15ZM267,331L267,759L240,759L240,331L267,331ZM240,-115"
"L267,-115L267,331L240,331L240,-115Z"; "L267,-115L267,331L240,331L240,-115Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
{ {
var.value = 500; var.value = 500;
@ -710,8 +717,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M251,36C206,36 165,42 118,61L176,21L161,99C151,152 129,167 101,167" char expected[] = "M251,36C206,36 165,42 118,61L176,21L161,99C151,152 129,167 101,167"
"C78,167 61,155 51,131C54,43 133,-14 247,-14C388,-14 474,64 474,171" "C78,167 61,155 51,131C54,43 133,-14 247,-14C388,-14 474,64 474,171"
"C474,258 430,321 294,370L257,383C188,406 150,438 150,499" "C474,258 430,321 294,370L257,383C188,406 150,438 150,499"
@ -720,7 +727,7 @@ test_hb_draw_font_kit_variations_tests (void)
"C450,597 370,656 264,656C140,656 57,576 57,474C57,373 119,318 227,279" "C450,597 370,656 264,656C140,656 57,576 57,474C57,373 119,318 227,279"
"L263,266C345,236 379,208 379,145C379,76 329,36 251,36ZM289,320" "L263,266C345,236 379,208 379,145C379,76 329,36 251,36ZM289,320"
"L289,746L242,746L242,320L289,320ZM240,-115L286,-115L286,320L240,320L240,-115Z"; "L289,746L242,746L242,320L289,320ZM240,-115L286,-115L286,320L240,320L240,-115Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
/* substitutes GSUB features depending on variations */ /* substitutes GSUB features depending on variations */
{ {
@ -735,8 +742,8 @@ test_hb_draw_font_kit_variations_tests (void)
codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint; codepoint = hb_buffer_get_glyph_infos (buffer, NULL)[0].codepoint;
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, codepoint, funcs, &user_data); hb_font_draw_glyph (font, codepoint, funcs, &draw_data);
char expected[] = "M258,38C197,38 167,48 118,71L192,19L183,103C177,155 155,174 115,174" char expected[] = "M258,38C197,38 167,48 118,71L192,19L183,103C177,155 155,174 115,174"
"C89,174 64,161 51,125C52,36 124,-16 258,-16C417,-16 513,67 513,175" "C89,174 64,161 51,125C52,36 124,-16 258,-16C417,-16 513,67 513,175"
"C513,278 457,328 322,388L289,403C232,429 203,452 203,500C203,562 244,589 301,589" "C513,278 457,328 322,388L289,403C232,429 203,452 203,500C203,562 244,589 301,589"
@ -744,7 +751,7 @@ test_hb_draw_font_kit_variations_tests (void)
"C491,590 408,643 290,643C141,643 57,563 57,460C57,357 122,307 233,256L265,241" "C491,590 408,643 290,643C141,643 57,563 57,460C57,357 122,307 233,256L265,241"
"C334,209 363,186 363,130C363,77 320,38 258,38ZM318,616L318,734L252,734L252,616" "C334,209 363,186 363,130C363,77 320,38 258,38ZM318,616L318,734L252,734L252,616"
"L318,616ZM253,-115L319,-115L319,14L253,14L253,-115Z"; "L318,616ZM253,-115L319,-115L319,14L253,14L253,-115Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
} }
hb_font_destroy (font); hb_font_destroy (font);
@ -756,7 +763,7 @@ test_hb_draw_estedad_vf (void)
{ {
/* https://github.com/harfbuzz/harfbuzz/issues/2215 */ /* https://github.com/harfbuzz/harfbuzz/issues/2215 */
char str[2048]; char str[2048];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
@ -770,18 +777,18 @@ test_hb_draw_estedad_vf (void)
hb_variation_from_string ("wght=100", -1, &var); hb_variation_from_string ("wght=100", -1, &var);
hb_font_set_variations (font, &var, 1); hb_font_set_variations (font, &var, 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 156, funcs, &user_data); hb_font_draw_glyph (font, 156, funcs, &draw_data);
/* Skip empty path where all the points of a path are equal */ /* Skip empty path where all the points of a path are equal */
char expected[] = "M150,1158L182,1158Q256,1158 317,1170Q377,1182 421,1213L421,430L521,430" char expected[] = "M150,1158L182,1158Q256,1158 317,1170Q377,1182 421,1213L421,430L521,430"
"L521,1490L421,1490L421,1320Q393,1279 344,1262Q294,1244 182,1244L150,1244" "L521,1490L421,1490L421,1320Q393,1279 344,1262Q294,1244 182,1244L150,1244"
"L150,1158ZM1815,-122L1669,-122L1669,642L1552,642L1055,-117L1055,-206" "L150,1158ZM1815,-122L1669,-122L1669,642L1552,642L1055,-117L1055,-206"
"L1569,-206L1569,-458L1669,-458L1669,-206L1815,-206L1815,-122ZM1569,-122" "L1569,-206L1569,-458L1669,-458L1669,-206L1815,-206L1815,-122ZM1569,-122"
"L1166,-122L1569,494L1569,-122ZM609,-79L1639,1288L1555,1334L525,-33L609,-79Z"; "L1166,-122L1569,494L1569,-122ZM609,-79L1639,1288L1555,1334L525,-33L609,-79Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 180, funcs, &user_data); hb_font_draw_glyph (font, 180, funcs, &draw_data);
/* Skip empty path where all the points of a path are equal */ /* Skip empty path where all the points of a path are equal */
char expected2[] = "M120,693Q120,545 177,414Q233,282 333,182Q433,81 567,24" char expected2[] = "M120,693Q120,545 177,414Q233,282 333,182Q433,81 567,24"
"Q701,-33 856,-33Q1010,-33 1144,24Q1277,81 1377,182Q1477,282 1534,414" "Q701,-33 856,-33Q1010,-33 1144,24Q1277,81 1377,182Q1477,282 1534,414"
@ -798,17 +805,17 @@ test_hb_draw_estedad_vf (void)
"M1165,334L973,568Q1065,591 1126,658Q1187,725 1187,819" "M1165,334L973,568Q1065,591 1126,658Q1187,725 1187,819"
"Q1187,896 1147,956Q1106,1015 1037,1049Q969,1083 886,1083" "Q1187,896 1147,956Q1106,1015 1037,1049Q969,1083 886,1083"
"L590,1083L590,310L690,310L690,557L860,557L1083,286L1165,334Z"; "L590,1083L590,310L690,310L690,557L860,557L1083,286L1165,334Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 262, funcs, &user_data); hb_font_draw_glyph (font, 262, funcs, &draw_data);
/* Skip empty path where all the points of a path are equal */ /* Skip empty path where all the points of a path are equal */
char expected3[] = "M422,598Q495,598 545,548Q595,498 595,426Q595,353 545,303Q494,252 422,252" char expected3[] = "M422,598Q495,598 545,548Q595,498 595,426Q595,353 545,303Q494,252 422,252"
"Q350,252 300,303Q250,353 250,426Q250,499 300,549Q349,598 422,598ZM422,698" "Q350,252 300,303Q250,353 250,426Q250,499 300,549Q349,598 422,598ZM422,698"
"Q347,698 285,662Q223,625 187,564Q150,502 150,426Q150,351 187,289" "Q347,698 285,662Q223,625 187,564Q150,502 150,426Q150,351 187,289"
"Q223,226 285,189Q346,152 422,152Q498,152 560,189Q622,226 658,288" "Q223,226 285,189Q346,152 422,152Q498,152 560,189Q622,226 658,288"
"Q695,351 695,426Q695,502 658,563Q621,625 559,661Q498,698 422,698Z"; "Q695,351 695,426Q695,502 658,563Q621,625 559,661Q498,698 422,698Z";
g_assert_cmpmem (str, user_data.consumed, expected3, sizeof (expected3) - 1); g_assert_cmpmem (str, draw_data.consumed, expected3, sizeof (expected3) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -820,7 +827,7 @@ test_hb_draw_stroking (void)
/* https://skia-review.googlesource.com/c/skia/+/266945 /* https://skia-review.googlesource.com/c/skia/+/266945
https://savannah.nongnu.org/bugs/index.php?57701 */ https://savannah.nongnu.org/bugs/index.php?57701 */
char str[2048]; char str[2048];
user_data_t user_data = { draw_data_t draw_data = {
.str = str, .str = str,
.size = sizeof (str) .size = sizeof (str)
}; };
@ -830,8 +837,8 @@ test_hb_draw_stroking (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 6, funcs, &user_data); hb_font_draw_glyph (font, 6, funcs, &draw_data);
/* Skip empty path where all the points of a path are equal */ /* 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" 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" "Q1868,332 2089,427Q2309,521 2468,680Q2627,839 2722,1060Q2816,1280 2816,1522"
@ -843,10 +850,10 @@ test_hb_draw_stroking (void)
"Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345" "Q2996,1342 2947,1165Q2897,987 2809,837Q2721,686 2595,560Q2468,433 2318,345"
"Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345" "Q2167,257 1990,208Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
"Q784,433 658,560Q531,686 443,837Q355,987 306,1165Q256,1342 256,1528Z"; "Q784,433 658,560Q531,686 443,837Q355,987 306,1165Q256,1342 256,1528Z";
g_assert_cmpmem (str, user_data.consumed, expected, sizeof (expected) - 1); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 7, funcs, &user_data); hb_font_draw_glyph (font, 7, funcs, &draw_data);
char expected2[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427" char expected2[] = "M436,1522Q436,1280 531,1060Q625,839 784,680Q943,521 1164,427"
"Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680" "Q1384,332 1626,332Q1868,332 2089,427Q2309,521 2468,680"
"Q2627,839 2722,1060Q2816,1280 2816,1522Q2816,1764 2722,1985" "Q2627,839 2722,1060Q2816,1280 2816,1522Q2816,1764 2722,1985"
@ -861,7 +868,7 @@ test_hb_draw_stroking (void)
"Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345" "Q1812,158 1626,158Q1440,158 1263,208Q1085,257 935,345"
"Q784,433 658,560Q531,686 443,837Q355,987 306,1165" "Q784,433 658,560Q531,686 443,837Q355,987 306,1165"
"Q256,1342 256,1528Z"; "Q256,1342 256,1528Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -871,21 +878,21 @@ test_hb_draw_stroking (void)
hb_font_t *font = hb_font_create (face); hb_font_t *font = hb_font_create (face);
hb_face_destroy (face); hb_face_destroy (face);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 4, funcs, &user_data); hb_font_draw_glyph (font, 4, funcs, &draw_data);
/* Skip empty path in CFF */ /* 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" 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"; "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); g_assert_cmpmem (str, draw_data.consumed, expected, sizeof (expected) - 1);
user_data.consumed = 0; draw_data.consumed = 0;
hb_font_draw_glyph (font, 5, funcs, &user_data); hb_font_draw_glyph (font, 5, funcs, &draw_data);
/* Fold consequent move-to commands */ /* Fold consequent move-to commands */
char expected2[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372" char expected2[] = "M106,372C106,532 237,662 397,662C557,662 688,532 688,372"
"C688,212 557,81 397,81C237,81 106,212 106,372ZM62,373" "C688,212 557,81 397,81C237,81 106,212 106,372ZM62,373"
"C62,188 212,39 397,39C582,39 731,188 731,373" "C62,188 212,39 397,39C582,39 731,188 731,373"
"C731,558 582,708 397,708C212,708 62,558 62,373Z"; "C731,558 582,708 397,708C212,708 62,558 62,373Z";
g_assert_cmpmem (str, user_data.consumed, expected2, sizeof (expected2) - 1); g_assert_cmpmem (str, draw_data.consumed, expected2, sizeof (expected2) - 1);
hb_font_destroy (font); hb_font_destroy (font);
} }
@ -905,18 +912,18 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
funcs = hb_draw_funcs_create (); funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to); hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to); hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to); hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to); hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path); hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
hb_draw_funcs_make_immutable (funcs); hb_draw_funcs_make_immutable (funcs);
funcs2 = hb_draw_funcs_create (); funcs2 = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs2, (hb_draw_move_to_func_t) move_to); hb_draw_funcs_set_move_to_func (funcs2, (hb_draw_move_to_func_t) move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs2, (hb_draw_line_to_func_t) line_to); hb_draw_funcs_set_line_to_func (funcs2, (hb_draw_line_to_func_t) line_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs2, (hb_draw_cubic_to_func_t) cubic_to); hb_draw_funcs_set_cubic_to_func (funcs2, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs2, (hb_draw_close_path_func_t) close_path); hb_draw_funcs_set_close_path_func (funcs2, (hb_draw_close_path_func_t) close_path, NULL, NULL);
hb_draw_funcs_make_immutable (funcs2); hb_draw_funcs_make_immutable (funcs2);
hb_test_init (&argc, &argv); hb_test_init (&argc, &argv);

View File

@ -5,7 +5,7 @@
#include "hb-fuzzer.hh" #include "hb-fuzzer.hh"
struct _user_data_t struct _draw_data_t
{ {
bool is_open; bool is_open;
unsigned path_len; unsigned path_len;
@ -16,63 +16,72 @@ struct _user_data_t
}; };
static void static void
_move_to (float to_x, float to_y, void *user_data_) _move_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
float to_x, float to_y,
void *user_data)
{ {
_user_data_t *user_data = (_user_data_t *) user_data_; _draw_data_t *draw_data = (_draw_data_t *) draw_data_;
assert (!user_data->is_open); assert (!draw_data->is_open);
user_data->is_open = true; draw_data->is_open = true;
user_data->path_start_x = user_data->path_last_x = to_x; draw_data->path_start_x = draw_data->path_last_x = to_x;
user_data->path_start_y = user_data->path_last_y = to_y; draw_data->path_start_y = draw_data->path_last_y = to_y;
} }
static void static void
_line_to (float to_x, float to_y, void *user_data_) _line_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
float to_x, float to_y,
void *user_data)
{ {
_user_data_t *user_data = (_user_data_t *) user_data_; _draw_data_t *draw_data = (_draw_data_t *) draw_data_;
assert (user_data->is_open); assert (draw_data->is_open);
assert (user_data->path_last_x != to_x || user_data->path_last_y != to_y); assert (draw_data->path_last_x != to_x || draw_data->path_last_y != to_y);
++user_data->path_len; ++draw_data->path_len;
user_data->path_last_x = to_x; draw_data->path_last_x = to_x;
user_data->path_last_y = to_y; draw_data->path_last_y = to_y;
} }
static void static void
_quadratic_to (float control_x, float control_y, _quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
float to_x, float to_y, void *user_data_) float control_x, float control_y,
float to_x, float to_y,
void *user_data)
{ {
_user_data_t *user_data = (_user_data_t *) user_data_; _draw_data_t *draw_data = (_draw_data_t *) draw_data_;
assert (user_data->is_open); assert (draw_data->is_open);
assert (user_data->path_last_x != control_x || user_data->path_last_y != control_y || assert (draw_data->path_last_x != control_x || draw_data->path_last_y != control_y ||
user_data->path_last_x != to_x || user_data->path_last_y != to_y); draw_data->path_last_x != to_x || draw_data->path_last_y != to_y);
++user_data->path_len; ++draw_data->path_len;
user_data->path_last_x = to_x; draw_data->path_last_x = to_x;
user_data->path_last_y = to_y; draw_data->path_last_y = to_y;
} }
static void static void
_cubic_to (float control1_x, float control1_y, _cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data_,
float control1_x, float control1_y,
float control2_x, float control2_y, float control2_x, float control2_y,
float to_x, float to_y, void *user_data_) float to_x, float to_y,
void *user_data)
{ {
_user_data_t *user_data = (_user_data_t *) user_data_; _draw_data_t *draw_data = (_draw_data_t *) draw_data_;
assert (user_data->is_open); assert (draw_data->is_open);
assert (user_data->path_last_x != control1_x || user_data->path_last_y != control1_y || assert (draw_data->path_last_x != control1_x || draw_data->path_last_y != control1_y ||
user_data->path_last_x != control2_x || user_data->path_last_y != control2_y || draw_data->path_last_x != control2_x || draw_data->path_last_y != control2_y ||
user_data->path_last_x != to_x || user_data->path_last_y != to_y); draw_data->path_last_x != to_x || draw_data->path_last_y != to_y);
++user_data->path_len; ++draw_data->path_len;
user_data->path_last_x = to_x; draw_data->path_last_x = to_x;
user_data->path_last_y = to_y; draw_data->path_last_y = to_y;
} }
static void static void
_close_path (void *user_data_) _close_path (hb_draw_funcs_t *dfuncs, void *draw_data_,
void *user_data)
{ {
_user_data_t *user_data = (_user_data_t *) user_data_; _draw_data_t *draw_data = (_draw_data_t *) draw_data_;
assert (user_data->is_open && user_data->path_len != 0); assert (draw_data->is_open && draw_data->path_len != 0);
user_data->path_len = 0; draw_data->path_len = 0;
user_data->is_open = false; draw_data->is_open = false;
assert (user_data->path_start_x == user_data->path_last_x && assert (draw_data->path_start_x == draw_data->path_last_x &&
user_data->path_start_y == user_data->path_last_y); draw_data->path_start_y == draw_data->path_last_y);
} }
/* Similar to test-ot-face.c's #test_font() */ /* Similar to test-ot-face.c's #test_font() */
@ -133,20 +142,20 @@ extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
unsigned glyph_count = hb_face_get_glyph_count (face); unsigned glyph_count = hb_face_get_glyph_count (face);
glyph_count = glyph_count > 16 ? 16 : glyph_count; glyph_count = glyph_count > 16 ? 16 : glyph_count;
_user_data_t user_data = {false, 0, 0, 0, 0, 0}; _draw_data_t draw_data = {false, 0, 0, 0, 0, 0};
hb_draw_funcs_t *funcs = hb_draw_funcs_create (); hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) _move_to); hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) _move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) _line_to); hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) _line_to, nullptr, nullptr);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) _quadratic_to); hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) _quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) _cubic_to); hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) _cubic_to, nullptr, nullptr);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) _close_path); hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) _close_path, nullptr, nullptr);
volatile unsigned counter = !glyph_count; volatile unsigned counter = !glyph_count;
hb_set_t *set = hb_set_create (); hb_set_t *set = hb_set_create ();
for (unsigned gid = 0; gid < glyph_count; ++gid) for (unsigned gid = 0; gid < glyph_count; ++gid)
{ {
hb_font_draw_glyph (font, gid, funcs, &user_data); hb_font_draw_glyph (font, gid, funcs, &draw_data);
assert (!user_data.is_open); assert (!draw_data.is_open);
/* Glyph extents also may practices the similar path, call it now that is related */ /* Glyph extents also may practices the similar path, call it now that is related */
hb_glyph_extents_t extents; hb_glyph_extents_t extents;