summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--pango/pangowin32-fontmap.c210
-rw-r--r--pango/pangowin32.h2
3 files changed, 141 insertions, 97 deletions
diff --git a/ChangeLog b/ChangeLog
index 20e2c35d..cc11d323 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2006-02-10 Tor Lillqvist <tml@novell.com>
+
+ Fix #135098 and #322510.
+
+ * pango/pangowin32-fontmap.c (case_insensitive_hash)
+ (case_insensitive_equal): New helper functions for string hashing
+ based on ASCII case insensitivity..
+ (logfont_nosize_hash): Use case_insensitive_hash().
+ (logfont_nosize_equal): Use case_insensitive_equal().
+ (pango_win32_font_map_init): Use the case-insensitive functions
+ for the PangoWin32FontMap::families hash table.
+ (pango_win32_font_map_load_font): Consequently we don't need to
+ lowercase the name before looking up from the hash table.
+ (get_family_name): Constify parameter.
+ (get_family_name_lowercase): Not needed any longer.
+ (pango_win32_pango_font_description_from_logfont): New public
+ function. Code moved from pango_win32_insert_font(). Use family
+ name as such, don't lowercase it.
+ (pango_win32_insert_font): Use the above new function. Don't
+ bother looking for superfluos copies of the font entry as that
+ shouldn't ever happen. We have pruned out fonts that differ only
+ in charset already earlier.
+
+ * pango/pangowin32.h: Declare
+ pango_win32_pango_font_description_from_logfont().
+
2006-02-09 Behdad Esfahbod <behdad@gnome.org>
Bug 330602 – pango_parse_weight
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index ca81ea01..3f70063a 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -92,31 +92,47 @@ static PangoWin32FontMap *default_fontmap = NULL;
G_DEFINE_TYPE (PangoWin32FontMap, pango_win32_font_map, PANGO_TYPE_FONT_MAP)
+#define TOLOWER(c) \
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+static guint
+case_insensitive_hash (const char *key)
+{
+ const char *p = key;
+ guint h = TOLOWER (*p);
+
+ if (h)
+ {
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + TOLOWER (*p);
+ }
+
+ return h;
+}
+
+static gboolean
+case_insensitive_equal (const char *key1,
+ const char *key2)
+{
+ return (g_ascii_strcasecmp (key1, key2) == 0);
+}
+
/* A hash function for LOGFONTs that takes into consideration only
* those fields that indicate a specific .ttf file is in use:
* lfFaceName, lfItalic and lfWeight. Dunno how correct this is.
*/
-
static guint
-logfont_nosize_hash (gconstpointer v)
+logfont_nosize_hash (const LOGFONT *lfp)
{
- const LOGFONT *lfp = v;
- gchar *face = g_ascii_strdown (lfp->lfFaceName, -1);
- guint result = g_str_hash (face) + lfp->lfItalic + lfp->lfWeight;
-
- g_free (face);
-
- return result;
+ return case_insensitive_hash (lfp->lfFaceName) + lfp->lfItalic + lfp->lfWeight;
}
/* Ditto comparison function */
static gboolean
-logfont_nosize_equal (gconstpointer v1,
- gconstpointer v2)
+logfont_nosize_equal (const LOGFONT *lfp1,
+ const LOGFONT *lfp2)
{
- const LOGFONT *lfp1 = v1, *lfp2 = v2;
-
- return (g_ascii_strcasecmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0
+ return (case_insensitive_equal (lfp1->lfFaceName, lfp2->lfFaceName)
&& lfp1->lfItalic == lfp2->lfItalic
&& lfp1->lfWeight == lfp2->lfWeight);
}
@@ -165,9 +181,10 @@ pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
{
LOGFONT logfont;
- win32fontmap->families = g_hash_table_new (g_str_hash, g_str_equal);
+ win32fontmap->families = g_hash_table_new ((GHashFunc) case_insensitive_hash,
+ (GEqualFunc) case_insensitive_equal);
win32fontmap->size_infos =
- g_hash_table_new (logfont_nosize_hash, logfont_nosize_equal);
+ g_hash_table_new ((GHashFunc) logfont_nosize_hash, (GEqualFunc) logfont_nosize_equal);
win32fontmap->n_fonts = 0;
win32fontmap->font_cache = pango_win32_font_cache_new ();
@@ -401,15 +418,13 @@ pango_win32_font_map_load_font (PangoFontMap *fontmap,
PangoWin32Family *win32family;
PangoFont *result = NULL;
GSList *tmp_list;
- gchar *name;
g_return_val_if_fail (description != NULL, NULL);
- name = g_ascii_strdown (pango_font_description_get_family (description), -1);
-
- PING(("name=%s", name));
+ PING(("name=%s", pango_font_description_get_family (description)));
- win32family = g_hash_table_lookup (win32fontmap->families, name);
+ win32family = g_hash_table_lookup (win32fontmap->families,
+ pango_font_description_get_family (description));
if (win32family)
{
PangoWin32Face *best_match = NULL;
@@ -436,7 +451,6 @@ pango_win32_font_map_load_font (PangoFontMap *fontmap,
PING(("no best match!"));
}
- g_free (name);
return result;
}
@@ -482,7 +496,7 @@ pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
}
static gchar *
-get_family_name (LOGFONT *lfp)
+get_family_name (const LOGFONT *lfp)
{
HFONT hfont;
HFONT oldhfont;
@@ -605,14 +619,72 @@ get_family_name (LOGFONT *lfp)
return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
}
-static gchar *
-get_family_name_lowercase (LOGFONT *lfp)
+/**
+ * pango_win32_pango_font_description_from_logfont:
+ * @lfp: pointer to a LOGFONT
+ *
+ * Creates a #PangoFontDescription from a LOGFONT.
+ *
+ * The face name, italicness and weight fields in the LOGFONT are used
+ * to set up the resulting #PangoFontDescription. If the face name in
+ * the LOGFONT contains non-ASCII characters the font is temporarily
+ * loaded (using CreateFontIndirect) and an ASCII (usually English)
+ * name for it is looked up from the font name tables in the font
+ * data. If that doesn't work, the face name is converted from the
+ * system codepage to UTF-8 and that is used.
+ *
+ * Return value: a new #PangoFontDescription that should be freed with
+ * pango_font_desciption_free() when no longer needed.
+ */
+PangoFontDescription *
+pango_win32_pango_font_description_from_logfont (const LOGFONT *lfp)
{
- gchar *family = get_family_name (lfp);
- gchar *lower = g_ascii_strdown (family, -1);
+ PangoFontDescription *description;
+ gchar *family;
+ PangoStyle style;
+ PangoVariant variant;
+ PangoWeight weight;
+ PangoStretch stretch;
+
+ family = get_family_name (lfp);
+
+ if (!lfp->lfItalic)
+ style = PANGO_STYLE_NORMAL;
+ else
+ style = PANGO_STYLE_ITALIC;
+
+ variant = PANGO_VARIANT_NORMAL;
+
+ /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
+ * values. Is this on purpose? Quantize the weight to exact
+ * PANGO_WEIGHT_* values. Is this a good idea?
+ */
+ if (lfp->lfWeight == FW_DONTCARE)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
+ weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (lfp->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
+ weight = PANGO_WEIGHT_LIGHT;
+ else if (lfp->lfWeight <= (FW_NORMAL + FW_BOLD) / 2)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (lfp->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
+ weight = PANGO_WEIGHT_BOLD;
+ else if (lfp->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
+ weight = PANGO_WEIGHT_ULTRABOLD;
+ else
+ weight = PANGO_WEIGHT_HEAVY;
+
+ /* XXX No idea how to figure out the stretch */
+ stretch = PANGO_STRETCH_NORMAL;
+
+ description = pango_font_description_new ();
+ pango_font_description_set_family (description, family);
+ pango_font_description_set_style (description, style);
+ pango_font_description_set_weight (description, weight);
+ pango_font_description_set_stretch (description, stretch);
+ pango_font_description_set_variant (description, variant);
- g_free (family);
- return lower;
+ return description;
}
/* This inserts the given font into the size_infos table. If a SizeInfo
@@ -625,15 +697,9 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
LOGFONT *lfp)
{
LOGFONT *lfp2 = NULL;
- PangoFontDescription *description;
- gchar *family_name;
PangoWin32Family *font_family;
PangoWin32Face *win32face;
PangoWin32SizeInfo *size_info;
- PangoStyle style;
- PangoVariant variant;
- PangoWeight weight;
- PangoStretch stretch;
GSList *tmp_list;
gint i;
@@ -677,7 +743,10 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
rover->lfOrientation == lfp->lfOrientation &&
rover->lfUnderline == lfp->lfUnderline &&
rover->lfStrikeOut == lfp->lfStrikeOut)
- return;
+ {
+ PING(("already have it"));
+ return;
+ }
tmp_list = tmp_list->next;
}
@@ -693,68 +762,9 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
PING(("g_slist_length(size_info->logfonts)=%d", g_slist_length(size_info->logfonts)));
- family_name = get_family_name_lowercase (lfp);
-
- /* Convert the LOGFONT into a PangoFontDescription
- */
- if (!lfp2->lfItalic)
- style = PANGO_STYLE_NORMAL;
- else
- style = PANGO_STYLE_ITALIC;
-
- variant = PANGO_VARIANT_NORMAL;
-
- /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
- * values. Is this on purpose? Quantize the weight to exact
- * PANGO_WEIGHT_* values. Is this a good idea?
- */
- if (lfp2->lfWeight == FW_DONTCARE)
- weight = PANGO_WEIGHT_NORMAL;
- else if (lfp2->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
- weight = PANGO_WEIGHT_ULTRALIGHT;
- else if (lfp2->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
- weight = PANGO_WEIGHT_LIGHT;
- else if (lfp2->lfWeight <= (FW_NORMAL + FW_BOLD) / 2)
- weight = PANGO_WEIGHT_NORMAL;
- else if (lfp2->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
- weight = PANGO_WEIGHT_BOLD;
- else if (lfp2->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
- weight = PANGO_WEIGHT_ULTRABOLD;
- else
- weight = PANGO_WEIGHT_HEAVY;
-
- /* XXX No idea how to figure out the stretch */
- stretch = PANGO_STRETCH_NORMAL;
-
- font_family = pango_win32_get_font_family (win32fontmap, family_name);
- g_free (family_name);
-
- tmp_list = font_family->font_entries;
- while (tmp_list)
- {
- win32face = tmp_list->data;
-
- if (pango_font_description_get_style (win32face->description) == style &&
- pango_font_description_get_weight (win32face->description) == weight &&
- pango_font_description_get_stretch (win32face->description) == stretch &&
- pango_font_description_get_variant (win32face->description) == variant)
- {
- PING(("returning early"));
- return;
- }
-
- tmp_list = tmp_list->next;
- }
-
- description = pango_font_description_new ();
- pango_font_description_set_family_static (description, font_family->family_name);
- pango_font_description_set_style (description, style);
- pango_font_description_set_weight (description, weight);
- pango_font_description_set_stretch (description, stretch);
- pango_font_description_set_variant (description, variant);
-
win32face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
- win32face->description = description;
+ win32face->description = pango_win32_pango_font_description_from_logfont (lfp2);
+
win32face->cached_fonts = NULL;
for (i = 0; i < PANGO_WIN32_N_COVERAGES; i++)
@@ -762,7 +772,13 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
win32face->logfont = *lfp;
win32face->cmap_format = 0;
win32face->cmap = NULL;
+
+ font_family =
+ pango_win32_get_font_family (win32fontmap,
+ pango_font_description_get_family (win32face->description));
font_family->font_entries = g_slist_append (font_family->font_entries, win32face);
+ PING(("g_slist_length(font_family->font_entries)=%d", g_slist_length(font_family->font_entries)));
+
win32fontmap->n_fonts++;
#if 1 /* Thought pango.aliases would make this code unnecessary, but no. */
diff --git a/pango/pangowin32.h b/pango/pangowin32.h
index 6f025d7a..dc1aef14 100644
--- a/pango/pangowin32.h
+++ b/pango/pangowin32.h
@@ -106,6 +106,8 @@ PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *fo
LOGFONT *pango_win32_font_logfont (PangoFont *font);
+PangoFontDescription *pango_win32_pango_font_description_from_logfont (const LOGFONT *lfp);
+
G_END_DECLS
#endif /* __PANGOWIN32_H__ */