[API] Add support for vertical text
Design not final yet, and in fact I'm going to change it immediately,
but this is an standalone change for itself.
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 8821ac1..875a884 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -48,28 +48,33 @@
/* Don't access these directly. Call hb_font_get_*() instead. */
+#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_FONT_FUNC_IMPLEMENT (glyph) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
+ HB_FONT_FUNC_IMPLEMENT (h_kerning) \
+ HB_FONT_FUNC_IMPLEMENT (v_kerning) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
+ HB_FONT_FUNC_IMPLEMENT (contour_point)
+
+
struct {
- hb_font_get_contour_point_func_t contour_point;
- hb_font_get_glyph_advance_func_t glyph_advance;
- hb_font_get_glyph_extents_func_t glyph_extents;
- hb_font_get_glyph_func_t glyph;
- hb_font_get_kerning_func_t kerning;
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
} get;
struct {
- void *contour_point;
- void *glyph_advance;
- void *glyph_extents;
- void *glyph;
- void *kerning;
+#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
} user_data;
struct {
- hb_destroy_func_t contour_point;
- hb_destroy_func_t glyph_advance;
- hb_destroy_func_t glyph_extents;
- hb_destroy_func_t glyph;
- hb_destroy_func_t kerning;
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
} destroy;
};
diff --git a/src/hb-font.cc b/src/hb-font.cc
index cff8527..9cdb302 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -42,64 +42,6 @@
*/
static hb_bool_t
-hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- unsigned int point_index,
- hb_position_t *x,
- hb_position_t *y,
- void *user_data HB_UNUSED)
-{
- if (font->parent) {
- hb_bool_t ret;
- ret = hb_font_get_contour_point (font->parent,
- glyph, point_index,
- x, y);
- font->parent_scale_position (x, y);
- return ret;
- }
-
- *x = *y = 0;
-
- return false;
-}
-
-static void
-hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_position_t *x_advance,
- hb_position_t *y_advance,
- void *user_data HB_UNUSED)
-{
- if (font->parent) {
- hb_font_get_glyph_advance (font->parent, glyph, x_advance, y_advance);
- font->parent_scale_distance (x_advance, y_advance);
- return;
- }
-
- *x_advance = *y_advance = 0;
-}
-
-static void
-hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data HB_UNUSED)
-{
- if (font->parent) {
- hb_font_get_glyph_extents (font->parent, glyph, extents);
- font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
- font->parent_scale_distance (&extents->width, &extents->height);
- return;
- }
-
- extents->x_bearing = extents->y_bearing = 0;
- extents->width = extents->height = 0;
-}
-
-static hb_bool_t
hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
@@ -114,22 +56,152 @@
return FALSE;
}
-static void
-hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
- hb_position_t *x_kern,
- hb_position_t *y_kern,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance,
+ hb_position_t *y_advance,
+ void *user_data HB_UNUSED)
{
if (font->parent) {
- hb_font_get_kerning (font->parent, left_glyph, right_glyph, x_kern, y_kern);
+ hb_bool_t ret = hb_font_get_glyph_h_advance (font->parent,
+ glyph,
+ x_advance, y_advance);
+ font->parent_scale_distance (x_advance, y_advance);
+ return ret;
+ }
+
+ *x_advance = *y_advance = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance,
+ hb_position_t *y_advance,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_v_advance (font->parent,
+ glyph,
+ x_advance, y_advance);
+ font->parent_scale_distance (x_advance, y_advance);
+ return ret;
+ }
+
+ *x_advance = *y_advance = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x_origin,
+ hb_position_t *y_origin,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
+ glyph,
+ x_origin, y_origin);
+ font->parent_scale_distance (x_origin, y_origin);
+ return ret;
+ }
+
+ *x_origin = *y_origin = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_h_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ hb_position_t *x_kern,
+ hb_position_t *y_kern,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_h_kerning (font->parent,
+ left_glyph, right_glyph,
+ x_kern, y_kern);
font->parent_scale_distance (x_kern, y_kern);
- return;
+ return ret;
}
*x_kern = *y_kern = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_v_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph,
+ hb_codepoint_t bottom_glyph,
+ hb_position_t *x_kern,
+ hb_position_t *y_kern,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_v_kerning (font->parent,
+ top_glyph, bottom_glyph,
+ x_kern, y_kern);
+ font->parent_scale_distance (x_kern, y_kern);
+ return ret;
+ }
+
+ *x_kern = *y_kern = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_bool_t *vertical,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
+ glyph,
+ vertical,
+ extents);
+ font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
+ font->parent_scale_distance (&extents->width, &extents->height);
+ return ret;
+ }
+
+ extents->x_bearing = extents->y_bearing = 0;
+ extents->width = extents->height = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_bool_t *vertical,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_contour_point (font->parent,
+ glyph, point_index,
+ vertical,
+ x, y);
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
}
@@ -139,11 +211,9 @@
TRUE, /* immutable */
{
- hb_font_get_contour_point_nil,
- hb_font_get_glyph_advance_nil,
- hb_font_get_glyph_extents_nil,
- hb_font_get_glyph_nil,
- hb_font_get_kerning_nil
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
}
};
@@ -178,13 +248,9 @@
{
if (!hb_object_destroy (ffuncs)) return;
-#define DESTROY(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name)
- DESTROY (contour_point);
- DESTROY (glyph_advance);
- DESTROY (glyph_extents);
- DESTROY (glyph);
- DESTROY (kerning);
-#undef DESTROY
+#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name);
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
free (ffuncs);
}
@@ -222,7 +288,7 @@
}
-#define IMPLEMENT(name) \
+#define HB_FONT_FUNC_IMPLEMENT(name) \
\
void \
hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
@@ -247,47 +313,9 @@
} \
}
-IMPLEMENT (contour_point);
-IMPLEMENT (glyph_advance);
-IMPLEMENT (glyph_extents);
-IMPLEMENT (glyph);
-IMPLEMENT (kerning);
+HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
-#undef IMPLEMENT
-
-
-hb_bool_t
-hb_font_get_contour_point (hb_font_t *font,
- hb_codepoint_t glyph, unsigned int point_index,
- hb_position_t *x, hb_position_t *y)
-{
- *x = 0; *y = 0;
- return font->klass->get.contour_point (font, font->user_data,
- glyph, point_index,
- x, y,
- font->klass->user_data.contour_point);
-}
-
-void
-hb_font_get_glyph_advance (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance)
-{
- *x_advance = *y_advance = 0;
- return font->klass->get.glyph_advance (font, font->user_data,
- glyph, x_advance, y_advance,
- font->klass->user_data.glyph_advance);
-}
-
-void
-hb_font_get_glyph_extents (hb_font_t *font,
- hb_codepoint_t glyph, hb_glyph_extents_t *extents)
-{
- memset (extents, 0, sizeof (*extents));
- return font->klass->get.glyph_extents (font, font->user_data,
- glyph, extents,
- font->klass->user_data.glyph_extents);
-}
hb_bool_t
hb_font_get_glyph (hb_font_t *font,
@@ -300,16 +328,165 @@
font->klass->user_data.glyph);
}
-void
-hb_font_get_kerning (hb_font_t *font,
- hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
- hb_position_t *x_kern, hb_position_t *y_kern)
+hb_bool_t
+hb_font_get_glyph_h_advance (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance)
+{
+ *x_advance = *y_advance = 0;
+ return font->klass->get.glyph_h_advance (font, font->user_data,
+ glyph, x_advance, y_advance,
+ font->klass->user_data.glyph_h_advance);
+}
+
+hb_bool_t
+hb_font_get_glyph_v_advance (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance)
+{
+ *x_advance = *y_advance = 0;
+ return font->klass->get.glyph_v_advance (font, font->user_data,
+ glyph, x_advance, y_advance,
+ font->klass->user_data.glyph_v_advance);
+}
+
+hb_bool_t
+hb_font_get_glyph_v_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_origin, hb_position_t *y_origin)
+{
+ *x_origin = *y_origin = 0;
+ return font->klass->get.glyph_v_origin (font, font->user_data,
+ glyph, x_origin, y_origin,
+ font->klass->user_data.glyph_v_origin);
+}
+
+hb_bool_t
+hb_font_get_h_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern)
{
*x_kern = *y_kern = 0;
- return font->klass->get.kerning (font, font->user_data,
- left_glyph, right_glyph,
- x_kern, y_kern,
- font->klass->user_data.kerning);
+ return font->klass->get.h_kerning (font, font->user_data,
+ left_glyph, right_glyph,
+ x_kern, y_kern,
+ font->klass->user_data.h_kerning);
+}
+
+hb_bool_t
+hb_font_get_v_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern)
+{
+ *x_kern = *y_kern = 0;
+ return font->klass->get.v_kerning (font, font->user_data,
+ left_glyph, right_glyph,
+ x_kern, y_kern,
+ font->klass->user_data.v_kerning);
+}
+
+hb_bool_t
+hb_font_get_glyph_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_bool_t *vertical,
+ hb_glyph_extents_t *extents)
+{
+ memset (extents, 0, sizeof (*extents));
+ return font->klass->get.glyph_extents (font, font->user_data,
+ glyph,
+ vertical,
+ extents,
+ font->klass->user_data.glyph_extents);
+}
+
+hb_bool_t
+hb_font_get_contour_point (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_bool_t *vertical,
+ hb_position_t *x, hb_position_t *y)
+{
+ *x = *y = 0;
+ return font->klass->get.contour_point (font, font->user_data,
+ glyph, point_index,
+ vertical,
+ x, y,
+ font->klass->user_data.contour_point);
+}
+
+
+/* A bit higher-level, and with fallback */
+
+void
+hb_font_get_glyph_advance_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x_advance, hb_position_t *y_advance)
+{
+ if (HB_DIRECTION_IS_VERTICAL (direction)) {
+ hb_bool_t ret = hb_font_get_glyph_v_advance (font, glyph, x_advance, y_advance);
+ if (!ret) {
+ /* TODO Simulate using h_advance and font_extents */
+ }
+ } else {
+ hb_font_get_glyph_h_advance (font, glyph, x_advance, y_advance);
+ }
+}
+
+void
+hb_font_get_kerning_for_direction (hb_font_t *font,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ hb_direction_t direction,
+ hb_position_t *x_kern, hb_position_t *y_kern)
+{
+ switch (direction) {
+ case HB_DIRECTION_LTR:
+ case HB_DIRECTION_RTL:
+ hb_font_get_h_kerning (font, first_glyph, second_glyph, x_kern, y_kern);
+ break;
+
+ case HB_DIRECTION_TTB:
+ case HB_DIRECTION_BTT:
+ hb_font_get_v_kerning (font, first_glyph, second_glyph, x_kern, y_kern);
+ break;
+
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
+ }
+}
+
+void
+hb_font_get_glyph_extents_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_glyph_extents_t *extents)
+{
+ hb_bool_t vertical = HB_DIRECTION_IS_VERTICAL (direction);
+ hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, &vertical, extents);
+
+ if (ret) {
+ if (vertical != HB_DIRECTION_IS_VERTICAL (direction)) {
+ /* XXX Adjust origin */
+ }
+ } else {
+ /* TODO Simulate using get_h_advance and font_extents? */
+ }
+}
+
+hb_bool_t
+hb_font_get_contour_point_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
+{
+ hb_bool_t vertical = HB_DIRECTION_IS_VERTICAL (direction);
+ hb_bool_t ret = hb_font_get_contour_point (font, glyph, point_index, &vertical, x, y);
+
+ if (ret && vertical != HB_DIRECTION_IS_VERTICAL (direction)) {
+ /* XXX Adjust origin */
+ }
+
+ return ret;
}
diff --git a/src/hb-font.h b/src/hb-font.h
index 1342c84..625ff4a 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -134,42 +134,47 @@
} hb_glyph_extents_t;
-typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph, unsigned int point_index,
- hb_position_t *x, hb_position_t *y,
- void *user_data);
-typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance,
- void *user_data);
-typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data);
+/* func types */
+
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data);
-typedef void (*hb_font_get_kerning_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
- hb_position_t *x_kern, hb_position_t *y_kern,
- void *user_data);
-void
-hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
- hb_font_get_contour_point_func_t contour_point_func,
- void *user_data, hb_destroy_func_t destroy);
+typedef hb_bool_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance,
+ void *user_data);
+typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
+typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
-void
-hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_advance_func_t glyph_advance_func,
- void *user_data, hb_destroy_func_t destroy);
+typedef hb_bool_t (*hb_font_get_glyph_v_origin_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_origin, hb_position_t *y_origin,
+ void *user_data);
-void
-hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_extents_func_t glyph_extents_func,
- void *user_data, hb_destroy_func_t destroy);
+typedef hb_bool_t (*hb_font_get_kerning_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern,
+ void *user_data);
+typedef hb_font_get_kerning_func_t hb_font_get_h_kerning_func_t;
+typedef hb_font_get_kerning_func_t hb_font_get_v_kerning_func_t;
+
+
+typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_bool_t *vertical,
+ hb_glyph_extents_t *extents,
+ void *user_data);
+typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_bool_t *vertical,
+ hb_position_t *x, hb_position_t *y,
+ void *user_data);
+
+
+/* func setters */
void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
@@ -177,35 +182,106 @@
void *user_data, hb_destroy_func_t destroy);
void
-hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
- hb_font_get_kerning_func_t kerning_func,
- void *user_data, hb_destroy_func_t destroy);
-
-
-hb_bool_t
-hb_font_get_contour_point (hb_font_t *font,
- hb_codepoint_t glyph, unsigned int point_index,
- hb_position_t *x, hb_position_t *y);
+hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_h_advance_func_t glyph_advance_func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_advance_func_t glyph_advance_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_get_glyph_advance (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance);
+hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_origin_func_t glyph_advance_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_get_glyph_extents (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents);
+hb_font_funcs_set_h_kerning_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_h_kerning_func_t kerning_func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_v_kerning_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_v_kerning_func_t kerning_func,
+ void *user_data, hb_destroy_func_t destroy);
+
+void
+hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_extents_func_t glyph_extents_func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_contour_point_func_t contour_point_func,
+ void *user_data, hb_destroy_func_t destroy);
+
+
+/* func dispatch */
hb_bool_t
hb_font_get_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph);
+hb_bool_t
+hb_font_get_glyph_h_advance (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance);
+hb_bool_t
+hb_font_get_glyph_v_advance (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance);
+
+hb_bool_t
+hb_font_get_glyph_v_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern);
+
+hb_bool_t
+hb_font_get_h_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern);
+hb_bool_t
+hb_font_get_v_kerning (hb_font_t *font,
+ hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph,
+ hb_position_t *x_kern, hb_position_t *y_kern);
+
+hb_bool_t
+hb_font_get_glyph_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_bool_t *vertical,
+ hb_glyph_extents_t *extents);
+
+hb_bool_t
+hb_font_get_contour_point (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_bool_t *vertical,
+ hb_position_t *x, hb_position_t *y);
+
+
+/* high-level funcs, with fallback */
+
void
-hb_font_get_kerning (hb_font_t *font,
- hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
- hb_position_t *x_kern, hb_position_t *y_kern);
+hb_font_get_glyph_advance_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x_advance, hb_position_t *y_advance);
+
+void
+hb_font_get_kerning_for_direction (hb_font_t *font,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ hb_direction_t direction,
+ hb_position_t *x_kern, hb_position_t *y_kern);
+
+void
+hb_font_get_glyph_extents_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_glyph_extents_t *extents);
+
+hb_bool_t
+hb_font_get_contour_point_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
/*
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index aef7e6f..3e66adc 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -36,76 +36,24 @@
HB_BEGIN_DECLS
-static hb_bool_t
-hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t glyph,
- unsigned int point_index,
- hb_position_t *x,
- hb_position_t *y,
- void *user_data HB_UNUSED)
-{
- FT_Face ft_face = (FT_Face) font_data;
- int load_flags = FT_LOAD_DEFAULT;
+/* TODO:
+ *
+ * In general, this file does a fine job of what it's supposed to do.
+ * There are, however, things that need more work:
+ *
+ * - We don't handle any load_flags. That definitely has API implications. :(
+ * I believe hb_ft_font_create() should take load_flags input.
+ *
+ * - We don't handle / allow for emboldening / obliqueing.
+ *
+ * - In the future, we should add constructors to create fonts in font space.
+ *
+ * - I believe transforms are not correctly implemented. FreeType does not
+ * provide any API to get to the transform/delta set on the face. :(
+ *
+ * - Always use FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH?
+ */
- /* TODO: load_flags, embolden, etc */
-
- if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
- return FALSE;
-
- if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
- return FALSE;
-
- if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
- return FALSE;
-
- *x = ft_face->glyph->outline.points[point_index].x;
- *y = ft_face->glyph->outline.points[point_index].y;
-
- return TRUE;
-}
-
-static void
-hb_ft_get_glyph_advance (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t glyph,
- hb_position_t *x_advance,
- hb_position_t *y_advance,
- void *user_data HB_UNUSED)
-{
- FT_Face ft_face = (FT_Face) font_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
- {
- *x_advance = ft_face->glyph->advance.x;
- *y_advance = ft_face->glyph->advance.y;
- }
-}
-
-static void
-hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data HB_UNUSED)
-{
- FT_Face ft_face = (FT_Face) font_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
- {
- /* XXX: A few negations should be in order here, not sure. */
- extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
- extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
- extents->width = ft_face->glyph->metrics.width;
- extents->height = ft_face->glyph->metrics.height;
- }
-}
static hb_bool_t
hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
@@ -130,23 +78,144 @@
return *glyph != 0;
}
-static void
-hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
- hb_position_t *x_kern,
- hb_position_t *y_kern,
- void *user_data HB_UNUSED)
+static hb_bool_t
+hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance,
+ hb_position_t *y_advance,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ *x_advance = ft_face->glyph->metrics.horiAdvance;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance,
+ hb_position_t *y_advance,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ *y_advance = -ft_face->glyph->metrics.vertAdvance;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_origin,
+ hb_position_t *y_origin,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ *y_origin = ft_face->glyph->metrics.vertAdvance;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_h_kerning (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ hb_position_t *x_kern,
+ hb_position_t *y_kern,
+ void *user_data HB_UNUSED)
{
FT_Face ft_face = (FT_Face) font_data;
FT_Vector kerning;
if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerning))
- return;
+ return FALSE;
*x_kern = kerning.x;
*y_kern = kerning.y;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_v_kerning (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t top_glyph,
+ hb_codepoint_t bottom_glyph,
+ hb_position_t *x_kern,
+ hb_position_t *y_kern,
+ void *user_data HB_UNUSED)
+{
+ /* FreeType API doesn't support vertical kerning */
+ return FALSE;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_bool_t *vertical,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ /* TODO: load_flags, embolden, etc, shape/transform */
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ /* XXX: A few negations should be in order here, not sure. */
+ extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
+ extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
+ extents->width = ft_face->glyph->metrics.width;
+ extents->height = ft_face->glyph->metrics.height;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_bool_t *vertical,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
+ return FALSE;
+
+ if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
+ return FALSE;
+
+ *x = ft_face->glyph->outline.points[point_index].x;
+ *y = ft_face->glyph->outline.points[point_index].y;
+ *vertical = FALSE; /* We always return position in horizontal coordinates */
+
+ return TRUE;
}
static hb_font_funcs_t ft_ffuncs = {
@@ -155,11 +224,14 @@
TRUE, /* immutable */
{
- hb_ft_get_contour_point,
- hb_ft_get_glyph_advance,
- hb_ft_get_glyph_extents,
hb_ft_get_glyph,
- hb_ft_get_kerning
+ hb_ft_get_glyph_h_advance,
+ hb_ft_get_glyph_v_advance,
+ hb_ft_get_glyph_v_origin,
+ hb_ft_get_h_kerning,
+ hb_ft_get_v_kerning,
+ hb_ft_get_glyph_extents,
+ hb_ft_get_contour_point,
}
};
@@ -210,7 +282,10 @@
blob = hb_blob_create ((const char *) ft_face->stream->base,
(unsigned int) ft_face->stream->size,
- /* TODO: Check FT_FACE_FLAG_EXTERNAL_STREAM? */
+ /* TODO: We assume that it's mmap()'ed, but FreeType code
+ * suggests that there are cases we reach here but font is
+ * not mmapped. For example, when mmap() fails. No idea
+ * how to deal with it better here. */
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
ft_face, destroy);
face = hb_face_create (blob, ft_face->face_index);
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index d06d7c2..a14dada 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -121,7 +121,7 @@
inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
{
hb_position_t x, y;
- if (hb_font_get_contour_point (font, glyph_id, caretValuePoint, &x, &y))
+ if (hb_font_get_contour_point_for_direction (font, glyph_id, caretValuePoint, direction, &x, &y))
return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
else
return 0;
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 100be67..6701a6a 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -210,6 +210,7 @@
private:
inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
+ hb_direction_t direction HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
*x = font->em_scale_x (xCoordinate);
@@ -235,6 +236,7 @@
private:
inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
+ hb_direction_t direction,
hb_position_t *x, hb_position_t *y) const
{
unsigned int x_ppem = font->x_ppem;
@@ -243,7 +245,7 @@
hb_bool_t ret = false;
if (x_ppem || y_ppem)
- ret = hb_font_get_contour_point (font, glyph_id, anchorPoint, &cx, &cy);
+ ret = hb_font_get_contour_point_for_direction (font, glyph_id, anchorPoint, direction, &cx, &cy);
*x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
*y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
}
@@ -268,6 +270,7 @@
private:
inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
+ hb_direction_t direction HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
*x = font->em_scale_x (xCoordinate);
@@ -306,14 +309,15 @@
struct Anchor
{
inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
+ hb_direction_t direction,
hb_position_t *x, hb_position_t *y) const
{
*x = *y = 0;
switch (u.format) {
- case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
- default: return;
+ case 1: u.format1.get_anchor (font, glyph_id, direction, x, y); return;
+ case 2: u.format2.get_anchor (font, glyph_id, direction, x, y); return;
+ case 3: u.format3.get_anchor (font, glyph_id, direction, x, y); return;
+ default: return;
}
}
@@ -403,8 +407,8 @@
hb_position_t mark_x, mark_y, base_x, base_y;
- mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->i].codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+ mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->i].codepoint, c->direction, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, c->direction, &base_x, &base_y);
hb_glyph_position_t &o = c->buffer->pos[c->buffer->i];
o.x_offset = base_x - mark_x;
@@ -859,23 +863,21 @@
unsigned int i = c->buffer->i;
hb_position_t entry_x, entry_y, exit_x, exit_y;
- (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y);
-
- hb_direction_t direction = c->buffer->props.direction;
+ (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, c->direction, &exit_x, &exit_y);
+ (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, c->direction, &entry_x, &entry_y);
/* Align the exit anchor of the left/top glyph with the entry anchor of the right/bottom glyph
* by adjusting advance of the left/top glyph. */
- if (HB_DIRECTION_IS_BACKWARD (direction))
+ if (HB_DIRECTION_IS_BACKWARD (c->direction))
{
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
c->buffer->pos[j].x_advance = c->buffer->pos[j].x_offset + entry_x - exit_x;
else
c->buffer->pos[j].y_advance = c->buffer->pos[j].y_offset + entry_y - exit_y;
}
else
{
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
c->buffer->pos[i].x_advance = c->buffer->pos[i].x_offset + exit_x - entry_x;
else
c->buffer->pos[i].y_advance = c->buffer->pos[i].y_offset + exit_y - entry_y;
@@ -884,7 +886,7 @@
if (c->lookup_props & LookupFlag::RightToLeft)
{
c->buffer->pos[i].cursive_chain() = j - i;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
c->buffer->pos[i].y_offset = entry_y - exit_y;
else
c->buffer->pos[i].x_offset = entry_x - exit_x;
@@ -892,7 +894,7 @@
else
{
c->buffer->pos[j].cursive_chain() = i - j;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
c->buffer->pos[j].y_offset = exit_y - entry_y;
else
c->buffer->pos[j].x_offset = exit_x - entry_x;
@@ -1414,6 +1416,7 @@
c->font = font;
c->face = font->face;
c->buffer = buffer;
+ c->direction = buffer->props.direction;
c->lookup_mask = lookup_mask;
c->context_length = context_length;
c->nesting_level_left = nesting_level_left;
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 56dc817..237b7ce 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -773,6 +773,7 @@
c->face = face;
c->buffer = buffer;
+ c->direction = buffer->props.direction;
c->lookup_mask = lookup_mask;
c->context_length = context_length;
c->nesting_level_left = nesting_level_left;
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 422ee43..4d6656a 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -56,6 +56,7 @@
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
+ hb_direction_t direction;
hb_mask_t lookup_mask;
unsigned int context_length;
unsigned int nesting_level_left;
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index ad6c2e2..3b6aa5a 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -169,7 +169,7 @@
{
hb_direction_t direction = c->buffer->props.direction;
- /* TODO vertical */
+ /* XXX vertical */
if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
direction != hb_script_get_horizontal_direction (c->buffer->props.script))
{
@@ -258,9 +258,10 @@
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
- hb_font_get_glyph_advance (c->font, c->buffer->info[i].codepoint,
- &c->buffer->pos[i].x_advance,
- &c->buffer->pos[i].y_advance);
+ hb_font_get_glyph_advance_for_direction (c->font, c->buffer->info[i].codepoint,
+ c->buffer->props.direction,
+ &c->buffer->pos[i].x_advance,
+ &c->buffer->pos[i].y_advance);
}
}
@@ -277,7 +278,10 @@
unsigned int count = c->buffer->len;
for (unsigned int i = 1; i < count; i++) {
hb_position_t x_kern, y_kern, kern1, kern2;
- hb_font_get_kerning (c->font, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint, &x_kern, &y_kern);
+ hb_font_get_kerning_for_direction (c->font,
+ c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint,
+ c->buffer->props.direction,
+ &x_kern, &y_kern);
kern1 = x_kern >> 1;
kern2 = x_kern - kern1;
diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc
index 9fb6f10..0ed0c83 100644
--- a/src/hb-ot-tag.cc
+++ b/src/hb-ot-tag.cc
@@ -686,7 +686,7 @@
}
}
- /* Else return a custom language in the form of "x-hbotXXXX" */
+ /* Else return a custom language in the form of "x-hbotABCD" */
{
unsigned char buf[11] = "x-hbot";
buf[6] = tag >> 24;