summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog34
-rw-r--r--ChangeLog.pre-1-034
-rw-r--r--ChangeLog.pre-1-1034
-rw-r--r--ChangeLog.pre-1-234
-rw-r--r--ChangeLog.pre-1-434
-rw-r--r--ChangeLog.pre-1-634
-rw-r--r--ChangeLog.pre-1-834
-rw-r--r--configure.in3
-rw-r--r--examples/makefile.mingw22
-rw-r--r--examples/pangowin32.aliases7
-rw-r--r--examples/viewer-win32.c742
-rw-r--r--modules/basic/basic-win32.c363
-rw-r--r--modules/basic/makefile.mingw21
-rw-r--r--pango/makefile.mingw67
-rw-r--r--pango/modules.c14
-rw-r--r--pango/pango-utils.c94
-rw-r--r--pango/pango-utils.h13
-rw-r--r--pango/pangowin32-fontcache.c341
-rw-r--r--pango/pangowin32-fontmap.c1781
-rw-r--r--pango/pangowin32-private.h91
-rw-r--r--pango/pangowin32.c1465
-rw-r--r--pango/pangowin32.h187
-rw-r--r--pango/querymodules.c18
23 files changed, 5453 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-0 b/ChangeLog.pre-1-0
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-0
+++ b/ChangeLog.pre-1-0
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-10
+++ b/ChangeLog.pre-1-10
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-2
+++ b/ChangeLog.pre-1-2
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-4
+++ b/ChangeLog.pre-1-4
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-6
+++ b/ChangeLog.pre-1-6
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8
index 73581e5f..dcd6a5e8 100644
--- a/ChangeLog.pre-1-8
+++ b/ChangeLog.pre-1-8
@@ -1,3 +1,37 @@
+2000-07-15 Tor Lillqvist <tml@iki.fi>
+
+ * pango/pangowin32.h
+ * pango/pangowin32-private.h
+ * pango/pangowin32-fontcache.c
+ * pango/pangowin32-fontmap.c
+ * modules/basic/basic-win32.c
+ * examples/viewer-win32.c
+ * examples/pangowin32.aliases: New files. Start of a Win32
+ implementation. Does not work yet.
+
+ * configure.in: Chek for dirent.h and unistd.h.
+
+ * pango/pango-utils.h
+ * pango/pango-utils.c (pango_get_sysconf_subdirectory,
+ pango_get_lib_subdirectory): New functions, for better
+ portability, to enable installation-time choice of directory (on
+ Windows) instead of compile-time. Use these instead of SYSCONFDIR
+ "/pango" and LIBDIR "/pango".
+
+ (pango_split_file_list): Fix comment, the function splits on
+ searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
+ for portability. Don't try to expand '~' as home directory on
+ Windows.
+
+ (read_config): Use pango_get_sysconf_subdirectory().
+
+ * pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
+ Don't crash if a module file cannot be opened.
+
+ * pango/querymodules.c: Include config.h Conditionalize inclusion
+ of dirent.h and unistd.h. Use platform-specific shared library
+ extension. Use pango_get_lib_subdirectory().
+
Thu Jul 6 15:24:38 2000 Owen Taylor <otaylor@redhat.com>
* Released 0.12
diff --git a/configure.in b/configure.in
index 03a37962..c32cca2a 100644
--- a/configure.in
+++ b/configure.in
@@ -210,6 +210,9 @@ EOTEXT
included_modules=$included_modules
])
+AC_HEADER_DIRENT
+AC_CHECK_HEADER(unistd.h, AC_DEFINE(HAVE_UNISTD_H))
+
AC_OUTPUT([
Makefile
pango/Makefile
diff --git a/examples/makefile.mingw b/examples/makefile.mingw
new file mode 100644
index 00000000..259e02af
--- /dev/null
+++ b/examples/makefile.mingw
@@ -0,0 +1,22 @@
+PANGO_VER = 0.12
+
+TOP = ../..
+
+include $(TOP)/build/win32/make.mingw
+
+OPTIMIZE = -g
+
+INCLUDES = -I .. -I .
+DEFINES =
+DEPCFLAGS = $(GTK_CFLAGS) $(GLIB_CFLAGS)
+
+all : \
+ ../config.h \
+ viewer-win32.exe
+
+../config.h : ../config.h.win32
+ cp $< $@
+
+viewer-win32.exe : viewer-win32.o
+ $(CC) -o $@ $< -L ../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GTK_LIBS) $(GLIB_LIBS) -gdi32
+
diff --git a/examples/pangowin32.aliases b/examples/pangowin32.aliases
new file mode 100644
index 00000000..948642f4
--- /dev/null
+++ b/examples/pangowin32.aliases
@@ -0,0 +1,7 @@
+# File defining aliases of PangoFontDescription to Windows font set
+#
+# family style variant weight stretch facename,...
+
+sans normal normal normal normal "arial,gulimche,ms gothic,ms hei,mingliu"
+serif normal normal normal normal "times new roman,gulimche,ms gothic,ms song,mingliu"
+monospace normal normal normal normal "courier new,gulimche,ms gothic,ms song,mingliu"
diff --git a/examples/viewer-win32.c b/examples/viewer-win32.c
new file mode 100644
index 00000000..9304b7d2
--- /dev/null
+++ b/examples/viewer-win32.c
@@ -0,0 +1,742 @@
+#define PING() g_print ("%s:%d\n", __PRETTY_FUNCTION__, __LINE__)
+/* Pango
+ * viewer-win32.c: Example program to view a UTF-8 encoding file
+ * using Pango to render result.
+ *
+ * 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 <gtk/gtk.h>
+#include <gdk/win32/gdkwin32.h>
+
+#include <pango/pango.h>
+#include <pango/pangowin32.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define BUFSIZE 1024
+
+typedef struct _Paragraph Paragraph;
+
+/* Structure representing a paragraph
+ */
+struct _Paragraph {
+ char *text;
+ int length;
+ int height; /* Height, in pixels */
+ PangoLayout *layout;
+};
+
+GList *paragraphs;
+
+static PangoFontDescription font_description;
+static Paragraph *highlight_para;
+static int highlight_offset;
+
+GtkWidget *styles_combo;
+
+static GtkWidget *message_label;
+GtkWidget *layout;
+
+PangoContext *context;
+
+static void fill_styles_combo (GtkWidget *combo);
+
+/* Read an entire file into a string
+ */
+static char *
+read_file(char *name)
+{
+ GString *inbuf;
+ FILE *file;
+ char *text;
+ char buffer[BUFSIZE];
+
+ PING();
+ file = fopen (name, "r");
+ if (!file)
+ {
+ fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname ());
+ return NULL;
+ }
+
+ inbuf = g_string_new (NULL);
+ while (1)
+ {
+ char *bp = fgets (buffer, BUFSIZE-1, file);
+ if (ferror (file))
+ {
+ fprintf(stderr, "%s: Error reading %s\n", g_get_prgname ());
+ g_string_free (inbuf, TRUE);
+ return NULL;
+ }
+ else if (bp == NULL)
+ break;
+
+ g_string_append (inbuf, buffer);
+ }
+
+ fclose (file);
+
+ text = inbuf->str;
+ g_string_free (inbuf, FALSE);
+
+ return text;
+}
+
+/* Take a UTF8 string and break it into paragraphs on \n characters
+ */
+static GList *
+split_paragraphs (char *text)
+{
+ char *p = text;
+ char *next;
+ gunichar wc;
+ GList *result = NULL;
+ char *last_para = text;
+
+ while (*p)
+ {
+ wc = g_utf8_get_char (p);
+ next = g_utf8_next_char (p);
+ if (wc == (gunichar)-1)
+ {
+ fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ());
+ g_list_foreach (result, (GFunc)g_free, NULL);
+ return NULL;
+ }
+ if (!*p || !wc || wc == '\n')
+ {
+ Paragraph *para = g_new (Paragraph, 1);
+ para->text = last_para;
+ para->length = p - last_para;
+ para->layout = pango_layout_new (context);
+ pango_layout_set_text (para->layout, para->text, para->length);
+ para->height = 0;
+
+ last_para = next;
+
+ result = g_list_prepend (result, para);
+ }
+ if (!wc) /* incomplete character at end */
+ break;
+ p = next;
+ }
+
+ return g_list_reverse (result);
+}
+
+/* Given an x-y position, return the paragraph and offset
+ * within the paragraph of the click.
+ */
+gboolean
+xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index)
+{
+ GList *para_list;
+ int height = 0;
+
+ *para_return = NULL;
+
+ PING();
+ para_list = paragraphs;
+ while (para_list && height < y)
+ {
+ Paragraph *para = para_list->data;
+
+ if (height + para->height >= y)
+ {
+ gboolean result = pango_layout_xy_to_index (para->layout, x * 1000, (y - height) * 1000,
+ index, NULL);
+ if (result && para_return)
+ *para_return = para;
+
+ return result;
+ }
+
+ height += para->height;
+ para_list = para_list->next;
+ }
+ PING();
+
+ return FALSE;
+}
+
+/* Given a paragraph and offset in that paragraph, find the
+ * bounding rectangle for the character at the offset.
+ */
+void
+char_bounds (Paragraph *para, int index, int width, PangoRectangle *rect)
+{
+ GList *para_list;
+
+ int height = 0;
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *cur_para = para_list->data;
+
+ if (cur_para == para)
+ {
+ PangoRectangle pos;
+
+ pango_layout_index_to_pos (cur_para->layout, index, &pos);
+
+ rect->x = MIN (pos.x, pos.x + pos.width) / 1000;
+ rect->width = ABS (pos.width) / 1000;
+ rect->y = height + pos.y / 1000;
+ rect->height = pos.height / 1000;
+ }
+
+ height += cur_para->height;
+ para_list = para_list->next;
+ }
+}
+
+/* XOR a rectangle over a given character
+ */
+void
+xor_char (GtkWidget *layout, GdkRectangle *clip_rect,
+ Paragraph *para, int offset)
+{
+ static GdkGC *gc;
+ PangoRectangle rect; /* GdkRectangle in 1.2 is too limited
+ */
+ if (!gc)
+ {
+ GdkGCValues values;
+ values.foreground = layout->style->white.pixel ?
+ layout->style->white : layout->style->black;
+ values.function = GDK_XOR;
+ gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window,
+ &values,
+ GDK_GC_FOREGROUND | GDK_GC_FUNCTION);
+ }
+
+ gdk_gc_set_clip_rectangle (gc, clip_rect);
+
+ char_bounds (para, offset, layout->allocation.width, &rect);
+
+ rect.y -= GTK_LAYOUT (layout)->yoffset;
+
+ if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height))
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE,
+ rect.x, rect.y, rect.width, rect.height);
+}
+
+/* Handle a size allocation by re-laying-out each paragraph to
+ * the new width, setting the new size for the layout and
+ * then queing a redraw
+ */
+void
+size_allocate (GtkWidget *layout, GtkAllocation *allocation)
+{
+ GList *tmp_list;
+ int height = 0;
+ PangoDirection base_dir = pango_context_get_base_dir (context);
+
+ PING();
+ tmp_list = paragraphs;
+ while (tmp_list)
+ {
+ Paragraph *para = tmp_list->data;
+ PangoRectangle logical_rect;
+
+ tmp_list = tmp_list->next;
+
+ pango_layout_set_alignment (para->layout,
+ base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);
+ pango_layout_set_width (para->layout, layout->allocation.width * 1000);
+
+ pango_layout_get_extents (para->layout, NULL, &logical_rect);
+ para->height = logical_rect.height / 1000;
+
+ height += para->height;
+ }
+
+ gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height);
+
+ if (GTK_LAYOUT (layout)->yoffset + allocation->height > height)
+ gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, height - allocation->height);
+}
+
+/* Handle a draw/expose by finding the paragraphs that intersect
+ * the region and reexposing them.
+ */
+void
+draw (GtkWidget *layout, GdkRectangle *area)
+{
+ GList *tmp_list;
+ int height = 0;
+
+ PING();
+ gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window,
+ layout->style->base_gc[layout->state],
+ TRUE,
+ area->x, area->y,
+ area->width, area->height);
+
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area);
+
+ PING();
+ tmp_list = paragraphs;
+ while (tmp_list &&
+ height < area->y + area->height + GTK_LAYOUT (layout)->yoffset)
+ {
+ Paragraph *para = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ PING();
+ if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y)
+ {
+ GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND;
+ HDC hdc = gdk_win32_hdc_get (GDK_WINDOW_XWINDOW (GTK_LAYOUT (layout)->bin_window),
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+
+ pango_win32_render_layout (hdc, para->layout,
+ 0, height - GTK_LAYOUT (layout)->yoffset);
+
+ gdk_win32_hdc_release (GDK_WINDOW_XWINDOW (GTK_LAYOUT (layout)->bin_window),
+ layout->style->text_gc[GTK_STATE_NORMAL],
+ mask);
+ }
+
+ height += para->height;
+ }
+
+ PING();
+ gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL);
+
+ if (highlight_para)
+ xor_char (layout, area, highlight_para, highlight_offset);
+ PING();
+}
+
+gboolean
+expose (GtkWidget *layout, GdkEventExpose *event)
+{
+ PING();
+ if (event->window == GTK_LAYOUT (layout)->bin_window)
+ draw (layout, &event->area);
+
+ return TRUE;
+}
+
+void
+button_press (GtkWidget *layout, GdkEventButton *event)
+{
+ Paragraph *para = NULL;
+ int offset;
+ gchar *message;
+
+ PING();
+ xy_to_cp (layout->allocation.width,
+ event->x, event->y + GTK_LAYOUT (layout)->yoffset,
+ &para, &offset);
+
+ if (highlight_para)
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+
+ highlight_para = para;
+ highlight_offset = offset;
+
+ if (para)
+ {
+ gunichar wc;
+
+ wc = g_utf8_get_char (para->text + offset);
+ message = g_strdup_printf ("Current char: U%04x", wc);
+
+ xor_char (layout, NULL, highlight_para, highlight_offset);
+ }
+ else
+ message = g_strdup_printf ("Current char:");
+
+ PING();
+ gtk_label_set_text (GTK_LABEL (message_label), message);
+ g_free (message);
+}
+
+static void
+checkbutton_toggled (GtkWidget *widget, gpointer data)
+{
+ GList *para_list;
+
+ PING();
+ pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ gtk_widget_queue_resize (layout);
+}
+
+static void
+reload_font ()
+{
+ GList *para_list;
+
+ PING();
+ pango_context_set_font_description (context, &font_description);
+
+ para_list = paragraphs;
+ while (para_list)
+ {
+ Paragraph *para = para_list->data;
+
+ pango_layout_context_changed (para->layout);
+ para_list = para_list->next;
+ }
+
+ if (layout)
+ gtk_widget_queue_resize (layout);
+ PING();
+}
+
+void
+set_family (GtkWidget *entry, gpointer data)
+{
+ font_description.family_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ fill_styles_combo (styles_combo);
+}
+
+void
+set_style (GtkWidget *entry, gpointer data)
+{
+ char *str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ PangoFontDescription *tmp_desc;
+
+ PING();
+ tmp_desc = pango_font_description_from_string (str);
+
+ font_description.style = tmp_desc->style;
+ font_description.variant = tmp_desc->variant;
+ font_description.weight = tmp_desc->weight;
+ font_description.stretch = tmp_desc->stretch;
+
+ pango_font_description_free (tmp_desc);
+ g_free (str);
+
+ reload_font ();
+}
+
+void
+font_size_changed (GtkAdjustment *adj)
+{
+ PING();
+ font_description.size = (int)(adj->value * PANGO_SCALE + 0.5);
+ reload_font();
+}
+
+static int
+compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
+{
+ int val = strcmp (a->family_name, b->family_name);
+ if (val != 0)
+ return val;
+
+ if (a->weight != b->weight)
+ return a->weight - b->weight;
+
+ if (a->style != b->style)
+ return a->style - b->style;
+
+ if (a->stretch != b->stretch)
+ return a->stretch - b->stretch;
+
+ if (a->variant != b->variant)
+ return a->variant - b->variant;
+
+ return 0;
+}
+
+static int
+font_description_sort_func (const void *a, const void *b)
+{
+ return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b);
+}
+
+typedef struct
+{
+ PangoFontDescription **descs;
+ int n_descs;
+} FontDescInfo;
+
+static void
+free_info (FontDescInfo *info)
+{
+ pango_font_descriptions_free (info->descs, info->n_descs);
+}
+
+static void
+fill_styles_combo (GtkWidget *combo)
+{
+ int i;
+ GList *style_list = NULL;
+
+ FontDescInfo *info = g_new (FontDescInfo, 1);
+ PING();
+ pango_context_list_fonts (context, font_description.family_name, &info->descs, &info->n_descs);
+ gtk_object_set_data_full (GTK_OBJECT (combo), "descs", info, (GtkDestroyNotify)free_info);
+ PING();
+
+ qsort (info->descs, info->n_descs, sizeof(PangoFontDescription *), font_description_sort_func);
+
+ PING();
+ for (i=0; i<info->n_descs; i++)
+ {
+ char *str;
+
+ PangoFontDescription tmp_desc;
+
+ tmp_desc = *info->descs[i];
+ tmp_desc.family_name = NULL;
+ tmp_desc.size = 0;
+
+ str = pango_font_description_to_string (&tmp_desc);
+ style_list = g_list_prepend (style_list, str);
+ }
+
+ style_list = g_list_reverse (style_list);
+
+ PING();
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), style_list);
+ g_list_foreach (style_list, (GFunc)g_free, NULL);
+}
+
+static GtkWidget *
+make_styles_combo ()
+{
+ GtkWidget *combo;
+
+ PING();
+ combo = gtk_combo_new ();
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_style), NULL);
+
+ styles_combo = combo;
+ fill_styles_combo (combo);
+
+ PING();
+ return combo;
+}
+
+static int
+cmp_strings (const void *a, const void *b)
+{
+ return strcmp (*(const char **)a, *(const char **)b);
+}
+
+GtkWidget *
+make_families_menu ()
+{
+ GtkWidget *combo;
+ gchar **families;
+ int n_families;
+ GList *family_list = NULL;
+ int i;
+
+ PING();
+ pango_context_list_families (context, &families, &n_families);
+ qsort (families, n_families, sizeof(char *), cmp_strings);
+
+ PING();
+ for (i=0; i<n_families; i++)
+ family_list = g_list_prepend (family_list, families[i]);
+
+ family_list = g_list_reverse (family_list);
+
+ combo = gtk_combo_new ();
+ gtk_combo_set_popdown_strings (GTK_COMBO (combo), family_list);
+ gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE);
+ gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
+
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), font_description.family_name);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed",
+ GTK_SIGNAL_FUNC (set_family), NULL);
+
+ g_list_free (family_list);
+ pango_font_map_free_families (families, n_families);
+
+ PING();
+ return combo;
+}
+
+
+GtkWidget *
+make_font_selector (void)
+{
+ GtkWidget *hbox;
+ GtkWidget *util_hbox;
+ GtkWidget *label;
+ GtkWidget *option_menu;
+ GtkWidget *spin_button;
+ GtkAdjustment *adj;
+
+ hbox = gtk_hbox_new (FALSE, 4);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Family:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_families_menu ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Style:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ option_menu = make_styles_combo ();
+ gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 2);
+ label = gtk_label_new ("Size:");
+ gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0);
+ spin_button = gtk_spin_button_new (NULL, 1., 0);
+ gtk_box_pack_start (GTK_BOX (util_hbox), spin_button, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0);
+
+ adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button));
+ adj->value = font_description.size / 1000.;
+ adj->lower = 0;
+ adj->upper = 1024;
+ adj->step_increment = 1;
+ adj->page_size = 10;
+ gtk_adjustment_changed (adj);
+ gtk_adjustment_value_changed (adj);
+
+ gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
+ GTK_SIGNAL_FUNC (font_size_changed), NULL);
+
+ return hbox;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *text;
+ GtkWidget *window;
+ GtkWidget *scrollwin;
+ GtkWidget *vbox, *hbox;
+ GtkWidget *frame;
+ GtkWidget *checkbutton;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: %s FILE\n", g_get_prgname ());
+ exit(1);
+ }
+
+ /* Create the list of paragraphs from the supplied file
+ */
+ text = read_file (argv[1]);
+ if (!text)
+ exit(1);
+
+ context = pango_win32_get_context ();
+
+ paragraphs = split_paragraphs (text);
+
+ pango_context_set_lang (context, "en_US");
+ pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
+
+ font_description.family_name = g_strdup ("sans");
+ font_description.style = PANGO_STYLE_NORMAL;
+ font_description.variant = PANGO_VARIANT_NORMAL;
+ font_description.weight = 500;
+ font_description.stretch = PANGO_STRETCH_NORMAL;
+ font_description.size = 16000;
+
+ pango_context_set_font_description (context, &font_description);
+
+ /* Create the user interface
+ */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ hbox = make_font_selector ();
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ scrollwin = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
+
+ layout = gtk_layout_new (NULL, NULL);
+ gtk_widget_set_events (layout, GDK_BUTTON_PRESS_MASK);
+ gtk_widget_set_app_paintable (layout, TRUE);
+
+ gtk_signal_connect (GTK_OBJECT (layout), "size_allocate",
+ GTK_SIGNAL_FUNC (size_allocate), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "expose_event",
+ GTK_SIGNAL_FUNC (expose), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "draw",
+ GTK_SIGNAL_FUNC (draw), paragraphs);
+ gtk_signal_connect (GTK_OBJECT (layout), "button_press_event",
+ GTK_SIGNAL_FUNC (button_press), paragraphs);
+
+ gtk_container_add (GTK_CONTAINER (scrollwin), layout);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+ PING();
+ message_label = gtk_label_new ("Current char:");
+ gtk_misc_set_padding (GTK_MISC (message_label), 1, 1);
+ gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5);
+ gtk_container_add (GTK_CONTAINER (frame), message_label);
+
+ checkbutton = gtk_check_button_new_with_label ("Use RTL global direction");
+ gtk_signal_connect (GTK_OBJECT (checkbutton), "toggled",
+ GTK_SIGNAL_FUNC (checkbutton_toggled), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (window);
+
+ PING();
+ gtk_main ();
+
+ return 0;
+}
diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
new file mode 100644
index 00000000..d174d9e1
--- /dev/null
+++ b/modules/basic/basic-win32.c
@@ -0,0 +1,363 @@
+/* Pango
+ * basic-win32.c:
+ *
+ * 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 <glib.h>
+#include "pango.h"
+#include "pangowin32.h"
+#include <fribidi/fribidi.h>
+
+typedef struct _CharCache CharCache;
+
+#define MAX_CHARSETS 32
+
+struct _CharCache
+{
+ int n_subfonts;
+ PangoWin32Subfont *subfonts;
+};
+
+static PangoEngineRange basic_ranges[] = {
+ /* Language characters */
+ { 0x0000, 0x02af, "*" },
+ { 0x02b0, 0x02ff, "" },
+ { 0x0380, 0x058f, "*" },
+ { 0x0591, 0x05f4, "*" }, /* Hebrew */
+ { 0x060c, 0x06f9, "" }, /* Arabic */
+ { 0x0e01, 0x0e5b, "" }, /* Thai */
+ { 0x1e00, 0x1fff, "*" },
+ { 0x2000, 0x9fff, "*" },
+ { 0xac00, 0xd7a3, "kr" },
+ { 0xf900, 0xfa0b, "kr" },
+ { 0xff00, 0xffe3, "*" }
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ "BasicScriptEngineLang",
+ PANGO_ENGINE_TYPE_LANG,
+ PANGO_RENDER_TYPE_NONE,
+ basic_ranges, G_N_ELEMENTS(basic_ranges)
+ },
+ {
+ "BasicScriptEngineWin32",
+ PANGO_ENGINE_TYPE_SHAPE,
+ PANGO_RENDER_TYPE_WIN32,
+ basic_ranges, G_N_ELEMENTS(basic_ranges)
+ }
+};
+
+static gint n_script_engines = G_N_ELEMENTS (script_engines);
+
+/*
+ * Language script engine
+ */
+
+static void
+basic_engine_break (const char *text,
+ gint len,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs)
+{
+}
+
+static PangoEngine *
+basic_engine_lang_new ()
+{
+ PangoEngineLang *result;
+
+ result = g_new (PangoEngineLang, 1);
+
+ result->engine.id = "BasicScriptEngine";
+ result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ result->engine.length = sizeof (result);
+ result->script_break = basic_engine_break;
+
+ return (PangoEngine *)result;
+}
+
+/*
+ * Win32 system script engine portion
+ */
+
+static CharCache *
+char_cache_new (void)
+{
+ CharCache *result;
+ int i;
+
+ result = g_new (CharCache, 1);
+ result->subfonts = NULL;
+
+ return result;
+}
+
+static void
+char_cache_free (CharCache *cache)
+{
+ g_free (cache->subfonts);
+ g_free (cache);
+}
+
+static PangoGlyph
+find_char (CharCache *cache, PangoFont *font, gunichar wc)
+{
+ PangoWin32UnicodeSubrange subrange;
+ PangoWin32Subfont *subfonts;
+ int i;
+ int n_subfonts;
+
+ subrange = pango_win32_unicode_classify (wc);
+
+ n_subfonts = pango_win32_list_subfonts (font, subrange, &subfonts);
+
+ for (i=0; i<n_subfonts; i++)
+ {
+ PangoGlyph glyph;
+
+ glyph = PANGO_WIN32_MAKE_GLYPH (subfonts[i], wc);
+
+ if (pango_win32_has_glyph (font, glyph))
+ return glyph;
+ }
+
+ return 0;
+}
+
+static void
+set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static void
+swap_range (PangoGlyphString *glyphs, int start, int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+static CharCache *
+get_char_cache (PangoFont *font)
+{
+ GQuark cache_id = g_quark_from_string ("basic-char-cache");
+
+ CharCache *cache = g_object_get_qdata (G_OBJECT (font), cache_id);
+ if (!cache)
+ {
+ cache = char_cache_new ();
+ g_object_set_qdata_full (G_OBJECT (font), cache_id,
+ cache, (GDestroyNotify)char_cache_free);
+ }
+
+ return cache;
+}
+
+static void
+basic_engine_shape (PangoFont *font,
+ const char *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars;
+ int i;
+ const char *p;
+
+ CharCache *cache;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ cache = get_char_cache (font);
+
+ n_chars = g_utf8_strlen (text, length);
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ FriBidiChar mirrored_ch;
+ PangoGlyph index;
+ char buf[6];
+ const char *input;
+
+ wc = g_utf8_get_char (p);
+
+ input = p;
+ if (analysis->level % 2)
+ if (fribidi_get_mirror_char (wc, &mirrored_ch))
+ {
+ wc = mirrored_ch;
+
+ g_unichar_to_utf8 (wc, buf);
+ input = buf;
+ }
+
+ if (wc == 0x200B || wc == 0x200E || wc == 0x200F) /* Zero-width characters */
+ {
+ set_glyph (font, glyphs, i, p - text, 0);
+ }
+ else
+ {
+ index = find_char (cache, font, wc);
+ if (index)
+ {
+ set_glyph (font, glyphs, i, p - text, index);
+
+ if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
+ {
+ if (i > 0)
+ {
+ PangoRectangle logical_rect, ink_rect;
+
+ glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+ glyphs->glyphs[i].geometry.width);
+ glyphs->glyphs[i-1].geometry.width = 0;
+ glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+
+ /* Some heuristics to try to guess how overstrike glyphs are
+ * done and compensate
+ */
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
+ if (logical_rect.width == 0 && ink_rect.x == 0)
+ glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
+ }
+ }
+ }
+ else
+ set_glyph (font, glyphs, i, p - text, pango_win32_get_unknown_glyph (font));
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ /* Simple bidi support... may have separate modules later */
+
+ if (analysis->level % 2)
+ {
+ int start, end;
+
+ /* Swap all glyphs */
+ swap_range (glyphs, 0, n_chars);
+
+ /* Now reorder glyphs within each cluster back to LTR */
+ for (start=0; start<n_chars;)
+ {
+ end = start;
+ while (end < n_chars &&
+ glyphs->log_clusters[end] == glyphs->log_clusters[start])
+ end++;
+
+ swap_range (glyphs, start, end);
+ start = end;
+ }
+ }
+}
+
+static PangoCoverage *
+basic_engine_get_coverage (PangoFont *font,
+ const char *lang)
+{
+ CharCache *cache = get_char_cache (font);
+ PangoCoverage *result = pango_coverage_new ();
+ gunichar wc;
+
+ for (wc = 0; wc < 65536; wc++)
+ if (find_char (cache, font, wc))
+ pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
+
+ return result;
+}
+
+static PangoEngine *
+basic_engine_win32_new ()
+{
+ PangoEngineShape *result;
+
+ result = g_new (PangoEngineShape, 1);
+
+ result->engine.id = "BasicScriptEngine";
+ result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ result->engine.length = sizeof (result);
+ result->script_shape = basic_engine_shape;
+ result->get_coverage = basic_engine_get_coverage;
+
+ return (PangoEngine *)result;
+}
+
+/* The following three functions provide the public module API for
+ * Pango
+ */
+#ifdef MODULE_PREFIX
+#define MODULE_ENTRY(func) _pango_basic_##func
+#else
+#define MODULE_ENTRY(func) func
+#endif
+
+void
+MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = n_script_engines;
+}
+
+PangoEngine *
+MODULE_ENTRY(script_engine_load) (const char *id)
+{
+ if (!strcmp (id, "BasicScriptEngineLang"))
+ return basic_engine_lang_new ();
+ else if (!strcmp (id, "BasicScriptEngineWin32"))
+ return basic_engine_win32_new ();
+ else
+ return NULL;
+}
+
+void
+MODULE_ENTRY(script_engine_unload) (PangoEngine *engine)
+{
+}
+
diff --git a/modules/basic/makefile.mingw b/modules/basic/makefile.mingw
new file mode 100644
index 00000000..60377b99
--- /dev/null
+++ b/modules/basic/makefile.mingw
@@ -0,0 +1,21 @@
+PANGO_VER = 0.12
+
+TOP = ../../..
+
+include $(TOP)/build/win32/make.mingw
+
+OPTIMIZE = -g
+
+INCLUDES = -I ../../pango -I ../..
+DEFINES =
+DEPCFLAGS = $(GLIB_CFLAGS) $(FRIBIDI_CFLAGS)
+
+all : \
+ ../../config.h \
+ pango-basic-win32.dll
+
+../../config.h : ../../config.h.win32
+ cp $< $@
+
+pango-basic-win32.dll : basic-win32.o
+ $(GLIB)/build-dll pango-basic-win32 - ../engine.def $< -L ../../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS)
diff --git a/pango/makefile.mingw b/pango/makefile.mingw
new file mode 100644
index 00000000..e32f72f0
--- /dev/null
+++ b/pango/makefile.mingw
@@ -0,0 +1,67 @@
+PANGO_VER = 0.12
+
+TOP = ../..
+
+include $(TOP)/build/win32/make.mingw
+
+OPTIMIZE = -g
+
+INCLUDES = -I .. -I .
+DEFINES =
+DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FRIBIDI_CFLAGS)
+
+all : \
+ ../config.h \
+ pango-$(PANGO_VER).dll \
+ pangowin32-$(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 \
+ shape.o
+
+PANGOWIN32_OBJS = \
+ pangowin32.o \
+ pangowin32-fontcache.o \
+ pangowin32-fontmap.o
+
+PANGO_QUERYMODULES_OBJS = \
+ querymodules.o
+
+../config.h : ../config.h.win32
+ cp $< $@
+
+module-defs.c : module-defs.c.win32
+ cp $< $@
+
+pango-$(PANGO_VER).dll : $(PANGO_OBJS) pango.def
+ $(GLIB)/build-dll pango $(PANGO_VER) pango.def $(PANGO_OBJS) $(GLIB_LIBS) $(LIBICONV_LIBS) $(FRIBIDI_LIBS)
+
+pangowin32-$(PANGO_VER).dll : $(PANGOWIN32_OBJS) pangowin32.def
+ $(GLIB)/build-dll pangowin32 $(PANGO_VER) pangowin32.def $(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
+ $(CC) -o $@ $(PANGO_QUERYMODULES_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS)
+
+test1.exe : test1.o pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll
+ $(CC) -o $@ $(CFLAGS) test1.o -L . -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) -lgdi32
+
+test2.exe : test2.o
+ $(CC) -o $@ $(CFLAGS) test2.o -lgdi32
+
+test3.exe : test3.o
+ $(CC) -o $@ $(CFLAGS) test3.o -lgdi32
+
diff --git a/pango/modules.c b/pango/modules.c
index b7572aac..cad34866 100644
--- a/pango/modules.c
+++ b/pango/modules.c
@@ -19,6 +19,8 @@
* Boston, MA 02111-1307, USA.
*/
+#include "config.h"
+
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -316,7 +318,9 @@ read_modules (void)
int n;
if (!file_str)
- file_str = g_strdup (SYSCONFDIR "/pango/pango.modules");
+ file_str = g_strconcat (pango_get_sysconf_subdirectory (),
+ G_DIR_SEPARATOR_S "pango.modules",
+ NULL);
files = pango_split_file_list (file_str);
@@ -329,9 +333,11 @@ read_modules (void)
module_file = fopen (files[n], "r");
if (!module_file)
g_warning ("Error opening module file '%s': %s\n", files[n], g_strerror (errno));
-
- process_module_file(module_file);
- fclose(module_file);
+ else
+ {
+ process_module_file(module_file);
+ fclose(module_file);
+ }
}
g_strfreev (files);
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index 786ae07c..c267a692 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -33,6 +33,13 @@
# define getc_unlocked(f) getc(f)
#endif /* !HAVE_FLOCKFILE */
+#ifdef G_OS_WIN32
+
+#define STRICT
+#include <windows.h>
+
+#endif
+
/**
* pango_trim_string:
* @str: a string
@@ -62,8 +69,8 @@ pango_trim_string (const char *str)
* pango_split_file_list:
* @str: a comma separated list of filenames
*
- * Split a comma-separated list of files, stripping white space
- * and subsituting ~/ with $HOME/
+ * Split a G_SEARCHPATH_SEPARATOR-separated list of files, stripping
+ * white space and subsituting ~/ with $HOME/
*
* Return value: a list of strings to be freed with g_strfreev()
**/
@@ -74,7 +81,7 @@ pango_split_file_list (const char *str)
int j;
char **files;
- files = g_strsplit (str, ":", -1);
+ files = g_strsplit (str, G_SEARCHPATH_SEPARATOR_S, -1);
while (files[i])
{
@@ -93,14 +100,20 @@ pango_split_file_list (const char *str)
continue;
}
-
+#ifndef G_OS_WIN32
+ /* '~' is a quite normal and common character in file names on
+ * Windows, especially in the 8.3 versions of long file names, which
+ * still occur and then. Also, few Windows user are aware of the
+ * Unix shell convention that '~' stands for the home directory,
+ * even if they happen to have a home directory.
+ */
if (file[0] == '~' && file[1] == G_DIR_SEPARATOR)
{
char *tmp = g_strconcat (g_get_home_dir(), file + 1, NULL);
g_free (file);
file = tmp;
}
-
+#endif
g_free (files[i]);
files[i] = file;
@@ -539,14 +552,25 @@ read_config ()
if (!config_hash)
{
char *filename;
+ char *home;
config_hash = g_hash_table_new (g_str_hash, g_str_equal);
- read_config_file (SYSCONFDIR "/" "pango/pangorc", FALSE);
-
- filename = g_strconcat (g_get_home_dir (), "/.pangorc", NULL);
+ filename = g_strconcat (pango_get_sysconf_subdirectory (),
+ G_DIR_SEPARATOR_S "pangorc",
+ NULL);
read_config_file (filename, FALSE);
g_free (filename);
+ home = g_get_home_dir ();
+ if (home && *home)
+ {
+ filename = g_strconcat (home,
+ G_DIR_SEPARATOR_S ".pangorc",
+ NULL);
+ read_config_file (filename, FALSE);
+ g_free (filename);
+ }
+
filename = g_getenv ("PANGO_RC_FILE");
if (filename)
read_config_file (filename, TRUE);
@@ -573,3 +597,57 @@ pango_config_key_get (const char *key)
return g_strdup (g_hash_table_lookup (config_hash, key));
}
+
+char *
+pango_get_sysconf_subdirectory (void)
+{
+#ifdef G_OS_WIN32
+
+ /* On Windows we don't hardcode any paths (SYSCONFDIR) in the DLL,
+ * but rely on an installation program to store the installation
+ * directory in the registry. If no installation program has been
+ * used, punt and assume the Pango directory is %WINDIR%\Pango.
+ */
+
+ static gboolean been_here = FALSE;
+ static gchar pango_sysconf_dir[200];
+ gchar win_dir[100];
+ HKEY reg_key = NULL;
+ DWORD type;
+ DWORD nbytes = sizeof (pango_sysconf_dir);
+
+ if (been_here)
+ return pango_sysconf_dir;
+
+ been_here = TRUE;
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\GNU\\Pango", 0,
+ KEY_QUERY_VALUE, &reg_key) != ERROR_SUCCESS
+ || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+ &type, pango_sysconf_dir, &nbytes) != ERROR_SUCCESS
+ || type != REG_SZ)
+ {
+ /* Uh oh. Use %WinDir%\Pango */
+ GetWindowsDirectory (win_dir, sizeof (win_dir));
+ sprintf (pango_sysconf_dir, "%s\\pango", win_dir);
+ }
+
+ if (reg_key != NULL)
+ RegCloseKey (reg_key);
+
+ return pango_sysconf_dir;
+
+#else
+ return SYSCONFDIR "/pango";
+#endif
+}
+
+char *
+pango_get_lib_subdirectory (void)
+{
+#ifdef G_OS_WIN32
+ return pango_get_sysconf_subdirectory ();
+#else
+ return LIBDIR "/pango";
+#endif
+}
diff --git a/pango/pango-utils.h b/pango/pango-utils.h
index fe4f638d..1c8dfcaa 100644
--- a/pango/pango-utils.h
+++ b/pango/pango-utils.h
@@ -38,3 +38,16 @@ gboolean pango_scan_int (const char **pos,
char * pango_config_key_get (const char *key);
+/* On Unix, return the name of the "pango" subdirectory of SYSCONFDIR
+ * (which is set at compile time). On Win32, return the Pango
+ * installation directory (which is set at installation time, and
+ * stored in the registry). The returned string should not be
+ * g_free'd.
+ */
+char * pango_get_sysconf_subdirectory (void);
+
+/* Ditto for LIBDIR/pango. On Win32, use the same Pango
+ * installation directory. This returned string should not be
+ * g_free'd either.
+ */
+char * pango_get_lib_subdirectory (void);
diff --git a/pango/pangowin32-fontcache.c b/pango/pangowin32-fontcache.c
new file mode 100644
index 00000000..40d6eae3
--- /dev/null
+++ b/pango/pangowin32-fontcache.c
@@ -0,0 +1,341 @@
+/* Pango
+ * pangowin32-fontcache.c: Cache of HFONTs by LOGFONT
+ *
+ * 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 <stdio.h>
+
+#include "pangowin32-private.h"
+
+/* Font cache
+ */
+
+/* Number of fonts to retain after they are not otherwise referenced.
+ */
+#define CACHE_SIZE 16
+
+typedef struct _CacheEntry CacheEntry;
+
+struct _PangoWin32FontCache
+{
+ GHashTable *forward;
+ GHashTable *back;
+
+ GList *mru;
+ GList *mru_tail;
+ int mru_count;
+};
+
+struct _CacheEntry
+{
+ LOGFONT logfont;
+ HFONT hfont;
+
+ gint ref_count;
+ GList *mru;
+};
+
+static void
+free_cache_entry (LOGFONT *logfont,
+ CacheEntry *entry,
+ PangoWin32FontCache *cache)
+{
+ DeleteObject (entry->hfont);
+
+ g_free (entry);
+}
+
+/**
+ * pango_win32_font_cache_free:
+ * @cache: a #PangoWin32FontCache
+ *
+ * Free a #PangoWin32FontCache and all associated memory. All fonts loaded
+ * through this font cache will be freed along with the cache.
+ **/
+void
+pango_win32_font_cache_free (PangoWin32FontCache *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
+logfont_hash (gconstpointer v)
+{
+ const LOGFONT *lfp = v;
+
+ return g_str_hash (lfp->lfFaceName) +
+ lfp->lfItalic +
+ lfp->lfWeight/10 +
+ lfp->lfOrientation +
+ lfp->lfHeight * 10;
+}
+
+static gint
+logfont_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const LOGFONT *lfp1 = v1, *lfp2 = v2;
+
+ return (strcmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0
+ && lfp1->lfPitchAndFamily == lfp2->lfPitchAndFamily
+ && lfp1->lfStrikeOut == lfp2->lfStrikeOut
+ && lfp1->lfUnderline == lfp2->lfUnderline
+ && lfp1->lfItalic == lfp2->lfItalic
+ && lfp1->lfWeight == lfp2->lfWeight
+ && lfp1->lfOrientation == lfp2->lfOrientation
+ && lfp1->lfEscapement == lfp2->lfEscapement
+ && lfp1->lfWidth == lfp2->lfWidth
+ && lfp1->lfHeight == lfp2->lfHeight);
+}
+
+/**
+ * pango_win32_font_cache_new:
+ *
+ * Create a font cache.
+ *
+ * Return value: The new font cache. This must be freed with
+ * pango_win32_font_cache_free().
+ **/
+PangoWin32FontCache *
+pango_win32_font_cache_new (void)
+{
+ PangoWin32FontCache *cache;
+
+ cache = g_new (PangoWin32FontCache, 1);
+
+ cache->forward = g_hash_table_new (logfont_hash, logfont_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 (PangoWin32FontCache *cache,
+ CacheEntry *entry)
+{
+ entry->ref_count--;
+ if (entry->ref_count == 0)
+ {
+ g_hash_table_remove (cache->forward, &entry->logfont);
+ g_hash_table_remove (cache->back, entry->hfont);
+
+ free_cache_entry (NULL, entry, cache);
+ }
+}
+
+/**
+ * pango_win32_font_cache_load:
+ * @cache: a #PangoWin32FontCache
+ * @logfont: a pointer to a LOGFONT structure describing the font to load.
+ *
+ * Create a #HFONT from a LOGFONT. The
+ * result may be newly loaded, or it may have been previously
+ * stored
+ *
+ * Return value: The font structure, or %NULL if the font could
+ * not be loaded. In order to free this structure, you must call
+ * pango_win32_font_cache_unload().
+ **/
+HFONT
+pango_win32_font_cache_load (PangoWin32FontCache *cache,
+ const LOGFONT *lfp)
+{
+ CacheEntry *entry;
+ LOGFONT lf;
+ HFONT hfont;
+ int tries;
+
+ g_return_val_if_fail (cache != NULL, NULL);
+ g_return_val_if_fail (lfp != NULL, NULL);
+
+ entry = g_hash_table_lookup (cache->forward, lfp);
+
+ if (entry)
+ {
+ entry->ref_count++;
+ }
+ else
+ {
+ lf = *lfp;
+ for (tries = 0; ; tries++)
+ {
+#if 0
+ PANGO_NOTE
+ (g_print
+ ("... trying CreateFontIndirect, "
+ "height=%d,width=%d,escapement=%d,orientation=%d,"
+ "weight=%d,%s%s%s"
+ "charset=%d,outprecision=%d,clipprecision=%d,"
+ "quality=%d,pitchandfamily=%#.02x,facename=\"%s\")\n",
+ lf.lfHeight, lf.lfWidth, lf.lfEscapement, lf.lfOrientation,
+ lf.lfWeight, (lf.lfItalic ? "italic," : ""),
+ (lf.lfUnderline ? "underline," : ""),
+ (lf.lfStrikeOut ? "strikeout," : ""),
+ lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
+ lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName));
+#endif
+ hfont = CreateFontIndirect (&lf);
+
+ if (hfont != NULL)
+ break;
+
+ /* If we fail, try some similar fonts often found on Windows. */
+ if (tries == 0)
+ {
+ if (g_strcasecmp (lf.lfFaceName, "helvetica") == 0)
+ strcpy (lf.lfFaceName, "arial");
+ else if (g_strcasecmp (lf.lfFaceName, "new century schoolbook") == 0)
+ strcpy (lf.lfFaceName, "century schoolbook");
+ else if (g_strcasecmp (lf.lfFaceName, "courier") == 0)
+ strcpy (lf.lfFaceName, "courier new");
+ else if (g_strcasecmp (lf.lfFaceName, "lucida") == 0)
+ strcpy (lf.lfFaceName, "lucida sans unicode");
+ else if (g_strcasecmp (lf.lfFaceName, "lucidatypewriter") == 0)
+ strcpy (lf.lfFaceName, "lucida console");
+ else if (g_strcasecmp (lf.lfFaceName, "times") == 0)
+ strcpy (lf.lfFaceName, "times new roman");
+ }
+ else if (tries == 1)
+ {
+ if (g_strcasecmp (lf.lfFaceName, "courier") == 0)
+ {
+ strcpy (lf.lfFaceName, "");
+ lf.lfPitchAndFamily |= FF_MODERN;
+ }
+ else if (g_strcasecmp (lf.lfFaceName, "times new roman") == 0)
+ {
+ strcpy (lf.lfFaceName, "");
+ lf.lfPitchAndFamily |= FF_ROMAN;
+ }
+ else if (g_strcasecmp (lf.lfFaceName, "helvetica") == 0
+ || g_strcasecmp (lf.lfFaceName, "lucida") == 0)
+ {
+ strcpy (lf.lfFaceName, "");
+ lf.lfPitchAndFamily |= FF_SWISS;
+ }
+ else
+ {
+ strcpy (lf.lfFaceName, "");
+ lf.lfPitchAndFamily = (lf.lfPitchAndFamily & 0x0F) | FF_DONTCARE;
+ }
+ }
+ else
+ break;
+ tries++;
+ }
+
+ if (!hfont)
+ return NULL;
+
+ entry = g_new (CacheEntry, 1);
+
+ entry->logfont = lf;
+ entry->hfont = hfont;
+
+ entry->ref_count = 1;
+ entry->mru = NULL;
+
+ g_hash_table_insert (cache->forward, &entry->logfont, entry);
+ g_hash_table_insert (cache->back, entry->hfont, 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->hfont;
+}
+
+/**
+ * pango_win32_font_cache_unload:
+ * @cache: a #PangoWin32FontCache
+ * @hfont: the HFONT to unload
+ *
+ * Free a font structure previously loaded with pango_win32_font_cache_load()
+ **/
+void
+pango_win32_font_cache_unload (PangoWin32FontCache *cache,
+ HFONT hfont)
+{
+ CacheEntry *entry;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (hfont != NULL);
+
+ entry = g_hash_table_lookup (cache->back, hfont);
+ g_return_if_fail (entry != NULL);
+
+ cache_entry_unref (cache, entry);
+}
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
new file mode 100644
index 00000000..67d4129d
--- /dev/null
+++ b/pango/pangowin32-fontmap.c
@@ -0,0 +1,1781 @@
+/* Pango
+ * pangowin32-fontmap.c: Font handling
+ *
+ * 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>
+
+#include "pango-fontmap.h"
+#include "pango-utils.h"
+#include "pangowin32-private.h"
+
+#define PANGO_TYPE_WIN32_FONT_MAP (pango_win32_font_map_get_type ())
+#define PANGO_WIN32_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMap))
+#define PANGO_WIN32_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMapClass))
+#define PANGO_WIN32_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT_MAP))
+#define PANGO_WIN32_IS_FONT_MAP_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT_MAP))
+#define PANGO_WIN32_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMapClass))
+
+typedef struct _PangoWin32FamilyEntry PangoWin32FamilyEntry;
+typedef struct _PangoWin32FontMap PangoWin32FontMap;
+typedef struct _PangoWin32FontMapClass PangoWin32FontMapClass;
+typedef struct _PangoWin32SizeInfo PangoWin32SizeInfo;
+
+/* Number of freed fonts */
+#define MAX_FREED_FONTS 16
+
+struct _PangoWin32FontMap
+{
+ PangoFontMap parent_instance;
+
+ PangoWin32FontCache *font_cache;
+ GQueue *freed_fonts;
+
+ GHashTable *families;
+ GHashTable *size_infos;
+
+ int n_fonts;
+
+ double resolution; /* (points / pixel) * PANGO_SCALE */
+};
+
+struct _PangoWin32FontMapClass
+{
+ PangoFontMapClass parent_class;
+};
+
+struct _PangoWin32FamilyEntry
+{
+ char *family_name;
+ GSList *font_entries;
+};
+
+struct _PangoWin32FontEntry
+{
+ LOGFONT *lfp;
+ int n_fonts;
+ PangoFontDescription description;
+ PangoCoverage *coverage;
+
+ GSList *cached_fonts;
+};
+
+struct _PangoWin32SizeInfo
+{
+ FONTSIGNATURE signature;
+ 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 void pango_win32_font_map_finalize (GObject *object);
+static PangoFont *pango_win32_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description);
+static void pango_win32_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+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 PangoFontClass *parent_class; /* Parent class structure for PangoWin32FontMap */
+
+static GType
+pango_win32_font_map_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoWin32FontMapClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_win32_font_map_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoWin32FontMap),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_win32_font_map_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
+ "PangoWin32FontMap",
+ &object_info);
+ }
+
+ return object_type;
+}
+
+/* A hash function for LOGFONTs that takes into consideration
+ * only those fields that indicate a specific .ttf file is in
+ * use. Dunno how correct this is.
+ */
+
+static guint
+logfont_nosize_hash (gconstpointer v)
+{
+ const LOGFONT *lfp = v;
+
+ return g_str_hash (lfp->lfFaceName) +
+ lfp->lfItalic +
+ lfp->lfWeight;
+}
+
+/* Ditto comparison function */
+static gboolean
+logfont_nosize_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const LOGFONT *lfp1 = v1, *lfp2 = v2;
+
+ return (strcmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0
+ && lfp1->lfItalic == lfp2->lfItalic
+ && lfp1->lfWeight == lfp2->lfWeight);
+}
+
+static void
+pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
+{
+ win32fontmap->families = g_hash_table_new (g_str_hash, g_str_equal);
+ win32fontmap->size_infos = g_hash_table_new (logfont_nosize_hash, logfont_nosize_equal);
+ win32fontmap->n_fonts = 0;
+}
+
+static void
+pango_win32_font_map_class_init (PangoWin32FontMapClass *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_win32_font_map_finalize;
+ font_map_class->load_font = pango_win32_font_map_load_font;
+ font_map_class->list_fonts = pango_win32_font_map_list_fonts;
+ font_map_class->list_families = pango_win32_font_map_list_families;
+
+ if (pango_win32_hdc == NULL)
+ pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+}
+
+static PangoWin32FontMap *fontmap = NULL;
+
+static int CALLBACK
+pango_win32_inner_enum_proc (LOGFONT *lfp,
+ TEXTMETRIC *metrics,
+ DWORD fontType,
+ LPARAM lParam)
+{
+ pango_win32_insert_font (fontmap, lfp);
+
+ return 1;
+}
+
+static int CALLBACK
+pango_win32_enum_proc (LOGFONT *lfp,
+ TEXTMETRIC *metrics,
+ DWORD fontType,
+ LPARAM lParam)
+{
+ LOGFONT lf;
+
+ if (fontType != TRUETYPE_FONTTYPE)
+ return 1;
+
+ lf = *lfp;
+
+ EnumFontFamiliesEx (pango_win32_hdc, &lf, pango_win32_inner_enum_proc, lParam, 0);
+
+ return 1;
+}
+
+PangoFontMap *
+pango_win32_font_map_for_display (void)
+{
+ LOGFONT logfont;
+ int screen;
+
+ /* Make sure that the type system is initialized */
+ g_type_init();
+
+ if (fontmap != NULL)
+ return PANGO_FONT_MAP (fontmap);
+
+ fontmap = (PangoWin32FontMap *)g_type_create_instance (PANGO_TYPE_WIN32_FONT_MAP);
+
+ fontmap->font_cache = pango_win32_font_cache_new ();
+ fontmap->freed_fonts = g_queue_new ();
+
+ memset (&logfont, 0, sizeof (logfont));
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ EnumFontFamiliesEx (pango_win32_hdc, &logfont, pango_win32_enum_proc, 0, 0);
+
+ pango_win32_font_map_read_aliases (fontmap);
+
+ fontmap->resolution = 0; /* ??? */
+
+ return PANGO_FONT_MAP (fontmap);
+}
+
+/**
+ * pango_win32_shutdown_display:
+ *
+ * Free cached resources.
+ **/
+void
+pango_win32_shutdown_display (void)
+{
+ GList *tmp_list;
+
+ pango_win32_fontmap_cache_clear (fontmap);
+ g_object_unref (G_OBJECT (fontmap));
+
+ return;
+}
+
+static void
+pango_win32_font_map_finalize (GObject *object)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (object);
+
+ g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_queue_free (win32fontmap->freed_fonts);
+
+ pango_win32_font_cache_free (win32fontmap->font_cache);
+
+ /* ??? */
+}
+
+typedef struct
+{
+ int n_found;
+ PangoFontDescription **descs;
+} ListFontsInfo;
+
+static void
+list_fonts_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+ PangoWin32FamilyEntry *entry = value;
+ ListFontsInfo *info = user_data;
+ GSList *tmp_list = entry->font_entries;
+
+ while (tmp_list)
+ {
+ PangoWin32FontEntry *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_win32_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs)
+{
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
+ ListFontsInfo info;
+
+ if (!n_descs)
+ return;
+
+ if (family)
+ {
+ PangoWin32FamilyEntry *entry = g_hash_table_lookup (win32fontmap->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 = win32fontmap->n_fonts;
+ if (descs)
+ {
+ *descs = g_new (PangoFontDescription *, win32fontmap->n_fonts);
+
+ info.descs = *descs;
+ info.n_found = 0;
+
+ g_hash_table_foreach (win32fontmap->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_win32_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families)
+{
+ GSList *family_list = NULL;
+ GSList *tmp_list;
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
+
+ if (!n_families)
+ return;
+
+ g_hash_table_foreach (win32fontmap->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 PangoWin32FamilyEntry *
+pango_win32_get_family_entry (PangoWin32FontMap *win32fontmap,
+ const char *family_name)
+{
+ PangoWin32FamilyEntry *family_entry = g_hash_table_lookup (win32fontmap->families, family_name);
+ if (!family_entry)
+ {
+ family_entry = g_new (PangoWin32FamilyEntry, 1);
+ family_entry->family_name = g_strdup (family_name);
+ family_entry->font_entries = NULL;
+
+ g_hash_table_insert (win32fontmap->families, family_entry->family_name, family_entry);
+ }
+
+ return family_entry;
+}
+
+static PangoFont *
+pango_win32_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description)
+{
+ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
+ PangoWin32FamilyEntry *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 (win32fontmap->families, name);
+ if (family_entry)
+ {
+ PangoWin32FontEntry *best_match = NULL;
+
+ tmp_list = family_entry->font_entries;
+ while (tmp_list)
+ {
+ PangoWin32FontEntry *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)
+ {
+ PangoWin32Font *win32font = tmp_list->data;
+ if (win32font->size == description->size)
+ {
+ result = (PangoFont *)win32font;
+
+ g_object_ref (G_OBJECT (result));
+ if (win32font->in_cache)
+ pango_win32_fontmap_cache_remove (fontmap, win32font);
+
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (!result)
+ {
+ PangoWin32Font *win32font;
+
+ g_assert (best_match->lfp != NULL);
+ win32font = pango_win32_font_new (fontmap, best_match->lfp, best_match->n_fonts, description->size);
+ win32font->fontmap = fontmap;
+ win32font->entry = best_match;
+ best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, win32font);
+
+ result = (PangoFont *)win32font;
+ }
+ }
+ }
+
+ g_free (name);
+ return result;
+}
+
+/* Similar to GNU libc's getline, but buffer is g_malloc'd */
+static size_t
+pango_getline (char **lineptr, size_t *n, FILE *stream)
+{
+#define EXPAND_CHUNK 16
+
+ int n_read = 0;
+ int result = -1;
+
+ g_return_val_if_fail (lineptr != NULL, -1);
+ g_return_val_if_fail (n != NULL, -1);
+ g_return_val_if_fail (*lineptr != NULL || *n == 0, -1);
+
+#ifdef HAVE_FLOCKFILE
+ flockfile (stream);
+#endif
+
+ while (1)
+ {
+ int c;
+
+#ifdef HAVE_FLOCKFILE
+ c = getc_unlocked (stream);
+#else
+ c = getc (stream);
+#endif
+
+ if (c == EOF)
+ {
+ if (n_read > 0)
+ {
+ result = n_read;
+ (*lineptr)[n_read] = '\0';
+ }
+ break;
+ }
+
+ if (n_read + 2 >= *n)
+ {
+ *n += EXPAND_CHUNK;
+ *lineptr = g_realloc (*lineptr, *n);
+ }
+
+ (*lineptr)[n_read] = c;
+ n_read++;
+
+ if (c == '\n' || c == '\r')
+ {
+ result = n_read;
+ (*lineptr)[n_read] = '\0';
+ break;
+ }
+ }
+
+#ifdef HAVE_FLOCKFILE
+ funlockfile (stream);
+#endif
+
+ return n_read - 1;
+}
+
+static int
+find_tok (char **start, char **tok)
+{
+ char *p = *start;
+
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+
+ if (*p == 0 || *p == '\n' || *p == '\r')
+ return -1;
+
+ if (*p == '"')
+ {
+ p++;
+ *tok = p;
+
+ while (*p && *p != '"')
+ p++;
+
+ if (*p != '"')
+ return -1;
+
+ *start = p + 1;
+ return p - *tok;
+ }
+ else
+ {
+ *tok = p;
+
+ while (*p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n')
+ p++;
+
+ *start = p;
+ return p - *tok;
+ }
+}
+
+static gboolean
+get_style (GString *str, PangoFontDescription *desc)
+{
+ if (str->len == 0)
+ return FALSE;
+
+ switch (str->str[0])
+ {
+ case 'n':
+ case 'N':
+ if (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)
+ {
+ desc->style = PANGO_STYLE_ITALIC;
+ return TRUE;
+ }
+ break;
+ case 'o':
+ if (strncasecmp (str->str, "oblique", str->len) == 0)
+ {
+ desc->style = PANGO_STYLE_OBLIQUE;
+ return TRUE;
+ }
+ break;
+ }
+ g_warning ("Style must be normal, italic, or oblique");
+
+ return FALSE;
+}
+
+static gboolean
+get_variant (GString *str, PangoFontDescription *desc)
+{
+ if (str->len == 0)
+ return FALSE;
+
+ switch (str->str[0])
+ {
+ case 'n':
+ case 'N':
+ if (strncasecmp (str->str, "normal", str->len) == 0)
+ {
+ desc->variant = PANGO_VARIANT_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (strncasecmp (str->str, "small_caps", str->len) == 0)
+ {
+ desc->variant = PANGO_VARIANT_SMALL_CAPS;
+ return TRUE;
+ }
+ break;
+ }
+
+ g_warning ("Variant must be normal, or small_caps");
+ return FALSE;
+}
+
+static gboolean
+get_weight (GString *str, PangoFontDescription *desc)
+{
+ if (str->len == 0)
+ return FALSE;
+
+ switch (str->str[0])
+ {
+ case 'n':
+ case 'N':
+ if (strncasecmp (str->str, "normal", str->len) == 0)
+ {
+ desc->weight = PANGO_WEIGHT_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 'b':
+ case 'B':
+ if (strncasecmp (str->str, "bold", str->len) == 0)
+ {
+ desc->weight = PANGO_WEIGHT_BOLD;
+ return TRUE;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ char *numstr, *end;
+
+ numstr = g_strndup (str->str, str->len);
+
+ desc->weight = strtol (numstr, &end, 0);
+ if (*end != '\0')
+ {
+ g_warning ("Cannot parse numerical weight '%s'", numstr);
+ g_free (numstr);
+ return FALSE;
+ }
+
+ g_free (numstr);
+ return TRUE;
+ }
+ }
+
+ g_warning ("Weight must be normal, bold, or an integer");
+ return FALSE;
+}
+
+static gboolean
+get_stretch (GString *str, PangoFontDescription *desc)
+{
+ if (str->len == 0)
+ return FALSE;
+
+ switch (str->str[0])
+ {
+ case 'c':
+ case 'C':
+ if (strncasecmp (str->str, "condensed", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_CONDENSED;
+ return TRUE;
+ }
+ break;
+ case 'e':
+ case 'E':
+ if (strncasecmp (str->str, "extra_condensed", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_EXTRA_CONDENSED;
+ return TRUE;
+ }
+ if (strncasecmp (str->str, "extra_expanded", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_EXTRA_EXPANDED;
+ return TRUE;
+ }
+ if (strncasecmp (str->str, "expanded", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_EXPANDED;
+ return TRUE;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (strncasecmp (str->str, "normal", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_NORMAL;
+ return TRUE;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (strncasecmp (str->str, "semi_condensed", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_SEMI_CONDENSED;
+ return TRUE;
+ }
+ if (strncasecmp (str->str, "semi_expanded", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_SEMI_EXPANDED;
+ return TRUE;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if (strncasecmp (str->str, "ultra_condensed", str->len) == 0)
+ {
+ desc->stretch = PANGO_STRETCH_ULTRA_CONDENSED;
+ return TRUE;
+ }
+ if (strncasecmp (str->str, "ultra_expanded", str->len) == 0)
+ {
+ desc->variant = PANGO_STRETCH_ULTRA_EXPANDED;
+ return TRUE;
+ }
+ break;
+ }
+
+ g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded");
+ return FALSE;
+}
+
+static gboolean
+pango_win32_guess_subranges (UINT charset,
+ FONTSIGNATURE *fsp)
+{
+ gint i;
+ gboolean retval = FALSE;
+
+ /* If the fsUsb bit array has at least one of the bits set, trust it */
+ for (i = 0; i < PANGO_WIN32_U_LAST_PLUS_ONE; i++)
+ if (i != PANGO_WIN32_U_PRIVATE_USE_AREA &&
+ (fsp->fsUsb[i/32] & (1 << (i % 32))))
+ return FALSE;
+
+ /* Otherwise, guess what subranges there should be in the font */
+ fsp->fsUsb[0] = fsp->fsUsb[1] = fsp->fsUsb[2] = fsp->fsUsb[3] = 0;
+
+ /* Set Unicode subrange bits based on code pages supported.
+ * This is mostly just guesswork.
+ */
+
+#define check_cp(bit) (fsp->fsCsb[0] & (FS_##bit))
+
+#define set_bit(bitno) (fsp->fsUsb[(PANGO_WIN32_U_##bitno)/32] |= (1 << ((PANGO_WIN32_U_##bitno) % 32)))
+
+ if (check_cp(LATIN1))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (CURRENCY_SYMBOLS);
+ retval = TRUE;
+ }
+ if (check_cp (LATIN2))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (CURRENCY_SYMBOLS);
+ retval = TRUE;
+ }
+ if (check_cp (CYRILLIC))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (CYRILLIC);
+ retval = TRUE;
+ }
+ if (check_cp (GREEK))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (BASIC_GREEK);
+ retval = TRUE;
+ }
+ if (check_cp (TURKISH))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (CURRENCY_SYMBOLS);
+ retval = TRUE;
+ }
+ if (check_cp (HEBREW))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (BASIC_HEBREW);
+ set_bit (HEBREW_EXTENDED);
+ retval = TRUE;
+ }
+ if (check_cp (ARABIC))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (BASIC_ARABIC);
+ set_bit (ARABIC_EXTENDED);
+ retval = TRUE;
+ }
+ if (check_cp (BALTIC))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ retval = TRUE;
+ }
+ if (check_cp (VIETNAMESE))
+ {
+ /* ??? */
+ set_bit (BASIC_LATIN);
+ retval = TRUE;
+ }
+ if (check_cp (THAI))
+ {
+ set_bit (BASIC_LATIN);
+ set_bit (THAI);
+ retval = TRUE;
+ }
+ if (check_cp (JISJAPAN))
+ {
+ /* Based on what's in the MS Gothic font */
+ set_bit (BASIC_LATIN);
+ set_bit (CJK_SYMBOLS_AND_PUNCTUATION);
+ set_bit (HIRAGANA);
+ set_bit (KATAKANA);
+ set_bit (CJK_UNIFIED_IDEOGRAPHS);
+ set_bit (HALFWIDTH_AND_FULLWIDTH_FORMS);
+ retval = TRUE;
+ }
+ if (check_cp (CHINESESIMP))
+ {
+ /* Based on what's in the MS Hei font */
+ set_bit (BASIC_LATIN);
+ set_bit (HIRAGANA);
+ set_bit (KATAKANA);
+ set_bit (BOPOMOFO);
+ set_bit (CJK_UNIFIED_IDEOGRAPHS);
+ retval = TRUE;
+ }
+ if (check_cp (WANSUNG)
+ || check_cp (JOHAB)) /* ??? */
+ {
+ /* Based on the GulimChe font. I wonder if all Korean fonts
+ * really support this large range of Unicode subranges?
+ */
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_GREEK);
+ set_bit (CYRILLIC);
+ set_bit (HANGUL_JAMO);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (NUMBER_FORMS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (ENCLOSED_ALPHANUMERICS);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ set_bit (CJK_SYMBOLS_AND_PUNCTUATION);
+ set_bit (HIRAGANA);
+ set_bit (KATAKANA);
+ set_bit (HANGUL_COMPATIBILITY_JAMO);
+ set_bit (ENCLOSED_CJK);
+ set_bit (CJK_COMPATIBILITY_FORMS);
+ set_bit (HANGUL);
+ set_bit (CJK_UNIFIED_IDEOGRAPHS);
+ set_bit (CJK_COMPATIBILITY_IDEOGRAPHS);
+ set_bit (HALFWIDTH_AND_FULLWIDTH_FORMS);
+ retval = TRUE;
+ }
+ if (check_cp (CHINESETRAD))
+ {
+ /* Based on the MingLiU font */
+ set_bit (BASIC_LATIN);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (CJK_SYMBOLS_AND_PUNCTUATION);
+ set_bit (BOPOMOFO);
+ set_bit (CJK_UNIFIED_IDEOGRAPHS);
+ set_bit (CJK_COMPATIBILITY_IDEOGRAPHS);
+ set_bit (SMALL_FORM_VARIANTS);
+ set_bit (HALFWIDTH_AND_FULLWIDTH_FORMS);
+ retval = TRUE;
+ }
+ if (check_cp (SYMBOL) || charset == MAC_CHARSET)
+ {
+ /* Non-Unicode encoding, I guess. Pretend it covers
+ * the single-byte range of values.
+ */
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ retval = TRUE;
+ }
+
+ if (retval)
+ return TRUE;
+
+ /* Sigh. Not even any code page bits were set. Guess based on
+ * charset, then. These somewhat optimistic guesses are based on the
+ * table in Appendix M in the book "Developing ..." mentioned
+ * above.
+ */
+ switch (charset)
+ {
+ case ANSI_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (COMBINING_DIACRITICAL_MARKS);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+#if 0 /* I find this too hard to believe... */
+ set_bit (BASIC_GREEK);
+ set_bit (CYRILLIC);
+ set_bit (BASIC_HEBREW);
+ set_bit (HEBREW_EXTENDED);
+ set_bit (BASIC_ARABIC);
+ set_bit (ARABIC_EXTENDED);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (NUMBER_FORMS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (ENCLOSED_ALPHANUMERICS);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ set_bit (HIRAGANA);
+ set_bit (KATAKANA);
+ set_bit (BOPOMOFO);
+ set_bit (HANGUL_COMPATIBILITY_JAMO);
+ set_bit (CJK_MISCELLANEOUS);
+ set_bit (CJK_COMPATIBILITY);
+ set_bit (HANGUL);
+ set_bit (HANGUL_SUPPLEMENTARY_A);
+ set_bit (CJK_COMPATIBILITY_IDEOGRAPHS);
+ set_bit (ALPHABETIC_PRESENTATION_FORMS);
+ set_bit (SMALL_FORM_VARIANTS);
+ set_bit (ARABIC_PRESENTATION_FORMS_B);
+ set_bit (HALFWIDTH_AND_FULLWIDTH_FORMS);
+ set_bit (SPECIALS);
+#endif
+ retval = TRUE;
+ break;
+ case SYMBOL_CHARSET:
+ /* Unggh */
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ retval = TRUE;
+ break;
+ case SHIFTJIS_CHARSET:
+ case HANGEUL_CHARSET:
+ case GB2312_CHARSET:
+ case CHINESEBIG5_CHARSET:
+ case JOHAB_CHARSET:
+ /* The table really does claim these "locales" (it doesn't
+ * talk about charsets per se) cover the same Unicode
+ * subranges
+ */
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS);
+ set_bit (BASIC_GREEK);
+ set_bit (CYRILLIC);
+ set_bit (HANGUL_JAMO);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (NUMBER_FORMS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (ENCLOSED_ALPHANUMERICS);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ set_bit (CJK_SYMBOLS_AND_PUNCTUATION);
+ set_bit (HIRAGANA);
+ set_bit (KATAKANA);
+ set_bit (BOPOMOFO);
+ set_bit (HANGUL_COMPATIBILITY_JAMO);
+ set_bit (CJK_MISCELLANEOUS);
+ set_bit (CJK_COMPATIBILITY);
+ set_bit (HANGUL);
+ set_bit (HANGUL_SUPPLEMENTARY_A);
+ set_bit (CJK_UNIFIED_IDEOGRAPHS);
+ set_bit (CJK_COMPATIBILITY_IDEOGRAPHS);
+ set_bit (ALPHABETIC_PRESENTATION_FORMS);
+ set_bit (SMALL_FORM_VARIANTS);
+ set_bit (ARABIC_PRESENTATION_FORMS_B);
+ set_bit (SPECIALS);
+ retval = TRUE;
+ break;
+ case HEBREW_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_HEBREW);
+ set_bit (HEBREW_EXTENDED);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (LETTERLIKE_SYMBOLS);
+ retval = TRUE;
+ break;
+ case ARABIC_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_GREEK);
+ set_bit (BASIC_ARABIC);
+ set_bit (ARABIC_EXTENDED);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ set_bit (HALFWIDTH_AND_FULLWIDTH_FORMS);
+ retval = TRUE;
+ break;
+ case GREEK_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (BASIC_GREEK);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ retval = TRUE;
+ break;
+ case TURKISH_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_GREEK);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ retval = TRUE;
+ break;
+ case VIETNAMESE_CHARSET:
+ case THAI_CHARSET:
+ /* These are not in the table, so I have no idea */
+ break;
+ case BALTIC_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_GREEK);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ retval = TRUE;
+ break;
+ case EASTEUROPE_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (LATIN_EXTENDED_A);
+ set_bit (LATIN_EXTENDED_B);
+ set_bit (SPACING_MODIFIER_LETTERS);
+ set_bit (BASIC_GREEK);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (SUPERSCRIPTS_AND_SUBSCRIPTS);
+ set_bit (CURRENCY_SYMBOLS);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ retval = TRUE;
+ break;
+ case RUSSIAN_CHARSET:
+ set_bit (BASIC_LATIN);
+ set_bit (LATIN_1_SUPPLEMENT);
+ set_bit (CYRILLIC);
+ set_bit (GENERAL_PUNCTUATION);
+ set_bit (LETTERLIKE_SYMBOLS);
+ set_bit (ARROWS);
+ set_bit (MATHEMATICAL_OPERATORS);
+ set_bit (MISCELLANEOUS_TECHNICAL);
+ set_bit (BOX_DRAWING);
+ set_bit (BLOCK_ELEMENTS);
+ set_bit (GEOMETRIC_SHAPES);
+ set_bit (MISCELLANEOUS_SYMBOLS);
+ retval = TRUE;
+ break;
+ }
+#undef check_cp
+#undef set_bit
+
+ return retval;
+}
+
+static gboolean
+pango_win32_setup_signature (PangoWin32FontMap *win32fontmap,
+ LOGFONT *lfp,
+ FONTSIGNATURE *sigp)
+{
+ LOGFONT logfont;
+ HFONT hfont;
+ HGDIOBJ oldfont;
+ int charset;
+ int i;
+
+ logfont = *lfp;
+ logfont.lfHeight = 40;
+ hfont = pango_win32_font_cache_load (win32fontmap->font_cache,
+ &logfont);
+ if (!hfont)
+ {
+ g_warning ("font \"%s\" (%sweight:%d) not available",
+ (logfont.lfItalic ? "italic," : ""),
+ logfont.lfWeight,
+ logfont.lfFaceName);
+ return FALSE;
+ }
+ oldfont = SelectObject (pango_win32_hdc, hfont);
+ memset (sigp, 0, sizeof (*sigp));
+ charset = GetTextCharsetInfo (pango_win32_hdc, sigp, 0);
+ SelectObject (pango_win32_hdc, oldfont);
+ pango_win32_guess_subranges (charset, sigp);
+ pango_win32_font_cache_unload (win32fontmap->font_cache, hfont);
+}
+
+static void
+pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap,
+ const char *filename)
+{
+ PangoWin32FontEntry *font_entry = NULL;
+ FILE *infile;
+ char **faces;
+ char *buf = NULL;
+ int lineno = 0;
+ int charset;
+ int nfaces;
+ int i;
+
+ 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))
+ {
+ PangoWin32FamilyEntry *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 (PangoWin32FontEntry, 1);
+ 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 (!get_style (tmp_buf, &font_entry->description))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!get_variant (tmp_buf, &font_entry->description))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!get_weight (tmp_buf, &font_entry->description))
+ goto error;
+
+ if (!pango_scan_string (&p, tmp_buf))
+ goto error;
+
+ if (!get_stretch (tmp_buf, &font_entry->description))
+ 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->lfp = g_new0 (LOGFONT, nfaces);
+ font_entry->n_fonts = nfaces;
+ for (i=0; i<nfaces; i++)
+ {
+ strcpy (font_entry->lfp[i].lfFaceName, faces[i]);
+ }
+ g_strfreev (faces);
+
+ /* Insert the font entry into our structures */
+
+ family_entry = pango_win32_get_family_entry (win32fontmap, font_entry->description.family_name);
+ family_entry->font_entries = g_slist_prepend (family_entry->font_entries, font_entry);
+ win32fontmap->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 '%s': %s", filename, g_strerror(errno));
+
+ goto out;
+
+ error:
+ if (font_entry)
+ {
+ if (font_entry->lfp)
+ g_free (font_entry->lfp);
+ 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_win32_font_map_read_aliases (PangoWin32FontMap *win32fontmap)
+{
+ char **files;
+ char *files_str = pango_config_key_get ("PangoWin32/AliasFiles");
+ char *home;
+ char *tmp_str;
+ int n;
+
+ if (!files_str)
+ {
+ home = g_get_home_dir ();
+ if (home && *home)
+ files_str = g_strconcat (home, "\\.pangowin32_aliases;", NULL);
+
+ tmp_str = g_strconcat (files_str, pango_get_sysconf_subdirectory (),
+ "\\pangowin32.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_win32_font_map_read_alias_file (fontmap, files[n]);
+
+ g_strfreev (files);
+ g_free (files_str);
+}
+
+/* This inserts the given font into the SizeInfo table.
+ * If a SizeInfo already exists with the same typeface name, then the
+ * fontname is added to the SizeInfos list of fontnames, else a new SizeInfo
+ * is created and inserted in the table.
+ */
+static void
+pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
+ LOGFONT *lfp)
+{
+ LOGFONT *lfp2;
+ PangoFontDescription description;
+ GSList *tmp_list;
+ PangoWin32FamilyEntry *family_entry;
+ PangoWin32FontEntry *font_entry;
+ PangoWin32SizeInfo *size_info;
+ int i;
+
+ description.size = 0;
+
+ /* First insert the LOGFONT into the list of LOGFONTs for the typeface name
+ */
+ size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
+ if (!size_info)
+ {
+ size_info = g_new (PangoWin32SizeInfo, 1);
+ pango_win32_setup_signature (win32fontmap, lfp, &size_info->signature);
+ size_info->logfonts = NULL;
+
+ g_hash_table_insert (win32fontmap->size_infos, lfp, size_info);
+ }
+
+ lfp2 = g_new (LOGFONT, 1);
+ *lfp2 = *lfp;
+ size_info->logfonts = g_slist_prepend (size_info->logfonts, lfp2);
+
+ /* Convert the LOGFONT into a PangoFontDescription */
+
+ description.family_name = g_strdup (lfp->lfFaceName);
+ g_strdown (description.family_name);
+
+ if (!description.family_name[0])
+ return;
+
+ if (!lfp->lfItalic)
+ description.style = PANGO_STYLE_NORMAL;
+ else
+ description.style = PANGO_STYLE_ITALIC;
+
+ description.variant = PANGO_VARIANT_NORMAL;
+
+ /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_* values.
+ * Is this on purpose?
+ */
+ if (lfp->lfWeight == FW_DONTCARE)
+ description.weight = PANGO_WEIGHT_NORMAL;
+ else
+ description.weight = lfp->lfWeight;
+
+ /* XXX No idea how to figure out the stretch */
+ description.stretch = PANGO_STRETCH_NORMAL;
+
+ family_entry = pango_win32_get_family_entry (win32fontmap, 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)
+ return;
+
+ tmp_list = tmp_list->next;
+ }
+
+ font_entry = g_new (PangoWin32FontEntry, 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->lfp = g_new (LOGFONT, 1);
+ font_entry->n_fonts = 1;
+ *font_entry->lfp = *lfp;
+ g_strdown (font_entry->lfp->lfFaceName);
+ family_entry->font_entries = g_slist_append (family_entry->font_entries, font_entry);
+ 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,
+ PangoWin32UnicodeSubrange subrange)
+{
+ PangoWin32FontMap *win32fontmap;
+ PangoWin32SizeInfo *size_info;
+
+ win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+ size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
+ if (!size_info)
+ return FALSE;
+
+ return size_info->signature.fsUsb[subrange/32] & (1 << subrange % 32);
+}
+
+/* Given a LOGFONT and size, make a matching LOGFONT corresponding to
+ * an installed font.
+ */
+LOGFONT *
+pango_win32_make_matching_logfont (PangoFontMap *fontmap,
+ LOGFONT *lfp,
+ int size)
+{
+ PangoWin32FontMap *win32fontmap;
+ GSList *tmp_list;
+ PangoWin32SizeInfo *size_info;
+ LOGFONT *closest_match = NULL;
+ LOGFONT *result = NULL;
+ gint match_distance = 0;
+
+ win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp);
+
+ if (!size_info)
+ return NULL;
+
+ tmp_list = size_info->logfonts;
+ while (tmp_list)
+ {
+ LOGFONT *tmp_logfont = tmp_list->data;
+ int font_size = tmp_logfont->lfHeight;
+
+ if (size != -1)
+ {
+ int new_distance = (font_size == 0) ? 0 : abs (font_size - size);
+
+ if (!closest_match ||
+ new_distance < match_distance ||
+ (new_distance < PANGO_SCALE && font_size != 0))
+ {
+ closest_match = tmp_logfont;
+ match_distance = new_distance;
+ }
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (closest_match)
+ {
+ /* OK, we have a match; let's modify it to fit this size */
+
+ result = g_new (LOGFONT, 1);
+ result->lfHeight = (int)((double)size / win32fontmap->resolution + 0.5);
+ }
+
+ return result;
+}
+
+static void
+free_coverages_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ pango_coverage_unref (value);
+}
+
+PangoCoverage *
+pango_win32_font_entry_get_coverage (PangoWin32FontEntry *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_win32_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_win32_font_entry_remove (PangoWin32FontEntry *entry,
+ PangoFont *font)
+{
+ entry->cached_fonts = g_slist_remove (entry->cached_fonts, font);
+}
+
+PangoWin32FontCache *
+pango_win32_font_map_get_font_cache (PangoFontMap *font_map)
+{
+ g_return_val_if_fail (font_map != NULL, NULL);
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT_MAP (font_map), NULL);
+
+ return PANGO_WIN32_FONT_MAP (font_map)->font_cache;
+}
+
+void
+pango_win32_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoWin32Font *win32font)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ if (win32fontmap->freed_fonts->length == MAX_FREED_FONTS)
+ {
+ PangoWin32Font *old_font = g_queue_pop_tail (win32fontmap->freed_fonts);
+ g_object_unref (G_OBJECT (old_font));
+ }
+
+ g_object_ref (G_OBJECT (win32font));
+ g_queue_push_head (win32fontmap->freed_fonts, win32font);
+ win32font->in_cache = TRUE;
+}
+
+void
+pango_win32_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoWin32Font *win32font)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ GList *link = g_list_find (win32fontmap->freed_fonts->head, win32font);
+ if (link == win32fontmap->freed_fonts->tail)
+ {
+ win32fontmap->freed_fonts->tail = win32fontmap->freed_fonts->tail->prev;
+ if (win32fontmap->freed_fonts->tail)
+ win32fontmap->freed_fonts->tail->next = NULL;
+ }
+
+ win32fontmap->freed_fonts->head = g_list_delete_link (win32fontmap->freed_fonts->head, link);
+ win32fontmap->freed_fonts->length--;
+ win32font->in_cache = FALSE;
+
+ g_object_unref (G_OBJECT (win32font));
+}
+
+static void
+pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap)
+{
+ g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_list_free (win32fontmap->freed_fonts->head);
+ win32fontmap->freed_fonts->head = NULL;
+ win32fontmap->freed_fonts->tail = NULL;
+ win32fontmap->freed_fonts->length = 0;
+}
+
+static void
+pango_win32_font_entry_dump (int indent,
+ PangoWin32FontEntry *font_entry)
+{
+ int i;
+
+ printf ("%*sPangoWin32FontEntry@%p:\n"
+ "%*s lfp:\n",
+ indent, "", font_entry,
+ indent, "");
+
+ for (i=0; i<font_entry->n_fonts; i++)
+ printf ("%*s LOGFONT:%s\n",
+ indent, "", font_entry->lfp[i].lfFaceName);
+
+ 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_win32_family_entry_dump (int indent,
+ PangoWin32FamilyEntry *entry)
+{
+ GSList *tmp_list = entry->font_entries;
+
+ printf ("%*sPangoWin32FamilyEntry@%p:\n"
+ "%*s family_name: %s\n"
+ "%*s font_entries:\n",
+ indent, "", entry,
+ indent, "", entry->family_name,
+ indent, "");
+
+ while (tmp_list)
+ {
+ PangoWin32FontEntry *font_entry = tmp_list->data;
+
+ pango_win32_font_entry_dump (indent + 2, font_entry);
+ tmp_list = tmp_list->next;
+ }
+}
+
+static void
+dump_family (gpointer key, gpointer value, gpointer user_data)
+{
+ PangoWin32FamilyEntry *entry = value;
+ int indent = (int) user_data;
+
+ pango_win32_family_entry_dump (indent, entry);
+}
+
+void
+pango_win32_fontmap_dump (int indent,
+ PangoFontMap *fontmap)
+{
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
+
+ printf ("%*sPangoWin32FontMap@%p:\n",
+ indent, "", win32fontmap);
+ g_hash_table_foreach (win32fontmap->families, dump_family, (gpointer) (indent + 2));
+}
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
new file mode 100644
index 00000000..9d748798
--- /dev/null
+++ b/pango/pangowin32-private.h
@@ -0,0 +1,91 @@
+/* Pango
+ * pangowin32-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 __PANGOWIN32_PRIVATE_H__
+#define __PANGOWIN32_PRIVATE_H__
+
+#include "pango-modules.h"
+#include "pangowin32.h"
+
+#ifndef FS_VIETNAMESE
+#define FS_VIETNAMESE 0x100
+#endif
+
+#define PANGO_NOTE(x) x
+
+typedef struct _PangoWin32Font PangoWin32Font;
+typedef struct _PangoWin32FontEntry PangoWin32FontEntry;
+typedef struct _PangoWin32SubfontInfo PangoWin32SubfontInfo;
+
+struct _PangoWin32Font
+{
+ PangoFont font;
+
+ LOGFONT *fonts;
+ int n_fonts;
+ int size;
+
+ /* hash table mapping from Unicode subranges to array of PangoWin32Subfont
+ * ids, of length n_fonts
+ */
+ GHashTable *subfonts_by_subrange;
+
+ PangoWin32SubfontInfo **subfonts;
+
+ int n_subfonts;
+ int max_subfonts;
+
+ GSList *metrics_by_lang;
+
+ PangoFontMap *fontmap;
+ /* If TRUE, font is in cache of recently unused fonts and not otherwise
+ * in use.
+ */
+ gboolean in_cache;
+
+ PangoWin32FontEntry *entry; /* Used to remove cached fonts */
+};
+
+PangoWin32Font *pango_win32_font_new (PangoFontMap *fontmap,
+ const LOGFONT *lfp,
+ int n_fonts,
+ int size);
+PangoMap * pango_win32_get_shaper_map (const char *lang);
+gboolean pango_win32_logfont_has_subrange (PangoFontMap *fontmap,
+ LOGFONT *lfp,
+ PangoWin32UnicodeSubrange subrange);
+LOGFONT * pango_win32_make_matching_logfont (PangoFontMap *fontmap,
+ LOGFONT *lfp,
+ int size);
+PangoCoverage * pango_win32_font_entry_get_coverage (PangoWin32FontEntry *entry,
+ PangoFont *font,
+ const char *lang);
+void pango_win32_font_entry_remove (PangoWin32FontEntry *entry,
+ PangoFont *font);
+
+void pango_win32_fontmap_cache_add (PangoFontMap *fontmap,
+ PangoWin32Font *xfont);
+void pango_win32_fontmap_cache_remove (PangoFontMap *fontmap,
+ PangoWin32Font *xfont);
+
+extern HDC pango_win32_hdc;
+
+#endif /* __PANGOWIN32_PRIVATE_H__ */
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
new file mode 100644
index 00000000..38937184
--- /dev/null
+++ b/pango/pangowin32.c
@@ -0,0 +1,1465 @@
+/* Pango
+ * pangowin32.c: Routines for handling Windows 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 <glib.h>
+
+#include <fribidi/fribidi.h>
+
+#include "pangowin32.h"
+#include "pangowin32-private.h"
+
+#define PANGO_TYPE_WIN32_FONT (pango_win32_font_get_type ())
+#define PANGO_WIN32_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT, PangoWin32Font))
+#define PANGO_WIN32_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT, PangoWin32FontClass))
+#define PANGO_WIN32_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT, PangoWin32FontClass))
+
+HDC pango_win32_hdc;
+
+static HBRUSH white_brush;
+
+typedef struct _PangoWin32FontClass PangoWin32FontClass;
+typedef struct _PangoWin32MetricsInfo PangoWin32MetricsInfo;
+
+struct _PangoWin32SubfontInfo
+{
+ LOGFONT logfont;
+ HFONT hfont;
+
+ /* The following fields are used only to check whether a glyph is
+ * present in the subfont. On NT, there is the API GetGlyphIndices
+ * that can be used to do this very simply. But on Win9x,
+ * this isn't available. Bummer. As fas as I can think, the only
+ * way to determine if a glyph is present in a HFONT is to
+ * actually draw the glyph and compare the result to that from
+ * the font's "default character". Well, one other way would be
+ * to parse the font's character map via GetFontData, but that does
+ * also seem a bit complex, and might not work with new font
+ * technologies.
+ */
+ HBITMAP buf_hbm;
+ HDC buf_hdc;
+ RECT buf_rect;
+ int buf_x, buf_y;
+ HBITMAP default_char_hbm;
+ char *buf, *default_char_buf;
+ int buf_size;
+ HFONT oldfont;
+ HBITMAP oldbm;
+};
+
+struct _PangoWin32MetricsInfo
+{
+ const char *lang;
+ PangoFontMetrics metrics;
+};
+
+struct _PangoWin32FontClass
+{
+ PangoFontClass parent_class;
+};
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoWin32Font */
+
+static void pango_win32_font_class_init (PangoWin32FontClass *class);
+static void pango_win32_font_init (PangoWin32Font *win32font);
+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 PangoWin32SubfontInfo *pango_win32_find_subfont (PangoFont *font,
+ PangoWin32Subfont subfont_index);
+
+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,
+ gboolean *fg_set,
+ PangoAttrColor *bg_color,
+ gboolean *bg_set);
+
+static inline PangoWin32SubfontInfo *
+pango_win32_find_subfont (PangoFont *font,
+ PangoWin32Subfont subfont_index)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+
+ if (subfont_index < 1 || subfont_index > win32font->n_subfonts)
+ {
+ g_warning ("Invalid subfont %d", subfont_index);
+ return NULL;
+ }
+
+ return win32font->subfonts[subfont_index-1];
+}
+
+static void
+pango_win32_make_hfont (PangoFont *font,
+ PangoWin32SubfontInfo *info)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ PangoWin32FontCache *cache;
+
+ cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
+
+ info->hfont = pango_win32_font_cache_load (cache, &info->logfont);
+ if (!info->hfont)
+ g_warning ("Cannot load font '%s\n", info->logfont.lfFaceName);
+}
+
+static inline HFONT
+pango_win32_get_hfont (PangoFont *font,
+ PangoWin32SubfontInfo *info)
+{
+ if (!info->hfont)
+ pango_win32_make_hfont (font, info);
+
+ return info->hfont;
+}
+
+/**
+ * pango_win32_get_context:
+ *
+ * Retrieves a #PangoContext appropriate for rendering with Windows fonts.
+ *
+ * Return value: the new #PangoContext
+ **/
+PangoContext *
+pango_win32_get_context (void)
+{
+ PangoContext *result;
+
+ result = pango_context_new ();
+ pango_context_add_font_map (result, pango_win32_font_map_for_display ());
+
+ return result;
+}
+
+static GType
+pango_win32_font_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoWin32FontClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_win32_font_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoWin32Font),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_win32_font_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT,
+ "PangoWin32Font",
+ &object_info);
+ }
+
+ return object_type;
+}
+
+static void
+pango_win32_font_init (PangoWin32Font *win32font)
+{
+ win32font->subfonts_by_subrange = g_hash_table_new (g_direct_hash, g_direct_equal);
+ win32font->subfonts = g_new (PangoWin32SubfontInfo *, 1);
+
+ win32font->n_subfonts = 0;
+ win32font->max_subfonts = 1;
+
+ win32font->metrics_by_lang = NULL;
+
+ win32font->size = -1;
+ win32font->entry = NULL;
+}
+
+static void
+pango_win32_font_class_init (PangoWin32FontClass *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_win32_font_finalize;
+ object_class->shutdown = pango_win32_font_shutdown;
+
+ font_class->describe = pango_win32_font_describe;
+ font_class->get_coverage = pango_win32_font_get_coverage;
+ font_class->find_shaper = pango_win32_font_find_shaper;
+ font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;
+ font_class->get_metrics = pango_win32_font_get_metrics;
+
+ if (pango_win32_hdc == NULL)
+ {
+ pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+ white_brush = GetStockObject (WHITE_BRUSH);
+ }
+}
+
+PangoWin32Font *
+pango_win32_font_new (PangoFontMap *fontmap,
+ const LOGFONT *lfp,
+ int n_fonts,
+ int size)
+{
+ PangoWin32Font *result;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (lfp != NULL, NULL);
+
+ result = (PangoWin32Font *)g_type_create_instance (PANGO_TYPE_WIN32_FONT);
+
+ result->fontmap = fontmap;
+ g_object_ref (G_OBJECT (fontmap));
+
+ result -> n_fonts = n_fonts;
+ result->fonts = g_new (LOGFONT, n_fonts);
+ memcpy (result->fonts, lfp, sizeof (LOGFONT) * n_fonts);
+ result->size = size;
+
+ return result;
+}
+
+/**
+ * pango_win32_load_font:
+ * @lfps: an array of LOGFONTs
+ * @n_fonts: the number of LOGFONTS
+ *
+ * Loads a logical font based on a "fontset" style specification.
+ *
+ * Returns a new #PangoFont
+ */
+PangoFont *
+pango_win32_load_font (LOGFONT *lfp,
+ int n_fonts)
+{
+ PangoWin32Font *result;
+
+ g_return_val_if_fail (lfp != NULL, NULL);
+
+ result = pango_win32_font_new (pango_win32_font_map_for_display (),
+ lfp, n_fonts, -1);
+
+ return (PangoFont *)result;
+}
+
+/**
+ * pango_win32_render:
+ * @hdc: the device context
+ * @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 Windows DC
+ */
+void
+pango_win32_render (HDC hdc,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ /* Slow initial implementation. For speed, it should really
+ * collect the characters into runs, and draw multiple
+ * characters with each TextOutW.
+ */
+ HFONT old_hfont = NULL;
+ HFONT orig_hfont = NULL;
+ HFONT hfont;
+ int i;
+ int x_off = 0;
+
+ g_return_if_fail (glyphs != NULL);
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ if (glyphs->glyphs[i].glyph)
+ {
+ guint16 index = PANGO_WIN32_GLYPH_INDEX (glyphs->glyphs[i].glyph);
+ guint16 subfont_index = PANGO_WIN32_GLYPH_SUBFONT (glyphs->glyphs[i].glyph);
+ PangoWin32SubfontInfo *info;
+
+ info = pango_win32_find_subfont (font, subfont_index);
+ if (info)
+ {
+ hfont = pango_win32_get_hfont (font, info);
+ if (!hfont)
+ continue;
+
+ if (hfont != old_hfont)
+ {
+ if (orig_hfont == NULL)
+ orig_hfont = SelectObject (hdc, hfont);
+ else
+ SelectObject (hdc, hfont);
+ old_hfont = hfont;
+ }
+
+ TextOutW (hdc,
+ x + (x_off + glyphs->glyphs[i].geometry.x_offset) / PANGO_SCALE,
+ y + glyphs->glyphs[i].geometry.y_offset / PANGO_SCALE,
+ &index, 1);
+ }
+ }
+
+ x_off += glyphs->glyphs[i].geometry.width;
+ }
+ if (orig_hfont != NULL)
+ SelectObject (hdc, orig_hfont);
+}
+
+/* This table classifies Unicode characters according to the Microsoft
+ * Unicode subset 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
+ * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
+ * number as in the FONTSIGNATURE struct's fsUsb field.
+ * There are some grave bugs in the table in the books. For instance
+ * it claims there are Hangul at U+3400..U+4DFF while this range in
+ * fact contains CJK Unified Ideographs Extension A. Also, the whole
+ * block of Hangul Syllables U+AC00..U+D7A3 is missing from the book.
+ */
+
+static struct {
+ wchar_t low, high;
+ PangoWin32UnicodeSubrange bit;
+ gchar *name;
+} utab[] =
+{
+ { 0x0000, 0x007E,
+ PANGO_WIN32_U_BASIC_LATIN, "Basic Latin" },
+ { 0x00A0, 0x00FF,
+ PANGO_WIN32_U_LATIN_1_SUPPLEMENT, "Latin-1 Supplement" },
+ { 0x0100, 0x017F,
+ PANGO_WIN32_U_LATIN_EXTENDED_A, "Latin Extended-A" },
+ { 0x0180, 0x024F,
+ PANGO_WIN32_U_LATIN_EXTENDED_B, "Latin Extended-B" },
+ { 0x0250, 0x02AF,
+ PANGO_WIN32_U_IPA_EXTENSIONS, "IPA Extensions" },
+ { 0x02B0, 0x02FF,
+ PANGO_WIN32_U_SPACING_MODIFIER_LETTERS, "Spacing Modifier Letters" },
+ { 0x0300, 0x036F,
+ PANGO_WIN32_U_COMBINING_DIACRITICAL_MARKS, "Combining Diacritical Marks" },
+ { 0x0370, 0x03CF,
+ PANGO_WIN32_U_BASIC_GREEK, "Basic Greek" },
+ { 0x03D0, 0x03FF,
+ PANGO_WIN32_U_GREEK_SYMBOLS_AND_COPTIC, "Greek Symbols and Coptic" },
+ { 0x0400, 0x04FF,
+ PANGO_WIN32_U_CYRILLIC, "Cyrillic" },
+ { 0x0530, 0x058F,
+ PANGO_WIN32_U_ARMENIAN, "Armenian" },
+ { 0x0590, 0x05CF,
+ PANGO_WIN32_U_HEBREW_EXTENDED, "Hebrew Extended" },
+ { 0x05D0, 0x05FF,
+ PANGO_WIN32_U_BASIC_HEBREW, "Basic Hebrew" },
+ { 0x0600, 0x0652,
+ PANGO_WIN32_U_BASIC_ARABIC, "Basic Arabic" },
+ { 0x0653, 0x06FF,
+ PANGO_WIN32_U_ARABIC_EXTENDED, "Arabic Extended" },
+ { 0x0900, 0x097F,
+ PANGO_WIN32_U_DEVANAGARI, "Devanagari" },
+ { 0x0980, 0x09FF,
+ PANGO_WIN32_U_BENGALI, "Bengali" },
+ { 0x0A00, 0x0A7F,
+ PANGO_WIN32_U_GURMUKHI, "Gurmukhi" },
+ { 0x0A80, 0x0AFF,
+ PANGO_WIN32_U_GUJARATI, "Gujarati" },
+ { 0x0B00, 0x0B7F,
+ PANGO_WIN32_U_ORIYA, "Oriya" },
+ { 0x0B80, 0x0BFF,
+ PANGO_WIN32_U_TAMIL, "Tamil" },
+ { 0x0C00, 0x0C7F,
+ PANGO_WIN32_U_TELUGU, "Telugu" },
+ { 0x0C80, 0x0CFF,
+ PANGO_WIN32_U_KANNADA, "Kannada" },
+ { 0x0D00, 0x0D7F,
+ PANGO_WIN32_U_MALAYALAM, "Malayalam" },
+ { 0x0E00, 0x0E7F,
+ PANGO_WIN32_U_THAI, "Thai" },
+ { 0x0E80, 0x0EFF,
+ PANGO_WIN32_U_LAO, "Lao" },
+ { 0x10A0, 0x10CF,
+ PANGO_WIN32_U_GEORGIAN_EXTENDED, "Georgian Extended" },
+ { 0x10D0, 0x10FF,
+ PANGO_WIN32_U_BASIC_GEORGIAN, "Basic Georgian" },
+ { 0x1100, 0x11FF,
+ PANGO_WIN32_U_HANGUL_JAMO, "Hangul Jamo" },
+ { 0x1E00, 0x1EFF,
+ PANGO_WIN32_U_LATIN_EXTENDED_ADDITIONAL, "Latin Extended Additional" },
+ { 0x1F00, 0x1FFF,
+ PANGO_WIN32_U_GREEK_EXTENDED, "Greek Extended" },
+ { 0x2000, 0x206F,
+ PANGO_WIN32_U_GENERAL_PUNCTUATION, "General Punctuation" },
+ { 0x2070, 0x209F,
+ PANGO_WIN32_U_SUPERSCRIPTS_AND_SUBSCRIPTS, "Superscripts and Subscripts" },
+ { 0x20A0, 0x20CF,
+ PANGO_WIN32_U_CURRENCY_SYMBOLS, "Currency Symbols" },
+ { 0x20D0, 0x20FF,
+ PANGO_WIN32_U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, "Combining Diacritical Marks for Symbols" },
+ { 0x2100, 0x214F,
+ PANGO_WIN32_U_LETTERLIKE_SYMBOLS, "Letterlike Symbols" },
+ { 0x2150, 0x218F,
+ PANGO_WIN32_U_NUMBER_FORMS, "Number Forms" },
+ { 0x2190, 0x21FF,
+ PANGO_WIN32_U_ARROWS, "Arrows" },
+ { 0x2200, 0x22FF,
+ PANGO_WIN32_U_MATHEMATICAL_OPERATORS, "Mathematical Operators" },
+ { 0x2300, 0x23FF,
+ PANGO_WIN32_U_MISCELLANEOUS_TECHNICAL, "Miscellaneous Technical" },
+ { 0x2400, 0x243F,
+ PANGO_WIN32_U_CONTROL_PICTURES, "Control Pictures" },
+ { 0x2440, 0x245F,
+ PANGO_WIN32_U_OPTICAL_CHARACTER_RECOGNITION, "Optical Character Recognition" },
+ { 0x2460, 0x24FF,
+ PANGO_WIN32_U_ENCLOSED_ALPHANUMERICS, "Enclosed Alphanumerics" },
+ { 0x2500, 0x257F,
+ PANGO_WIN32_U_BOX_DRAWING, "Box Drawing" },
+ { 0x2580, 0x259F,
+ PANGO_WIN32_U_BLOCK_ELEMENTS, "Block Elements" },
+ { 0x25A0, 0x25FF,
+ PANGO_WIN32_U_GEOMETRIC_SHAPES, "Geometric Shapes" },
+ { 0x2600, 0x26FF,
+ PANGO_WIN32_U_MISCELLANEOUS_SYMBOLS, "Miscellaneous Symbols" },
+ { 0x2700, 0x27BF,
+ PANGO_WIN32_U_DINGBATS, "Dingbats" },
+ { 0x3000, 0x303F,
+ PANGO_WIN32_U_CJK_SYMBOLS_AND_PUNCTUATION, "CJK Symbols and Punctuation" },
+ { 0x3040, 0x309F,
+ PANGO_WIN32_U_HIRAGANA, "Hiragana" },
+ { 0x30A0, 0x30FF,
+ PANGO_WIN32_U_KATAKANA, "Katakana" },
+ { 0x3100, 0x312F,
+ PANGO_WIN32_U_BOPOMOFO, "Bopomofo" },
+ { 0x3130, 0x318F,
+ PANGO_WIN32_U_HANGUL_COMPATIBILITY_JAMO, "Hangul Compatibility Jamo" },
+ { 0x3190, 0x319F,
+ PANGO_WIN32_U_CJK_MISCELLANEOUS, "CJK Miscellaneous" },
+ { 0x3200, 0x32FF,
+ PANGO_WIN32_U_ENCLOSED_CJK, "Enclosed CJK" },
+ { 0x3300, 0x33FF,
+ PANGO_WIN32_U_CJK_COMPATIBILITY, "CJK Compatibility" },
+ /* The book claims:
+ * U+3400..U+3D2D Hangul
+ * U+3D2E..U+44B7 Hangul Supplementary A
+ * U+44B8..U+4DFF Hangul Supplementary B
+ * but actually in Unicode
+ * U+3400..U+4DB5 is CJK Unified Ideographs Extension A
+ */
+ { 0x3400, 0x4DB5,
+ PANGO_WIN32_U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs Extension A" },
+ { 0x4E00, 0x9FFF,
+ PANGO_WIN32_U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs" },
+ /* This was missing completely from the book's table. */
+ { 0xAC00, 0xD7A3,
+ PANGO_WIN32_U_HANGUL, "Hangul Syllables" },
+ { 0xE000, 0xF8FF,
+ PANGO_WIN32_U_PRIVATE_USE_AREA, "Private Use Area" },
+ { 0xF900, 0xFAFF,
+ PANGO_WIN32_U_CJK_COMPATIBILITY_IDEOGRAPHS, "CJK Compatibility Ideographs" },
+ { 0xFB00, 0xFB4F,
+ PANGO_WIN32_U_ALPHABETIC_PRESENTATION_FORMS, "Alphabetic Presentation Forms" },
+ { 0xFB50, 0xFDFF,
+ PANGO_WIN32_U_ARABIC_PRESENTATION_FORMS_A, "Arabic Presentation Forms-A" },
+ { 0xFE20, 0xFE2F,
+ PANGO_WIN32_U_COMBINING_HALF_MARKS, "Combining Half Marks" },
+ { 0xFE30, 0xFE4F,
+ PANGO_WIN32_U_CJK_COMPATIBILITY_FORMS, "CJK Compatibility Forms" },
+ { 0xFE50, 0xFE6F,
+ PANGO_WIN32_U_SMALL_FORM_VARIANTS, "Small Form Variants" },
+ { 0xFE70, 0xFEFE,
+ PANGO_WIN32_U_ARABIC_PRESENTATION_FORMS_B, "Arabic Presentation Forms-B" },
+ { 0xFEFF, 0xFEFF,
+ PANGO_WIN32_U_SPECIALS, "Specials" },
+ { 0xFF00, 0xFFEF,
+ PANGO_WIN32_U_HALFWIDTH_AND_FULLWIDTH_FORMS, "Halfwidth and Fullwidth Forms" },
+ { 0xFFF0, 0xFFFD,
+ PANGO_WIN32_U_SPECIALS, "Specials" }
+};
+
+/* Return the Unicode subrange number for a Unicode character */
+PangoWin32UnicodeSubrange
+pango_win32_unicode_classify (wchar_t wc)
+{
+ int min = 0;
+ int max = sizeof (utab) / sizeof (utab[0]) - 1;
+ int mid;
+
+ while (max >= min)
+ {
+ mid = (min + max) / 2;
+ if (utab[mid].high < wc)
+ min = mid + 1;
+ else if (wc < utab[mid].low)
+ max = mid - 1;
+ else if (utab[mid].low <= wc && wc <= utab[mid].high)
+ return utab[mid].bit;
+ else
+ return -1;
+ }
+}
+
+static void
+pango_win32_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoWin32SubfontInfo *info;
+ SIZE size;
+
+ if (glyph && pango_win32_find_glyph (font, glyph, &info, &size))
+ {
+ /* This is totally bogus */
+ if (ink_rect)
+ {
+ ink_rect->x = PANGO_SCALE * size.cx;
+ ink_rect->width = ink_rect->x;
+ ink_rect->y = PANGO_SCALE * 0;
+ ink_rect->height = PANGO_SCALE * size.cy;
+ }
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->width = PANGO_SCALE * size.cx;
+ logical_rect->y = 0;
+ logical_rect->height = PANGO_SCALE * size.cy;
+ }
+ }
+ 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;
+ }
+ }
+}
+
+/* Get composite font metrics for all subfonts in list
+ */
+static void
+get_font_metrics_from_subfonts (PangoFont *font,
+ GSList *subfonts,
+ PangoFontMetrics *metrics)
+{
+ HFONT hfont;
+ HGDIOBJ oldfont;
+ TEXTMETRIC tm;
+ GSList *tmp_list = subfonts;
+ gboolean first = TRUE;
+
+ metrics->ascent = 0;
+ metrics->descent = 0;
+
+ while (tmp_list)
+ {
+ PangoWin32SubfontInfo *info = pango_win32_find_subfont (font, GPOINTER_TO_UINT (tmp_list->data));
+
+ if (info)
+ {
+ hfont = pango_win32_get_hfont (font, info);
+ if (hfont != NULL)
+ {
+ oldfont = SelectObject (pango_win32_hdc, hfont);
+ GetTextMetrics (pango_win32_hdc, &tm);
+ SelectObject (pango_win32_hdc, oldfont);
+ if (first)
+ {
+ metrics->ascent = tm.tmAscent * PANGO_SCALE;
+ metrics->descent = tm.tmDescent * PANGO_SCALE;
+ first = FALSE;
+ }
+ else
+ {
+ metrics->ascent = MAX (tm.tmAscent * PANGO_SCALE, metrics->ascent);
+ metrics->descent = MAX (tm.tmDescent * PANGO_SCALE, metrics->descent);
+ }
+ }
+ }
+ else
+ g_warning ("Invalid subfont %d in get_font_metrics_from_subfonts", GPOINTER_TO_UINT (tmp_list->data));
+
+ 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++)
+ {
+ PangoWin32Subfont subfont = PANGO_WIN32_GLYPH_SUBFONT (glyph_str->glyphs[j].glyph);
+ if (!g_slist_find (subfonts, GUINT_TO_POINTER ((guint)subfont)))
+ subfonts = g_slist_prepend (subfonts, GUINT_TO_POINTER ((guint)subfont));
+ }
+
+ 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 السلام عليكم" },
+ { "cs", "Czech (česky) Dobrý den" },
+ { "da", "Danish (Dansk) Hej, Goddag" },
+ { "el", "Greek (Ελληνικά) Γειά σας" },
+ { "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 (日本語) こんにちは, コンニチハ" },
+ { "ko", "Korean (한글) 안녕하세요, 안녕하십니까" },
+ { "mt", "Maltese Ċaw, Saħħa" },
+ { "nl", "Nederlands, Vlaams Hallo, Dag" },
+ { "no", "Norwegian (Norsk) Hei, God dag" },
+ { "pl", "Polish Dzień dobry, Hej" },
+ { "ru", "Russian (Русский)" },
+ { "sk", "Slovak Dobrý deň" },
+ { "sv", "Swedish (Svenska) Hej på dej" },
+ { "tr", "Turkish (Türkçe) Merhaba" },
+ { "zh", "Chinese (中文,普通话,汉语)" }
+};
+
+static void
+pango_win32_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics)
+{
+ PangoWin32MetricsInfo *info;
+ PangoWin32Font *win32font = (PangoWin32Font *)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 = "السلام عليكم česky Ελληνικά Français 日本語 한글 Русский 中文,普通话,汉语 Türkçe";
+ }
+
+ tmp_list = win32font->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 (PangoWin32MetricsInfo, 1);
+ info->lang = lookup_lang;
+
+ win32font->metrics_by_lang = g_slist_prepend (win32font->metrics_by_lang, info);
+
+ get_font_metrics_from_string (font, lang, str, &info->metrics);
+ }
+
+ *metrics = info->metrics;
+ return;
+}
+
+static PangoWin32Subfont
+pango_win32_insert_subfont (PangoFont *font,
+ const LOGFONT *lfp)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ PangoWin32SubfontInfo *info;
+
+ info = g_new (PangoWin32SubfontInfo, 1);
+
+ info->logfont = *lfp;
+ info->hfont = NULL;
+ info->buf_hbm = NULL;
+
+ win32font->n_subfonts++;
+
+ if (win32font->n_subfonts > win32font->max_subfonts)
+ {
+ win32font->max_subfonts *= 2;
+ win32font->subfonts = g_renew (PangoWin32SubfontInfo *, win32font->subfonts, win32font->max_subfonts);
+ }
+
+ win32font->subfonts[win32font->n_subfonts - 1] = info;
+
+ return win32font->n_subfonts;
+}
+
+/**
+ * pango_win32_list_subfonts:
+ * @font: a PangoFont
+ * @subrange: the Unicode subrange to list subfonts for
+ * @subfont_ids: location to store a pointer to an array of subfont IDs for each found subfont
+ * the result must be freed using g_free()
+ *
+ * Returns number of subfonts found
+ **/
+int
+pango_win32_list_subfonts (PangoFont *font,
+ PangoWin32UnicodeSubrange subrange,
+ PangoWin32Subfont **subfont_ids)
+{
+ LOGFONT *lfp;
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ PangoWin32Subfont *subfont_list;
+ PangoFontMap *fontmap;
+ int i, j;
+ int n_subfonts = 0;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ fontmap = pango_win32_font_map_for_display ();
+
+ subfont_list = g_hash_table_lookup (win32font->subfonts_by_subrange, (gpointer) subrange);
+ if (!subfont_list)
+ {
+ subfont_list = g_new (PangoWin32Subfont, win32font->n_fonts);
+
+ for (i = 0; i < win32font->n_fonts; i++)
+ {
+ /* Does this font cover the subrange? */
+ PangoWin32Subfont subfont = 0;
+
+ if (pango_win32_logfont_has_subrange (fontmap, win32font->fonts+i, subrange))
+ {
+ lfp = pango_win32_make_matching_logfont (fontmap, win32font->fonts+i, win32font->size);
+ if (lfp)
+ {
+ subfont = pango_win32_insert_subfont (font, lfp);
+ g_free (lfp);
+ }
+ }
+
+ subfont_list[i] = subfont;
+ }
+
+ g_hash_table_insert (win32font->subfonts_by_subrange, (gpointer) subrange, subfont_list);
+ }
+
+ for (i = 0; i < win32font->n_fonts; i++)
+ if (subfont_list[i])
+ n_subfonts++;
+
+ *subfont_ids = g_new (PangoWin32Subfont, n_subfonts);
+
+ n_subfonts = 0;
+
+ for (i=0; i<win32font->n_fonts; i++)
+ if (subfont_list[i])
+ {
+ (*subfont_ids)[n_subfonts] = subfont_list[i];
+ n_subfonts++;
+ }
+
+ g_free (subfont_list);
+
+ return n_subfonts;
+}
+
+gboolean
+subfont_has_glyph (PangoWin32SubfontInfo *info,
+ wchar_t c)
+
+{
+ struct {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[2];
+ } bmi;
+ DIBSECTION ds;
+ TEXTMETRIC tm;
+ HFONT hfont;
+
+ if (info->buf_hbm == NULL)
+ {
+ info->buf_hdc = CreateCompatibleDC (pango_win32_hdc);
+ GetTextMetrics (pango_win32_hdc, &tm);
+
+ bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = tm.tmMaxCharWidth;
+ bmi.bmiHeader.biHeight = -tm.tmHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+ bmi.bmiHeader.biXPelsPerMeter =
+ bmi.bmiHeader.biYPelsPerMeter = 0;
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+
+ bmi.bmiColors[0].rgbBlue =
+ bmi.bmiColors[0].rgbGreen =
+ bmi.bmiColors[0].rgbRed = 0x00;
+ bmi.bmiColors[0].rgbReserved = 0x00;
+
+ bmi.bmiColors[1].rgbBlue =
+ bmi.bmiColors[1].rgbGreen =
+ bmi.bmiColors[1].rgbRed = 0xFF;
+ bmi.bmiColors[1].rgbReserved = 0x00;
+
+ info->default_char_hbm =
+ CreateDIBSection (info->buf_hdc, (BITMAPINFO *)&bmi,
+ DIB_RGB_COLORS, (PVOID *)&info->default_char_buf, NULL, 0);
+ GetObject (info->default_char_hbm, sizeof (ds), &ds);
+ info->buf_size = ds.dsBmih.biSizeImage;
+
+ info->oldbm = SelectObject (info->buf_hdc, info->default_char_hbm);
+ info->buf_rect.left = 0;
+ info->buf_rect.top = 0;
+ info->buf_rect.right = tm.tmMaxCharWidth;
+ info->buf_rect.bottom = tm.tmHeight;
+ info->buf_x = 0;
+ info->buf_y = tm.tmHeight - tm.tmDescent;
+ FillRect (info->buf_hdc, &info->buf_rect, white_brush);
+
+ info->oldfont = SelectObject (info->buf_hdc, hfont);
+ c = tm.tmDefaultChar;
+ TextOutW (info->buf_hdc, info->buf_x, info->buf_y, &c, 1);
+
+ info->buf_hbm =
+ CreateDIBSection (info->buf_hdc, (BITMAPINFO *)&bmi,
+ DIB_RGB_COLORS, (PVOID *)&info->buf, NULL, 0);
+
+ SelectObject (info->buf_hdc, info->buf_hbm);
+ }
+
+ /* Draw character into our bitmap; compare with the bitmap for
+ * the default character. If they are identical, this character
+ * does not exist in the font.
+ */
+ FillRect (info->buf_hdc, &info->buf_rect, white_brush);
+ TextOutW (info->buf_hdc, info->buf_x, info->buf_y,
+ &c, 1);
+ return (memcmp (info->buf, info->default_char_buf, info->buf_size) != 0);
+ }
+
+/**
+ * pango_win32_has_glyph:
+ * @font: a #PangoFont which must be from the Win32 backend.
+ * @glyph: the index of a glyph in the font. (Formed
+ * using the PANGO_WIN32_MAKE_GLYPH macro)
+ *
+ * Check if the given glyph is present in a Win32 font.
+ *
+ * Return value: %TRUE if the glyph is present.
+ **/
+gboolean
+pango_win32_has_glyph (PangoFont *font,
+ PangoGlyph glyph)
+{
+ HFONT hfont;
+ PangoWin32SubfontInfo *info;
+ guint16 char_index = PANGO_WIN32_GLYPH_INDEX (glyph);
+ guint16 subfont_index = PANGO_WIN32_GLYPH_SUBFONT (glyph);
+ wchar_t c;
+
+ info = pango_win32_find_subfont (font, subfont_index);
+ if (!info)
+ return FALSE;
+
+ hfont = pango_win32_get_hfont (font, info);
+ if (hfont == NULL)
+ return FALSE;
+
+ return subfont_has_glyph (info, char_index);
+}
+
+/**
+ * pango_win32_font_subfont_logfont:
+ * @font: a #PangoFont which must be from the Win32 backend
+ * @subfont_id: the id of a subfont within the font.
+ *
+ * Determine the LOGFONT struct for the specified subfont.
+ *
+ * Return value: A newly allocated LOGFONT struct. It must be
+ * freed with g_free().
+ **/
+LOGFONT *
+pango_win32_font_subfont_logfont (PangoFont *font,
+ PangoWin32Subfont subfont_id)
+{
+ PangoWin32SubfontInfo *info;
+ LOGFONT *lfp;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), NULL);
+
+ info = pango_win32_find_subfont (font, subfont_id);
+ if (!info)
+ {
+ g_warning ("pango_win32_font_subfont_logfont: Invalid subfont_id specified");
+ return NULL;
+ }
+
+ lfp = g_new (LOGFONT, 1);
+ *lfp = info->logfont;
+
+ return lfp;
+}
+
+static void
+pango_win32_font_shutdown (GObject *object)
+{
+ PangoWin32Font *win32font = PANGO_WIN32_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 (!win32font->in_cache && win32font->fontmap)
+ pango_win32_fontmap_cache_add (win32font->fontmap, win32font);
+
+ G_OBJECT_CLASS (parent_class)->shutdown (object);
+}
+
+static void
+subfonts_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ g_free (value);
+}
+
+static void
+pango_win32_font_finalize (GObject *object)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)object;
+ PangoWin32FontCache *cache = pango_win32_font_map_get_font_cache (win32font->fontmap);
+ int i;
+
+ for (i=0; i<win32font->n_subfonts; i++)
+ {
+ PangoWin32SubfontInfo *info = win32font->subfonts[i];
+
+ if (info->hfont != NULL)
+ pango_win32_font_cache_unload (cache, info->hfont);
+
+ if (info->buf_hbm != NULL)
+ {
+ SelectObject (info->buf_hdc, info->oldfont);
+ SelectObject (info->buf_hdc, info->oldbm);
+ DeleteObject (info->buf_hbm);
+ DeleteObject (info->default_char_hbm);
+ DeleteDC (info->buf_hdc);
+ }
+ g_free (info);
+ }
+
+ g_free (win32font->subfonts);
+
+ g_hash_table_foreach (win32font->subfonts_by_subrange, subfonts_foreach, NULL);
+ g_hash_table_destroy (win32font->subfonts_by_subrange);
+
+ g_slist_foreach (win32font->metrics_by_lang, (GFunc)g_free, NULL);
+ g_slist_free (win32font->metrics_by_lang);
+
+ if (win32font->entry)
+ pango_win32_font_entry_remove (win32font->entry, (PangoFont *)win32font);
+
+ g_object_unref (G_OBJECT (win32font->fontmap));
+
+ g_free (win32font->fonts);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_win32_font_describe (PangoFont *font)
+{
+ /* FIXME: implement */
+ return NULL;
+}
+
+PangoMap *
+pango_win32_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_WIN32);
+ }
+
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static PangoCoverage *
+pango_win32_font_get_coverage (PangoFont *font,
+ const char *lang)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+
+ return pango_win32_font_entry_get_coverage (win32font->entry, font, lang);
+}
+
+static PangoEngineShape *
+pango_win32_font_find_shaper (PangoFont *font,
+ const gchar *lang,
+ guint32 ch)
+{
+ PangoMap *shape_map = NULL;
+
+ shape_map = pango_win32_get_shaper_map (lang);
+ return (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
+}
+
+/* Utility functions */
+
+static gboolean
+pango_win32_find_glyph (PangoFont *font,
+ PangoGlyph glyph,
+ PangoWin32SubfontInfo **subfont_return,
+ SIZE *size_return)
+{
+ SIZE size;
+ HFONT hfont, oldfont;
+ PangoWin32SubfontInfo *info;
+ guint16 char_index = PANGO_WIN32_GLYPH_INDEX (glyph);
+ guint16 subfont_index = PANGO_WIN32_GLYPH_SUBFONT (glyph);
+
+ info = pango_win32_find_subfont (font, subfont_index);
+ if (!info)
+ return FALSE;
+
+ if (!subfont_has_glyph (info, char_index))
+ return FALSE;
+
+ oldfont = SelectObject (pango_win32_hdc, hfont);
+ GetTextExtentPoint32W (pango_win32_hdc, &char_index, 1, &size);
+ SelectObject (pango_win32_hdc, oldfont);
+
+ if (subfont_return)
+ *subfont_return = info;
+
+ if (size_return)
+ *size_return = size;
+
+ return TRUE;
+}
+
+/**
+ * pango_win32_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_win32_get_unknown_glyph (PangoFont *font)
+{
+ return PANGO_WIN32_MAKE_GLYPH (0, 0); /* XXX */
+}
+
+/**
+ * pango_win32_render_layout_line:
+ * @hdc: HDC to use for uncolored drawing
+ * @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 device context
+ */
+void
+pango_win32_render_layout_line (HDC hdc,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ GSList *tmp_list = line->runs;
+ PangoRectangle overall_rect;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ PangoContext *context = pango_layout_get_context (line->layout);
+
+ int x_off = 0;
+
+ pango_layout_line_get_extents (line,NULL, &overall_rect);
+
+ while (tmp_list)
+ {
+ HBRUSH oldfg;
+ HBRUSH brush;
+ POINT points[2];
+ 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_win32_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);
+
+ if (bg_set)
+ {
+ HBRUSH oldbrush;
+
+ brush = CreateSolidBrush (RGB ((bg_color.red + 128) >> 8,
+ (bg_color.green + 128) >> 8,
+ (bg_color.blue + 128) >> 8));
+ oldbrush = SelectObject (hdc, brush);
+ Rectangle (hdc, x + (x_off + logical_rect.x) / PANGO_SCALE,
+ y + overall_rect.y / PANGO_SCALE,
+ logical_rect.width / PANGO_SCALE,
+ overall_rect.height / PANGO_SCALE);
+ SelectObject (hdc, oldbrush);
+ DeleteObject (brush);
+ }
+
+ if (fg_set)
+ {
+ brush = CreateSolidBrush (RGB ((fg_color.red + 128) >> 8,
+ (fg_color.green + 128) >> 8,
+ (fg_color.blue + 128) >> 8));
+ oldfg = SelectObject (hdc, brush);
+ }
+
+ pango_win32_render (hdc, run->item->analysis.font, run->glyphs,
+ x + x_off / PANGO_SCALE, y);
+
+ switch (uline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ points[0].x = x + (x_off + ink_rect.x) / PANGO_SCALE - 1;
+ points[0].y = points[1].y = y + 4;
+ points[1].x = x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE;
+ Polyline (hdc, points, 2);
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ points[0].y = points[1].y = y + 2;
+ Polyline (hdc, points, 2);
+ break;
+ case PANGO_UNDERLINE_LOW:
+ points[0].x = x + (x_off + ink_rect.x) / PANGO_SCALE - 1;
+ points[0].y = points[1].y = y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2;
+ points[1].x = x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE;
+ Polyline (hdc, points, 2);
+ break;
+ }
+
+ if (fg_set)
+ {
+ SelectObject (hdc, oldfg);
+ DeleteObject (brush);
+ }
+
+ x_off += logical_rect.width;
+ }
+}
+
+/**
+ * pango_win32_render_layout:
+ * @hdc: HDC to use for uncolored drawing
+ * @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 an X drawable
+ */
+void
+pango_win32_render_layout (HDC hdc,
+ 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 (layout != NULL);
+
+ indent = pango_layout_get_indent (layout);
+ width = pango_layout_get_width (layout);
+ align = pango_layout_get_alignment (layout);
+
+ 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;
+ }
+ }
+
+ pango_win32_render_layout_line (hdc, line,
+ x + x_offset / PANGO_SCALE,
+ y + (y_offset - logical_rect.y) / PANGO_SCALE);
+
+ 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_win32_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;
+ }
+}
+
diff --git a/pango/pangowin32.h b/pango/pangowin32.h
new file mode 100644
index 00000000..7d040f5b
--- /dev/null
+++ b/pango/pangowin32.h
@@ -0,0 +1,187 @@
+/* Pango
+ * pangowin32.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 __PANGOWIN32_H__
+#define __PANGOWIN32_H__
+
+#include <glib.h>
+#include <pango/pango.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define STRICT
+#include <windows.h>
+
+#define PANGO_RENDER_TYPE_WIN32 "PangoRenderWin32"
+
+/* This enum divides 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
+ * Blocks.txt from ftp.unicode.org.
+ */
+typedef enum
+{
+ PANGO_WIN32_U_BASIC_LATIN = 0,
+ PANGO_WIN32_U_LATIN_1_SUPPLEMENT = 1,
+ PANGO_WIN32_U_LATIN_EXTENDED_A = 2,
+ PANGO_WIN32_U_LATIN_EXTENDED_B = 3,
+ PANGO_WIN32_U_IPA_EXTENSIONS = 4,
+ PANGO_WIN32_U_SPACING_MODIFIER_LETTERS = 5,
+ PANGO_WIN32_U_COMBINING_DIACRITICAL_MARKS = 6,
+ PANGO_WIN32_U_BASIC_GREEK = 7,
+ PANGO_WIN32_U_GREEK_SYMBOLS_AND_COPTIC = 8,
+ PANGO_WIN32_U_CYRILLIC = 9,
+ PANGO_WIN32_U_ARMENIAN = 10,
+ PANGO_WIN32_U_HEBREW_EXTENDED = 12,
+ PANGO_WIN32_U_BASIC_HEBREW = 11,
+ PANGO_WIN32_U_BASIC_ARABIC = 13,
+ PANGO_WIN32_U_ARABIC_EXTENDED = 14,
+ PANGO_WIN32_U_DEVANAGARI = 15,
+ PANGO_WIN32_U_BENGALI = 16,
+ PANGO_WIN32_U_GURMUKHI = 17,
+ PANGO_WIN32_U_GUJARATI = 18,
+ PANGO_WIN32_U_ORIYA = 19,
+ PANGO_WIN32_U_TAMIL = 20,
+ PANGO_WIN32_U_TELUGU = 21,
+ PANGO_WIN32_U_KANNADA = 22,
+ PANGO_WIN32_U_MALAYALAM = 23,
+ PANGO_WIN32_U_THAI = 24,
+ PANGO_WIN32_U_LAO = 25,
+ PANGO_WIN32_U_GEORGIAN_EXTENDED = 27,
+ PANGO_WIN32_U_BASIC_GEORGIAN = 26,
+ PANGO_WIN32_U_HANGUL_JAMO = 28,
+ PANGO_WIN32_U_LATIN_EXTENDED_ADDITIONAL = 29,
+ PANGO_WIN32_U_GREEK_EXTENDED = 30,
+ PANGO_WIN32_U_GENERAL_PUNCTUATION = 31,
+ PANGO_WIN32_U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
+ PANGO_WIN32_U_CURRENCY_SYMBOLS = 33,
+ PANGO_WIN32_U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
+ PANGO_WIN32_U_LETTERLIKE_SYMBOLS = 35,
+ PANGO_WIN32_U_NUMBER_FORMS = 36,
+ PANGO_WIN32_U_ARROWS = 37,
+ PANGO_WIN32_U_MATHEMATICAL_OPERATORS = 38,
+ PANGO_WIN32_U_MISCELLANEOUS_TECHNICAL = 39,
+ PANGO_WIN32_U_CONTROL_PICTURES = 40,
+ PANGO_WIN32_U_OPTICAL_CHARACTER_RECOGNITION = 41,
+ PANGO_WIN32_U_ENCLOSED_ALPHANUMERICS = 42,
+ PANGO_WIN32_U_BOX_DRAWING = 43,
+ PANGO_WIN32_U_BLOCK_ELEMENTS = 44,
+ PANGO_WIN32_U_GEOMETRIC_SHAPES = 45,
+ PANGO_WIN32_U_MISCELLANEOUS_SYMBOLS = 46,
+ PANGO_WIN32_U_DINGBATS = 47,
+ PANGO_WIN32_U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
+ PANGO_WIN32_U_HIRAGANA = 49,
+ PANGO_WIN32_U_KATAKANA = 50,
+ PANGO_WIN32_U_BOPOMOFO = 51,
+ PANGO_WIN32_U_HANGUL_COMPATIBILITY_JAMO = 52,
+ PANGO_WIN32_U_CJK_MISCELLANEOUS = 53,
+ PANGO_WIN32_U_ENCLOSED_CJK = 54,
+ PANGO_WIN32_U_CJK_COMPATIBILITY = 55,
+ PANGO_WIN32_U_HANGUL = 56,
+ PANGO_WIN32_U_HANGUL_SUPPLEMENTARY_A = 57,
+ PANGO_WIN32_U_HANGUL_SUPPLEMENTARY_B = 58,
+ PANGO_WIN32_U_CJK_UNIFIED_IDEOGRAPHS = 59,
+ PANGO_WIN32_U_PRIVATE_USE_AREA = 60,
+ PANGO_WIN32_U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
+ PANGO_WIN32_U_ALPHABETIC_PRESENTATION_FORMS = 62,
+ PANGO_WIN32_U_ARABIC_PRESENTATION_FORMS_A = 63,
+ PANGO_WIN32_U_COMBINING_HALF_MARKS = 64,
+ PANGO_WIN32_U_CJK_COMPATIBILITY_FORMS = 65,
+ PANGO_WIN32_U_SMALL_FORM_VARIANTS = 66,
+ PANGO_WIN32_U_ARABIC_PRESENTATION_FORMS_B = 67,
+ PANGO_WIN32_U_SPECIALS = 69,
+ PANGO_WIN32_U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
+ 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);
+
+
+
+/* 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);
+
+/* 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);
+
+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);
+
+/* Debugging.
+ */
+void pango_win32_fontmap_dump (int indent,
+ PangoFontMap *fontmap);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __PANGOWIN32_H__ */
diff --git a/pango/querymodules.c b/pango/querymodules.c
index 051b41d7..6d8b3210 100644
--- a/pango/querymodules.c
+++ b/pango/querymodules.c
@@ -19,17 +19,29 @@
* Boston, MA 02111-1307, USA.
*/
+#include "config.h"
+
#include <glib.h>
+#ifdef HAVE_DIRENT_H
#include <dirent.h>
+#endif
#include <gmodule.h>
#include "pango.h"
#include "pango-utils.h"
#include <errno.h>
#include <string.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <stdio.h>
+#ifdef G_OS_WIN32
+#define SOEXT ".dll"
+#else
+#define SOEXT ".so"
+#endif
+
void
query_module (const char *dir, const char *name)
{
@@ -102,7 +114,9 @@ int main (int argc, char **argv)
path = pango_config_key_get ("Pango/ModulesPath");
if (!path)
- path = g_strdup (LIBDIR "/pango/modules");
+ path = g_strconcat (pango_get_lib_subdirectory (),
+ G_DIR_SEPARATOR_S "modules",
+ NULL);
printf ("# ModulesPath = %s\n#\n", path);
@@ -118,7 +132,7 @@ int main (int argc, char **argv)
while ((dent = readdir (dir)))
{
int len = strlen (dent->d_name);
- if (len > 3 && strcmp (dent->d_name + len - 3, ".so") == 0)
+ if (len > 3 && strcmp (dent->d_name + len - strlen (SOEXT), SOEXT) == 0)
query_module (dirs[i], dent->d_name);
}