diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | pango/pangowin32-fontmap.c | 247 |
2 files changed, 186 insertions, 71 deletions
@@ -1,5 +1,15 @@ 2008-05-27 Tor Lillqvist <tml@novell.com> + * pango/pangowin32-fontmap.c: Synthesize also Bold and Bold Italic + (or Oblique) faces when feasible. Don't synthesize these for + decorative or script fonts. Kill the magic code snippet mentioned + below. Instead, explicitly create font families for the standard + pseudo fonts that correspond to the first existing font of the + corresponding built-in alias list. Use the face style name Oblique + for slanted sans and monospace fonts, not Italic. + +2008-05-27 Tor Lillqvist <tml@novell.com> + * pango/pangowin32-fontmap.c (pango_win32_family_list_faces): Prune duplicated face names. Makes the GTK+ font selector look a bit saner for the "sans", "serif" and "monospace" standard pseudo diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index 3ee1d1d1..21c7583e 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -90,6 +90,9 @@ static void pango_win32_insert_font (PangoWin32FontMap LOGFONTW *lfp, gboolean is_synthetic); +static PangoWin32Family *pango_win32_get_font_family (PangoWin32FontMap *win32fontmap, + const char *family_name); + static const char *pango_win32_face_get_face_name (PangoFontFace *face); static PangoWin32FontMap *default_fontmap = NULL; @@ -210,28 +213,64 @@ pango_win32_enum_proc (LOGFONTW *lfp, typedef struct _ItalicHelper { + const char *style; + gboolean (*check) (const LOGFONTW *lf); + void (*modify) (LOGFONTW *lf); PangoWin32FontMap *fontmap; - GSList *list; -} ItalicHelper; + GSList *list; +} SynthesizeHelper; + +static gboolean +slanted_feasible (const LOGFONTW *lfp) +{ + return (((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN || + (lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN || + (lfp->lfPitchAndFamily & 0xF0) == FF_SWISS) && + !lfp->lfItalic); +} static void -ensure_italic (gpointer key, - gpointer value, - gpointer user_data) +italicize (LOGFONTW *lfp) { - ItalicHelper *helper = (ItalicHelper *)user_data; + lfp->lfItalic = 1; +} + +static gboolean +bold_feasible (const LOGFONTW *lfp) +{ + return (((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN || + (lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN || + (lfp->lfPitchAndFamily & 0xF0) == FF_SWISS) && + lfp->lfWeight == FW_NORMAL); +} + +static void +boldify (LOGFONTW *lfp) +{ + lfp->lfWeight = FW_BOLD; +} + +static void +synthesize_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + SynthesizeHelper *helper = (SynthesizeHelper *)user_data; const LOGFONTW *lfp = (const LOGFONTW *) value; LOGFONTW *lfpnew; - if (!lfp->lfItalic) + if (helper->check (lfp)) { - /* We have a non-italic variant, look if there is an italic */ + /* We have "normal" variant, look if we need to synthesize the required style */ LOGFONTW logfontw = *lfp; - logfontw.lfItalic = 1; + helper->modify (&logfontw); if (!g_hash_table_lookup (helper->fontmap->fonts, &logfontw)) { - /* Remember the italic variant to be added later */ - PING (("synthesizing italic: %S wt=%ld", lfp->lfFaceName, lfp->lfWeight)); + PING (("synthesizing %s %s%S wt=%ld", + helper->style, + lfp->lfItalic ? "Italic " : "", + lfp->lfFaceName, + lfp->lfWeight)); lfpnew = g_new (LOGFONTW, 1); *lfpnew = logfontw; helper->list = g_slist_append (helper->list, lfpnew); @@ -240,11 +279,89 @@ ensure_italic (gpointer key, } static void +synthesize_faces (PangoWin32FontMap *win32fontmap, + const char *style, + gboolean (*check_func) (const LOGFONTW *lfp), + void (*modify_func) (LOGFONTW *lfp)) +{ + SynthesizeHelper helper = { style, check_func, modify_func, win32fontmap, NULL }; + GSList *list; + + g_hash_table_foreach (win32fontmap->fonts, synthesize_foreach, &helper); + + /* Process the list of LOGFONTWs for the synthesized fonts */ + list = helper.list; + while (list) + { + pango_win32_insert_font (win32fontmap, (LOGFONTW *)list->data, TRUE); + g_free (list->data); + list = list->next; + } + g_slist_free (helper.list); +} + +static void +create_standard_family (PangoWin32FontMap *win32fontmap, + const char *standard_family_name) +{ + int i; + int n_aliases; + char **aliases; + + pango_lookup_aliases (standard_family_name, &aliases, &n_aliases); + for (i = 0; i < n_aliases; i++) + { + PangoWin32Family *existing_family = g_hash_table_lookup (win32fontmap->families, aliases[i]); + + if (existing_family) + { + PangoWin32Family *new_family = pango_win32_get_font_family (win32fontmap, standard_family_name); + GSList *p = existing_family->faces; + + new_family->is_monospace = existing_family->is_monospace; + + while (p) + { + const PangoWin32Face *old_face = (const PangoWin32Face *) p->data; + PangoWin32Face *new_face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL); + int j; + + new_face->logfontw = old_face->logfontw; + new_face->description = pango_font_description_copy_static (old_face->description); + pango_font_description_set_family_static (new_face->description, standard_family_name); + + for (j = 0; j < PANGO_WIN32_N_COVERAGES; j++) + { + if (old_face->coverages[j] != NULL) + new_face->coverages[j] = pango_coverage_ref (old_face->coverages[j]); + else + new_face->coverages[j] = NULL; + } + + new_face->is_synthetic = TRUE; + + new_face->has_cmap = old_face->has_cmap; + new_face->cmap_format = old_face->cmap_format; + new_face->cmap = old_face->cmap; + + new_face->cached_fonts = NULL; + + new_family->faces = g_slist_append (new_family->faces, new_face); + + p = p->next; + } + return; + } + } + /* XXX What to do if none of the members of aliases for standard_family_name + * exists on this machine? + */ +} + +static void _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) { LOGFONTW logfont; - ItalicHelper helper = { win32fontmap, NULL }; - GSList *list; win32fontmap->families = g_hash_table_new ((GHashFunc) case_insensitive_str_hash, (GEqualFunc) case_insensitive_str_equal); @@ -260,18 +377,16 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) (FONTENUMPROCW) pango_win32_enum_proc, (LPARAM) win32fontmap, 0); - /* Create synthetic italic entries */ - g_hash_table_foreach (win32fontmap->fonts, ensure_italic, &helper); + /* Create synthetic Italic faces */ + synthesize_faces (win32fontmap, "Italic", slanted_feasible, italicize); - /* Process the list of LOGFONTWs for synthesized italic fonts */ - list = helper.list; - while (list) - { - pango_win32_insert_font (win32fontmap, (LOGFONTW *)list->data, TRUE); - g_free (list->data); - list = list->next; - } - g_slist_free (helper.list); + /* Create synthetic Bold (and Bold Italic) faces */ + synthesize_faces (win32fontmap, "Bold", bold_feasible, boldify); + + /* Create synthetic "Sans", "Serif" and "Monospace" families */ + create_standard_family (win32fontmap, "Sans"); + create_standard_family (win32fontmap, "Serif"); + create_standard_family (win32fontmap, "Monospace"); win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0; } @@ -980,10 +1095,12 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp) family = get_family_nameW (lfp); - if (!lfp->lfItalic) - style = PANGO_STYLE_NORMAL; - else + if ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN && lfp->lfItalic) style = PANGO_STYLE_ITALIC; + else if (lfp->lfItalic) + style = PANGO_STYLE_OBLIQUE; + else + style = PANGO_STYLE_NORMAL; variant = PANGO_VARIANT_NORMAL; @@ -1054,6 +1171,27 @@ charset_name (int charset) } } +static char * +ff_name (int ff) +{ + static char num[10]; + + switch (ff) + { +#define CASE(x) case FF_##x: return #x + CASE (DECORATIVE); + CASE (DONTCARE); + CASE (MODERN); + CASE (ROMAN); + CASE (SCRIPT); + CASE (SWISS); +#undef CASE + default: + sprintf (num, "%d", ff); + return num; + } +} + static void pango_win32_insert_font (PangoWin32FontMap *win32fontmap, LOGFONTW *lfp, @@ -1064,10 +1202,14 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, PangoWin32Family *win32family; PangoWin32Face *win32face; gint i; - gchar *p; - PING (("face=%S,charset=%s,it=%d,wt=%ld,ht=%ld", - lfp->lfFaceName, charset_name (lfp->lfCharSet), lfp->lfItalic, lfp->lfWeight, lfp->lfHeight)); + PING (("face=%S,charset=%s,it=%s,wt=%ld,ht=%ld,ff=%s", + lfp->lfFaceName, + charset_name (lfp->lfCharSet), + lfp->lfItalic ? "yes" : "no", + lfp->lfWeight, + lfp->lfHeight, + ff_name (lfp->lfPitchAndFamily & 0xF0))); /* Ignore Symbol fonts (which don't have any Unicode mapping * table). We could also be fancy and use the PostScript glyph name @@ -1120,49 +1262,12 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, win32family = pango_win32_get_font_family (win32fontmap, pango_font_description_get_family (win32face->description)); + if ((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN) + win32family->is_monospace = TRUE; + win32family->faces = g_slist_append (win32family->faces, win32face); - PING (("g_slist_length(win32family->faces)=%d", g_slist_length (win32family->faces))); - -#if 1 /* Thought pango.aliases would make this code unnecessary, but no. */ - /* - * There are magic family names coming from the X implementation. - * They can be simply mapped to lfPitchAndFamily flag of the logfont - * struct. These additional entries should probably only be references - * to the respective entry created above. Thy are simply using the - * same entry at the moment and it isn't crashing on g_free () ??? - * Maybe a memory leak ... - */ - switch (lfp->lfPitchAndFamily & 0xF0) - { - case FF_MODERN : /* monospace */ - PING (("monospace")); - win32family->is_monospace = TRUE; /* modify before reuse */ - win32family = pango_win32_get_font_family (win32fontmap, "monospace"); - win32family->faces = g_slist_append (win32family->faces, win32face); - break; - case FF_ROMAN : /* serif */ - PING (("serif")); - win32family = pango_win32_get_font_family (win32fontmap, "serif"); - win32family->faces = g_slist_append (win32family->faces, win32face); - break; - case FF_SWISS : /* sans */ - PING (("sans")); - win32family = pango_win32_get_font_family (win32fontmap, "sans"); - win32family->faces = g_slist_append (win32family->faces, win32face); - break; - } - - /* Some other magic names */ - /* Recognize just "courier" for "courier new" */ - p = g_utf16_to_utf8 (win32face->logfontw.lfFaceName, -1, NULL, NULL, NULL); - if (p && g_ascii_strcasecmp (p, "courier new") == 0) - { - win32family = pango_win32_get_font_family (win32fontmap, "courier"); - win32family->faces = g_slist_append (win32family->faces, win32face); - } - g_free (p); -#endif + PING (("g_slist_length(win32family->faces)=%d", g_slist_length (win32family->faces))); } /* Given a LOGFONTW and size, make a matching LOGFONTW corresponding to |