diff options
author | Matthias Clasen <mclasen@redhat.com> | 2019-07-18 23:17:32 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2019-07-18 23:17:32 +0000 |
commit | fdd9e9e707e42131e7749d8674c59f57e0923a35 (patch) | |
tree | 736a19c4682b2de18cdc6f96feaa14cd3258cf7f /pango | |
parent | be4d29953196744ab87b7e27be21a60131b109d1 (diff) | |
parent | 2a08070eb8db3132bea4c3d2ecd49e40c293e1a5 (diff) | |
download | pango-fdd9e9e707e42131e7749d8674c59f57e0923a35.tar.gz |
Merge branch 'kill-ft-face' into 'master'
Use harfbuzz for font metrics and glyph lookup
See merge request GNOME/pango!58
Diffstat (limited to 'pango')
-rw-r--r-- | pango/fonts.c | 46 | ||||
-rw-r--r-- | pango/pango-font-private.h | 6 | ||||
-rw-r--r-- | pango/pango-font.h | 3 | ||||
-rw-r--r-- | pango/pangocairo-fcfont.c | 2 | ||||
-rw-r--r-- | pango/pangocoretext.c | 24 | ||||
-rw-r--r-- | pango/pangofc-font-private.h | 2 | ||||
-rw-r--r-- | pango/pangofc-font.c | 435 | ||||
-rw-r--r-- | pango/pangofc-font.h | 9 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 78 | ||||
-rw-r--r-- | pango/pangofc-fontmap.h | 6 | ||||
-rw-r--r-- | pango/pangofc-private.h | 24 | ||||
-rw-r--r-- | pango/pangofc-shape.c | 386 | ||||
-rw-r--r-- | pango/pangoft2.c | 6 | ||||
-rw-r--r-- | pango/pangowin32.c | 85 | ||||
-rw-r--r-- | pango/pangoxft-font.c | 7 |
15 files changed, 456 insertions, 663 deletions
diff --git a/pango/fonts.c b/pango/fonts.c index fafd6a2d..4ba9d3fe 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -1617,11 +1617,29 @@ pango_parse_stretch (const char *str, * PangoFont */ -G_DEFINE_ABSTRACT_TYPE (PangoFont, pango_font, G_TYPE_OBJECT) +typedef struct { + hb_font_t *hb_font; +} PangoFontPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (PangoFont, pango_font, G_TYPE_OBJECT) + +static void +pango_font_finalize (GObject *object) +{ + PangoFont *font = PANGO_FONT (object); + PangoFontPrivate *priv = pango_font_get_instance_private (font); + + hb_font_destroy (priv->hb_font); + + G_OBJECT_CLASS (pango_font_parent_class)->finalize (object); +} static void pango_font_class_init (PangoFontClass *class G_GNUC_UNUSED) { + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = pango_font_finalize; } static void @@ -1838,6 +1856,32 @@ pango_font_get_font_map (PangoFont *font) return NULL; } +/** + * pango_font_get_hb_font: + * @font: a #PangoFont + * + * Get a hb_font_t object backing this font. + * + * Returns: (transfer none) (nullable): the hb_font_t object backing the + * font, or %NULL if the font does not have one + * + * Since: 1.44 + */ +hb_font_t * +pango_font_get_hb_font (PangoFont *font) +{ + PangoFontPrivate *priv = pango_font_get_instance_private (font); + + g_return_val_if_fail (PANGO_IS_FONT (font), NULL); + + if (priv->hb_font) + return priv->hb_font; + + priv->hb_font = PANGO_FONT_GET_CLASS (font)->create_hb_font (font); + + return priv->hb_font; +} + G_DEFINE_BOXED_TYPE (PangoFontMetrics, pango_font_metrics, pango_font_metrics_ref, pango_font_metrics_unref); diff --git a/pango/pango-font-private.h b/pango/pango-font-private.h index be399d7d..029bef99 100644 --- a/pango/pango-font-private.h +++ b/pango/pango-font-private.h @@ -179,11 +179,7 @@ struct _PangoFontClass hb_feature_t *features, guint len, guint *num_features); - - /*< private >*/ - - /* Padding for future expansion */ - void (*_pango_reserved1) (void); + hb_font_t * (*create_hb_font) (PangoFont *font); }; /* used for very rare and miserable situtations that we cannot even diff --git a/pango/pango-font.h b/pango/pango-font.h index 5e49d266..cec7efc6 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -26,6 +26,7 @@ #include <pango/pango-types.h> #include <glib-object.h> +#include <hb.h> G_BEGIN_DECLS @@ -492,6 +493,8 @@ void pango_font_get_features (PangoFont *font, hb_feature_t *features, guint len, guint *num_features); +PANGO_AVAILABLE_IN_1_44 +hb_font_t * pango_font_get_hb_font (PangoFont *font); /** diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c index 0019f83a..9c450317 100644 --- a/pango/pangocairo-fcfont.c +++ b/pango/pangocairo-fcfont.c @@ -118,7 +118,7 @@ pango_cairo_fc_font_get_glyph_extents (PangoFont *font, logical_rect); } -static FT_Face +static gpointer pango_cairo_fc_font_lock_face (PangoFcFont *font) { PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font); diff --git a/pango/pangocoretext.c b/pango/pangocoretext.c index a6eaa1fc..70fd67d4 100644 --- a/pango/pangocoretext.c +++ b/pango/pangocoretext.c @@ -32,6 +32,7 @@ #include "pangocoretext.h" #include "pangocoretext-private.h" +#include <harfbuzz/hb-coretext.h> struct _PangoCoreTextFontPrivate { @@ -208,6 +209,28 @@ pango_core_text_font_get_font_map (PangoFont *font) return ctfont->priv->fontmap; } +static hb_font_t * +pango_core_text_font_create_hb_font (PangoFont *font) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font; + + if (ctfont->priv->font_ref) + { + hb_font_t *hb_font; + int size; + + size = pango_core_text_font_key_get_size (ctfont->priv->key); + hb_font = hb_coretext_font_create (ctfont->priv->font_ref); + hb_font_set_scale (hb_font, size, size); + + hb_font_make_immutable (hb_font); + + return hb_font; + } + + return hb_font_get_empty (); +} + static void pango_core_text_font_init (PangoCoreTextFont *ctfont) { @@ -227,6 +250,7 @@ pango_core_text_font_class_init (PangoCoreTextFontClass *class) font_class->get_coverage = pango_core_text_font_get_coverage; font_class->find_shaper = pango_core_text_font_find_shaper; font_class->get_font_map = pango_core_text_font_get_font_map; + font_class->create_hb_font = pango_core_text_font_create_hb_font; } void diff --git a/pango/pangofc-font-private.h b/pango/pangofc-font-private.h index 07b088b3..91f89207 100644 --- a/pango/pangofc-font-private.h +++ b/pango/pangofc-font-private.h @@ -109,7 +109,7 @@ struct _PangoFcFontClass PangoFontClass parent_class; /*< public >*/ - FT_Face (*lock_face) (PangoFcFont *font); + gpointer (*lock_face) (PangoFcFont *font); void (*unlock_face) (PangoFcFont *font); gboolean (*has_char) (PangoFcFont *font, gunichar wc); diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index 870fd935..76afdf7e 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -46,9 +46,7 @@ #include "pango-layout.h" #include "pango-impl-utils.h" -#include <fontconfig/fcfreetype.h> - -#include FT_TRUETYPE_TABLES_H +#include <harfbuzz/hb-ot.h> enum { PROP_0, @@ -62,7 +60,6 @@ struct _PangoFcFontPrivate { PangoFcDecoder *decoder; PangoFcFontKey *key; - PangoFcCmapCache *cmap_cache; }; static gboolean pango_fc_font_real_has_char (PangoFcFont *font, @@ -93,6 +90,7 @@ static void pango_fc_font_get_features (PangoFont *font, hb_feature_t *features, guint len, guint *num_features); +static hb_font_t * pango_fc_font_create_hb_font (PangoFont *font); #define PANGO_FC_FONT_LOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->lock_face (font)) #define PANGO_FC_FONT_UNLOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->unlock_face (font)) @@ -120,6 +118,8 @@ pango_fc_font_class_init (PangoFcFontClass *class) font_class->get_metrics = pango_fc_font_get_metrics; font_class->get_font_map = pango_fc_font_get_font_map; font_class->get_features = pango_fc_font_get_features; + font_class->create_hb_font = pango_fc_font_create_hb_font; + font_class->get_features = pango_fc_font_get_features; g_object_class_install_property (object_class, PROP_PATTERN, g_param_spec_pointer ("pattern", @@ -173,9 +173,6 @@ pango_fc_font_finalize (GObject *object) if (priv->decoder) _pango_fc_font_set_decoder (fcfont, NULL); - if (priv->cmap_cache) - _pango_fc_cmap_cache_unref (priv->cmap_cache); - G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object); } @@ -198,16 +195,8 @@ pattern_is_transformed (FcPattern *pattern) if (FcPatternGetMatrix (pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch) { - FT_Matrix ft_matrix; - - ft_matrix.xx = 0x10000L * fc_matrix->xx; - ft_matrix.yy = 0x10000L * fc_matrix->yy; - ft_matrix.xy = 0x10000L * fc_matrix->xy; - ft_matrix.yx = 0x10000L * fc_matrix->yx; - - return ((ft_matrix.xy | ft_matrix.yx) != 0 || - ft_matrix.xx != 0x10000L || - ft_matrix.yy != 0x10000L); + return fc_matrix->xx != 1 || fc_matrix->xy != 0 || + fc_matrix->yx != 0 || fc_matrix->yy != 1; } else return FALSE; @@ -384,135 +373,55 @@ static void get_face_metrics (PangoFcFont *fcfont, PangoFontMetrics *metrics) { - FT_Face face = PANGO_FC_FONT_LOCK_FACE (fcfont); + hb_font_t *hb_font = pango_font_get_hb_font (PANGO_FONT (fcfont)); + hb_font_extents_t extents; + FcMatrix *fc_matrix; - FT_Matrix ft_matrix; - TT_OS2 *os2; gboolean have_transform = FALSE; - if (G_UNLIKELY (!face)) - { - metrics->descent = 0; - metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT; - metrics->height = metrics->ascent; - metrics->underline_thickness = PANGO_SCALE; - metrics->underline_position = - PANGO_SCALE; - metrics->strikethrough_thickness = PANGO_SCALE; - metrics->strikethrough_position = PANGO_SCALE * (PANGO_UNKNOWN_GLYPH_HEIGHT/2); - return; - } + hb_font_get_extents_for_direction (hb_font, HB_DIRECTION_LTR, &extents); if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch) { - ft_matrix.xx = 0x10000L * fc_matrix->xx; - ft_matrix.yy = 0x10000L * fc_matrix->yy; - ft_matrix.xy = 0x10000L * fc_matrix->xy; - ft_matrix.yx = 0x10000L * fc_matrix->yx; - - have_transform = (ft_matrix.xx != 0x10000 || ft_matrix.xy != 0 || - ft_matrix.yx != 0 || ft_matrix.yy != 0x10000); + have_transform = (fc_matrix->xx != 1 || fc_matrix->xy != 0 || + fc_matrix->yx != 0 || fc_matrix->yy != 1); } if (have_transform) { - FT_Vector vector; - - vector.x = 0; - vector.y = face->size->metrics.descender; - FT_Vector_Transform (&vector, &ft_matrix); - metrics->descent = - PANGO_UNITS_26_6 (vector.y); - - vector.x = 0; - vector.y = face->size->metrics.ascender; - FT_Vector_Transform (&vector, &ft_matrix); - metrics->ascent = PANGO_UNITS_26_6 (vector.y); - - vector.x = 0; - vector.y = face->size->metrics.height; - FT_Vector_Transform (&vector, &ft_matrix); - metrics->height = PANGO_UNITS_26_6 (vector.y); - } - else if (fcfont->is_hinted || - (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) - { - metrics->descent = - PANGO_UNITS_26_6 (face->size->metrics.descender); - metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender); - metrics->height = PANGO_UNITS_26_6 (face->size->metrics.height); + metrics->descent = - extents.descender * fc_matrix->yy; + metrics->ascent = extents.ascender * fc_matrix->yy; + metrics->height = (extents.ascender - extents.descender + extents.line_gap) * fc_matrix->yy; } else { - FT_Fixed ascender, descender, height; - - descender = FT_MulFix (face->descender, face->size->metrics.y_scale); - metrics->descent = - PANGO_UNITS_26_6 (descender); - - ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale); - metrics->ascent = PANGO_UNITS_26_6 (ascender); - - height = FT_MulFix (face->height, face->size->metrics.y_scale); - metrics->height = PANGO_UNITS_26_6 (height); - } - - metrics->underline_thickness = 0; - metrics->underline_position = 0; - - { - FT_Fixed ft_thickness, ft_position; - - ft_thickness = FT_MulFix (face->underline_thickness, face->size->metrics.y_scale); - metrics->underline_thickness = PANGO_UNITS_26_6 (ft_thickness); - - ft_position = FT_MulFix (face->underline_position, face->size->metrics.y_scale); - metrics->underline_position = PANGO_UNITS_26_6 (ft_position); - } - - if (metrics->underline_thickness == 0 || metrics->underline_position == 0) - { - metrics->underline_thickness = (PANGO_SCALE * face->size->metrics.y_ppem) / 14; - metrics->underline_position = - metrics->underline_thickness; + metrics->descent = - extents.descender; + metrics->ascent = extents.ascender; + metrics->height = extents.ascender - extents.descender + extents.line_gap; } + metrics->underline_thickness = PANGO_SCALE; + metrics->underline_position = - PANGO_SCALE; + metrics->strikethrough_thickness = PANGO_SCALE; + metrics->strikethrough_position = metrics->ascent / 2; - metrics->strikethrough_thickness = 0; - metrics->strikethrough_position = 0; - - os2 = FT_Get_Sfnt_Table (face, ft_sfnt_os2); - if (os2 && os2->version != 0xFFFF) - { - FT_Fixed ft_thickness, ft_position; + /* FIXME: use the right hb version */ +#if HB_VERSION_ATLEAST(2,5,4) + hb_position_t position; - ft_thickness = FT_MulFix (os2->yStrikeoutSize, face->size->metrics.y_scale); - metrics->strikethrough_thickness = PANGO_UNITS_26_6 (ft_thickness); + if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_UNDERLINE_SIZE, &position)) + metrics->underline_thickness = position; - ft_position = FT_MulFix (os2->yStrikeoutPosition, face->size->metrics.y_scale); - metrics->strikethrough_position = PANGO_UNITS_26_6 (ft_position); - } - - if (metrics->strikethrough_thickness == 0 || metrics->strikethrough_position == 0) - { - metrics->strikethrough_thickness = metrics->underline_thickness; - metrics->strikethrough_position = (PANGO_SCALE * face->size->metrics.y_ppem) / 4; - } - - - /* If hinting is on for this font, quantize the underline and strikethrough position - * to integer values. - */ - if (fcfont->is_hinted) - { - pango_quantize_line_geometry (&metrics->underline_thickness, - &metrics->underline_position); - pango_quantize_line_geometry (&metrics->strikethrough_thickness, - &metrics->strikethrough_position); - - /* Quantizing may have pushed underline_position to 0. Not good */ - if (metrics->underline_position == 0) - metrics->underline_position = - metrics->underline_thickness; - } + if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_UNDERLINE_OFFSET, &position)) + metrics->underline_position = position; + if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_STRIKEOUT_SIZE, &position)) + metrics->strikethrough_thickness = position; - PANGO_FC_FONT_UNLOCK_FACE (fcfont); + if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_STRIKEOUT_OFFSET, &position)) + metrics->strikethrough_position = position; +#endif } PangoFontMetrics * @@ -660,50 +569,12 @@ static guint pango_fc_font_real_get_glyph (PangoFcFont *font, gunichar wc) { - PangoFcFontPrivate *priv = font->priv; - FT_Face face; - FT_UInt index; - - guint idx; - PangoFcCmapCacheEntry *entry; - - - if (G_UNLIKELY (priv->cmap_cache == NULL)) - { - PangoFcFontMap *fontmap = g_weak_ref_get ((GWeakRef *) &font->fontmap); - if (G_UNLIKELY (!fontmap)) - return 0; - - priv->cmap_cache = _pango_fc_font_map_get_cmap_cache (fontmap, font); - - g_object_unref (fontmap); - - if (G_UNLIKELY (!priv->cmap_cache)) - return 0; - } - - idx = wc & CMAP_CACHE_MASK; - entry = priv->cmap_cache->entries + idx; - - if (entry->ch != wc) - { - face = PANGO_FC_FONT_LOCK_FACE (font); - if (G_LIKELY (face)) - { - index = FcFreeTypeCharIndex (face, wc); - if (index > (FT_UInt)face->num_glyphs) - index = 0; - - PANGO_FC_FONT_UNLOCK_FACE (font); - } - else - index = 0; + hb_font_t *hb_font = pango_font_get_hb_font (PANGO_FONT (font)); + hb_codepoint_t glyph = PANGO_GET_UNKNOWN_GLYPH (wc); - entry->ch = wc; - entry->glyph = index; - } + hb_font_get_nominal_glyph (hb_font, wc, &glyph); - return entry->glyph; + return glyph; } /** @@ -717,8 +588,9 @@ pango_fc_font_real_get_glyph (PangoFcFont *font, * Return value: the FreeType <type>FT_Face</type> associated with @font. * * Since: 1.4 + * Deprecated: 1.44: Use pango_font_get_hb_font() instead **/ -FT_Face +gpointer pango_fc_font_lock_face (PangoFcFont *font) { g_return_val_if_fail (PANGO_IS_FC_FONT (font), NULL); @@ -734,6 +606,7 @@ pango_fc_font_lock_face (PangoFcFont *font) * pango_fc_font_lock_face(). * * Since: 1.4 + * Deprecated: 1.44: Use pango_font_get_hb_font() instead **/ void pango_fc_font_unlock_face (PangoFcFont *font) @@ -921,27 +794,9 @@ _pango_fc_font_set_font_key (PangoFcFont *fcfont, priv->key = key; } -static FT_Glyph_Metrics * -get_per_char (FT_Face face, - FT_Int32 load_flags, - PangoGlyph glyph) -{ - FT_Error error; - FT_Glyph_Metrics *result; - - error = FT_Load_Glyph (face, glyph, load_flags); - if (error == FT_Err_Ok) - result = &face->glyph->metrics; - else - result = NULL; - - return result; -} - /** * pango_fc_font_get_raw_extents: * @fcfont: a #PangoFcFont - * @load_flags: flags to pass to FT_Load_Glyph() * @glyph: the glyph index to load * @ink_rect: (out) (optional): location to store ink extents of the * glyph, or %NULL @@ -962,81 +817,62 @@ get_per_char (FT_Face face, **/ void pango_fc_font_get_raw_extents (PangoFcFont *fcfont, - FT_Int32 load_flags, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect) { - FT_Glyph_Metrics *gm; - FT_Face face; - g_return_if_fail (PANGO_IS_FC_FONT (fcfont)); - face = PANGO_FC_FONT_LOCK_FACE (fcfont); - if (G_UNLIKELY (!face)) - { - /* Get generic unknown-glyph extents. */ - pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect); - return; - } - if (glyph == PANGO_GLYPH_EMPTY) - gm = NULL; - else - gm = get_per_char (face, load_flags, glyph); - - if (gm) { if (ink_rect) { - ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX); - ink_rect->width = PANGO_UNITS_26_6 (gm->width); - ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY); - ink_rect->height = PANGO_UNITS_26_6 (gm->height); + ink_rect->x = 0; + ink_rect->width = 0; + ink_rect->y = 0; + ink_rect->height = 0; } if (logical_rect) { logical_rect->x = 0; - logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance); - if (fcfont->is_hinted || - (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) - { - logical_rect->y = - PANGO_UNITS_26_6 (face->size->metrics.ascender); - logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender - face->size->metrics.descender); - } - else - { - FT_Fixed ascender, descender; - - ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale); - descender = FT_MulFix (face->descender, face->size->metrics.y_scale); - - logical_rect->y = - PANGO_UNITS_26_6 (ascender); - logical_rect->height = PANGO_UNITS_26_6 (ascender - descender); - } + logical_rect->width = 0; + logical_rect->y = 0; + logical_rect->height = 0; } } else { + hb_font_t *hb_font = pango_font_get_hb_font (PANGO_FONT (fcfont)); + hb_glyph_extents_t extents; + hb_font_extents_t font_extents; + + hb_font_get_glyph_extents (hb_font, glyph, &extents); + hb_font_get_extents_for_direction (hb_font, HB_DIRECTION_LTR, &font_extents); + if (ink_rect) { - ink_rect->x = 0; - ink_rect->width = 0; - ink_rect->y = 0; - ink_rect->height = 0; + ink_rect->x = extents.x_bearing; + ink_rect->width = extents.width; + ink_rect->y = -extents.y_bearing; + ink_rect->height = extents.height; } if (logical_rect) { + hb_position_t x, y; + + hb_font_get_glyph_advance_for_direction (hb_font, + glyph, + HB_DIRECTION_LTR, + &x, &y); + logical_rect->x = 0; - logical_rect->width = 0; - logical_rect->y = 0; - logical_rect->height = 0; + logical_rect->width = x; + logical_rect->y = - font_extents.ascender; + logical_rect->height = font_extents.ascender - font_extents.descender; } } - - PANGO_FC_FONT_UNLOCK_FACE (fcfont); } static void @@ -1064,3 +900,136 @@ pango_fc_font_get_features (PangoFont *font, } } } + +extern gpointer get_gravity_class (void); + +static PangoGravity +pango_fc_font_key_get_gravity (PangoFcFontKey *key) +{ + FcPattern *pattern; + PangoGravity gravity = PANGO_GRAVITY_SOUTH; + FcChar8 *s; + + pattern = pango_fc_font_key_get_pattern (key); + if (FcPatternGetString (pattern, PANGO_FC_GRAVITY, 0, (FcChar8 **)&s) == FcResultMatch) + { + GEnumValue *value = g_enum_get_value_by_nick (get_gravity_class (), (char *)s); + gravity = value->value; + } + + return gravity; +} + +static double +get_font_size (PangoFcFontKey *key) +{ + FcPattern *pattern; + double size; + double dpi; + + pattern = pango_fc_font_key_get_pattern (key); + if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) + return size; + + /* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern() + * and here. That would be very weird. + */ + + if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) != FcResultMatch) + dpi = 72; + + if (FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch) + return size * dpi / 72.; + + /* Whatever */ + return 18.; +} + +static void +parse_variations (const char *variations, + hb_variation_t **hb_variations, + guint *n_variations) +{ + guint n; + hb_variation_t *var; + int i; + const char *p; + + n = 1; + for (i = 0; variations[i]; i++) + { + if (variations[i] == ',') + n++; + } + + var = g_new (hb_variation_t, n); + + p = variations; + n = 0; + while (p && *p) + { + char *end = strchr (p, ','); + if (hb_variation_from_string (p, end ? end - p: -1, &var[n])) + n++; + p = end ? end + 1 : NULL; + } + + *hb_variations = var; + *n_variations = n; +} + +static hb_font_t * +pango_fc_font_create_hb_font (PangoFont *font) +{ + PangoFcFont *fc_font = PANGO_FC_FONT (font); + PangoFcFontKey *key; + hb_face_t *hb_face; + hb_font_t *hb_font; + double x_scale_inv, y_scale_inv; + double x_scale, y_scale; + double size; + PangoGravity gravity; + + x_scale_inv = y_scale_inv = 1.0; + key = _pango_fc_font_get_font_key (fc_font); + if (key) + { + const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key); + pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv); + } + if (PANGO_GRAVITY_IS_IMPROPER (gravity)) + { + x_scale_inv = -x_scale_inv; + y_scale_inv = -y_scale_inv; + } + + x_scale = 1. / x_scale_inv; + y_scale = 1. / y_scale_inv; + + size = get_font_size (key); + gravity = pango_fc_font_key_get_gravity (key); + hb_face = pango_fc_font_map_get_hb_face (PANGO_FC_FONT_MAP (fc_font->fontmap), fc_font); + + hb_font = hb_font_create (hb_face); + hb_font_set_scale (hb_font, + size * PANGO_SCALE * x_scale, + size * PANGO_SCALE * y_scale); + if (key) + { + const char *variations = pango_fc_font_key_get_variations (key); + if (variations) + { + guint n_variations; + hb_variation_t *hb_variations; + + parse_variations (variations, &hb_variations, &n_variations); + hb_font_set_variations (hb_font, hb_variations, n_variations); + + g_free (hb_variations); + } + } + + hb_font_make_immutable (hb_font); + + return hb_font; +} diff --git a/pango/pangofc-font.h b/pango/pangofc-font.h index 38d86fa9..fc6ee529 100644 --- a/pango/pangofc-font.h +++ b/pango/pangofc-font.h @@ -30,8 +30,6 @@ #pragma GCC diagnostic ignored "-Wundef" #endif -#include <ft2build.h> -#include FT_FREETYPE_H #include <fontconfig/fontconfig.h> #ifdef PANGO_COMPILATION @@ -47,13 +45,12 @@ G_BEGIN_DECLS typedef struct _PangoFcFont PangoFcFont; typedef struct _PangoFcFontClass PangoFcFontClass; - PANGO_AVAILABLE_IN_ALL GType pango_fc_font_get_type (void) G_GNUC_CONST; -PANGO_AVAILABLE_IN_1_4 -FT_Face pango_fc_font_lock_face (PangoFcFont *font); -PANGO_AVAILABLE_IN_1_4 +PANGO_DEPRECATED_IN_1_44_FOR(pango_font_get_hb_font) +gpointer pango_fc_font_lock_face (PangoFcFont *font); +PANGO_DEPRECATED_IN_1_44_FOR(pango_font_get_hb_font) void pango_fc_font_unlock_face (PangoFcFont *font); G_END_DECLS diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 27abb29e..0659b078 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -52,6 +52,7 @@ #include "pango-impl-utils.h" #include "pango-enum-types.h" #include "pango-coverage-private.h" +#include <hb-ft.h> /* Overview: @@ -165,7 +166,8 @@ struct _PangoFcFontFaceData /* Data */ FcPattern *pattern; /* Referenced pattern that owns filename */ PangoCoverage *coverage; - PangoFcCmapCache *cmap_cache; + + hb_face_t *hb_face; }; struct _PangoFcFace @@ -261,7 +263,9 @@ static FcPattern *pango_fc_patterns_get_font_pattern (PangoFcPatterns *pat static FcPattern *uniquify_pattern (PangoFcFontMap *fcfontmap, FcPattern *pattern); -static gpointer +gpointer get_gravity_class (void); + +gpointer get_gravity_class (void) { static GEnumClass *class = NULL; /* MT-safe */ @@ -294,8 +298,7 @@ pango_fc_font_face_data_free (PangoFcFontFaceData *data) if (data->coverage) pango_coverage_unref (data->coverage); - if (data->cmap_cache) - _pango_fc_cmap_cache_unref (data->cmap_cache); + hb_face_destroy (data->hb_face); g_slice_free (PangoFcFontFaceData, data); } @@ -1932,53 +1935,6 @@ pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap, return data; } -static PangoFcCmapCache * -_pango_fc_cmap_cache_ref (PangoFcCmapCache *cmap_cache) -{ - g_atomic_int_inc ((int *) &cmap_cache->ref_count); - - return cmap_cache; -} - -void -_pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache) -{ - g_return_if_fail (cmap_cache->ref_count > 0); - - if (g_atomic_int_dec_and_test ((int *) &cmap_cache->ref_count)) - { - g_free (cmap_cache); - } -} - -PangoFcCmapCache * -_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap, - PangoFcFont *fcfont) -{ - PangoFcFontFaceData *data; - - if (G_UNLIKELY (fcfontmap == NULL)) - return NULL; - - if (G_UNLIKELY (!fcfont->font_pattern)) - return NULL; - - data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); - if (G_UNLIKELY (!data)) - return NULL; - - if (G_UNLIKELY (data->cmap_cache == NULL)) - { - data->cmap_cache = g_new0 (PangoFcCmapCache, 1); - data->cmap_cache->ref_count = 1; - - /* Make sure all cache entries are invalid initially */ - data->cmap_cache->entries[0].ch = 1; /* char 1 cannot happen in bucket 0 */ - } - - return _pango_fc_cmap_cache_ref (data->cmap_cache); -} - typedef struct { PangoCoverage parent_instance; @@ -2728,3 +2684,23 @@ pango_fc_family_init (PangoFcFamily *fcfamily) { fcfamily->n_faces = -1; } + +hb_face_t * +pango_fc_font_map_get_hb_face (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont) +{ + PangoFcFontFaceData *data; + + data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); + + if (!data->hb_face) + { + hb_blob_t *blob; + + blob = hb_blob_create_from_file (data->filename); + data->hb_face = hb_face_create (blob, data->id); + hb_blob_destroy (blob); + } + + return data->hb_face; +} diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h index 5195d761..495adc52 100644 --- a/pango/pangofc-fontmap.h +++ b/pango/pangofc-fontmap.h @@ -26,6 +26,7 @@ #include <fontconfig/fontconfig.h> #include <pango/pangofc-decoder.h> #include <pango/pangofc-font.h> +#include <hb.h> G_BEGIN_DECLS @@ -42,7 +43,6 @@ typedef struct _PangoFcFontMap PangoFcFontMap; typedef struct _PangoFcFontMapClass PangoFcFontMapClass; typedef struct _PangoFcFontMapPrivate PangoFcFontMapPrivate; - PANGO_AVAILABLE_IN_ALL GType pango_fc_font_map_get_type (void) G_GNUC_CONST; @@ -87,6 +87,10 @@ PANGO_AVAILABLE_IN_1_4 PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_size); +PANGO_AVAILABLE_IN_1_44 +hb_face_t * pango_fc_font_map_get_hb_face (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); + /** * PANGO_FC_GRAVITY: * diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h index 5babc536..8d281ad8 100644 --- a/pango/pangofc-private.h +++ b/pango/pangofc-private.h @@ -43,25 +43,6 @@ struct _PangoFcMetricsInfo }; -typedef struct _PangoFcCmapCacheEntry PangoFcCmapCacheEntry; -typedef struct _PangoFcCmapCache PangoFcCmapCache; - -#define CMAP_CACHE_NUM_ENTRIES 256 /* should be power of two */ -#define CMAP_CACHE_MASK (CMAP_CACHE_NUM_ENTRIES - 1) - -struct _PangoFcCmapCacheEntry -{ - gunichar ch; - PangoGlyph glyph; -}; - -struct _PangoFcCmapCache -{ - guint ref_count; - PangoFcCmapCacheEntry entries[CMAP_CACHE_NUM_ENTRIES]; -}; - - #define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) #define PANGO_PIXELS_26_6(d) \ (((d) >= 0) ? \ @@ -79,10 +60,6 @@ PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, PangoFcFont *fcfont); PangoCoverage *_pango_fc_font_map_fc_to_coverage (FcCharSet *charset); -PangoFcCmapCache *_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap, - PangoFcFont *fcfont); -void _pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache); - PangoFcDecoder *_pango_fc_font_get_decoder (PangoFcFont *font); void _pango_fc_font_set_decoder (PangoFcFont *font, PangoFcDecoder *decoder); @@ -93,7 +70,6 @@ void _pango_fc_font_set_font_key (PangoFcFont *fcfont, _PANGO_EXTERN void pango_fc_font_get_raw_extents (PangoFcFont *font, - FT_Int32 load_flags, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect); diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c index 9bedd28a..59b90c40 100644 --- a/pango/pangofc-shape.c +++ b/pango/pangofc-shape.c @@ -70,249 +70,6 @@ release_buffer (hb_buffer_t *buffer, gboolean free_buffer) hb_buffer_destroy (buffer); } -typedef struct _PangoFcHbContext { - FT_Face ft_face; - PangoFcFont *fc_font; - gboolean vertical; - double x_scale, y_scale; /* CTM scales. */ -} PangoFcHbContext; - -static hb_bool_t -pango_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - PangoFcFont *fc_font = context->fc_font; - - *glyph = pango_fc_font_get_glyph (fc_font, unicode); - if (G_LIKELY (*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_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - FT_Face ft_face = context->ft_face; - unsigned int g; - - g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); - - if (G_UNLIKELY (!g)) - return FALSE; - - *glyph = g; - return TRUE; -} - -static hb_bool_t -pango_fc_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) -{ - return FALSE; -#if 0 - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT; - - /* TODO: load_flags, embolden, etc */ - - if (HB_UNLIKELY (FT_Load_Glyph (ft_face, glyph, load_flags))) - return FALSE; - - if (HB_UNLIKELY (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) - return FALSE; - - if (HB_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; -#endif -} - -static hb_position_t -pango_fc_hb_font_get_glyph_advance (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - void *user_data G_GNUC_UNUSED) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - PangoFcFont *fc_font = context->fc_font; - PangoRectangle logical; - - pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, NULL, &logical); - - return logical.width; -} - -static hb_bool_t -pango_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - PangoFcFont *fc_font = context->fc_font; - PangoRectangle ink; - - pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, &ink, NULL); - - if (G_LIKELY (!context->vertical)) { - extents->x_bearing = ink.x; - extents->y_bearing = ink.y; - extents->width = ink.width; - extents->height = ink.height; - } else { - /* XXX */ - extents->x_bearing = ink.x; - extents->y_bearing = ink.y; - extents->width = ink.height; - extents->height = ink.width; - } - - return TRUE; -} - -static hb_bool_t -pango_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - FT_Face ft_face = context->ft_face; - int load_flags = FT_LOAD_DEFAULT; - - if (!context->vertical) return TRUE; - - if (FT_Load_Glyph (ft_face, glyph, load_flags)) - return FALSE; - - /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates - * have a Y growing upward. Hence the extra negations. */ - *x = -PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX); - *y = +PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY)); - - return TRUE; -} - -static hb_bool_t -pango_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - FT_Face ft_face = context->ft_face; - int load_flags = FT_LOAD_DEFAULT; - - /* pangocairo-fc configures font in vertical origin for vertical writing. */ - if (context->vertical) return TRUE; - - if (FT_Load_Glyph (ft_face, glyph, load_flags)) - return FALSE; - - /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates - * have a Y growing upward. Hence the extra negation. */ - *x = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX); - *y = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY)); - - /* XXX */ - - return TRUE; -} - - -static hb_position_t -pango_fc_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) -{ - PangoFcHbContext *context = (PangoFcHbContext *) font_data; - FT_Face ft_face = context->ft_face; - FT_Vector kerning; - - if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerning)) - return 0; - - return PANGO_UNITS_26_6 (kerning.x * context->x_scale); -} - -static hb_font_funcs_t * -pango_fc_get_hb_font_funcs (void) -{ - static hb_font_funcs_t *funcs; - - if (G_UNLIKELY (!funcs)) { - funcs = hb_font_funcs_create (); - hb_font_funcs_set_nominal_glyph_func (funcs, pango_fc_hb_font_get_nominal_glyph, NULL, NULL); - hb_font_funcs_set_variation_glyph_func (funcs, pango_fc_hb_font_get_variation_glyph, NULL, NULL); - hb_font_funcs_set_glyph_h_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL); - hb_font_funcs_set_glyph_v_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL); - hb_font_funcs_set_glyph_h_origin_func (funcs, pango_fc_hb_font_get_glyph_h_origin, NULL, NULL); - hb_font_funcs_set_glyph_v_origin_func (funcs, pango_fc_hb_font_get_glyph_v_origin, NULL, NULL); - hb_font_funcs_set_glyph_h_kerning_func (funcs, pango_fc_hb_font_get_h_kerning, NULL, NULL); - /* Don't need v_kerning. */ - hb_font_funcs_set_glyph_extents_func (funcs, pango_fc_hb_font_get_glyph_extents, NULL, NULL); - hb_font_funcs_set_glyph_contour_point_func (funcs, pango_fc_hb_font_get_glyph_contour_point, NULL, NULL); - /* Don't need glyph_name / glyph_from_name */ - } - - return funcs; -} - -static void -parse_variations (const char *variations, - hb_variation_t **hb_variations, - guint *n_variations) -{ - guint n; - hb_variation_t *var; - int i; - const char *p; - - n = 1; - for (i = 0; variations[i]; i++) - { - if (variations[i] == ',') - n++; - } - - var = g_new (hb_variation_t, n); - - p = variations; - n = 0; - while (p && *p) - { - char *end = strchr (p, ','); - if (hb_variation_from_string (p, end ? end - p: -1, &var[n])) - n++; - p = end ? end + 1 : NULL; - } - - *hb_variations = var; - *n_variations = n; -} - static void apply_extra_attributes (GSList *attrs, hb_feature_t *features, @@ -365,11 +122,6 @@ _pango_fc_shape (PangoFont *font, const char *paragraph_text, unsigned int paragraph_length) { - PangoFcHbContext context; - PangoFcFont *fc_font; - PangoFcFontKey *key; - FT_Face ft_face; - hb_face_t *hb_face; hb_font_t *hb_font; hb_buffer_t *hb_buffer; hb_direction_t hb_direction; @@ -381,64 +133,12 @@ _pango_fc_shape (PangoFont *font, unsigned int item_offset = item_text - paragraph_text; hb_feature_t features[32]; unsigned int num_features = 0; - double x_scale_inv, y_scale_inv; PangoGlyphInfo *infos; - const char *variations; g_return_if_fail (font != NULL); g_return_if_fail (analysis != NULL); - fc_font = PANGO_FC_FONT (font); - ft_face = pango_fc_font_lock_face (fc_font); - if (!ft_face) - return; - - /* TODO: Cache hb_font? */ - - x_scale_inv = y_scale_inv = 1.0; - key = _pango_fc_font_get_font_key (fc_font); - if (key) - { - const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key); - pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv); - } - if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity)) - { - x_scale_inv = -x_scale_inv; - y_scale_inv = -y_scale_inv; - } - context.x_scale = 1. / x_scale_inv; - context.y_scale = 1. / y_scale_inv; - context.ft_face = ft_face; - context.fc_font = fc_font; - context.vertical = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity); - hb_face = hb_ft_face_create_cached (ft_face); - hb_font = hb_font_create (hb_face); - hb_font_set_funcs (hb_font, - pango_fc_get_hb_font_funcs (), - &context, - NULL); - hb_font_set_scale (hb_font, - +(((gint64) ft_face->size->metrics.x_scale * ft_face->units_per_EM) >> 12) * context.x_scale, - -(((gint64) ft_face->size->metrics.y_scale * ft_face->units_per_EM) >> 12) * context.y_scale); - hb_font_set_ppem (hb_font, - fc_font->is_hinted ? ft_face->size->metrics.x_ppem : 0, - fc_font->is_hinted ? ft_face->size->metrics.y_ppem : 0); - - if (key) - { - variations = pango_fc_font_key_get_variations (key); - if (variations) - { - guint n_variations; - hb_variation_t *hb_variations; - - parse_variations (variations, &hb_variations, &n_variations); - hb_font_set_variations (hb_font, hb_variations, n_variations); - - g_free (hb_variations); - } - } + hb_font = pango_font_get_hb_font (font); hb_buffer = acquire_buffer (&free_buffer); @@ -460,8 +160,8 @@ _pango_fc_shape (PangoFont *font, hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length); - pango_font_get_features (font, features, 32, &num_features); - apply_extra_attributes (analysis->extra_attrs, features, 32, &num_features); + 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); @@ -484,7 +184,7 @@ _pango_fc_shape (PangoFont *font, } hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL); - if (context.vertical) + if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity)) for (i = 0; i < num_glyphs; i++) { /* 90 degrees rotation counter-clockwise. */ @@ -502,41 +202,61 @@ _pango_fc_shape (PangoFont *font, hb_position++; } - if (fc_font->is_hinted) - { - if (context.x_scale == 1.0 && context.y_scale == 1.0) - { - for (i = 0; i < num_glyphs; i++) - infos[i].geometry.width = PANGO_UNITS_ROUND (infos[i].geometry.width); - } - else - { + if (PANGO_IS_FC_FONT (font)) + { + PangoFcFont *fc_font = PANGO_FC_FONT (font); + if (fc_font->is_hinted) + { + double x_scale_inv, y_scale_inv; + double x_scale, y_scale; + PangoFcFontKey *key; + + x_scale_inv = y_scale_inv = 1.0; + key = _pango_fc_font_get_font_key (fc_font); + if (key) + { + const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key); + pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv); + } + if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity)) + { + x_scale_inv = -x_scale_inv; + y_scale_inv = -y_scale_inv; + } + x_scale = 1. / x_scale_inv; + y_scale = 1. / y_scale_inv; + + if (x_scale == 1.0 && y_scale == 1.0) + { + for (i = 0; i < num_glyphs; i++) + infos[i].geometry.width = PANGO_UNITS_ROUND (infos[i].geometry.width); + } + else + { #if 0 - if (context.vertical) - { - /* XXX */ - double tmp = x_scale; - x_scale = y_scale; - y_scale = -tmp; - } + if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity)) + { + /* XXX */ + double tmp = x_scale; + x_scale = y_scale; + y_scale = -tmp; + } #endif #define HINT(value, scale_inv, scale) (PANGO_UNITS_ROUND ((int) ((value) * scale)) * scale_inv) -#define HINT_X(value) HINT ((value), context.x_scale, x_scale_inv) -#define HINT_Y(value) HINT ((value), context.y_scale, y_scale_inv) - for (i = 0; i < num_glyphs; i++) - { - infos[i].geometry.width = HINT_X (infos[i].geometry.width); - infos[i].geometry.x_offset = HINT_X (infos[i].geometry.x_offset); - infos[i].geometry.y_offset = HINT_Y (infos[i].geometry.y_offset); - } +#define HINT_X(value) HINT ((value), x_scale, x_scale_inv) +#define HINT_Y(value) HINT ((value), y_scale, y_scale_inv) + for (i = 0; i < num_glyphs; i++) + { + infos[i].geometry.width = HINT_X (infos[i].geometry.width); + infos[i].geometry.x_offset = HINT_X (infos[i].geometry.x_offset); + infos[i].geometry.y_offset = HINT_Y (infos[i].geometry.y_offset); + } #undef HINT_Y #undef HINT_X #undef HINT - } - } + } + } + } release_buffer (hb_buffer, free_buffer); - hb_font_destroy (hb_font); - hb_face_destroy (hb_face); - pango_fc_font_unlock_face (fc_font); } diff --git a/pango/pangoft2.c b/pango/pangoft2.c index a5ac6fc5..e8bb8e1f 100644 --- a/pango/pangoft2.c +++ b/pango/pangoft2.c @@ -64,7 +64,7 @@ static void pango_ft2_font_get_glyph_extents (PangoFont *font, PangoRectangle *ink_rect, PangoRectangle *logical_rect); -static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font); +static gpointer pango_ft2_font_real_lock_face (PangoFcFont *font); static void pango_ft2_font_real_unlock_face (PangoFcFont *font); @@ -309,7 +309,7 @@ pango_ft2_font_get_glyph_info (PangoFont *font, { info = g_slice_new0 (PangoFT2GlyphInfo); - pango_fc_font_get_raw_extents (fcfont, ft2font->load_flags, + pango_fc_font_get_raw_extents (fcfont, glyph, &info->ink_rect, &info->logical_rect); @@ -430,7 +430,7 @@ pango_ft2_font_get_kerning (PangoFont *font, return PANGO_UNITS_26_6 (kerning.x); } -static FT_Face +static gpointer pango_ft2_font_real_lock_face (PangoFcFont *font) { return pango_ft2_font_get_face ((PangoFont *)font); diff --git a/pango/pangowin32.c b/pango/pangowin32.c index 80abb0b4..0e877820 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -35,6 +35,7 @@ #include <string.h> #include <stdlib.h> #include <glib.h> +#include <hb.h> #include "pango-impl-utils.h" #include "pangowin32.h" @@ -86,6 +87,8 @@ static void pango_win32_get_item_properties (PangoItem PangoAttrColor *bg_color, gboolean *bg_set); +static hb_font_t * pango_win32_font_create_hb_font (PangoFont *font); + HFONT _pango_win32_font_get_hfont (PangoFont *font) { @@ -207,6 +210,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class) font_class->get_glyph_extents = pango_win32_font_get_glyph_extents; font_class->get_metrics = pango_win32_font_get_metrics; font_class->get_font_map = pango_win32_font_get_font_map; + font_class->create_hb_font = pango_win32_font_create_hb_font; class->select_font = pango_win32_font_real_select_font; class->done_font = pango_win32_font_real_done_font; @@ -1909,3 +1913,84 @@ pango_win32_font_calc_coverage (PangoFont *font, g_print ("\n"); #endif } + +/* + * Swap HarfBuzz-style tags to tags that GetFontData() understands, + * adapted from https://github.com/harfbuzz/harfbuzz/pull/1832, + * by Ebrahim Byagowi. + */ + +static inline guint16 hb_gdi_uint16_swap (const guint16 v) +{ return (v >> 8) | (v << 8); } +static inline guint32 hb_gdi_uint32_swap (const guint32 v) +{ return (hb_gdi_uint16_swap (v) << 16) | hb_gdi_uint16_swap (v >> 16); } + +/* + * Adapted from https://www.mail-archive.com/harfbuzz@lists.freedesktop.org/msg06538.html + * by Konstantin Ritt. + */ +static hb_blob_t * +hfont_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data) +{ + HDC hdc; + HFONT hfont, old_hfont; + gchar *buf = NULL; + DWORD size; + + /* We have a common DC for our PangoWin32Font, so let's just use it */ + hdc = pango_win32_get_dc (); + hfont = (HFONT) user_data; + + /* we want to restore things, just to be safe */ + old_hfont = SelectObject (hdc, hfont); + if (old_hfont == NULL) + { + g_warning ("SelectObject() for the PangoWin32Font failed!"); + return hb_blob_get_empty (); + } + + size = GetFontData (hdc, hb_gdi_uint32_swap (tag), 0, NULL, 0); + + /* + * not all tags support retrieving the sizes, so don't warn, + * just return hb_blob_get_empty() + */ + if (size == GDI_ERROR) + { + SelectObject (hdc, old_hfont); + return hb_blob_get_empty (); + } + + buf = g_malloc (size * sizeof (gchar)); + + /* This should be quite unlikely to fail if size was not GDI_ERROR */ + if (GetFontData (hdc, hb_gdi_uint32_swap (tag), 0, buf, size) == GDI_ERROR) + size = 0; + + SelectObject (hdc, old_hfont); + return hb_blob_create (buf, size, HB_MEMORY_MODE_READONLY, buf, g_free); +} + +static hb_font_t * +pango_win32_font_create_hb_font (PangoFont *font) +{ + PangoWin32Font *win32font = (PangoWin32Font *)font; + HFONT hfont; + hb_face_t *face = NULL; + hb_font_t *hb_font = NULL; + + g_return_val_if_fail (font != NULL, NULL); + + hfont = _pango_win32_font_get_hfont (font); + + /* We are *not* allowed to destroy the HFONT here ! */ + face = hb_face_create_for_tables (hfont_reference_table, (void *)hfont, NULL); + + hb_font = hb_font_create (face); + hb_font_set_scale (hb_font, win32font->size, win32font->size); + hb_face_destroy (face); + + hb_font_make_immutable (hb_font); + + return hb_font; +} diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c index 91856304..779eb886 100644 --- a/pango/pangoxft-font.c +++ b/pango/pangoxft-font.c @@ -75,7 +75,7 @@ static void pango_xft_font_get_glyph_extents (PangoFont PangoRectangle *ink_rect, PangoRectangle *logical_rect); -static FT_Face pango_xft_font_real_lock_face (PangoFcFont *font); +static gpointer pango_xft_font_real_lock_face (PangoFcFont *font); static void pango_xft_font_real_unlock_face (PangoFcFont *font); static gboolean pango_xft_font_real_has_char (PangoFcFont *font, gunichar wc); @@ -331,7 +331,6 @@ get_glyph_extents_raw (PangoXftFont *xfont, extents = g_slice_new (Extents); pango_fc_font_get_raw_extents (PANGO_FC_FONT (xfont), - FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING, glyph, &extents->ink_rect, &extents->logical_rect); @@ -450,12 +449,12 @@ xft_font_get_font (PangoFont *font) return xfont->xft_font; } -static FT_Face +static gpointer pango_xft_font_real_lock_face (PangoFcFont *font) { XftFont *xft_font = xft_font_get_font ((PangoFont *)font); - return XftLockFace (xft_font); + return (gpointer)XftLockFace (xft_font); } static void |