diff options
Diffstat (limited to 'pango/pangofc-shape.c')
-rw-r--r-- | pango/pangofc-shape.c | 425 |
1 files changed, 0 insertions, 425 deletions
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c deleted file mode 100644 index 0a5ce7f9..00000000 --- a/pango/pangofc-shape.c +++ /dev/null @@ -1,425 +0,0 @@ -/* Pango - * pangofc-shape.c: Basic shaper for FreeType-based backends - * - * Copyright (C) 2000, 2007, 2009 Red Hat Software - * Authors: - * Owen Taylor <otaylor@redhat.com> - * Behdad Esfahbod <behdad@behdad.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" -#include <string.h> -#include <math.h> - -#include "pangohb-private.h" -#include "pango-impl-utils.h" - -#include <glib.h> - -/* cache a single hb_buffer_t */ -static hb_buffer_t *cached_buffer = NULL; /* MT-safe */ -G_LOCK_DEFINE_STATIC (cached_buffer); - -static hb_buffer_t * -acquire_buffer (gboolean *free_buffer) -{ - hb_buffer_t *buffer; - - if (G_LIKELY (G_TRYLOCK (cached_buffer))) - { - if (G_UNLIKELY (!cached_buffer)) - cached_buffer = hb_buffer_create (); - - buffer = cached_buffer; - *free_buffer = FALSE; - } - else - { - buffer = hb_buffer_create (); - *free_buffer = TRUE; - } - - return buffer; -} - -static void -release_buffer (hb_buffer_t *buffer, gboolean free_buffer) -{ - if (G_LIKELY (!free_buffer)) - { - hb_buffer_reset (buffer); - G_UNLOCK (cached_buffer); - } - else - hb_buffer_destroy (buffer); -} - -static void -apply_extra_attributes (GSList *attrs, - hb_feature_t *features, - guint length, - guint *num_features) -{ - GSList *l; - - for (l = attrs; l && *num_features < length; l = l->next) - { - PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_FONT_FEATURES) - { - PangoAttrFontFeatures *fattr = (PangoAttrFontFeatures *) attr; - const gchar *feat; - const gchar *end; - int len; - - feat = fattr->features; - - while (feat != NULL && *num_features < length) - { - end = strchr (feat, ','); - if (end) - len = end - feat; - else - len = -1; - if (hb_feature_from_string (feat, len, &features[*num_features])) - { - features[*num_features].start = attr->start_index; - features[*num_features].end = attr->end_index; - (*num_features)++; - } - - if (end == NULL) - break; - - feat = end + 1; - } - } - } - - /* Turn off ligatures when letterspacing */ - for (l = attrs; l && *num_features < length; l = l->next) - { - PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_LETTER_SPACING) - { - hb_tag_t tags[] = { - HB_TAG('l','i','g','a'), - HB_TAG('c','l','i','g'), - HB_TAG('d','l','i','g'), - }; - int i; - for (i = 0; i < G_N_ELEMENTS (tags); i++) - { - features[*num_features].tag = tags[i]; - features[*num_features].value = 0; - features[*num_features].start = attr->start_index; - features[*num_features].end = attr->end_index; - (*num_features)++; - } - } - } -} - -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 != 0) - { - if ((context->show_flags & PANGO_SHOW_SPACES) != 0 && - 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_IGNORABLES) != 0 && - pango_get_ignorable (unicode)) - { - *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode); - return TRUE; - } - - if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0 && - 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_nominal_glyph (context->parent, unicode, 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_position_t -pango_hb_font_get_glyph_h_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_position_t -pango_hb_font_get_glyph_v_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.height; - } - - return hb_font_get_glyph_v_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_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 (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_glyph_h_advance_func (funcs, pango_hb_font_get_glyph_h_advance, NULL, NULL); - hb_font_funcs_set_glyph_v_advance_func (funcs, pango_hb_font_get_glyph_v_advance, NULL, NULL); - hb_font_funcs_set_glyph_extents_func (funcs, pango_hb_font_get_glyph_extents, NULL, NULL); - - hb_font_funcs_make_immutable (funcs); - } - - 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, - unsigned int item_length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - const char *paragraph_text, - unsigned int paragraph_length) -{ - PangoHbShapeContext context = { 0, }; - hb_buffer_flags_t hb_buffer_flags; - hb_font_t *hb_font; - hb_buffer_t *hb_buffer; - hb_direction_t hb_direction; - gboolean free_buffer; - hb_glyph_info_t *hb_glyph; - hb_glyph_position_t *hb_position; - int last_cluster; - guint i, num_glyphs; - unsigned int item_offset = item_text - paragraph_text; - hb_feature_t features[32]; - unsigned int num_features = 0; - PangoGlyphInfo *infos; - - g_return_if_fail (font != NULL); - g_return_if_fail (analysis != NULL); - - 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; - if (analysis->level % 2) - hb_direction = HB_DIRECTION_REVERSE (hb_direction); - 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); - hb_buffer_set_script (hb_buffer, (hb_script_t) g_unicode_script_to_iso15924 (analysis->script)); - hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis->language), -1)); - hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); - 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) - { - /* Insert either a Unicode or ASCII hyphen. We may - * want to look for script-specific hyphens here. - */ - const char *p = paragraph_text + item_offset + item_length; - int last_char_len = p - g_utf8_prev_char (p); - hb_codepoint_t glyph; - - if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph)) - hb_buffer_add (hb_buffer, 0x2010, item_offset + item_length - last_char_len); - else if (hb_font_get_nominal_glyph (hb_font, '-', &glyph)) - hb_buffer_add (hb_buffer, '-', item_offset + item_length - last_char_len); - } - - pango_font_get_features (font, features, G_N_ELEMENTS (features), &num_features); - apply_extra_attributes (analysis->extra_attrs, features, G_N_ELEMENTS (features), &num_features); - - hb_shape (hb_font, hb_buffer, features, num_features); - - if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity)) - hb_buffer_reverse (hb_buffer); - - /* buffer output */ - num_glyphs = hb_buffer_get_length (hb_buffer); - hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL); - pango_glyph_string_set_size (glyphs, num_glyphs); - infos = glyphs->glyphs; - last_cluster = -1; - for (i = 0; i < num_glyphs; i++) - { - infos[i].glyph = hb_glyph->codepoint; - glyphs->log_clusters[i] = hb_glyph->cluster - item_offset; - infos[i].attr.is_cluster_start = glyphs->log_clusters[i] != last_cluster; - hb_glyph++; - last_cluster = glyphs->log_clusters[i]; - } - - hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL); - if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity)) - for (i = 0; i < num_glyphs; i++) - { - /* 90 degrees rotation counter-clockwise. */ - infos[i].geometry.width = - hb_position->y_advance; - infos[i].geometry.x_offset = - hb_position->y_offset; - infos[i].geometry.y_offset = - hb_position->x_offset; - hb_position++; - } - else /* horizontal */ - for (i = 0; i < num_glyphs; i++) - { - infos[i].geometry.width = hb_position->x_advance; - infos[i].geometry.x_offset = hb_position->x_offset; - infos[i].geometry.y_offset = - hb_position->y_offset; - hb_position++; - } - - release_buffer (hb_buffer, free_buffer); - hb_font_destroy (hb_font); -} |