diff options
Diffstat (limited to 'pango/pangofc-shape.c')
-rw-r--r-- | pango/pangofc-shape.c | 248 |
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); } |