From 93e8d660766b628369d7af0c854592ba0023c6d4 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Sat, 6 Mar 2010 19:06:36 +0100 Subject: Handle oblique fonts; synthesize italic fonts when needed Deduce from the given style name whether a font is oblique. If a font family does not have an italic or oblique variant, then add synthetic italic variants that are handled by Pango. --- pango/pangocairo-coretextfont.c | 14 ++++++-- pango/pangocoretext-fontmap.c | 71 ++++++++++++++++++++++++++++++++++++++++- pango/pangocoretext-private.h | 1 + 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/pango/pangocairo-coretextfont.c b/pango/pangocairo-coretextfont.c index 81747ac3..0f0c4041 100644 --- a/pango/pangocairo-coretextfont.c +++ b/pango/pangocairo-coretextfont.c @@ -212,6 +212,7 @@ _pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, const PangoFontDescription *desc) { const char *postscript_name; + gboolean synthesize_italic = FALSE; PangoCairoCoreTextFont *cafont; PangoCoreTextFont *cfont; CFStringRef cfstr; @@ -245,7 +246,9 @@ _pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, font_ref = CTFontCreateWithName (cfstr, size, NULL); CFRelease (cfstr); - /* FIXME: Do we need the synthetic italic handling here? */ + if (_pango_core_text_face_get_synthetic_italic (face)) + synthesize_italic = TRUE; + font_id = CTFontCopyGraphicsFont (font_ref, NULL); if (!font_id) return NULL; @@ -265,7 +268,14 @@ _pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, cafont->size = size; - cairo_matrix_init_identity (&font_matrix); + if (synthesize_italic) + cairo_matrix_init (&font_matrix, + 1, 0, + -0.25, 1, + 0, 0); + else + cairo_matrix_init_identity (&font_matrix); + cairo_matrix_scale (&font_matrix, size, size); _pango_cairo_font_private_initialize (&cafont->cf_priv, diff --git a/pango/pangocoretext-fontmap.c b/pango/pangocoretext-fontmap.c index 67a72097..ce55a5b3 100644 --- a/pango/pangocoretext-fontmap.c +++ b/pango/pangocoretext-fontmap.c @@ -65,6 +65,7 @@ struct _PangoCoreTextFace float weight; int traits; + guint synthetic_italic : 1; }; static GType pango_core_text_family_get_type (void); @@ -145,6 +146,12 @@ pango_coverage_from_cf_charset (CFCharacterSetRef charset) return coverage; } +static inline gboolean +pango_core_text_face_is_oblique (PangoCoreTextFace *face) +{ + return g_strrstr (face->style_name, "Oblique") != NULL; +} + static inline PangoCoreTextFace * pango_core_text_face_from_ct_font_descriptor (CTFontDescriptorRef desc) { @@ -158,6 +165,8 @@ pango_core_text_face_from_ct_font_descriptor (CTFontDescriptorRef desc) PangoCoreTextFace *face = g_object_new (PANGO_TYPE_CORE_TEXT_FACE, NULL); + face->synthetic_italic = FALSE; + /* Get font name */ str = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute); buffer = gchar_from_cf_string (str); @@ -215,6 +224,8 @@ pango_core_text_family_list_faces (PangoFontFamily *family, { GList *l; GList *faces = NULL; + GList *synthetic_faces = NULL; + GHashTable *italic_faces; const char *real_family = get_real_family (ctfamily->family_name); CTFontCollectionRef collection; CFArrayRef ctfaces; @@ -250,7 +261,8 @@ pango_core_text_family_list_faces (PangoFontFamily *family, ctfaces = CTFontCollectionCreateMatchingFontDescriptors (collection); - /* FIXME: do we need the code for the synthetic italic faces? */ + italic_faces = g_hash_table_new (g_direct_hash, g_direct_equal); + count = CFArrayGetCount (ctfaces); for (i = 0; i < count; i++) { @@ -261,12 +273,51 @@ pango_core_text_family_list_faces (PangoFontFamily *family, face->family = ctfamily; faces = g_list_prepend (faces, face); + + if (face->traits & kCTFontItalicTrait + || pango_core_text_face_is_oblique (face)) + g_hash_table_insert (italic_faces, GINT_TO_POINTER (face->weight), + face); } CFRelease (font_descriptors); CFRelease (attributes); CFRelease (ctfaces); + /* For all fonts for which a non-synthetic italic variant does + * not exist on the system, we create synthesized versions here. + */ + for (l = faces; l; l = l->next) + { + PangoCoreTextFace *face = l->data; + + if (!g_hash_table_lookup (italic_faces, + GINT_TO_POINTER (face->weight))) + { + PangoCoreTextFace *italic_face; + + italic_face = g_object_new (PANGO_TYPE_CORE_TEXT_FACE, NULL); + + italic_face->family = ctfamily; + italic_face->postscript_name = g_strdup (face->postscript_name); + italic_face->weight = face->weight; + italic_face->traits = face->traits | kCTFontItalicTrait; + italic_face->synthetic_italic = TRUE; + italic_face->coverage = pango_coverage_ref (face->coverage); + + /* Try to create a sensible face name. */ + if (strcasecmp (face->style_name, "regular") == 0) + italic_face->style_name = g_strdup ("Oblique"); + else + italic_face->style_name = g_strdup_printf ("%s Oblique", + face->style_name); + + synthetic_faces = g_list_prepend (synthetic_faces, italic_face); + } + } + + faces = g_list_concat (faces, synthetic_faces); + ctfamily->n_faces = g_list_length (faces); ctfamily->faces = g_new (PangoFontFace *, ctfamily->n_faces); @@ -274,6 +325,7 @@ pango_core_text_family_list_faces (PangoFontFamily *family, ctfamily->faces[i] = l->data; g_list_free (faces); + g_hash_table_destroy (italic_faces); } if (n_faces) @@ -429,6 +481,8 @@ pango_core_text_face_describe (PangoFontFace *face) if (ctface->traits & kCTFontItalicTrait) pango_style = PANGO_STYLE_ITALIC; + else if (pango_core_text_face_is_oblique (ctface)) + pango_style = PANGO_STYLE_OBLIQUE; else pango_style = PANGO_STYLE_NORMAL; @@ -478,6 +532,14 @@ pango_core_text_face_finalize (GObject *object) G_OBJECT_CLASS (pango_core_text_face_parent_class)->finalize (object); } +static gboolean +pango_core_text_face_is_synthesized (PangoFontFace *face) +{ + PangoCoreTextFace *cface = PANGO_CORE_TEXT_FACE (face); + + return cface->synthetic_italic; +} + static void pango_core_text_face_class_init (PangoFontFaceClass *class) { @@ -490,6 +552,7 @@ pango_core_text_face_class_init (PangoFontFaceClass *class) class->describe = pango_core_text_face_describe; class->get_face_name = pango_core_text_face_get_face_name; class->list_sizes = pango_core_text_face_list_sizes; + class->is_synthesized = pango_core_text_face_is_synthesized; } GType @@ -526,6 +589,12 @@ _pango_core_text_face_get_postscript_name (PangoCoreTextFace *face) return face->postscript_name; } +gboolean +_pango_core_text_face_get_synthetic_italic (PangoCoreTextFace *face) +{ + return face->synthetic_italic; +} + PangoCoverage * _pango_core_text_face_get_coverage (PangoCoreTextFace *face, PangoLanguage *language) diff --git a/pango/pangocoretext-private.h b/pango/pangocoretext-private.h index dd5cff84..4ed0e8e5 100644 --- a/pango/pangocoretext-private.h +++ b/pango/pangocoretext-private.h @@ -79,6 +79,7 @@ struct _PangoCoreTextFontMapClass GType pango_core_text_font_map_get_type (void) G_GNUC_CONST; const char * _pango_core_text_face_get_postscript_name (PangoCoreTextFace *face); +gboolean _pango_core_text_face_get_synthetic_italic (PangoCoreTextFace *face); PangoCoverage * _pango_core_text_face_get_coverage (PangoCoreTextFace *face, PangoLanguage *language); -- cgit v1.2.1