summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/Makefile.am21
-rw-r--r--pango/makefile.mingw.in (renamed from pango/makefile.mingw)70
-rw-r--r--pango/pango-utils.c74
-rw-r--r--pango/pango-utils.h16
-rw-r--r--pango/pangoft2-fontcache.c305
-rw-r--r--pango/pangoft2-fontmap.c1110
-rw-r--r--pango/pangoft2-private.h97
-rw-r--r--pango/pangoft2.c1126
-rw-r--r--pango/pangoft2.h107
-rw-r--r--pango/pangowin32-fontmap.c104
-rw-r--r--pango/pangowin32.c27
-rw-r--r--pango/pangowin32.h93
-rw-r--r--pango/pangox-fontmap.c8
13 files changed, 2969 insertions, 189 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index ee780e98..df653b17 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -66,10 +66,19 @@ pango_querymodules_SOURCES = \
querymodules.c
pango_querymodules_LDADD = libpangox.la libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(UNICODE_LIBS) $(X_LIBS)
-EXTRA_DIST = \
- pangowin32.h \
- pangowin32.c \
- pangowin32-private.h \
- pangowin32-fontcache.c \
- pangowin32-fontmap.c
+EXTRA_DIST = \
+ pangowin32.h \
+ pangowin32.c \
+ pangowin32-private.h \
+ pangowin32-fontcache.c \
+ pangowin32-fontmap.c \
+ pangoft2.h \
+ pangoft2.c \
+ pangoft2-private.h \
+ pangoft2-fontcache.c \
+ pangoft2-fontmap.c \
+ makefile.mingw \
+ makefile.mingw.in
+makefile.mingw: $(top_builddir)/config.status $(top_srcdir)/pango/makefile.mingw.in
+ cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/pango/makefile.mingw b/pango/makefile.mingw.in
index dca8e55d..3bcc4beb 100644
--- a/pango/makefile.mingw
+++ b/pango/makefile.mingw.in
@@ -1,44 +1,51 @@
-PANGO_VER = 0.12
-
TOP = ../..
include $(TOP)/build/win32/make.mingw
-OPTIMIZE = -g
+# Possibly override Pango version from build/win32/module.defs
+PANGO_VER = @VERSION@
+
+OPTIMIZE = -g -Wall
INCLUDES = -I .. -I .
DEFINES =
-DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FRIBIDI_CFLAGS)
+DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FRIBIDI_CFLAGS) $(FREETYPE2_CFLAGS)
-all : \
- ../config.h \
- pango-$(PANGO_VER).dll \
- pangowin32-$(PANGO_VER).dll \
+all : \
+ ../config.h \
+ pango-$(PANGO_VER).dll \
+ pangowin32-$(PANGO_VER).dll \
+ pangoft2-$(PANGO_VER).dll \
pango-querymodules.exe
-PANGO_OBJS = \
- break.o \
- fonts.o \
- glyphstring.o \
- mapping.o \
- modules.o \
- module-defs.o \
- pango-attributes.o \
- pango-context.o \
- pango-coverage.o \
- pango-fontmap.o \
- pango-item.o \
- pango-layout.o \
- pango-utils.o \
- reorder-items.o \
+PANGO_OBJS = \
+ break.o \
+ fonts.o \
+ glyphstring.o \
+ mapping.o \
+ modules.o \
+ module-defs.o \
+ pango-attributes.o \
+ pango-context.o \
+ pango-coverage.o \
+ pango-fontmap.o \
+ pango-item.o \
+ pango-layout.o \
+ pango-utils.o \
+ reorder-items.o \
shape.o
-PANGOWIN32_OBJS = \
- pangowin32.o \
- pangowin32-fontcache.o \
+PANGOWIN32_OBJS = \
+ pangowin32.o \
+ pangowin32-fontcache.o \
pangowin32-fontmap.o
-PANGO_QUERYMODULES_OBJS = \
+PANGOFT2_OBJS = \
+ pangoft2.o \
+ pangoft2-fontcache.o \
+ pangoft2-fontmap.o
+
+PANGO_QUERYMODULES_OBJS = \
querymodules.o
../config.h : ../config.h.win32
@@ -53,7 +60,10 @@ pango-$(PANGO_VER).dll : $(PANGO_OBJS) pango.def
pangowin32-$(PANGO_VER).dll : $(PANGOWIN32_OBJS) pangowin32.def
$(GLIB)/build-dll pangowin32 $(PANGO_VER) pangowin32.def $(OPTIMIZE) $(PANGOWIN32_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) -lgdi32
-pango-querymodules.exe : $(PANGO_QUERYMODULES_OBJS) pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll
+pangoft2-$(PANGO_VER).dll : $(PANGOFT2_OBJS) pangoft2.def
+ $(GLIB)/build-dll pangoft2 $(PANGO_VER) pangoft2.def $(OPTIMIZE) $(PANGOFT2_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) $(FREETYPE2_LIBS) -lgdi32
+
+pango-querymodules.exe : $(PANGO_QUERYMODULES_OBJS) pango-$(PANGO_VER).dll
$(CC) -o $@ $(PANGO_QUERYMODULES_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS)
test1.exe : test1.o pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll
@@ -71,3 +81,7 @@ test4.exe : test4.o pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll
test5.exe : test5.o
$(CC) -o $@ $(CFLAGS) test5.o -lgdi32
+# Hack to get an updated makefile.mingw automatically after updating
+# makefile.mingw.in. Only for developer use.
+makefile.mingw: makefile.mingw.in
+ sed -e 's,@VER[S]ION@,@VERSION@,' <$< >$@
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index f48b197b..807adac8 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -657,7 +657,8 @@ pango_get_lib_subdirectory (void)
gboolean
pango_parse_style (GString *str,
- PangoFontDescription *desc)
+ PangoFontDescription *desc,
+ gboolean warn)
{
if (str->len == 0)
return FALSE;
@@ -666,35 +667,37 @@ pango_parse_style (GString *str,
{
case 'n':
case 'N':
- if (strncasecmp (str->str, "normal", str->len) == 0)
+ if (g_strncasecmp (str->str, "normal", str->len) == 0)
{
desc->style = PANGO_STYLE_NORMAL;
return TRUE;
}
break;
case 'i':
- if (strncasecmp (str->str, "italic", str->len) == 0)
+ if (g_strncasecmp (str->str, "italic", str->len) == 0)
{
desc->style = PANGO_STYLE_ITALIC;
return TRUE;
}
break;
case 'o':
- if (strncasecmp (str->str, "oblique", str->len) == 0)
+ if (g_strncasecmp (str->str, "oblique", str->len) == 0)
{
desc->style = PANGO_STYLE_OBLIQUE;
return TRUE;
}
break;
}
- g_warning ("Style must be normal, italic, or oblique");
+ if (warn)
+ g_warning ("Style must be normal, italic, or oblique");
return FALSE;
}
gboolean
pango_parse_variant (GString *str,
- PangoFontDescription *desc)
+ PangoFontDescription *desc,
+ gboolean warn)
{
if (str->len == 0)
return FALSE;
@@ -703,7 +706,7 @@ pango_parse_variant (GString *str,
{
case 'n':
case 'N':
- if (strncasecmp (str->str, "normal", str->len) == 0)
+ if (g_strncasecmp (str->str, "normal", str->len) == 0)
{
desc->variant = PANGO_VARIANT_NORMAL;
return TRUE;
@@ -711,7 +714,8 @@ pango_parse_variant (GString *str,
break;
case 's':
case 'S':
- if (strncasecmp (str->str, "small_caps", str->len) == 0)
+ if (g_strncasecmp (str->str, "small_caps", str->len) == 0 ||
+ g_strncasecmp (str->str, "smallcaps", str->len) == 0)
{
desc->variant = PANGO_VARIANT_SMALL_CAPS;
return TRUE;
@@ -719,13 +723,15 @@ pango_parse_variant (GString *str,
break;
}
- g_warning ("Variant must be normal, or small_caps");
+ if (warn)
+ g_warning ("Variant must be normal or small_caps");
return FALSE;
}
gboolean
pango_parse_weight (GString *str,
- PangoFontDescription *desc)
+ PangoFontDescription *desc,
+ gboolean warn)
{
if (str->len == 0)
return FALSE;
@@ -734,7 +740,7 @@ pango_parse_weight (GString *str,
{
case 'b':
case 'B':
- if (strncasecmp (str->str, "bold", str->len) == 0)
+ if (g_strncasecmp (str->str, "bold", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_BOLD;
return TRUE;
@@ -742,7 +748,7 @@ pango_parse_weight (GString *str,
break;
case 'h':
case 'H':
- if (strncasecmp (str->str, "heavy", str->len) == 0)
+ if (g_strncasecmp (str->str, "heavy", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_HEAVY;
return TRUE;
@@ -750,7 +756,7 @@ pango_parse_weight (GString *str,
break;
case 'l':
case 'L':
- if (strncasecmp (str->str, "light", str->len) == 0)
+ if (g_strncasecmp (str->str, "light", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_LIGHT;
return TRUE;
@@ -758,7 +764,7 @@ pango_parse_weight (GString *str,
break;
case 'n':
case 'N':
- if (strncasecmp (str->str, "normal", str->len) == 0)
+ if (g_strncasecmp (str->str, "normal", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_NORMAL;
return TRUE;
@@ -766,12 +772,12 @@ pango_parse_weight (GString *str,
break;
case 'u':
case 'U':
- if (strncasecmp (str->str, "ultralight", str->len) == 0)
+ if (g_strncasecmp (str->str, "ultralight", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_ULTRALIGHT;
return TRUE;
}
- else if (strncasecmp (str->str, "ultrabold", str->len) == 0)
+ else if (g_strncasecmp (str->str, "ultrabold", str->len) == 0)
{
desc->weight = PANGO_WEIGHT_ULTRABOLD;
return TRUE;
@@ -795,7 +801,8 @@ pango_parse_weight (GString *str,
desc->weight = strtol (numstr, &end, 0);
if (*end != '\0')
{
- g_warning ("Cannot parse numerical weight '%s'", numstr);
+ if (warn)
+ g_warning ("Cannot parse numerical weight '%s'", numstr);
g_free (numstr);
return FALSE;
}
@@ -805,13 +812,15 @@ pango_parse_weight (GString *str,
}
}
- g_warning ("Weight must be ultralight, light, normal, bold, ultrabold, heavy, or an integer");
+ if (warn)
+ g_warning ("Weight must be ultralight, light, normal, bold, ultrabold, heavy, or an integer");
return FALSE;
}
gboolean
pango_parse_stretch (GString *str,
- PangoFontDescription *desc)
+ PangoFontDescription *desc,
+ gboolean warn)
{
if (str->len == 0)
return FALSE;
@@ -820,7 +829,7 @@ pango_parse_stretch (GString *str,
{
case 'c':
case 'C':
- if (strncasecmp (str->str, "condensed", str->len) == 0)
+ if (g_strncasecmp (str->str, "condensed", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_CONDENSED;
return TRUE;
@@ -828,17 +837,19 @@ pango_parse_stretch (GString *str,
break;
case 'e':
case 'E':
- if (strncasecmp (str->str, "extra_condensed", str->len) == 0)
+ if (g_strncasecmp (str->str, "extra_condensed", str->len) == 0 ||
+ g_strncasecmp (str->str, "extracondensed", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_EXTRA_CONDENSED;
return TRUE;
}
- if (strncasecmp (str->str, "extra_expanded", str->len) == 0)
+ if (g_strncasecmp (str->str, "extra_expanded", str->len) == 0 ||
+ g_strncasecmp (str->str, "extraexpanded", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_EXTRA_EXPANDED;
return TRUE;
}
- if (strncasecmp (str->str, "expanded", str->len) == 0)
+ if (g_strncasecmp (str->str, "expanded", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_EXPANDED;
return TRUE;
@@ -846,7 +857,7 @@ pango_parse_stretch (GString *str,
break;
case 'n':
case 'N':
- if (strncasecmp (str->str, "normal", str->len) == 0)
+ if (g_strncasecmp (str->str, "normal", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_NORMAL;
return TRUE;
@@ -854,12 +865,14 @@ pango_parse_stretch (GString *str,
break;
case 's':
case 'S':
- if (strncasecmp (str->str, "semi_condensed", str->len) == 0)
+ if (g_strncasecmp (str->str, "semi_condensed", str->len) == 0 ||
+ g_strncasecmp (str->str, "semicondensed", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_SEMI_CONDENSED;
return TRUE;
}
- if (strncasecmp (str->str, "semi_expanded", str->len) == 0)
+ if (g_strncasecmp (str->str, "semi_expanded", str->len) == 0 ||
+ g_strncasecmp (str->str, "semiexpanded", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_SEMI_EXPANDED;
return TRUE;
@@ -867,12 +880,14 @@ pango_parse_stretch (GString *str,
break;
case 'u':
case 'U':
- if (strncasecmp (str->str, "ultra_condensed", str->len) == 0)
+ if (g_strncasecmp (str->str, "ultra_condensed", str->len) == 0 ||
+ g_strncasecmp (str->str, "ultracondensed", str->len) == 0)
{
desc->stretch = PANGO_STRETCH_ULTRA_CONDENSED;
return TRUE;
}
- if (strncasecmp (str->str, "ultra_expanded", str->len) == 0)
+ if (g_strncasecmp (str->str, "ultra_expanded", str->len) == 0 ||
+ g_strncasecmp (str->str, "ultraexpanded", str->len) == 0)
{
desc->variant = PANGO_STRETCH_ULTRA_EXPANDED;
return TRUE;
@@ -880,7 +895,8 @@ pango_parse_stretch (GString *str,
break;
}
- g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded");
+ if (warn)
+ g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded");
return FALSE;
}
diff --git a/pango/pango-utils.h b/pango/pango-utils.h
index 941ad515..4891767e 100644
--- a/pango/pango-utils.h
+++ b/pango/pango-utils.h
@@ -41,16 +41,22 @@ char * pango_config_key_get (const char *key);
/* Functions for parsing textual representations
* of PangoFontDescription fields. They return TRUE if the input string
* contains a valid value, which then has been assigned to the corresponding
- * field in the PangoFontDescription.
+ * field in the PangoFontDescription. If the warn parameter is TRUE,
+ * a warning is printed (with g_warning) if the string does not
+ * contain a valid value.
*/
gboolean pango_parse_style (GString *str,
- PangoFontDescription *desc);
+ PangoFontDescription *desc,
+ gboolean warn);
gboolean pango_parse_variant (GString *str,
- PangoFontDescription *desc);
+ PangoFontDescription *desc,
+ gboolean warn);
gboolean pango_parse_weight (GString *str,
- PangoFontDescription *desc);
+ PangoFontDescription *desc,
+ gboolean warn);
gboolean pango_parse_stretch (GString *str,
- PangoFontDescription *desc);
+ PangoFontDescription *desc,
+ gboolean warn);
/* On Unix, return the name of the "pango" subdirectory of SYSCONFDIR
* (which is set at compile time). On Win32, return the Pango
diff --git a/pango/pangoft2-fontcache.c b/pango/pangoft2-fontcache.c
new file mode 100644
index 00000000..4f7f82b5
--- /dev/null
+++ b/pango/pangoft2-fontcache.c
@@ -0,0 +1,305 @@
+/* Pango
+ * pangoft2-fontcache.c: Cache of FreeType2 faces (FT_Face)
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "pangoft2-private.h"
+
+/* Font cache
+ */
+
+/* Number of fonts to retain after they are not otherwise referenced.
+ */
+#define CACHE_SIZE 3
+
+typedef struct _CacheEntry CacheEntry;
+
+struct _PangoFT2FontCache
+{
+ FT_Library library;
+
+ GHashTable *forward;
+ GHashTable *back;
+
+ GList *mru;
+ GList *mru_tail;
+ int mru_count;
+};
+
+struct _CacheEntry
+{
+ PangoFT2OA oa;
+ FT_Face face;
+
+ gint ref_count;
+ GList *mru;
+};
+
+static void
+free_cache_entry (PangoFT2OA *oa,
+ CacheEntry *entry,
+ PangoFT2FontCache *cache)
+{
+ FT_Error error;
+
+ PING (("FT_Done_Face (%p)\n", entry->face));
+
+ error = FT_Done_Face (entry->face);
+ if (error != FT_Err_Ok)
+ g_warning ("Error from FT_Done_Face: %s",
+ pango_ft2_ft_strerror (error));
+
+ g_free (entry);
+}
+
+/**
+ * pango_ft2_font_cache_free:
+ * @cache: a #PangoFT2FontCache
+ *
+ * Free a #PangoFT2FontCache and all associated memory. All fonts loaded
+ * through this font cache will be freed along with the cache.
+ **/
+void
+pango_ft2_font_cache_free (PangoFT2FontCache *cache)
+{
+ g_return_if_fail (cache != NULL);
+
+ g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
+
+ g_hash_table_destroy (cache->forward);
+ g_hash_table_destroy (cache->back);
+
+ g_list_free (cache->mru);
+}
+
+static guint
+oa_hash (gconstpointer v)
+{
+ PangoFT2OA *oa = (PangoFT2OA *) v;
+
+ if (oa->open_args->flags & ft_open_memory)
+ return (guint) oa->open_args->memory_base;
+ else if (oa->open_args->flags == ft_open_pathname)
+ return g_str_hash (oa->open_args->pathname);
+ else if (oa->open_args->flags & ft_open_stream)
+ return (guint) oa->open_args->stream;
+ else
+ return 0;
+}
+
+static gint
+oa_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ PangoFT2OA *oa1 = (PangoFT2OA *) v1;
+ PangoFT2OA *oa2 = (PangoFT2OA *) v2;
+
+ if (oa1->open_args->flags != oa2->open_args->flags)
+ return 0;
+ else if (oa1->open_args->flags & ft_open_memory)
+ return (oa1->open_args->memory_base == oa2->open_args->memory_base &&
+ oa1->face_index == oa2->face_index);
+ else if (oa1->open_args->flags == ft_open_pathname)
+ return (strcmp (oa1->open_args->pathname,
+ oa2->open_args->pathname) == 0 &&
+ oa1->face_index == oa2->face_index);
+ else if (oa1->open_args->flags & ft_open_stream)
+ return (oa1->open_args->stream == oa2->open_args->stream &&
+ oa1->face_index == oa2->face_index);
+ else
+ return 0;
+}
+
+/**
+ * pango_ft2_font_cache_new:
+ *
+ * Create a font cache.
+ *
+ * Return value: The new font cache. This must be freed with
+ * pango_ft2_font_cache_free().
+ **/
+PangoFT2FontCache *
+pango_ft2_font_cache_new (FT_Library library)
+{
+ PangoFT2FontCache *cache;
+
+ cache = g_new (PangoFT2FontCache, 1);
+
+ cache->library = library;
+
+ cache->forward = g_hash_table_new (oa_hash, oa_equal);
+ cache->back = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ cache->mru = NULL;
+ cache->mru_tail = NULL;
+ cache->mru_count = 0;
+
+ return cache;
+}
+
+static void
+cache_entry_unref (PangoFT2FontCache *cache,
+ CacheEntry *entry)
+{
+ entry->ref_count--;
+ PING (("face:%p ref_count:%d\n", entry->face, entry->ref_count));
+ if (entry->ref_count == 0)
+ {
+ g_hash_table_remove (cache->forward, &entry->oa);
+ g_hash_table_remove (cache->back, entry->face);
+
+ free_cache_entry (NULL, entry, cache);
+ }
+}
+
+/**
+ * pango_ft2_font_cache_load:
+ * @cache: a #PangoFT2FontCache
+ *
+ * Load a #FT_Face from #FT_Open_Args and a face index. The
+ * result may be newly loaded, or it may have been previously
+ * stored
+ *
+ * Return value: The #FT_Face, or %NULL if the font could
+ * not be loaded. In order to free this structure, you must call
+ * pango_ft2_font_cache_unload().
+ **/
+FT_Face
+pango_ft2_font_cache_load (PangoFT2FontCache *cache,
+ FT_Open_Args *args,
+ FT_Long face_index)
+{
+ CacheEntry *entry;
+ PangoFT2OA oa;
+
+ g_return_val_if_fail (cache != NULL, NULL);
+ g_return_val_if_fail (args != NULL, NULL);
+
+ oa.open_args = args;
+ oa.face_index = face_index;
+
+ entry = g_hash_table_lookup (cache->forward, &oa);
+
+ if (entry)
+ entry->ref_count++;
+ else
+ {
+ FT_Face face;
+ FT_Error error;
+
+ PING (("FT_Open_Face (%s,%ld)\n", args->pathname, face_index));
+
+ error = FT_Open_Face (cache->library, args, face_index, &face);
+ if (error != FT_Err_Ok)
+ {
+ g_warning ("Error from FT_Open_Face: %s",
+ pango_ft2_ft_strerror (error));
+ return NULL;
+ }
+
+#if DEBUGGING
+ g_print (" = %p\n", face);
+#endif
+
+ entry = g_new (CacheEntry, 1);
+
+ entry->oa = oa;
+ entry->face = face;
+
+ entry->ref_count = 1;
+ entry->mru = NULL;
+
+ g_hash_table_insert (cache->forward, &entry->oa, entry);
+ g_hash_table_insert (cache->back, entry->face, entry);
+ }
+
+ if (entry->mru)
+ {
+ if (cache->mru_count > 1 && entry->mru->prev)
+ {
+ /* Move to the head of the mru list */
+
+ if (entry->mru == cache->mru_tail)
+ {
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+ }
+ else
+ {
+ entry->mru->prev->next = entry->mru->next;
+ entry->mru->next->prev = entry->mru->prev;
+ }
+
+ entry->mru->next = cache->mru;
+ entry->mru->prev = NULL;
+ cache->mru->prev = entry->mru;
+ cache->mru = entry->mru;
+ }
+ }
+ else
+ {
+ entry->ref_count++;
+
+ /* Insert into the mru list */
+
+ if (cache->mru_count == CACHE_SIZE)
+ {
+ CacheEntry *old_entry = cache->mru_tail->data;
+
+ cache->mru_tail = cache->mru_tail->prev;
+ cache->mru_tail->next = NULL;
+
+ g_list_free_1 (old_entry->mru);
+ old_entry->mru = NULL;
+ cache_entry_unref (cache, old_entry);
+ }
+ else
+ cache->mru_count++;
+
+ cache->mru = g_list_prepend (cache->mru, entry);
+ if (!cache->mru_tail)
+ cache->mru_tail = cache->mru;
+ entry->mru = cache->mru;
+ }
+
+ return entry->face;
+}
+
+/**
+ * pango_ft2_font_cache_unload:
+ * @cache: a #PangoFT2FontCache
+ * @face: the face to unload
+ *
+ * Free a font structure previously loaded with pango_ft2_font_cache_load()
+ **/
+void
+pango_ft2_font_cache_unload (PangoFT2FontCache *cache,
+ FT_Face face)
+{
+ CacheEntry *entry;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (face != NULL);
+
+ entry = g_hash_table_lookup (cache->back, face);
+ g_return_if_fail (entry != NULL);
+
+ PING (("pango_ft2_font_cache_unload\n"));
+ cache_entry_unref (cache, entry);
+}
diff --git a/pango/pangoft2-fontmap.c b/pango/pangoft2-fontmap.c
new file mode 100644
index 00000000..a81c8639
--- /dev/null
+++ b/pango/pangoft2-fontmap.c
@@ -0,0 +1,1110 @@
+/* Pango
+ * pangoft2-fontmap.c:
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <sys/stat.h>
+
+#include "pango-fontmap.h"
+#include "pango-utils.h"
+#include "pangoft2-private.h"
+
+#define PANGO_TYPE_FT2_FONT_MAP (pango_ft2_font_map_get_type ())
+#define PANGO_FT2_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMap))
+#define PANGO_FT2_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMapClass))
+#define PANGO_FT2_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT_MAP))
+#define PANGO_FT2_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT_MAP))
+#define PANGO_FT2_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT_MAP, PangoFontMapClass))
+
+typedef struct _PangoFT2FamilyEntry PangoFT2FamilyEntry;
+typedef struct _PangoFT2FontMap PangoFT2FontMap;
+typedef struct _PangoFT2FontMapClass PangoFT2FontMapClass;
+typedef struct _PangoFT2SizeInfo PangoFT2SizeInfo;
+
+/* Number of freed fonts */
+#define MAX_FREED_FONTS 16
+
+struct _PangoFT2FontMap
+{
+ PangoFontMap parent_instance;
+
+ FT_Library library;
+
+ PangoFT2FontCache *font_cache;
+ GQueue *freed_fonts;
+
+ /* Maps Pango family names to PangoFT2FamilyEntry structs */
+ GHashTable *families;
+
+ /* Maps the family and style of a face to a PangoFT2OA struct */
+ GHashTable *faces;
+
+ int n_fonts;
+
+ double resolution; /* (points / pixel) * PANGO_SCALE */
+};
+
+struct _PangoFT2FontMapClass
+{
+ PangoFontMapClass parent_class;
+};
+
+struct _PangoFT2FamilyEntry
+{
+ char *family_name;
+
+ /* List of PangoFT2FontEntry structs */
+ GSList *font_entries;
+};
+
+struct _PangoFT2FontEntry
+{
+ FT_Open_Args **open_args;
+ FT_Long *face_indices;
+ int n_fonts;
+ PangoFontDescription description;
+ PangoCoverage *coverage;
+
+ GSList *cached_fonts;
+};
+
+static GType pango_ft2_font_map_get_type (void);
+
+static void pango_ft2_font_map_init (PangoFT2FontMap *fontmap);
+
+static void pango_ft2_font_map_class_init (PangoFT2FontMapClass *class);
+
+static void pango_ft2_font_map_finalize (GObject *object);
+
+static PangoFont *pango_ft2_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description);
+
+static void pango_ft2_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+static void pango_ft2_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families);
+
+static void pango_ft2_fontmap_cache_clear (PangoFT2FontMap *ft2fontmap);
+
+static void pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap);
+
+static void pango_ft2_insert_face (PangoFT2FontMap *fontmap,
+ FT_Face face,
+ const char *path,
+ int face_index);
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoFT2FontMap */
+
+static PangoFT2FontMap *pango_ft2_global_fontmap = NULL;
+static GSList *pango_ft2_font_directories = NULL;
+
+static GType
+pango_ft2_font_map_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFT2FontMapClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_ft2_font_map_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFT2FontMap),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_ft2_font_map_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
+ "PangoFT2FontMap",
+ &object_info);
+ }
+
+ return object_type;
+}
+
+static guint
+face_style_hash (gconstpointer v)
+{
+ PangoFontDescription *desc = (PangoFontDescription *)v;
+
+ return g_str_hash (desc->family_name) +
+ desc->style + desc->variant + desc->weight + desc->stretch;
+}
+
+static gint
+face_style_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ PangoFontDescription *desc1 = (PangoFontDescription *)v1;
+ PangoFontDescription *desc2 = (PangoFontDescription *)v2;
+
+ return (g_strcasecmp (desc1->family_name, desc2->family_name) == 0 &&
+ desc1->style == desc2->style &&
+ desc1->variant == desc2->variant &&
+ desc1->weight == desc2->weight &&
+ desc1->stretch == desc2->stretch);
+}
+
+static void
+pango_ft2_font_map_init (PangoFT2FontMap *ft2fontmap)
+{
+ ft2fontmap->families = g_hash_table_new (g_str_hash, g_str_equal);
+ ft2fontmap->faces = g_hash_table_new (face_style_hash, face_style_equal);
+ ft2fontmap->n_fonts = 0;
+}
+
+static void
+pango_ft2_font_map_class_init (PangoFT2FontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontMapClass *font_map_class = PANGO_FONT_MAP_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_ft2_font_map_finalize;
+ font_map_class->load_font = pango_ft2_font_map_load_font;
+ font_map_class->list_fonts = pango_ft2_font_map_list_fonts;
+ font_map_class->list_families = pango_ft2_font_map_list_families;
+
+ /* FIXME */
+ pango_ft2_font_directories = g_slist_append (pango_ft2_font_directories, "C:\\windows\\fonts");
+}
+
+static gboolean
+pango_ft2_is_font_file (const char *name)
+{
+ struct stat filestat;
+ int err, len;
+
+ err = stat (name, &filestat);
+
+ if (!err && S_ISREG (filestat.st_mode))
+ {
+ len = strlen (name);
+ if (len > 4 &&
+ (g_strncasecmp (&name[len-4], ".pfa", 4) == 0 ||
+ g_strncasecmp (&name[len-4], ".pfb", 4) == 0 ||
+ g_strncasecmp (&name[len-4], ".ttf", 4) == 0))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+pango_ft2_scan_directory (const char *path,
+ PangoFT2FontMap *ft2fontmap)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char *fullname;
+ FT_Face face;
+ FT_Error error;
+ int i;
+
+ dir = opendir (path);
+ if (!dir)
+ g_warning ("Error opening directory '%s'", path);
+ else
+ {
+ while ((entry = readdir (dir)) != NULL)
+ {
+ fullname = g_strconcat (path,
+ (path[strlen (path)-1] == G_DIR_SEPARATOR ?
+ "" : G_DIR_SEPARATOR_S),
+ entry->d_name,
+ NULL);
+ if (pango_ft2_is_font_file (fullname))
+ {
+ error = FT_New_Face (ft2fontmap->library, fullname, 0, &face);
+ if (error != FT_Err_Ok)
+ g_warning ("Error loading font from '%s': %s",
+ fullname, pango_ft2_ft_strerror (error));
+ else
+ {
+ if (face->face_flags & FT_FACE_FLAG_SCALABLE)
+ pango_ft2_insert_face (ft2fontmap, face, fullname, 0);
+
+ for (i = 1; i < face->num_faces; i++)
+ {
+ error = FT_Done_Face (face);
+ if (error != FT_Err_Ok)
+ g_warning ("Error from FT_Done_Face: %s",
+ pango_ft2_ft_strerror (error));
+ error = FT_New_Face (ft2fontmap->library, fullname, i, &face);
+ if (error != FT_Err_Ok)
+ g_warning ("Error loading font %d from '%s': %s",
+ i, fullname, pango_ft2_ft_strerror (error));
+ else if (face->face_flags & FT_FACE_FLAG_SCALABLE)
+ pango_ft2_insert_face (ft2fontmap, face, fullname, i);
+ }
+ error = FT_Done_Face (face);
+ if (error != FT_Err_Ok)
+ g_warning ("Error from FT_Done_Face: %s",
+ pango_ft2_ft_strerror (error));
+ }
+ }
+ g_free (fullname);
+ }
+ closedir (dir);
+ }
+}
+
+PangoFontMap *
+pango_ft2_font_map_for_display (void)
+{
+ GSList *tmp_list;
+ FT_Error error;
+
+ /* Make sure that the type system is initialized */
+ g_type_init();
+
+ if (pango_ft2_global_fontmap != NULL)
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+
+ pango_ft2_global_fontmap = (PangoFT2FontMap *)g_type_create_instance (PANGO_TYPE_FT2_FONT_MAP);
+
+ error = FT_Init_FreeType (&pango_ft2_global_fontmap->library);
+ if (error != FT_Err_Ok)
+ {
+ g_warning ("Error from FT_Init_FreeType: %s",
+ pango_ft2_ft_strerror (error));
+ return NULL;
+ }
+
+ pango_ft2_global_fontmap->font_cache = pango_ft2_font_cache_new (pango_ft2_global_fontmap->library);
+ pango_ft2_global_fontmap->freed_fonts = g_queue_new ();
+
+ tmp_list = pango_ft2_font_directories;
+
+ while (tmp_list)
+ {
+ pango_ft2_scan_directory ((const char *) tmp_list->data, pango_ft2_global_fontmap);
+ tmp_list = tmp_list->next;
+ }
+
+ pango_ft2_font_map_read_aliases (pango_ft2_global_fontmap);
+
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+}
+
+/**
+ * pango_ft2_shutdown_display:
+ *
+ * Free cached resources.
+ **/
+void
+pango_ft2_shutdown_display (void)
+{
+ pango_ft2_fontmap_cache_clear (pango_ft2_global_fontmap);
+
+ g_object_unref (G_OBJECT (pango_ft2_global_fontmap));
+
+ pango_ft2_global_fontmap = NULL;
+}
+
+static void
+pango_ft2_font_map_finalize (GObject *object)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object);
+
+ g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_queue_free (ft2fontmap->freed_fonts);
+
+ pango_ft2_font_cache_free (ft2fontmap->font_cache);
+
+ FT_Done_FreeType (ft2fontmap->library);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+typedef struct
+{
+ int n_found;
+ PangoFontDescription **descs;
+} ListFontsInfo;
+
+static void
+list_fonts_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ PangoFT2FamilyEntry *entry = value;
+ ListFontsInfo *info = user_data;
+
+ GSList *tmp_list = entry->font_entries;
+
+ while (tmp_list)
+ {
+ PangoFT2FontEntry *font_entry = tmp_list->data;
+
+ info->descs[info->n_found++] = pango_font_description_copy (&font_entry->description);
+ tmp_list = tmp_list->next;
+ }
+}
+
+static void
+pango_ft2_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs)
+{
+ PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+ ListFontsInfo info;
+
+ if (!n_descs)
+ return;
+
+ if (family)
+ {
+ PangoFT2FamilyEntry *entry = g_hash_table_lookup (ft2fontmap->families, family);
+ if (entry)
+ {
+ *n_descs = g_slist_length (entry->font_entries);
+ if (descs)
+ {
+ *descs = g_new (PangoFontDescription *, *n_descs);
+
+ info.descs = *descs;
+ info.n_found = 0;
+
+ list_fonts_foreach ((gpointer)family, (gpointer)entry, &info);
+ }
+ }
+ else
+ {
+ *n_descs = 0;
+ if (descs)
+ *descs = NULL;
+ }
+ }
+ else
+ {
+ *n_descs = ft2fontmap->n_fonts;
+ if (descs)
+ {
+ *descs = g_new (PangoFontDescription *, ft2fontmap->n_fonts);
+
+ info.descs = *descs;
+ info.n_found = 0;
+
+ g_hash_table_foreach (ft2fontmap->families, list_fonts_foreach, &info);
+ }
+ }
+}
+
+static void
+list_families_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **list = user_data;
+
+ *list = g_slist_prepend (*list, key);
+}
+
+static void
+pango_ft2_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families)
+{
+ GSList *family_list = NULL;
+ GSList *tmp_list;
+ PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+
+ if (!n_families)
+ return;
+
+ g_hash_table_foreach (ft2fontmap->families, list_families_foreach, &family_list);
+
+ *n_families = g_slist_length (family_list);
+
+ if (families)
+ {
+ int i = 0;
+
+ *families = g_new (gchar *, *n_families);
+
+ tmp_list = family_list;
+ while (tmp_list)
+ {
+ (*families)[i] = g_strdup (tmp_list->data);
+ i++;
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ g_slist_free (family_list);
+}
+
+static PangoFT2FamilyEntry *
+pango_ft2_get_family_entry (PangoFT2FontMap *ft2fontmap,
+ const char *family_name)
+{
+ PangoFT2FamilyEntry *family_entry = g_hash_table_lookup (ft2fontmap->families, family_name);
+ if (!family_entry)
+ {
+ family_entry = g_new (PangoFT2FamilyEntry, 1);
+ family_entry->family_name = g_strdup (family_name);
+ family_entry->font_entries = NULL;
+
+ g_hash_table_insert (ft2fontmap->families, family_entry->family_name, family_entry);
+ }
+
+ return family_entry;
+}
+
+static PangoFont *
+pango_ft2_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description)
+{
+ PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+ PangoFT2FamilyEntry *family_entry;
+ PangoFont *result = NULL;
+ GSList *tmp_list;
+ gchar *name;
+
+ g_return_val_if_fail (description != NULL, NULL);
+ g_return_val_if_fail (description->size > 0, NULL);
+
+ name = g_strdup (description->family_name);
+ g_strdown (name);
+
+ family_entry = g_hash_table_lookup (ft2fontmap->families, name);
+ if (family_entry)
+ {
+ PangoFT2FontEntry *best_match = NULL;
+
+ tmp_list = family_entry->font_entries;
+ while (tmp_list)
+ {
+ PangoFT2FontEntry *font_entry = tmp_list->data;
+
+ if (font_entry->description.style == description->style &&
+ font_entry->description.variant == description->variant &&
+ font_entry->description.stretch == description->stretch)
+ {
+ int distance = abs (font_entry->description.weight - description->weight);
+ int old_distance = best_match ? abs (best_match->description.weight - description->weight) : G_MAXINT;
+
+ if (distance < old_distance)
+ {
+ best_match = font_entry;
+ }
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (best_match)
+ {
+ GSList *tmp_list = best_match->cached_fonts;
+
+ while (tmp_list)
+ {
+ PangoFT2Font *ft2font = tmp_list->data;
+
+ if (ft2font->size == description->size)
+ {
+ result = (PangoFont *)ft2font;
+
+ g_object_ref (G_OBJECT (result));
+ if (ft2font->in_cache)
+ pango_ft2_fontmap_cache_remove (fontmap, ft2font);
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (!result)
+ {
+ PangoFT2Font *ft2font =
+ (PangoFT2Font *) pango_ft2_load_font (fontmap,
+ best_match->open_args,
+ best_match->face_indices,
+ best_match->n_fonts,
+ description->size);
+
+ ft2font->fontmap = fontmap;
+ ft2font->entry = best_match;
+ best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, ft2font);
+
+ result = (PangoFont *)ft2font;
+ }
+ }
+ }
+
+ g_free (name);
+ return result;
+}
+
+static void
+pango_ft2_font_map_read_alias_file (PangoFT2FontMap *ft2fontmap,
+ const char *filename)
+{
+ FILE *infile;
+ int lineno = 0;
+ int nfaces;
+ int i;
+ PangoFT2FontEntry *font_entry = NULL;
+ gchar **faces;
+
+ infile = fopen (filename, "r");
+ if (infile)
+ {
+ GString *line_buf = g_string_new (NULL);
+ GString *tmp_buf = g_string_new (NULL);
+
+ while (pango_read_line (infile, line_buf))
+ {
+ PangoFT2FamilyEntry *family_entry;
+
+ const char *p = line_buf->str;
+
+ lineno++;
+
+ if (!pango_skip_space (&p))
+ continue;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ font_entry = g_new (PangoFT2FontEntry, 1);
+ font_entry->n_fonts = 0;
+ font_entry->open_args = NULL;
+ font_entry->face_indices = NULL;
+
+ font_entry->description.family_name = g_strdup (tmp_buf->str);
+ g_strdown (font_entry->description.family_name);
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ /* Remove excess whitespace and check for complete fields */
+
+ faces = g_strsplit (tmp_buf->str, ",", -1);
+ nfaces = 0;
+ for (i = 0; faces[i]; i++)
+ {
+ char *trimmed = pango_trim_string (faces[i]);
+ g_free (faces[i]);
+ faces[i] = trimmed;
+ nfaces++;
+ }
+
+ font_entry->open_args = g_new (FT_Open_Args *, nfaces);
+ font_entry->face_indices = g_new (FT_Long, nfaces);
+
+ for (i = 0; i < nfaces; i++)
+ {
+ PangoFontDescription desc;
+ PangoFT2OA *oa;
+
+ desc = font_entry->description;
+ desc.family_name = faces[i];
+ oa = g_hash_table_lookup (ft2fontmap->faces, &desc);
+ if (!oa)
+ g_warning ("Face '%s' on line %d of '%s' not found", faces[i], lineno, filename);
+ else
+ {
+ font_entry->open_args[font_entry->n_fonts] = oa->open_args;
+ font_entry->face_indices[font_entry->n_fonts] = oa->face_index;
+ font_entry->n_fonts++;
+ }
+ }
+
+ /* Insert the font entry into our structures */
+
+ family_entry = pango_ft2_get_family_entry (ft2fontmap, font_entry->description.family_name);
+ family_entry->font_entries = g_slist_prepend (family_entry->font_entries, font_entry);
+ ft2fontmap->n_fonts++;
+
+ g_free (font_entry->description.family_name);
+ font_entry->description.family_name = family_entry->family_name;
+ font_entry->cached_fonts = NULL;
+ font_entry->coverage = NULL;
+ }
+
+ if (ferror (infile))
+ g_warning ("Error reading file '%s': %s", filename, g_strerror(errno));
+
+ goto out;
+
+ error:
+ if (font_entry)
+ {
+ if (font_entry->open_args)
+ g_free (font_entry->open_args);
+ if (font_entry->face_indices)
+ g_free (font_entry->face_indices);
+ if (font_entry->description.family_name)
+ g_free (font_entry->description.family_name);
+ g_free (font_entry);
+ }
+
+ g_warning ("Error parsing line %d of alias file '%s'", lineno, filename);
+
+ out:
+ g_string_free (tmp_buf, TRUE);
+ g_string_free (line_buf, TRUE);
+
+ fclose (infile);
+ }
+
+}
+
+static void
+pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap)
+{
+ char **files;
+ char *files_str = pango_config_key_get ("PangoFT2/AliasFiles");
+ char *home;
+ char *tmp_str;
+ int n;
+
+ if (!files_str)
+ {
+ home = g_get_home_dir ();
+ if (home && *home)
+ files_str = g_strconcat (home, "\\.pangoft2_aliases;", NULL);
+
+ tmp_str = g_strconcat (files_str, pango_get_sysconf_subdirectory (),
+ "\\pangoft2.aliases",
+ NULL);
+ g_free (files_str);
+ files_str = tmp_str;
+ }
+
+ files = pango_split_file_list (files_str);
+
+ n = 0;
+ while (files[n])
+ n++;
+
+ while (n-- > 0)
+ pango_ft2_font_map_read_alias_file (ft2fontmap, files[n]);
+
+ g_strfreev (files);
+ g_free (files_str);
+}
+
+#if DEBUGGING
+
+static void
+pango_print_desc (PangoFontDescription *desc)
+{
+ g_print ("%s%s%s%s%s",
+ desc->family_name,
+ (desc->style == PANGO_STYLE_NORMAL ? "" :
+ (desc->style == PANGO_STYLE_OBLIQUE ? " OBLIQUE" :
+ (desc->style == PANGO_STYLE_ITALIC ? " ITALIC" : " ???"))),
+ (desc->variant == PANGO_VARIANT_NORMAL ? "" :
+ (desc->variant == PANGO_VARIANT_SMALL_CAPS ? " SMALL CAPS" : "???")),
+ (desc->weight >= (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 &&
+ desc->weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 ? "" :
+ (desc->weight < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 ? " ULTRALIGHT" :
+ (desc->weight >= (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 &&
+ desc->weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 ? " LIGHT" :
+ (desc->weight >= (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 &&
+ desc->weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 ? " BOLD" :
+ (desc->weight >= (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 &&
+ desc->weight < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2 ? " ULTRABOLD" :
+ " HEAVY"))))),
+ (desc->stretch == PANGO_STRETCH_ULTRA_CONDENSED ? " ULTRA CONDENSED" :
+ (desc->stretch == PANGO_STRETCH_EXTRA_CONDENSED ? " EXTRA CONDENSED" :
+ (desc->stretch == PANGO_STRETCH_CONDENSED ? " CONDENSED" :
+ (desc->stretch == PANGO_STRETCH_SEMI_CONDENSED ? " SEMI CONDENSED" :
+ (desc->stretch == PANGO_STRETCH_NORMAL ? "" :
+ (desc->stretch == PANGO_STRETCH_SEMI_EXPANDED ? " SEMI EXPANDED" :
+ (desc->stretch == PANGO_STRETCH_EXPANDED ? " EXPANDED" :
+ (desc->stretch == PANGO_STRETCH_EXTRA_EXPANDED ? " EXTRA EXPANDED" :
+ (desc->stretch == PANGO_STRETCH_ULTRA_EXPANDED ? " ULTRA EXPANDED" : " ???"))))))))));
+}
+
+static void
+pango_ft2_print_oa (PangoFT2OA *oa)
+{
+ g_print ("%s:%ld", oa->open_args->pathname, oa->face_index);
+}
+
+#endif
+
+static void
+pango_ft2_insert_face (PangoFT2FontMap *ft2fontmap,
+ FT_Face face,
+ const char *path,
+ int face_index)
+{
+ PangoFontDescription *description;
+ GSList *tmp_list;
+ PangoFT2FamilyEntry *family_entry;
+ PangoFT2FontEntry *font_entry;
+ PangoFT2OA *oa;
+ FT_Open_Args *open_args;
+
+ description = g_new (PangoFontDescription, 1);
+ description->family_name = g_strdup (face->family_name);
+ g_strdown (description->family_name);
+
+ if (face->style_flags & FT_STYLE_FLAG_ITALIC)
+ description->style = PANGO_STYLE_ITALIC;
+ else
+ description->style = PANGO_STYLE_NORMAL;
+
+ description->variant = PANGO_VARIANT_NORMAL;
+
+ if (face->style_flags & FT_STYLE_FLAG_BOLD)
+ description->weight = PANGO_WEIGHT_BOLD;
+ else
+ description->weight = PANGO_WEIGHT_NORMAL;
+
+ description->stretch = PANGO_STRETCH_NORMAL;
+
+ if (face->style_name)
+ {
+ gchar **styles = g_strsplit (face->style_name, " ", 0);
+ gint i = 0;
+
+ while (styles[i])
+ {
+ GString *s = g_string_new (styles[i]);
+ (void) (pango_parse_style (s, description, FALSE) ||
+ pango_parse_variant (s, description, FALSE) ||
+ pango_parse_weight (s, description, FALSE) ||
+ pango_parse_stretch (s, description, FALSE));
+ g_string_free (s, TRUE);
+ i++;
+ }
+ g_strfreev (styles);
+ }
+
+ description->size = 0;
+
+#if 0
+ PING ((""));
+ pango_print_desc (description);
+#endif
+
+ family_entry = pango_ft2_get_family_entry (ft2fontmap, description->family_name);
+
+ tmp_list = family_entry->font_entries;
+ while (tmp_list)
+ {
+ font_entry = tmp_list->data;
+
+ if (font_entry->description.style == description->style &&
+ font_entry->description.variant == description->variant &&
+ font_entry->description.weight == description->weight &&
+ font_entry->description.stretch == description->stretch)
+ {
+ g_free (description->family_name);
+ g_free (description);
+#if 0
+ PING ((" family and description matched (!)\n"));
+#endif
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ oa = g_hash_table_lookup (ft2fontmap->faces, description);
+ if (!oa)
+ {
+ oa = g_new (PangoFT2OA, 1);
+ open_args = g_new (FT_Open_Args, 1);
+ open_args->flags = ft_open_pathname;
+ open_args->pathname = g_strdup (path);
+ open_args->driver = NULL;
+ open_args->num_params = 0;
+ oa->open_args = open_args;
+ oa->face_index = face_index;
+#if 0
+ PING (("adding mapping: "));
+ pango_ft2_print_oa (oa);
+#endif
+ g_hash_table_insert (ft2fontmap->faces, description, oa);
+ }
+#if 0
+ g_print ("\n");
+#endif
+
+ font_entry = g_new (PangoFT2FontEntry, 1);
+ font_entry->description = *description;
+ font_entry->description.family_name = family_entry->family_name;
+ font_entry->cached_fonts = NULL;
+ font_entry->coverage = NULL;
+ font_entry->open_args = g_new (FT_Open_Args *, 1);
+ font_entry->open_args[0] = oa->open_args;
+ font_entry->face_indices = g_new (FT_Long, 1);
+ font_entry->face_indices[0] = oa->face_index;
+ font_entry->n_fonts = 1;
+ family_entry->font_entries = g_slist_append (family_entry->font_entries, font_entry);
+ ft2fontmap->n_fonts++;
+}
+
+static void
+free_coverages_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ pango_coverage_unref (value);
+}
+
+PangoCoverage *
+pango_ft2_font_entry_get_coverage (PangoFT2FontEntry *entry,
+ PangoFont *font,
+ const char *lang)
+{
+ guint32 ch;
+ PangoMap *shape_map;
+ PangoCoverage *coverage;
+ PangoCoverage *result;
+ PangoCoverageLevel font_level;
+ PangoMapEntry *map_entry;
+ GHashTable *coverage_hash;
+
+ if (entry)
+ if (entry->coverage)
+ {
+ pango_coverage_ref (entry->coverage);
+ return entry->coverage;
+ }
+
+ result = pango_coverage_new ();
+
+ coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ shape_map = pango_ft2_get_shaper_map (lang);
+
+ for (ch = 0; ch < 65536; ch++)
+ {
+ map_entry = pango_map_get_entry (shape_map, ch);
+ if (map_entry->info)
+ {
+ coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id);
+ if (!coverage)
+ {
+ PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
+ coverage = engine->get_coverage (font, lang);
+ g_hash_table_insert (coverage_hash, map_entry->info->id, coverage);
+ }
+
+ font_level = pango_coverage_get (coverage, ch);
+ if (font_level == PANGO_COVERAGE_EXACT && !map_entry->is_exact)
+ font_level = PANGO_COVERAGE_APPROXIMATE;
+
+ if (font_level != PANGO_COVERAGE_NONE)
+ pango_coverage_set (result, ch, font_level);
+ }
+ }
+
+ g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL);
+ g_hash_table_destroy (coverage_hash);
+
+ if (entry)
+ {
+ entry->coverage = result;
+ pango_coverage_ref (result);
+ }
+
+ return result;
+}
+
+void
+pango_ft2_font_entry_remove (PangoFT2FontEntry *entry,
+ PangoFont *font)
+{
+ entry->cached_fonts = g_slist_remove (entry->cached_fonts, font);
+}
+
+PangoFT2FontCache *
+pango_ft2_font_map_get_font_cache (PangoFontMap *font_map)
+{
+ g_return_val_if_fail (font_map != NULL, NULL);
+ g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (font_map), NULL);
+
+ return PANGO_FT2_FONT_MAP (font_map)->font_cache;
+}
+
+void
+pango_ft2_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoFT2Font *ft2font)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
+
+ if (ft2fontmap->freed_fonts->length == MAX_FREED_FONTS)
+ {
+ PangoFT2Font *old_font = g_queue_pop_tail (ft2fontmap->freed_fonts);
+ g_object_unref (G_OBJECT (old_font));
+ }
+
+ g_object_ref (G_OBJECT (ft2font));
+ g_queue_push_head (ft2fontmap->freed_fonts, ft2font);
+ ft2font->in_cache = TRUE;
+}
+
+void
+pango_ft2_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoFT2Font *ft2font)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
+
+ GList *link = g_list_find (ft2fontmap->freed_fonts->head, ft2font);
+ if (link == ft2fontmap->freed_fonts->tail)
+ {
+ ft2fontmap->freed_fonts->tail = ft2fontmap->freed_fonts->tail->prev;
+ if (ft2fontmap->freed_fonts->tail)
+ ft2fontmap->freed_fonts->tail->next = NULL;
+ }
+
+ ft2fontmap->freed_fonts->head = g_list_delete_link (ft2fontmap->freed_fonts->head, link);
+ ft2fontmap->freed_fonts->length--;
+ ft2font->in_cache = FALSE;
+
+ g_object_unref (G_OBJECT (ft2font));
+}
+
+static void
+pango_ft2_fontmap_cache_clear (PangoFT2FontMap *ft2fontmap)
+{
+ g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_list_free (ft2fontmap->freed_fonts->head);
+ ft2fontmap->freed_fonts->head = NULL;
+ ft2fontmap->freed_fonts->tail = NULL;
+ ft2fontmap->freed_fonts->length = 0;
+}
+
+static void
+pango_ft2_font_entry_dump (int indent,
+ PangoFT2FontEntry *font_entry)
+{
+ int i;
+
+ printf ("%*sPangoFT2FontEntry@%p:\n"
+ "%*s lfp:\n",
+ indent, "", font_entry,
+ indent, "");
+
+ for (i = 0; i < font_entry->n_fonts; i++)
+ printf ("%*s PangoFT2OpenArgs:%s:%ld\n",
+ indent, "", font_entry->open_args[i]->pathname, font_entry->face_indices[i]);
+
+ printf ("%*s description:\n"
+ "%*s family_name: %s\n"
+ "%*s style: %d\n"
+ "%*s variant: %d\n"
+ "%*s weight: %d\n"
+ "%*s stretch: %d\n"
+ "%*s coverage: %p\n",
+ indent, "",
+ indent, "", font_entry->description.family_name,
+ indent, "", font_entry->description.style,
+ indent, "", font_entry->description.variant,
+ indent, "", font_entry->description.weight,
+ indent, "", font_entry->description.stretch,
+ indent, "", font_entry->coverage);
+}
+
+static void
+pango_ft2_family_entry_dump (int indent,
+ PangoFT2FamilyEntry *entry)
+{
+ GSList *tmp_list = entry->font_entries;
+
+ printf ("%*sPangoFT2FamilyEntry@%p:\n"
+ "%*s family_name: %s\n"
+ "%*s font_entries:\n",
+ indent, "", entry,
+ indent, "", entry->family_name,
+ indent, "");
+
+ while (tmp_list)
+ {
+ PangoFT2FontEntry *font_entry = tmp_list->data;
+
+ pango_ft2_font_entry_dump (indent + 2, font_entry);
+ tmp_list = tmp_list->next;
+ }
+}
+
+static void
+dump_family (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ PangoFT2FamilyEntry *entry = value;
+ int indent = (int) user_data;
+
+ pango_ft2_family_entry_dump (indent, entry);
+}
+
+void
+pango_ft2_fontmap_dump (int indent,
+ PangoFontMap *fontmap)
+{
+ PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
+
+ printf ("%*sPangoFT2FontMap@%p:\n",
+ indent, "", ft2fontmap);
+ g_hash_table_foreach (ft2fontmap->families, dump_family, (gpointer) (indent + 2));
+}
diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h
new file mode 100644
index 00000000..92b1c053
--- /dev/null
+++ b/pango/pangoft2-private.h
@@ -0,0 +1,97 @@
+/* Pango
+ * pangoft2-private.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOFT2_PRIVATE_H__
+#define __PANGOFT2_PRIVATE_H__
+
+#include "pango-modules.h"
+#include "pangoft2.h"
+
+/* Debugging... */
+#define DEBUGGING 1
+
+#ifdef DEBUGGING
+#define PING(printlist) \
+(g_print ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \
+ g_print printlist)
+#else
+#define PING(printlist)
+#endif
+
+#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
+#define PANGO_PIXELS_26_6(d) \
+ (((d) >= 0) ? \
+ ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \
+ ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6)
+#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
+
+typedef struct _PangoFT2OA PangoFT2OA;
+typedef struct _PangoFT2Font PangoFT2Font;
+typedef struct _PangoFT2FontEntry PangoFT2FontEntry;
+typedef struct _PangoFT2SubfontInfo PangoFT2SubfontInfo;
+
+struct _PangoFT2OA
+{
+ FT_Open_Args *open_args;
+ FT_Long face_index;
+};
+
+struct _PangoFT2Font
+{
+ PangoFont font;
+
+ /* A PangoFT2Font consists of one or several FT2 fonts (faces) that
+ * are assumed to blend visually well, and cover separate parts of
+ * the Unicode characters. The FT2 faces are not kept unnecessarily
+ * open, thus also we keep both the FT_Open_Args (and face index),
+ * and FT_Face.
+ */
+ PangoFT2OA **oa;
+ FT_Face *faces;
+ int n_fonts;
+
+ int size;
+
+ GSList *metrics_by_lang;
+
+ PangoFontMap *fontmap;
+ /* If TRUE, font is in cache of recently unused fonts and not otherwise
+ * in use.
+ */
+ gboolean in_cache;
+
+ PangoFT2FontEntry *entry; /* Used to remove cached fonts */
+};
+
+PangoMap *pango_ft2_get_shaper_map (const char *lang);
+PangoCoverage *pango_ft2_font_entry_get_coverage (PangoFT2FontEntry *entry,
+ PangoFont *font,
+ const char *lang);
+void pango_ft2_font_entry_remove (PangoFT2FontEntry *entry,
+ PangoFont *font);
+FT_Library *pango_ft2_fontmap_get_library (PangoFontMap *fontmap);
+void pango_ft2_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoFT2Font *ft2font);
+void pango_ft2_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoFT2Font *ft2font);
+const char *pango_ft2_ft_strerror (FT_Error error);
+
+#endif /* __PANGOFT2_PRIVATE_H__ */
diff --git a/pango/pangoft2.c b/pango/pangoft2.c
new file mode 100644
index 00000000..faffe580
--- /dev/null
+++ b/pango/pangoft2.c
@@ -0,0 +1,1126 @@
+/* Pango
+ * pangoft2.c: Routines for handling FreeType2 fonts
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <glib.h>
+
+#include <freetype/freetype.h>
+#include <fribidi/fribidi.h>
+
+#include "pangoft2.h"
+#include "pangoft2-private.h"
+
+#define PANGO_TYPE_FT2_FONT (pango_ft2_font_get_type ())
+#define PANGO_FT2_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT, PangoFT2Font))
+#define PANGO_FT2_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
+#define PANGO_FT2_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT))
+#define PANGO_FT2_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT))
+#define PANGO_FT2_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT, PangoFT2FontClass))
+
+typedef struct _PangoFT2FontClass PangoFT2FontClass;
+typedef struct _PangoFT2MetricsInfo PangoFT2MetricsInfo;
+typedef struct _PangoFT2ContextInfo PangoFT2ContextInfo;
+
+struct _PangoFT2MetricsInfo
+{
+ const char *lang;
+ PangoFontMetrics metrics;
+};
+
+struct _PangoFT2FontClass
+{
+ PangoFontClass parent_class;
+};
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoFT2Font */
+
+static void pango_ft2_font_class_init (PangoFT2FontClass *class);
+static void pango_ft2_font_init (PangoFT2Font *xfont);
+static void pango_ft2_font_shutdown (GObject *object);
+static void pango_ft2_font_finalize (GObject *object);
+
+static PangoFontDescription *pango_ft2_font_describe (PangoFont *font);
+
+static PangoCoverage * pango_ft2_font_get_coverage (PangoFont *font,
+ const char *lang);
+
+static PangoEngineShape * pango_ft2_font_find_shaper (PangoFont *font,
+ const char *lang,
+ guint32 ch);
+
+static void pango_ft2_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+static void pango_ft2_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics);
+
+static void pango_ft2_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set);
+
+static char *
+pango_ft2_open_args_describe (PangoFT2OA *oa)
+{
+ if (oa->open_args->flags & ft_open_memory)
+ return g_strdup_printf ("memory at %p", oa->open_args->memory_base);
+ else if (oa->open_args->flags == ft_open_pathname)
+ return g_strdup_printf ("file '%s'", oa->open_args->pathname);
+ else if (oa->open_args->flags & ft_open_stream)
+ return g_strdup_printf ("FT_Stream at %p", oa->open_args->stream);
+ else
+ return g_strdup_printf ("open_args at %p, face_index %ld", oa->open_args, oa->face_index);
+}
+
+static inline FT_Face
+pango_ft2_get_face (PangoFont *font,
+ PangoFT2Subfont subfont_index)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ PangoFT2FontCache *cache;
+
+ if (subfont_index < 1 || subfont_index > ft2font->n_fonts)
+ {
+ g_warning ("Invalid subfont %d", subfont_index);
+ return NULL;
+ }
+
+ if (!ft2font->faces[subfont_index-1])
+ {
+ cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap);
+
+ ft2font->faces[subfont_index-1] =
+ pango_ft2_font_cache_load (cache,
+ ft2font->oa[subfont_index-1]->open_args,
+ ft2font->oa[subfont_index-1]->face_index);
+
+ if (!ft2font->faces[subfont_index-1])
+ g_warning ("Cannot load font for %s",
+ pango_ft2_open_args_describe (ft2font->oa[subfont_index-1]));
+ }
+ return ft2font->faces[subfont_index-1];
+}
+
+/**
+ * pango_ft2_get_context:
+ *
+ * Retrieves a #PangoContext appropriate for rendering with Pango fonts.
+ *
+ * Return value: the new #PangoContext
+ **/
+PangoContext *
+pango_ft2_get_context (void)
+{
+ PangoContext *result;
+
+ result = pango_context_new ();
+ pango_context_add_font_map (result, pango_ft2_font_map_for_display ());
+
+ return result;
+}
+
+static GType
+pango_ft2_font_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFT2FontClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_ft2_font_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFT2Font),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_ft2_font_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT,
+ "PangoFT2Font",
+ &object_info);
+ }
+
+ return object_type;
+}
+
+static void
+pango_ft2_font_init (PangoFT2Font *ft2font)
+{
+ ft2font->oa = NULL;
+ ft2font->faces = NULL;
+
+ ft2font->n_fonts = 0;
+
+ ft2font->metrics_by_lang = NULL;
+
+ ft2font->entry = NULL;
+}
+
+static void
+pango_ft2_font_class_init (PangoFT2FontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_ft2_font_finalize;
+ object_class->shutdown = pango_ft2_font_shutdown;
+
+ font_class->describe = pango_ft2_font_describe;
+ font_class->get_coverage = pango_ft2_font_get_coverage;
+ font_class->find_shaper = pango_ft2_font_find_shaper;
+ font_class->get_glyph_extents = pango_ft2_font_get_glyph_extents;
+ font_class->get_metrics = pango_ft2_font_get_metrics;
+}
+
+/**
+ * pango_ft2_load_font:
+ *
+ * Loads a logical font based on XXX
+ *
+ * Returns a new #PangoFont
+ */
+PangoFont *
+pango_ft2_load_font (PangoFontMap *fontmap,
+ FT_Open_Args **open_args,
+ FT_Long *face_indices,
+ int n_fonts,
+ int size)
+{
+ PangoFT2Font *result;
+ int i;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (open_args != NULL, NULL);
+ g_return_val_if_fail (face_indices != NULL, NULL);
+ g_return_val_if_fail (n_fonts > 0, NULL);
+
+ result = (PangoFT2Font *)g_type_create_instance (PANGO_TYPE_FT2_FONT);
+
+ result->fontmap = fontmap;
+ g_object_ref (G_OBJECT (result->fontmap));
+
+ result->oa = g_new (PangoFT2OA *, n_fonts);
+ result->faces = g_new (FT_Face, n_fonts);
+ result->n_fonts = n_fonts;
+ result->size = size;
+
+ for (i = 0; i < n_fonts; i++)
+ {
+ result->oa[i] = g_new (PangoFT2OA, 1);
+ result->oa[i]->open_args = open_args[i];
+ result->oa[i]->face_index = face_indices[i];
+ result->faces[i] = NULL;
+ }
+
+ return &result->font;
+}
+
+/**
+ * pango_ft2_render:
+ *
+ * @bitmap: the FreeType2 bitmap onto which draw the string
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a PangoGlyphString onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render (FT_Bitmap *bitmap,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ FT_Face face;
+ FT_Face prev_face = NULL;
+ FT_UInt glyph_index, prev_index;
+ int i;
+ int x_position = 0;
+ int ix, iy, ixoff, iyoff, y_start, y_limit, x_start, x_limit;
+ guint16 char_index;
+ PangoFT2Subfont subfont_index;
+ PangoGlyphInfo *gi;
+ guchar *p, *q;
+
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (glyphs != NULL);
+
+ PING (("bitmap: %dx%d@+%d+%d\n", bitmap->width, bitmap->rows, x, y));
+
+ gi = glyphs->glyphs;
+ for (i = 0; i < glyphs->num_glyphs; i++, gi++)
+ {
+ if (gi->glyph)
+ {
+ char_index = PANGO_FT2_GLYPH_INDEX (gi->glyph);
+ subfont_index = PANGO_FT2_GLYPH_SUBFONT (gi->glyph);
+ face = pango_ft2_get_face (font, subfont_index);
+
+ if (face)
+ {
+ /* Draw glyph */
+ glyph_index = FT_Get_Char_Index (face, char_index);
+ /* FIXME hint or not? */
+ FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
+ FT_Render_Glyph (face->glyph, ft_render_mode_normal);
+
+ ixoff = x + PANGO_PIXELS (x_position + gi->geometry.x_offset);
+ iyoff = y + PANGO_PIXELS (gi->geometry.y_offset);
+
+ x_start = MAX (0, -face->glyph->bitmap_left - ixoff);
+ x_limit = MIN (face->glyph->bitmap.width, face->glyph->bitmap_left - ixoff + bitmap->width);
+
+ y_start = MAX (0, face->glyph->bitmap_top - iyoff);
+ y_limit = MIN (face->glyph->bitmap.rows, face->glyph->bitmap_top - iyoff + bitmap->rows);
+
+
+ PING (("glyph %d:%d: bitmap: %dx%d, left:%d top:%d\n",
+ i, glyph_index,
+ face->glyph->bitmap.width, face->glyph->bitmap.rows,
+ face->glyph->bitmap_left, face->glyph->bitmap_top));
+ PING (("xstart:%d xlim:%d ystart:%d ylim:%d\n",
+ x_start, x_limit, y_start, y_limit));
+
+ for (iy = y_start; iy < y_limit; iy++)
+ {
+ p = bitmap->buffer +
+ (iyoff - face->glyph->bitmap_top + iy) * bitmap->pitch +
+ ixoff +
+ face->glyph->bitmap_left + x_start;
+
+ q = face->glyph->bitmap.buffer + iy*face->glyph->bitmap.pitch;
+ for (ix = x_start; ix < x_limit; ix++)
+ {
+ *p = MIN (*p, 0xFF - *q);
+ q++;
+ p++;
+ }
+ }
+
+ prev_face = face;
+ prev_index = glyph_index;
+ }
+ }
+
+ x_position += glyphs->glyphs[i].geometry.width;
+ }
+}
+
+static FT_Glyph_Metrics *
+pango_ft2_get_per_char (PangoFont *font,
+ PangoFT2Subfont subfont_index,
+ guint16 char_index)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ FT_Face face;
+ FT_UInt glyph_index;
+ FT_Error error;
+
+ if (!(face = pango_ft2_get_face (font, subfont_index)))
+ return NULL;
+
+ glyph_index = FT_Get_Char_Index (face, char_index);
+ if (!glyph_index)
+ return NULL;
+
+ error = FT_Set_Pixel_Sizes (face, PANGO_PIXELS (ft2font->size), 0);
+ if (error)
+ g_warning ("Error in FT_Set_Pixel_Sizes: %d", error);
+
+ FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
+ return &face->glyph->metrics;
+}
+
+static void
+pango_ft2_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ guint16 char_index = PANGO_FT2_GLYPH_INDEX (glyph);
+ PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph);
+ FT_Glyph_Metrics *gm;
+
+ if (glyph && (gm = pango_ft2_get_per_char (font, subfont_index, char_index)))
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX);
+ ink_rect->width = PANGO_UNITS_26_6 (gm->width);
+ ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY);
+ ink_rect->height = PANGO_UNITS_26_6 (gm->height);
+ }
+ if (logical_rect)
+ {
+ FT_Face face = pango_ft2_get_face (font, subfont_index);
+
+ logical_rect->x = 0;
+ logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance);
+ logical_rect->y = -PANGO_UNITS_26_6 (face->size->metrics.ascender + 64);
+ /* Some fonts report negative descender, some positive ! (?) */
+ logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender + ABS (face->size->metrics.descender) + 128);
+ }
+ PING (("glyph:%d logical: %dx%d@%d+%d\n",
+ char_index, logical_rect->width, logical_rect->height,
+ logical_rect->x, logical_rect->y));
+ }
+ else
+ {
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->width = 0;
+ ink_rect->y = 0;
+ ink_rect->height = 0;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = 0;
+ logical_rect->y = 0;
+ logical_rect->height = 0;
+ }
+ }
+}
+
+int
+pango_ft2_font_get_kerning (PangoFont *font,
+ PangoGlyph left,
+ PangoGlyph right)
+{
+ PangoFT2Subfont subfont_index;
+ guint16 left_char_index;
+ guint16 right_char_index;
+ FT_Face face;
+ FT_UInt left_glyph_index, right_glyph_index;
+ FT_Error error;
+ FT_Vector kerning;
+
+ subfont_index = PANGO_FT2_GLYPH_SUBFONT (left);
+ if (PANGO_FT2_GLYPH_SUBFONT (right) != subfont_index)
+ return 0;
+
+ face = pango_ft2_get_face (font, subfont_index);
+ if (!face)
+ return 0;
+
+ if (!FT_HAS_KERNING (face))
+ return 0;
+
+ left_char_index = PANGO_FT2_GLYPH_INDEX (left);
+ right_char_index = PANGO_FT2_GLYPH_INDEX (right);
+
+ left_glyph_index = FT_Get_Char_Index (face, left_char_index);
+ right_glyph_index = FT_Get_Char_Index (face, right_char_index);
+ if (!left_glyph_index || !right_char_index)
+ return 0;
+
+ error = FT_Get_Kerning (face, left_glyph_index, right_glyph_index,
+ ft_kerning_default, &kerning);
+ if (error != FT_Err_Ok)
+ g_warning ("FT_Get_Kerning returns error: %s",
+ pango_ft2_ft_strerror (error));
+
+ return PANGO_UNITS_26_6 (kerning.x);
+}
+
+/* Get composite font metrics for all subfonts in list
+ */
+static void
+get_font_metrics_from_subfonts (PangoFont *font,
+ GSList *subfonts,
+ PangoFontMetrics *metrics)
+{
+ GSList *tmp_list = subfonts;
+ gboolean first = TRUE;
+
+ metrics->ascent = 0;
+ metrics->descent = 0;
+
+ while (tmp_list)
+ {
+ FT_Face face = pango_ft2_get_face (font, GPOINTER_TO_UINT (tmp_list->data));
+
+ g_assert (face != NULL);
+
+ if (first)
+ {
+ metrics->ascent = PANGO_UNITS_26_6 (face->ascender);
+ metrics->descent = PANGO_UNITS_26_6 (face->descender);
+ first = FALSE;
+ }
+ else
+ {
+ metrics->ascent = MAX (PANGO_UNITS_26_6 (face->ascender), metrics->ascent);
+ metrics->descent = MAX (PANGO_UNITS_26_6 (face->descender), metrics->descent);
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* Get composite font metrics for all subfonts resulting from shaping
+ * string str with the given font
+ *
+ * This duplicates quite a bit of code from pango_itemize. This function
+ * should die and we should simply add the ability to specify particular
+ * fonts when itemizing.
+ */
+static void
+get_font_metrics_from_string (PangoFont *font,
+ const char *lang,
+ const char *str,
+ PangoFontMetrics *metrics)
+{
+ const char *start, *p;
+ PangoGlyphString *glyph_str = pango_glyph_string_new ();
+ PangoEngineShape *shaper, *last_shaper;
+ int last_level;
+ gunichar *text_ucs4;
+ int n_chars, i;
+ guint8 *embedding_levels;
+ FriBidiCharType base_dir = PANGO_DIRECTION_LTR;
+ GSList *subfonts = NULL;
+
+ n_chars = g_utf8_strlen (str, -1);
+
+ text_ucs4 = g_utf8_to_ucs4 (str, strlen (str));
+ if (!text_ucs4)
+ return;
+
+ embedding_levels = g_new (guint8, n_chars);
+ fribidi_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir,
+ embedding_levels);
+ g_free (text_ucs4);
+
+ last_shaper = NULL;
+ last_level = 0;
+
+ i = 0;
+ p = start = str;
+ while (*p)
+ {
+ gunichar wc = g_utf8_get_char (p);
+ p = g_utf8_next_char (p);
+
+ shaper = pango_font_find_shaper (font, lang, wc);
+ if (p > start &&
+ (shaper != last_shaper || last_level != embedding_levels[i]))
+ {
+ PangoAnalysis analysis;
+ int j;
+
+ analysis.shape_engine = shaper;
+ analysis.lang_engine = NULL;
+ analysis.font = font;
+ analysis.level = last_level;
+
+ pango_shape (start, p - start, &analysis, glyph_str);
+
+ for (j = 0; j < glyph_str->num_glyphs; j++)
+ {
+ PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph_str->glyphs[j].glyph);
+ if (!g_slist_find (subfonts, GUINT_TO_POINTER ((guint)subfont_index)))
+ subfonts = g_slist_prepend (subfonts, GUINT_TO_POINTER ((guint)subfont_index));
+ }
+
+ start = p;
+ }
+
+ last_shaper = shaper;
+ last_level = embedding_levels[i];
+ i++;
+ }
+
+ get_font_metrics_from_subfonts (font, subfonts, metrics);
+ g_slist_free (subfonts);
+
+ pango_glyph_string_free (glyph_str);
+ g_free (embedding_levels);
+}
+
+typedef struct {
+ const char *lang;
+ const char *str;
+} LangInfo;
+
+int
+lang_info_compare (const void *key,
+ const void *val)
+{
+ const LangInfo *lang_info = val;
+
+ return strncmp (key, lang_info->lang, 2);
+}
+
+/* The following array is supposed to contain enough text to tickle all necessary fonts for each
+ * of the languages in the following. Yes, it's pretty lame. Not all of the languages
+ * in the following have sufficient text to excercise all the accents for the language, and
+ * there are obviously many more languages to include as well.
+ */
+LangInfo lang_texts[] = {
+ { "ar", "Arabic ا,DXXم عY(JY,CY(B" },
+ { "cs", "Czech (česky) Dobrý den" },
+ { "da", "Danish (Dansk) Hej, Goddag" },
+ { "el", "Greek ($(GN;ληνικά(B) $(CN5ιά ,CNς(B" },
+ { "en", "English Hello" },
+ { "eo", "Esperanto Saluton" },
+ { "es", "Spanish (Español) ¡Hola!" },
+ { "et", "Estonian Tere, Tervist" },
+ { "fi", "Finnish (Suomi) Hei, Hyvää päivää" },
+ { "fr", "French (Français)" },
+ { "de", "German Grüß Gott" },
+ { "iw", "Hebrew שלום" },
+ { "il", "Italiano Ciao, Buon giorno" },
+ { "ja", "Japanese (日語) こん, コン,Foハ(B" },
+ { "ko", "Korean (한글) ,Hk하,D8요(B, ,Hk하십j(B" },
+ { "mt", "Maltese Ċaw, Saħħa" },
+ { "nl", "Nederlands, Vlaams Hallo, Dag" },
+ { "no", "Norwegian (Norsk) Hei, God dag" },
+ { "pl", "Polish Dzień dobry, Hej" },
+ { "ru", "Russian (Р,CQкий(B)" },
+ { "sk", "Slovak Dobrý deň" },
+ { "sv", "Swedish (Svenska) Hej på dej, Goddag" },
+ { "tr", "Turkish (Türkçe) Merhaba" },
+ { "zh", "Chinese (中文,$(1.i话(B,(Ih(B)" }
+};
+
+static void
+pango_ft2_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics)
+{
+ PangoFT2MetricsInfo *info;
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ GSList *tmp_list;
+
+ const char *lookup_lang;
+ const char *str;
+
+ if (lang)
+ {
+ LangInfo *lang_info = bsearch (lang, lang_texts,
+ G_N_ELEMENTS (lang_texts), sizeof (LangInfo),
+ lang_info_compare);
+
+ if (lang_info)
+ {
+ lookup_lang = lang_info->lang;
+ str = lang_info->str;
+ }
+ else
+ {
+ lookup_lang = "UNKNOWN";
+ str = "French (Français)"; /* Assume iso-8859-1 */
+ }
+ }
+ else
+ {
+ lookup_lang = "NONE";
+
+ /* Complete junk
+ */
+ str = "ا,DXXم عY(JY,CY č(Besky $(GN;ληνικά (BFrançais 日語 한글 Р,CQкий 中文(B,$(1.i话(B,(Ih (BTürkçe";
+ }
+
+ tmp_list = ft2font->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->lang == lookup_lang) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ info = g_new (PangoFT2MetricsInfo, 1);
+ info->lang = lookup_lang;
+
+ ft2font->metrics_by_lang = g_slist_prepend (ft2font->metrics_by_lang, info);
+
+ get_font_metrics_from_string (font, lang, str, &info->metrics);
+ }
+
+ *metrics = info->metrics;
+}
+
+/**
+ * pango_ft2_n_subfonts:
+ * @font: a PangoFont
+ * Returns number of subfonts in a PangoFT2Font.
+ **/
+int
+pango_ft2_n_subfonts (PangoFont *font)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ return ft2font->n_fonts;
+}
+
+/**
+ * pango_ft2_has_glyph:
+ * @font: a #PangoFont which must be from the FreeType2 backend.
+ * @glyph: the index of a glyph in the font. (Formed
+ * using the PANGO_FT2_MAKE_GLYPH macro)
+ *
+ * Check if the given glyph is present in a FT2 font.
+ *
+ * Return value: %TRUE if the glyph is present.
+ **/
+gboolean
+pango_ft2_has_glyph (PangoFont *font,
+ PangoGlyph glyph)
+{
+ guint16 char_index = PANGO_FT2_GLYPH_INDEX (glyph);
+ PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph);
+ FT_Face face = pango_ft2_get_face (font, subfont_index);
+
+ if (!face)
+ return FALSE;
+
+ if (FT_Get_Char_Index (face, char_index) == 0)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
+ * pango_ft2_font_subfont_open_args:
+ * @font: a #PangoFont which must be from the FT2 backend
+ * @open_args: pointer where to store the #FT_Open_Args for this subfont
+ * @face_index: pointer where to store the face index for this subfont
+ *
+ * Determine the FT_Open_Args and face index for the specified subfont.
+ **/
+void
+pango_ft2_font_subfont_open_args (PangoFont *font,
+ PangoFT2Subfont subfont_id,
+ FT_Open_Args **open_args,
+ FT_Long *face_index)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+ *open_args = NULL;
+ *face_index = 0;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (PANGO_FT2_IS_FONT (font));
+
+ if (subfont_id < 1 || subfont_id > ft2font->n_fonts)
+ g_warning ("pango_ft2_font_subfont_open_args: Invalid subfont_id specified");
+ else
+ {
+ *open_args = ft2font->oa[subfont_id-1]->open_args;
+ *face_index = ft2font->oa[subfont_id-1]->face_index;
+ }
+}
+
+static void
+pango_ft2_font_shutdown (GObject *object)
+{
+ PangoFT2Font *ft2font = PANGO_FT2_FONT (object);
+
+ /* If the font is not already in the freed-fonts cache, add it,
+ * if it is already there, do nothing and the font will be
+ * freed.
+ */
+ if (!ft2font->in_cache && ft2font->fontmap)
+ pango_ft2_fontmap_cache_add (ft2font->fontmap, ft2font);
+
+ G_OBJECT_CLASS (parent_class)->shutdown (object);
+}
+
+
+static void
+pango_ft2_font_finalize (GObject *object)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)object;
+ PangoFT2FontCache *cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap);
+ int i;
+
+ PING (("\n"));
+
+ for (i = 0; i < ft2font->n_fonts; i++)
+ {
+ if (ft2font->faces[i])
+ pango_ft2_font_cache_unload (cache, ft2font->faces[i]);
+ }
+
+ g_free (ft2font->oa);
+ g_free (ft2font->faces);
+
+ g_slist_foreach (ft2font->metrics_by_lang, (GFunc)g_free, NULL);
+ g_slist_free (ft2font->metrics_by_lang);
+
+ if (ft2font->entry)
+ pango_ft2_font_entry_remove (ft2font->entry, (PangoFont *)ft2font);
+
+ g_object_unref (G_OBJECT (ft2font->fontmap));
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_ft2_font_describe (PangoFont *font)
+{
+ /* FIXME: implement */
+ return NULL;
+}
+
+PangoMap *
+pango_ft2_get_shaper_map (const char *lang)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_FT2);
+ }
+
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static PangoCoverage *
+pango_ft2_font_get_coverage (PangoFont *font,
+ const char *lang)
+{
+ PangoFT2Font *ft2font = (PangoFT2Font *)font;
+
+ return pango_ft2_font_entry_get_coverage (ft2font->entry, font, lang);
+}
+
+static PangoEngineShape *
+pango_ft2_font_find_shaper (PangoFont *font,
+ const gchar *lang,
+ guint32 ch)
+{
+ PangoMap *shape_map = NULL;
+
+ shape_map = pango_ft2_get_shaper_map (lang);
+ return (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
+}
+
+/* Utility functions */
+
+/**
+ * pango_ft2_get_unknown_glyph:
+ * @font: a #PangoFont
+ *
+ * Return the index of a glyph suitable for drawing unknown characters.
+ *
+ * Return value: a glyph index into @font
+ **/
+PangoGlyph
+pango_ft2_get_unknown_glyph (PangoFont *font)
+{
+ return PANGO_FT2_MAKE_GLYPH (1, 0);
+}
+
+/**
+ * pango_ft2_render_layout_line:
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout_line (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ GSList *tmp_list = line->runs;
+ PangoRectangle overall_rect;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ unsigned char *p;
+ int ix;
+ int x_off = 0;
+ int x_limit;
+
+ pango_layout_line_get_extents (line,NULL, &overall_rect);
+
+ while (tmp_list)
+ {
+ PangoUnderline uline = PANGO_UNDERLINE_NONE;
+ PangoLayoutRun *run = tmp_list->data;
+ PangoAttrColor fg_color, bg_color;
+ gboolean fg_set, bg_set;
+
+ tmp_list = tmp_list->next;
+
+ pango_ft2_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set);
+
+ if (uline == PANGO_UNDERLINE_NONE)
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ NULL, &logical_rect);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ &ink_rect, &logical_rect);
+
+ pango_ft2_render (bitmap, run->item->analysis.font, run->glyphs,
+ x + PANGO_PIXELS (x_off), y);
+
+ x_limit = PANGO_PIXELS (ink_rect.width);
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ p = bitmap->buffer +
+ (y + 4) * bitmap->pitch +
+ x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+
+ /* Don't drawn the underline through descenders */
+ for (ix = 0; ix < x_limit; ix++)
+ if (*p == 0xFF &&
+ (ix == x_limit - 1 || p[1] == 0xFF))
+ *p++ = 0;
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ p = bitmap->buffer +
+ (y + 2) * bitmap->pitch +
+ x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ for (ix = 0; ix < x_limit; ix++)
+ if (*p == 0xFF &&
+ (ix == x_limit - 1 || p[1] == 0xFF))
+ *p++ = 0;
+ break;
+ case PANGO_UNDERLINE_LOW:
+ p = bitmap->buffer +
+ (y + PANGO_PIXELS (ink_rect.y + ink_rect.height)) * bitmap->pitch +
+ x + PANGO_PIXELS (x_off + ink_rect.x) - 1;
+ for (ix = 0; ix < PANGO_PIXELS (ink_rect.width); ix++)
+ *p++ = 0;
+ break;
+ }
+
+ x_off += logical_rect.width;
+ }
+}
+
+/**
+ * pango_ft2_render_layout:
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in pixels)
+ * @y: the Y position of the top of the layout (in pixels)
+ *
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoRectangle logical_rect;
+ GSList *tmp_list;
+ PangoAlignment align;
+ int indent;
+ int width;
+ int y_offset = 0;
+
+ gboolean first = FALSE;
+
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (layout != NULL);
+
+ indent = pango_layout_get_indent (layout);
+ width = pango_layout_get_width (layout);
+ align = pango_layout_get_alignment (layout);
+
+ PING (("x:%d y:%d indent:%d width:%d\n", x, y, indent, width));
+
+ if (width == -1 && align != PANGO_ALIGN_LEFT)
+ {
+ pango_layout_get_extents (layout, NULL, &logical_rect);
+ width = logical_rect.width;
+ }
+
+ tmp_list = pango_layout_get_lines (layout);
+ while (tmp_list)
+ {
+ PangoLayoutLine *line = tmp_list->data;
+ int x_offset;
+
+ pango_layout_line_get_extents (line, NULL, &logical_rect);
+
+ if (width != 1 && align == PANGO_ALIGN_RIGHT)
+ x_offset = width - logical_rect.width;
+ else if (width != 1 && align == PANGO_ALIGN_CENTER)
+ x_offset = (width - logical_rect.width) / 2;
+ else
+ x_offset = 0;
+
+ if (first)
+ {
+ if (indent > 0)
+ {
+ if (align == PANGO_ALIGN_LEFT)
+ x_offset += indent;
+ else
+ x_offset -= indent;
+ }
+
+ first = FALSE;
+ }
+ else
+ {
+ if (indent < 0)
+ {
+ if (align == PANGO_ALIGN_LEFT)
+ x_offset -= indent;
+ else
+ x_offset += indent;
+ }
+ }
+
+ PING (("x_offset:%d y_offset:%d logical_rect.y:%d logical_rect.height:%d\n", x_offset, y_offset, logical_rect.y, logical_rect.height));
+
+ pango_ft2_render_layout_line (bitmap, line,
+ x + PANGO_PIXELS (x_offset),
+ y + PANGO_PIXELS (y_offset - logical_rect.y));
+
+ y_offset += logical_rect.height;
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* This utility function is duplicated here and in pango-layout.c; should it be
+ * public? Trouble is - what is the appropriate set of properties?
+ */
+static void
+pango_ft2_get_item_properties (PangoItem *item,
+ PangoUnderline *uline,
+ PangoAttrColor *fg_color,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set)
+{
+ GSList *tmp_list = item->extra_attrs;
+
+ if (fg_set)
+ *fg_set = FALSE;
+
+ if (bg_set)
+ *bg_set = FALSE;
+
+ while (tmp_list)
+ {
+ PangoAttribute *attr = tmp_list->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ if (uline)
+ *uline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ if (fg_color)
+ *fg_color = *((PangoAttrColor *)attr);
+ if (fg_set)
+ *fg_set = TRUE;
+
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ if (bg_color)
+ *bg_color = *((PangoAttrColor *)attr);
+ if (bg_set)
+ *bg_set = TRUE;
+
+ break;
+
+ default:
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+typedef struct
+{
+ FT_Error code;
+ const char* msg;
+} ft_error_description;
+
+static int
+ft_error_compare (const void *pkey,
+ const void *pbase)
+{
+ return ((ft_error_description *) pkey)->code - ((ft_error_description *) pbase)->code;
+}
+
+const char *
+pango_ft2_ft_strerror (FT_Error error)
+{
+#undef FTERRORS_H
+#define FT_ERRORDEF( e, v, s ) { e, s },
+#define FT_ERROR_START_LIST {
+#define FT_ERROR_END_LIST { 0, 0 } }
+
+ const ft_error_description ft_errors[] =
+#include <freetype/fterrors.h>
+ ;
+
+#undef FT_ERRORDEF
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+ ft_error_description *found =
+ bsearch (&error, ft_errors, G_N_ELEMENTS (ft_errors) - 1,
+ sizeof (ft_errors[0]), ft_error_compare);
+ if (found != NULL)
+ return found->msg;
+ else
+ {
+ static char default_msg[100];
+
+ sprintf (default_msg, "Unknown FreeType2 error %#x", error);
+ return default_msg;
+ }
+}
diff --git a/pango/pangoft2.h b/pango/pangoft2.h
new file mode 100644
index 00000000..ededcbc9
--- /dev/null
+++ b/pango/pangoft2.h
@@ -0,0 +1,107 @@
+/* Pango
+ * pangoft2.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGOFT2_H__
+#define __PANGOFT2_H__
+
+#include <glib.h>
+#include <pango/pango.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <freetype/freetype.h>
+
+#define PANGO_RENDER_TYPE_FT2 "PangoRenderFT2"
+
+/* Calls for applications
+ */
+PangoContext *pango_ft2_get_context (void);
+
+PangoFont *pango_ft2_load_font (PangoFontMap *fontmap,
+ FT_Open_Args **args,
+ FT_Long *face_indices,
+ int n_fonts,
+ int size);
+void pango_ft2_render (FT_Bitmap *bitmap,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_ft2_render_layout_line (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_ft2_render_layout (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+
+/* API for rendering modules
+ */
+typedef guint16 PangoFT2Subfont;
+
+#define PANGO_FT2_MAKE_GLYPH(subfont,index) ((subfont)<<16 | (index))
+#define PANGO_FT2_GLYPH_SUBFONT(glyph) ((glyph)>>16)
+#define PANGO_FT2_GLYPH_INDEX(glyph) ((glyph) & 0xFFFF)
+
+int pango_ft2_n_subfonts (PangoFont *font);
+gboolean pango_ft2_has_glyph (PangoFont *font,
+ PangoGlyph glyph);
+PangoGlyph pango_ft2_get_unknown_glyph (PangoFont *font);
+int pango_ft2_font_get_kerning (PangoFont *font,
+ PangoGlyph left,
+ PangoGlyph right);
+
+/* API for libraries that want to use PangoFT2 mixed with classic
+ * FT2 fonts.
+ */
+typedef struct _PangoFT2FontCache PangoFT2FontCache;
+
+PangoFT2FontCache *pango_ft2_font_cache_new (FT_Library library);
+void pango_ft2_font_cache_free (PangoFT2FontCache *cache);
+FT_Face pango_ft2_font_cache_load (PangoFT2FontCache *cache,
+ FT_Open_Args *args,
+ FT_Long face_index);
+void pango_ft2_font_cache_unload (PangoFT2FontCache *cache,
+ FT_Face face);
+PangoFontMap *pango_ft2_font_map_for_display (void);
+void pango_ft2_shutdown_display (void);
+PangoFT2FontCache *pango_ft2_font_map_get_font_cache (PangoFontMap *font_map);
+void pango_ft2_font_subfont_open_args (PangoFont *font,
+ PangoFT2Subfont subfont_id,
+ FT_Open_Args **open_args,
+ FT_Long *face_index);
+
+
+/* Debugging.
+ */
+void pango_ft2_fontmap_dump (int indent,
+ PangoFontMap *fontmap);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __PANGOFT2_H__ */
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index 86565d26..3f9caa2d 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -53,7 +53,12 @@ struct _PangoWin32FontMap
PangoWin32FontCache *font_cache;
GQueue *freed_fonts;
+ /* Map Pango family names tp PangoWin32FamilyEntry structs */
GHashTable *families;
+
+ /* Map LOGFONTS (taking into account only the lfFaceName, lfItalic
+ * and lfWeight fields) to PangoWin32SizeInfo structs.
+ */
GHashTable *size_infos;
int n_fonts;
@@ -88,18 +93,9 @@ struct _PangoWin32SizeInfo
GSList *logfonts;
};
-const struct {
- const gchar *text;
- PangoStretch value;
-} stretches_map[] = {
- { "normal", PANGO_STRETCH_NORMAL },
- { "semicondensed", PANGO_STRETCH_SEMI_CONDENSED },
- { "condensed", PANGO_STRETCH_CONDENSED },
-};
-
-static GType pango_win32_font_map_get_type (void);
-static void pango_win32_font_map_init (PangoWin32FontMap *fontmap);
-static void pango_win32_font_map_class_init (PangoWin32FontMapClass *class);
+static GType pango_win32_font_map_get_type (void);
+static void pango_win32_font_map_init (PangoWin32FontMap *fontmap);
+static void pango_win32_font_map_class_init (PangoWin32FontMapClass *class);
static void pango_win32_font_map_finalize (GObject *object);
static PangoFont *pango_win32_font_map_load_font (PangoFontMap *fontmap,
@@ -111,12 +107,12 @@ static void pango_win32_font_map_list_fonts (PangoFontMap
static void pango_win32_font_map_list_families (PangoFontMap *fontmap,
gchar ***families,
int *n_families);
-
-static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);
-static void pango_win32_font_map_read_aliases (PangoWin32FontMap *win32fontmap);
-
-static void pango_win32_insert_font (PangoWin32FontMap *fontmap,
- LOGFONT *lfp);
+
+static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);
+static void pango_win32_font_map_read_aliases (PangoWin32FontMap *win32fontmap);
+
+static void pango_win32_insert_font (PangoWin32FontMap *fontmap,
+ LOGFONT *lfp);
static PangoFontClass *parent_class; /* Parent class structure for PangoWin32FontMap */
@@ -226,7 +222,7 @@ pango_win32_enum_proc (LOGFONT *lfp,
lf = *lfp;
- EnumFontFamiliesEx (pango_win32_hdc, &lf, pango_win32_inner_enum_proc, lParam, 0);
+ EnumFontFamiliesEx (pango_win32_hdc, &lf, (FONTENUMPROC) pango_win32_inner_enum_proc, lParam, 0);
return 1;
}
@@ -250,7 +246,7 @@ pango_win32_font_map_for_display (void)
memset (&logfont, 0, sizeof (logfont));
logfont.lfCharSet = DEFAULT_CHARSET;
- EnumFontFamiliesEx (pango_win32_hdc, &logfont, pango_win32_enum_proc, 0, 0);
+ EnumFontFamiliesEx (pango_win32_hdc, &logfont, (FONTENUMPROC) pango_win32_enum_proc, 0, 0);
pango_win32_font_map_read_aliases (fontmap);
@@ -270,12 +266,8 @@ pango_win32_font_map_for_display (void)
void
pango_win32_shutdown_display (void)
{
- GList *tmp_list;
-
pango_win32_fontmap_cache_clear (fontmap);
g_object_unref (G_OBJECT (fontmap));
-
- return;
}
static void
@@ -289,6 +281,7 @@ pango_win32_font_map_finalize (GObject *object)
pango_win32_font_cache_free (win32fontmap->font_cache);
/* ??? */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
typedef struct
@@ -298,7 +291,9 @@ typedef struct
} ListFontsInfo;
static void
-list_fonts_foreach (gpointer key, gpointer value, gpointer user_data)
+list_fonts_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
PangoWin32FamilyEntry *entry = value;
ListFontsInfo *info = user_data;
@@ -364,7 +359,9 @@ pango_win32_font_map_list_fonts (PangoFontMap *fontmap,
}
static void
-list_families_foreach (gpointer key, gpointer value, gpointer user_data)
+list_families_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
GSList **list = user_data;
@@ -372,9 +369,9 @@ list_families_foreach (gpointer key, gpointer value, gpointer user_data)
}
static void
-pango_win32_font_map_list_families (PangoFontMap *fontmap,
- gchar ***families,
- int *n_families)
+pango_win32_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families)
{
GSList *family_list = NULL;
GSList *tmp_list;
@@ -931,7 +928,7 @@ pango_win32_guess_subranges (UINT charset,
return retval;
}
-static gboolean
+static void
pango_win32_setup_signature (PangoWin32FontMap *win32fontmap,
LOGFONT *lfp,
FONTSIGNATURE *sigp)
@@ -940,7 +937,6 @@ pango_win32_setup_signature (PangoWin32FontMap *win32fontmap,
HFONT hfont;
HGDIOBJ oldfont;
int charset;
- int i;
logfont = *lfp;
logfont.lfHeight = 40;
@@ -948,11 +944,11 @@ pango_win32_setup_signature (PangoWin32FontMap *win32fontmap,
&logfont);
if (!hfont)
{
- g_warning ("font \"%s\" (%sweight:%d) not available",
+ g_warning ("font \"%s\" (%sweight:%ld) not available",
+ logfont.lfFaceName,
(logfont.lfItalic ? "italic," : ""),
- logfont.lfWeight,
- logfont.lfFaceName);
- return FALSE;
+ logfont.lfWeight);
+ return;
}
oldfont = SelectObject (pango_win32_hdc, hfont);
memset (sigp, 0, sizeof (*sigp));
@@ -969,9 +965,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap,
PangoWin32FontEntry *font_entry = NULL;
FILE *infile;
char **faces;
- char *buf = NULL;
int lineno = 0;
- int charset;
int nfaces;
int i;
@@ -1002,25 +996,25 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap,
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_style (tmp_buf, &font_entry->description))
+ if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_variant (tmp_buf, &font_entry->description))
+ if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_weight (tmp_buf, &font_entry->description))
+ if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_stretch (tmp_buf, &font_entry->description))
+ if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
@@ -1030,7 +1024,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap,
faces = g_strsplit (tmp_buf->str, ",", -1);
nfaces = 0;
- for (i=0; faces[i]; i++)
+ for (i = 0; faces[i]; i++)
{
char *trimmed = pango_trim_string (faces[i]);
g_free (faces[i]);
@@ -1039,7 +1033,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap,
}
font_entry->lfp = g_new0 (LOGFONT, nfaces);
font_entry->n_fonts = nfaces;
- for (i=0; i<nfaces; i++)
+ for (i = 0; i < nfaces; i++)
{
strcpy (font_entry->lfp[i].lfFaceName, faces[i]);
@@ -1165,9 +1159,8 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
PangoWin32FamilyEntry *family_entry;
PangoWin32FontEntry *font_entry;
PangoWin32SizeInfo *size_info;
- int i;
- PING(("lfp.face=%s,wt=%d,ht=%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight));
+ PING(("lfp.face=%s,wt=%ld,ht=%ld",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight));
description.size = 0;
/* First insert the LOGFONT into the list of LOGFONTs for the typeface name
@@ -1251,19 +1244,6 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
win32fontmap->n_fonts++;
}
-/* Compare the tail of a to b */
-static gboolean
-match_end (char *a, char *b)
-{
- size_t len_a = strlen (a);
- size_t len_b = strlen (b);
-
- if (len_b > len_a)
- return FALSE;
- else
- return (strcmp (a + len_a - len_b, b) == 0);
-}
-
gboolean
pango_win32_logfont_has_subrange (PangoFontMap *fontmap,
LOGFONT *lfp,
@@ -1298,7 +1278,7 @@ pango_win32_make_matching_logfont (PangoFontMap *fontmap,
LOGFONT *result = NULL;
gint match_distance = 0;
- PING(("lfp.face=%s,wt=%d,ht=%d,size:%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight,size));
+ PING(("lfp.face=%s,wt=%ld,ht=%ld,size:%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight,size));
win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
@@ -1487,7 +1467,7 @@ pango_win32_font_entry_dump (int indent,
indent, "", font_entry,
indent, "");
- for (i=0; i<font_entry->n_fonts; i++)
+ for (i = 0; i < font_entry->n_fonts; i++)
printf ("%*s LOGFONT:%s\n",
indent, "", font_entry->lfp[i].lfFaceName);
@@ -1530,7 +1510,9 @@ pango_win32_family_entry_dump (int indent,
}
static void
-dump_family (gpointer key, gpointer value, gpointer user_data)
+dump_family (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
PangoWin32FamilyEntry *entry = value;
int indent = (int) user_data;
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index d5e6663f..9bf2a026 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -90,18 +90,22 @@ static void pango_win32_font_shutdown (GObject *object);
static void pango_win32_font_finalize (GObject *object);
static PangoFontDescription *pango_win32_font_describe (PangoFont *font);
+
static PangoCoverage *pango_win32_font_get_coverage (PangoFont *font,
const char *lang);
+
static PangoEngineShape *pango_win32_font_find_shaper (PangoFont *font,
const char *lang,
guint32 ch);
-static void pango_win32_font_get_glyph_extents (PangoFont *font,
- PangoGlyph glyph,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
-static void pango_win32_font_get_metrics (PangoFont *font,
- const gchar *lang,
- PangoFontMetrics *metrics);
+
+static void pango_win32_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+
+static void pango_win32_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics);
static PangoWin32SubfontInfo *pango_win32_find_subfont (PangoFont *font,
PangoWin32Subfont subfont_index);
@@ -110,9 +114,11 @@ static gboolean pango_win32_find_glyph (PangoFont *font,
PangoGlyph glyph,
PangoWin32SubfontInfo **subfont_return,
SIZE *size_return);
+
static HFONT pango_win32_get_hfont (PangoFont *font,
PangoWin32SubfontInfo *info);
+
static void pango_win32_get_item_properties (PangoItem *item,
PangoUnderline *uline,
PangoAttrColor *fg_color,
@@ -540,6 +546,8 @@ pango_win32_unicode_classify (wchar_t wc)
else
return -1;
}
+ /* NOTREACHED */
+ return 0;
}
static void
@@ -867,7 +875,7 @@ pango_win32_list_subfonts (PangoFont *font,
LOGFONT *lfp;
PangoWin32Font *win32font = (PangoWin32Font *)font;
PangoWin32Subfont *subfont_list;
- int i, j;
+ int i;
int n_subfonts;
g_return_val_if_fail (font != NULL, 0);
@@ -985,7 +993,7 @@ subfont_has_glyph (PangoFont *font,
info->oldfont = SelectObject (info->buf_hdc, info->hfont);
SetTextAlign (info->buf_hdc, TA_LEFT|TA_BASELINE|TA_NOUPDATECP);
GetTextMetrics (info->buf_hdc, &tm);
- PING(("wt:%d,ht:%d",tm.tmMaxCharWidth,tm.tmHeight));
+ PING(("wt:%ld,ht:%ld",tm.tmMaxCharWidth,tm.tmHeight));
info->default_char_hbm =
create_bitmap_dibsection (info->buf_hdc, &info->default_char_buf,
@@ -1279,7 +1287,6 @@ pango_win32_render_layout_line (HDC hdc,
PangoRectangle overall_rect;
PangoRectangle logical_rect;
PangoRectangle ink_rect;
- PangoContext *context = pango_layout_get_context (line->layout);
int x_off = 0;
diff --git a/pango/pangowin32.h b/pango/pangowin32.h
index 7d040f5b..64275185 100644
--- a/pango/pangowin32.h
+++ b/pango/pangowin32.h
@@ -34,7 +34,32 @@ extern "C" {
#define PANGO_RENDER_TYPE_WIN32 "PangoRenderWin32"
-/* This enum divides Unicode characters according to the Microsoft
+/* Calls for applications
+ */
+PangoContext * pango_win32_get_context (void);
+
+PangoFont * pango_win32_load_font (LOGFONT *lfp,
+ int n_fonts);
+void pango_win32_render (HDC hdc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_win32_render_layout_line (HDC hdc,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_win32_render_layout (HDC hdc,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+
+
+/* API for rendering modules
+ */
+
+/* This enum classifies Unicode characters according to the Microsoft
* Unicode subrange numbering. This is based on the table in "Developing
* International Software for Windows 95 and Windows NT". This is almost,
* but not quite, the same as the official Unicode block table in
@@ -115,69 +140,45 @@ typedef enum
PANGO_WIN32_U_LAST_PLUS_ONE
} PangoWin32UnicodeSubrange;
-/* Calls for applications
- */
-PangoContext * pango_win32_get_context (void);
-
-PangoFont * pango_win32_load_font (LOGFONT *lfp,
- int n_fonts);
-void pango_win32_render (HDC hdc,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y);
-void pango_win32_render_layout_line (HDC hdc,
- PangoLayoutLine *line,
- int x,
- int y);
-void pango_win32_render_layout (HDC hdc,
- PangoLayout *layout,
- int x,
- int y);
-
-
+PangoWin32UnicodeSubrange pango_win32_unicode_classify (wchar_t wc);
-/* API for rendering modules
- */
typedef guint16 PangoWin32Subfont;
#define PANGO_WIN32_MAKE_GLYPH(subfont,index) ((subfont)<<16 | (index))
#define PANGO_WIN32_GLYPH_SUBFONT(glyph) ((glyph)>>16)
#define PANGO_WIN32_GLYPH_INDEX(glyph) ((glyph) & 0xffff)
-int pango_win32_list_subfonts (PangoFont *font,
- PangoWin32UnicodeSubrange subrange,
- PangoWin32Subfont **subfont_ids);
-gboolean pango_win32_has_glyph (PangoFont *font,
- PangoGlyph glyph);
-PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font);
-
-PangoWin32UnicodeSubrange pango_win32_unicode_classify (wchar_t wc);
+int pango_win32_list_subfonts (PangoFont *font,
+ PangoWin32UnicodeSubrange subrange,
+ PangoWin32Subfont **subfont_ids);
+gboolean pango_win32_has_glyph (PangoFont *font,
+ PangoGlyph glyph);
+PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font);
/* API for libraries that want to use PangoWin32 mixed with classic
* Win32 fonts.
*/
typedef struct _PangoWin32FontCache PangoWin32FontCache;
-PangoWin32FontCache *pango_win32_font_cache_new (void);
-void pango_win32_font_cache_free (PangoWin32FontCache *cache);
-
-HFONT pango_win32_font_cache_load (PangoWin32FontCache *cache,
- const LOGFONT *lfp);
-void pango_win32_font_cache_unload (PangoWin32FontCache *cache,
- HFONT hfont);
+PangoWin32FontCache *pango_win32_font_cache_new (void);
+void pango_win32_font_cache_free (PangoWin32FontCache *cache);
+
+HFONT pango_win32_font_cache_load (PangoWin32FontCache *cache,
+ const LOGFONT *lfp);
+void pango_win32_font_cache_unload (PangoWin32FontCache *cache,
+ HFONT hfont);
-PangoFontMap * pango_win32_font_map_for_display (void);
-void pango_win32_shutdown_display (void);
-PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *font_map);
+PangoFontMap *pango_win32_font_map_for_display (void);
+void pango_win32_shutdown_display (void);
+PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *font_map);
-LOGFONT *pango_win32_font_subfont_logfont (PangoFont *font,
- PangoWin32Subfont subfont_id);
+LOGFONT *pango_win32_font_subfont_logfont (PangoFont *font,
+ PangoWin32Subfont subfont_id);
/* Debugging.
*/
-void pango_win32_fontmap_dump (int indent,
- PangoFontMap *fontmap);
+void pango_win32_fontmap_dump (int indent,
+ PangoFontMap *fontmap);
#ifdef __cplusplus
}
diff --git a/pango/pangox-fontmap.c b/pango/pangox-fontmap.c
index 34a0cc3f..4a92c816 100644
--- a/pango/pangox-fontmap.c
+++ b/pango/pangox-fontmap.c
@@ -853,25 +853,25 @@ pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap,
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_style (tmp_buf, &font_entry->description))
+ if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_variant (tmp_buf, &font_entry->description))
+ if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_weight (tmp_buf, &font_entry->description))
+ if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))
goto error;
- if (!pango_parse_stretch (tmp_buf, &font_entry->description))
+ if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE))
goto error;
if (!pango_scan_string (&p, tmp_buf))