summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hult <richard@imendio.com>2007-05-05 09:42:40 +0000
committerRichard Hult <rhult@src.gnome.org>2007-05-05 09:42:40 +0000
commitef570b9272342323bfeb38d6df9e517e320313eb (patch)
tree0c6ddb587c810302da6fa01cb3467bc58d665c4d
parent2be159384023796768b86ec5f2cc0802ce710075 (diff)
downloadpango-ef570b9272342323bfeb38d6df9e517e320313eb.tar.gz
Bug 434160 - [atsui] Italic versions of some faces can't be created
2007-05-05 Richard Hult <richard@imendio.com> Bug 434160 - [atsui] Italic versions of some faces can't be created * pango/pangoatsui-fontmap.c: * pango/pangoatsui-private.h: * pango/pangocairo-atsuifont.c: Follow the other backends and create italic faces when they are not available. Apply synthetic italic in two cases, when the font manager hands out italic faces that are not in fact italic, and for the ones we've created ourselves. svn path=/trunk/; revision=2264
-rw-r--r--ChangeLog11
-rw-r--r--pango/pangoatsui-fontmap.c155
-rw-r--r--pango/pangoatsui-private.h7
-rw-r--r--pango/pangocairo-atsuifont.c55
4 files changed, 178 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index bfd62cad..33564c50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-05-05 Richard Hult <richard@imendio.com>
+
+ Bug 434160 - [atsui] Italic versions of some faces can't be created
+
+ * pango/pangoatsui-fontmap.c:
+ * pango/pangoatsui-private.h:
+ * pango/pangocairo-atsuifont.c: Follow the other backends and create
+ italic faces when they are not available. Apply synthetic italic
+ in two cases, when the font manager hands out italic faces that are
+ not in fact italic, and for the ones we've created ourselves.
+
2007-05-04 Behdad Esfahbod <behdad@gnome.org>
Bug 435709 – pango_cairo_context_[sg]et_shape_renderer()
diff --git a/pango/pangoatsui-fontmap.c b/pango/pangoatsui-fontmap.c
index 7eee93b7..ee153074 100644
--- a/pango/pangoatsui-fontmap.c
+++ b/pango/pangoatsui-fontmap.c
@@ -62,6 +62,7 @@ struct _PangoATSUIFace
int weight;
int traits;
+ guint synthetic_italic : 1;
};
static GType pango_atsui_family_get_type (void);
@@ -98,18 +99,30 @@ pango_atsui_family_list_faces (PangoFontFamily *family,
int *n_faces)
{
PangoATSUIFamily *atsuifamily = PANGO_ATSUI_FAMILY (family);
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (atsuifamily->n_faces < 0)
{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
const char *real_family = get_real_family (atsuifamily->family_name);
- NSArray *members = [[NSFontManager sharedFontManager] availableMembersOfFontFamily:[NSString stringWithUTF8String:real_family]];
- int i;
-
- atsuifamily->n_faces = [members count];
- atsuifamily->faces = g_new (PangoFontFace *, atsuifamily->n_faces);
-
- for (i = 0; i < atsuifamily->n_faces; i++)
+ NSFontManager *manager = [NSFontManager sharedFontManager];
+ NSArray *members = [manager availableMembersOfFontFamily:[NSString stringWithUTF8String:real_family]];
+ int i, count;
+ GHashTable *hash_table;
+ GList *faces = NULL, *l;
+ GList *synthetic_faces = NULL;
+
+ /* The NSFontManager API returns italic faces for some families
+ * even if they don't exist. When using Cocoa to create
+ * instances of those fonts, Cocoa synthesizes italic versions
+ * by applying a shear transformation. We do that manually for
+ * those fonts in pangocairo-atsuifont.c. For many other fonts,
+ * there is no italic face at all, so we create synthesized
+ * versions of those like in the win32 and fontconfig backends.
+ */
+ hash_table = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ count = [members count];
+ for (i = 0; i < count; i++)
{
PangoATSUIFace *face = g_object_new (PANGO_TYPE_ATSUI_FACE, NULL);
NSArray *font_array = [members objectAtIndex:i];
@@ -120,8 +133,48 @@ pango_atsui_family_list_faces (PangoFontFamily *family,
face->weight = [[font_array objectAtIndex:2] intValue];
face->traits = [[font_array objectAtIndex:3] intValue];
- atsuifamily->faces[i] = (PangoFontFace *)face;
+ faces = g_list_prepend (faces, face);
+
+ if (face->traits & NSItalicFontMask)
+ g_hash_table_insert (hash_table, GINT_TO_POINTER (face->weight), face);
+ }
+
+ for (l = faces; l; l = l->next)
+ {
+ PangoATSUIFace *face = l->data;
+
+ if (!g_hash_table_lookup (hash_table, GINT_TO_POINTER (face->weight)))
+ {
+ PangoATSUIFace *italic_face = g_object_new (PANGO_TYPE_ATSUI_FACE, NULL);
+
+ italic_face->family = atsuifamily;
+ italic_face->postscript_name = g_strdup (face->postscript_name);
+ italic_face->weight = face->weight;
+ italic_face->traits = face->traits | NSItalicFontMask;
+ italic_face->synthetic_italic = TRUE;
+
+ /* 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);
+
+ atsuifamily->n_faces = g_list_length (faces);
+ atsuifamily->faces = g_new (PangoFontFace *, atsuifamily->n_faces);
+
+ for (l = faces, i = 0; l; l = l->next, i++)
+ atsuifamily->faces[i] = l->data;
+
+ g_list_free (faces);
+ g_hash_table_destroy (hash_table);
+
+ [pool release];
}
if (n_faces)
@@ -129,8 +182,6 @@ pango_atsui_family_list_faces (PangoFontFamily *family,
if (faces)
*faces = g_memdup (atsuifamily->faces, atsuifamily->n_faces * sizeof (PangoFontFace *));
-
- [pool release];
}
static const char *
@@ -159,9 +210,7 @@ pango_atsui_family_finalize (GObject *object)
if (family->n_faces != -1)
{
for (i = 0; i < family->n_faces; i++)
- {
- g_object_unref (family->faces[i]);
- }
+ g_object_unref (family->faces[i]);
g_free (family->faces);
}
@@ -266,6 +315,7 @@ pango_atsui_face_describe (PangoFontFace *face)
pango_font_description_set_weight (description, pango_weight);
pango_font_description_set_style (description, pango_style);
+ pango_font_description_set_variant (description, pango_variant);
return description;
}
@@ -349,6 +399,12 @@ _pango_atsui_face_get_postscript_name (PangoATSUIFace *face)
return face->postscript_name;
}
+gboolean
+_pango_atsui_face_get_synthetic_italic (PangoATSUIFace *face)
+{
+ return face->synthetic_italic;
+}
+
PangoCoverage *
_pango_atsui_face_get_coverage (PangoATSUIFace *face,
PangoLanguage *language)
@@ -562,6 +618,38 @@ pango_atsui_font_map_lookup (PangoATSUIFontMap *atsuifontmap,
return g_hash_table_lookup (atsuifontmap->font_hash, &key);
}
+static gboolean
+find_best_match (PangoATSUIFamily *font_family,
+ const PangoFontDescription *description,
+ PangoFontDescription **best_description,
+ PangoATSUIFace **best_face)
+{
+ PangoFontDescription *new_desc;
+ int i;
+
+ *best_description = NULL;
+ *best_face = NULL;
+
+ for (i = 0; i < font_family->n_faces; i++)
+ {
+ new_desc = pango_font_face_describe (font_family->faces[i]);
+
+ if (pango_font_description_better_match (description, *best_description, new_desc))
+ {
+ pango_font_description_free (*best_description);
+ *best_description = new_desc;
+ *best_face = (PangoATSUIFace *)font_family->faces[i];
+ }
+ else
+ pango_font_description_free (new_desc);
+ }
+
+ if (*best_description)
+ return TRUE;
+
+ return FALSE;
+}
+
static PangoFont *
pango_atsui_font_map_load_font (PangoFontMap *fontmap,
PangoContext *context,
@@ -572,52 +660,31 @@ pango_atsui_font_map_load_font (PangoFontMap *fontmap,
gchar *name;
gint size;
- g_return_val_if_fail (description != NULL, NULL);
-
size = pango_font_description_get_size (description);
-
if (size < 0)
return NULL;
name = g_utf8_casefold (pango_font_description_get_family (description), -1);
font_family = g_hash_table_lookup (atsuifontmap->families, name);
-
g_free (name);
if (font_family)
{
- PangoFontDescription *best_desc = NULL, *new_desc;
- PangoATSUIFace *best_face = NULL;
+ PangoFontDescription *best_description;
+ PangoATSUIFace *best_face;
PangoATSUIFont *best_font;
- int i;
/* Force a listing of the available faces */
pango_font_family_list_faces ((PangoFontFamily *)font_family, NULL, NULL);
- for (i = 0; i < font_family->n_faces; i++)
- {
- new_desc = pango_font_face_describe (font_family->faces[i]);
-
- if (pango_font_description_better_match (description, best_desc, new_desc))
- {
- pango_font_description_free (best_desc);
- best_desc = new_desc;
- best_face = (PangoATSUIFace *)font_family->faces[i];
- }
- else
- {
- pango_font_description_free (new_desc);
- }
- }
-
- if (best_desc == NULL || best_face == NULL)
+ if (!find_best_match (font_family, description, &best_description, &best_face))
return NULL;
-
- pango_font_description_set_size (best_desc, size);
+
+ pango_font_description_set_size (best_description, size);
best_font = pango_atsui_font_map_lookup (atsuifontmap,
context,
- best_desc,
+ best_description,
best_face);
if (best_font)
@@ -628,16 +695,16 @@ pango_atsui_font_map_load_font (PangoFontMap *fontmap,
klass = PANGO_ATSUI_FONT_MAP_GET_CLASS (atsuifontmap);
best_font = klass->create_font (atsuifontmap, context,
- best_face, best_desc);
+ best_face, best_description);
if (best_font)
pango_atsui_font_map_add (atsuifontmap, context, best_font);
/* TODO: Handle the else case here. */
}
- pango_font_description_free (best_desc);
+ pango_font_description_free (best_description);
- return PANGO_FONT (best_font);
+ return (PangoFont *)best_font;
}
return NULL;
diff --git a/pango/pangoatsui-private.h b/pango/pangoatsui-private.h
index a8be49e1..d63600d6 100644
--- a/pango/pangoatsui-private.h
+++ b/pango/pangoatsui-private.h
@@ -103,9 +103,10 @@ struct _PangoATSUIFontClass
GType pango_atsui_font_map_get_type (void);
GType pango_atsui_font_get_type (void);
-const char * _pango_atsui_face_get_postscript_name (PangoATSUIFace *face);
-PangoCoverage *_pango_atsui_face_get_coverage (PangoATSUIFace *face,
- PangoLanguage *language);
+const char * _pango_atsui_face_get_postscript_name (PangoATSUIFace *face);
+PangoCoverage *_pango_atsui_face_get_coverage (PangoATSUIFace *face,
+ PangoLanguage *language);
+gboolean _pango_atsui_face_get_synthetic_italic (PangoATSUIFace *face);
G_END_DECLS
diff --git a/pango/pangocairo-atsuifont.c b/pango/pangocairo-atsuifont.c
index 5d087af9..d185fa6f 100644
--- a/pango/pangocairo-atsuifont.c
+++ b/pango/pangocairo-atsuifont.c
@@ -22,6 +22,8 @@
#include <config.h>
+#import <Cocoa/Cocoa.h>
+
#include "pangoatsui-private.h"
#include "pangocairo.h"
#include "pangocairo-private.h"
@@ -269,6 +271,7 @@ _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
const PangoFontDescription *desc)
{
const char *postscript_name;
+ gboolean synthesize_italic = FALSE;
PangoCairoATSUIFont *cafont;
PangoATSUIFont *afont;
CFStringRef cfstr;
@@ -277,14 +280,46 @@ _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
ATSUFontID font_id;
postscript_name = _pango_atsui_face_get_postscript_name (face);
+
cfstr = CFStringCreateWithCString (NULL, postscript_name,
kCFStringEncodingUTF8);
-
font_ref = ATSFontFindFromPostScriptName (cfstr, kATSOptionFlagsDefault);
- font_id = FMGetFontFromATSFontRef (font_ref);
-
CFRelease (cfstr);
+ /* We synthesize italic in two cases. The first is when
+ * NSFontManager has handed out a face that it claims has italic but
+ * it doesn't. The other is when an italic face is requested that
+ * doesn't have a real version.
+ */
+ if (font_ref == kATSFontRefUnspecified &&
+ pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSString *nsname;
+ NSFont *nsfont, *converted_font;
+ gdouble size;
+
+ size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
+
+ nsname = [NSString stringWithUTF8String:postscript_name];
+ nsfont = [NSFont fontWithName:nsname size:size];
+
+ converted_font = [[NSFontManager sharedFontManager] convertFont:nsfont
+ toHaveTrait:NSUnitalicFontMask];
+ font_ref = ATSFontFindFromPostScriptName ((CFStringRef) [converted_font fontName],
+ kATSOptionFlagsDefault);
+
+ [pool release];
+
+ synthesize_italic = TRUE;
+ }
+ else if (_pango_atsui_face_get_synthetic_italic (face))
+ synthesize_italic = TRUE;
+
+ if (font_ref == kATSFontRefUnspecified)
+ return NULL;
+
+ font_id = FMGetFontFromATSFontRef (font_ref);
if (!font_id)
return NULL;
@@ -314,6 +349,20 @@ _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
else
cairo_matrix_init_identity (&cafont->ctm);
+ if (synthesize_italic)
+ {
+ cairo_matrix_t shear, result;
+
+ /* Apply a shear matrix, matching what Cocoa does. */
+ cairo_matrix_init (&shear,
+ 1, 0,
+ 0.25, 1,
+ 0, 0);
+
+ cairo_matrix_multiply (&result, &shear, &cafont->font_matrix);
+ cafont->font_matrix = result;
+ }
+
cafont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context));
return afont;