[pango] Handle oblique fonts; synthesize italic fonts when needed



commit b5efdc928f392c2ec47c206af3cbeddb986553a0
Author: Kristian Rietveld <kris gtk org>
Date:   Sat Mar 6 19:06:36 2010 +0100

    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 81747ac..0f0c404 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 67a7209..ce55a5b 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 dd5cff8..4ed0e8e 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);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]