summaryrefslogtreecommitdiff
path: root/pango/pangofc-shape.c
diff options
context:
space:
mode:
Diffstat (limited to 'pango/pangofc-shape.c')
-rw-r--r--pango/pangofc-shape.c248
1 files changed, 245 insertions, 3 deletions
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c
index 12ce7ddb..c2b8dc3e 100644
--- a/pango/pangofc-shape.c
+++ b/pango/pangofc-shape.c
@@ -112,6 +112,239 @@ apply_extra_attributes (GSList *attrs,
}
}
+typedef struct
+{
+ PangoFont *font;
+ hb_font_t *parent;
+ PangoShowFlags show_flags;
+} PangoHbShapeContext;
+
+static hb_bool_t
+pango_hb_font_get_nominal_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if ((context->show_flags & PANGO_SHOW_IGNORABLES) != 0)
+ {
+ if (pango_get_ignorable (unicode))
+ {
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+ }
+
+ if ((context->show_flags & PANGO_SHOW_SPACES) != 0)
+ {
+ if (g_unichar_type (unicode) == G_UNICODE_SPACE_SEPARATOR)
+ {
+ /* Replace 0x20 by visible space, since we
+ * don't draw a hex box for 0x20
+ */
+ if (unicode == 0x20)
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (0x2423);
+ else
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+ }
+
+ if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0)
+ {
+ if (unicode == 0x2028)
+ {
+ /* Always mark LS as unknown. If it ends up
+ * at the line end, PangoLayout takes care of
+ * hiding them, and if they end up in the middle
+ * of a line, we are in single paragraph mode
+ * and want to show the LS
+ */
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+ }
+
+ if (hb_font_get_glyph (context->parent, unicode, 0, glyph))
+ return TRUE;
+
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+
+ /* We draw our own invalid-Unicode shape, so prevent HarfBuzz
+ * from using REPLACEMENT CHARACTER. */
+ if (unicode > 0x10FFFF)
+ return TRUE;
+
+ return FALSE;
+}
+
+static hb_bool_t
+pango_hb_font_get_variation_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (hb_font_get_glyph (context->parent,
+ unicode, variation_selector, glyph))
+ return TRUE;
+
+ return FALSE;
+}
+
+static hb_bool_t
+pango_hb_font_get_glyph_contour_point (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 G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ return hb_font_get_glyph_contour_point (context->parent, glyph, point_index, x, y);
+}
+
+static hb_position_t
+pango_hb_font_get_glyph_advance (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoRectangle logical;
+
+ pango_font_get_glyph_extents (context->font, glyph, NULL, &logical);
+ return logical.width;
+ }
+
+ return hb_font_get_glyph_h_advance (context->parent, glyph);
+}
+
+static hb_bool_t
+pango_hb_font_get_glyph_extents (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoRectangle ink;
+
+ pango_font_get_glyph_extents (context->font, glyph, &ink, NULL);
+
+ extents->x_bearing = ink.x;
+ extents->y_bearing = ink.y;
+ extents->width = ink.width;
+ extents->height = ink.height;
+
+ return TRUE;
+ }
+
+ return hb_font_get_glyph_extents (context->parent, glyph, extents);
+}
+
+static hb_bool_t
+pango_hb_font_get_glyph_h_origin (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ return hb_font_get_glyph_h_origin (context->parent, glyph, x, y);
+}
+
+static hb_bool_t
+pango_hb_font_get_glyph_v_origin (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ return hb_font_get_glyph_v_origin (context->parent, glyph, x, y);
+}
+
+static hb_position_t
+pango_hb_font_get_h_kerning (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ return hb_font_get_glyph_h_kerning (context->parent, left_glyph, right_glyph);
+}
+
+static hb_font_t *
+pango_font_get_hb_font_for_context (PangoFont *font,
+ PangoHbShapeContext *context)
+{
+ hb_font_t *hb_font;
+ static hb_font_funcs_t *funcs;
+
+ hb_font = pango_font_get_hb_font (font);
+ if (context->show_flags == PANGO_SHOW_NONE)
+ return hb_font_reference (hb_font);
+
+ if (G_UNLIKELY (!funcs))
+ {
+ funcs = hb_font_funcs_create ();
+ hb_font_funcs_set_nominal_glyph_func (funcs, pango_hb_font_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_variation_glyph_func (funcs, pango_hb_font_get_variation_glyph, NULL, NULL);
+ hb_font_funcs_set_glyph_h_advance_func (funcs, pango_hb_font_get_glyph_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_v_advance_func (funcs, pango_hb_font_get_glyph_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_h_origin_func (funcs, pango_hb_font_get_glyph_h_origin, NULL, NULL);
+ hb_font_funcs_set_glyph_v_origin_func (funcs, pango_hb_font_get_glyph_v_origin, NULL, NULL);
+ hb_font_funcs_set_glyph_h_kerning_func (funcs, pango_hb_font_get_h_kerning, NULL, NULL);
+ hb_font_funcs_set_glyph_extents_func (funcs, pango_hb_font_get_glyph_extents, NULL, NULL);
+ hb_font_funcs_set_glyph_contour_point_func (funcs, pango_hb_font_get_glyph_contour_point, NULL, NULL);
+ }
+
+ context->font = font;
+ context->parent = hb_font;
+
+ hb_font = hb_font_create_sub_font (hb_font);
+ hb_font_set_funcs (hb_font, funcs, context, NULL);
+
+ return hb_font;
+}
+
+static PangoShowFlags
+find_show_flags (const PangoAnalysis *analysis)
+{
+ GSList *l;
+ PangoShowFlags flags = 0;
+
+ for (l = analysis->extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ if (attr->klass->type == PANGO_ATTR_SHOW)
+ flags |= ((PangoAttrInt*)attr)->value;
+ }
+
+ return flags;
+}
+
void
pango_hb_shape (PangoFont *font,
const char *item_text,
@@ -121,6 +354,8 @@ pango_hb_shape (PangoFont *font,
const char *paragraph_text,
unsigned int paragraph_length)
{
+ PangoHbShapeContext context;
+ hb_buffer_flags_t hb_buffer_flags;
hb_font_t *hb_font;
hb_buffer_t *hb_buffer;
hb_direction_t hb_direction;
@@ -137,8 +372,8 @@ pango_hb_shape (PangoFont *font,
g_return_if_fail (font != NULL);
g_return_if_fail (analysis != NULL);
- hb_font = pango_font_get_hb_font (font);
-
+ context.show_flags = find_show_flags (analysis);
+ hb_font = pango_font_get_hb_font_for_context (font, &context);
hb_buffer = acquire_buffer (&free_buffer);
hb_direction = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity) ? HB_DIRECTION_TTB : HB_DIRECTION_LTR;
@@ -147,6 +382,11 @@ pango_hb_shape (PangoFont *font,
if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
hb_direction = HB_DIRECTION_REVERSE (hb_direction);
+ hb_buffer_flags = HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT;
+
+ if (context.show_flags & PANGO_SHOW_IGNORABLES)
+ hb_buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
+
/* setup buffer */
hb_buffer_set_direction (hb_buffer, hb_direction);
@@ -155,7 +395,8 @@ pango_hb_shape (PangoFont *font,
#if HB_VERSION_ATLEAST(1,0,3)
hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
#endif
- hb_buffer_set_flags (hb_buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (hb_buffer, hb_buffer_flags);
+ hb_buffer_set_invisible_glyph (hb_buffer, PANGO_GLYPH_EMPTY);
hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
if (analysis->flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN)
@@ -216,4 +457,5 @@ pango_hb_shape (PangoFont *font,
}
release_buffer (hb_buffer, free_buffer);
+ hb_font_destroy (hb_font);
}