summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2002-10-21 23:48:24 +0000
committerTor Lillqvist <tml@src.gnome.org>2002-10-21 23:48:24 +0000
commitefe38161780103a7f01e1f241eca4d02e2039326 (patch)
tree07f9cd08c2af02229fe0cfb32dfee53189f4b889
parentf1da959cfb199c97e45b2bde9a093205e2405247 (diff)
downloadpango-efe38161780103a7f01e1f241eca4d02e2039326.tar.gz
Add --with-usp10 flag to indicate where to find the usp10.h header, for
2002-10-22 Tor Lillqvist <tml@iki.fi> * configure.in: Add --with-usp10 flag to indicate where to find the usp10.h header, for using Uniscribe on Win32. Set USP10_H autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H automake conditional. * acconfig.h: Add HAVE_USP10_H. * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change semantics of this flag. If defined, also need to set env var PANGO_WIN32_DEBUG to get the copious debugging output. Change PING() macro accordingly. Add variable pango_win32_debug. * pango/pangowin32.c (pango_win32_get_dc): New function. Code factored out from pango_win32_font_class_init() and pango_win32_font_map_class_init(). (pango_win32_get_debug_flag): New function. (pango_win32_render): Handle y offsets, too. Potentially need to call ExtTextOutW several times, one for each run of sequential glyphs with the same y offset. * pango/pangowin32.h: Declare above new functions, in the part only for shaper engine use. * pango/pangowin32.def: Export above new functions. * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init): Call pango_win32_get_dc() as mentioned above. * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo depend on usp10.h. * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe DLL usp10.dll is present, use Uniscribe. (uniscribe_shape, itemize_shape_and_place, set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets, make_langid, init_uniscribe): New functions. (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging functions.
-rw-r--r--ChangeLog41
-rw-r--r--ChangeLog.pre-1-1041
-rw-r--r--ChangeLog.pre-1-241
-rw-r--r--ChangeLog.pre-1-441
-rw-r--r--ChangeLog.pre-1-641
-rw-r--r--ChangeLog.pre-1-841
-rw-r--r--acconfig.h1
-rw-r--r--configure.in29
-rw-r--r--modules/basic/Makefile.am10
-rw-r--r--modules/basic/basic-win32.c749
-rw-r--r--pango/pangowin32-fontmap.c5
-rw-r--r--pango/pangowin32-private.h30
-rw-r--r--pango/pangowin32.c249
-rw-r--r--pango/pangowin32.def2
-rw-r--r--pango/pangowin32.h4
15 files changed, 1233 insertions, 92 deletions
diff --git a/ChangeLog b/ChangeLog
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog.pre-1-10
+++ b/ChangeLog.pre-1-10
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog.pre-1-2
+++ b/ChangeLog.pre-1-2
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog.pre-1-4
+++ b/ChangeLog.pre-1-4
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog.pre-1-6
+++ b/ChangeLog.pre-1-6
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8
index 925f9fc8..a9b0644b 100644
--- a/ChangeLog.pre-1-8
+++ b/ChangeLog.pre-1-8
@@ -1,3 +1,44 @@
+2002-10-22 Tor Lillqvist <tml@iki.fi>
+
+ * configure.in: Add --with-usp10 flag to indicate where to find
+ the usp10.h header, for using Uniscribe on Win32. Set USP10_H
+ autoconf variable, HAVE_USP10_H config.h macro and HAVE_USP10_H
+ automake conditional.
+
+ * acconfig.h: Add HAVE_USP10_H.
+
+ * pango/pangowin32-private.h (PANGO_WIN32_DEBUGGING): Change
+ semantics of this flag. If defined, also need to set env var
+ PANGO_WIN32_DEBUG to get the copious debugging output.
+ Change PING() macro accordingly. Add variable pango_win32_debug.
+
+ * pango/pangowin32.c (pango_win32_get_dc): New function. Code
+ factored out from pango_win32_font_class_init() and
+ pango_win32_font_map_class_init().
+ (pango_win32_get_debug_flag): New function.
+ (pango_win32_render): Handle y offsets, too. Potentially need to
+ call ExtTextOutW several times, one for each run of sequential
+ glyphs with the same y offset.
+
+ * pango/pangowin32.h: Declare above new functions, in the part
+ only for shaper engine use.
+
+ * pango/pangowin32.def: Export above new functions.
+
+ * pango/pangowin32-fontmap.c (pango_win32_font_map_class_init):
+ Call pango_win32_get_dc() as mentioned above.
+
+ * modules/basic/Makefile.am: If HAVE_USP10_H, let basic-win32.lo
+ depend on usp10.h.
+
+ * modules/basic/basic-win32.c: If HAVE_USP10_H, and the Uniscribe
+ DLL usp10.dll is present, use Uniscribe.
+ (uniscribe_shape, itemize_shape_and_place,
+ set_up_pango_log_clusters, convert_log_clusters_to_byte_offsets,
+ make_langid, init_uniscribe): New functions.
+ (dump_glyphs_and_log_clusters, lang_name, charset_name): Debugging
+ functions.
+
2002-10-20 Matthias Clasen <maclas@gmx.de>
* docs/Makefile.am (SCANOBJ_FILES): Add $(DOC_MODULE).prerequisites.
diff --git a/acconfig.h b/acconfig.h
index 56970a73..e4f933d9 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -17,6 +17,7 @@
#undef HAVE_FRIBIDI
#undef HAVE_UNISTD_H
#undef HAVE_FREETYPE_2_0_3
+#undef HAVE_USP10_H
#undef MINI_XFTCONFIG_DIR
#undef HAVE_XFT2
diff --git a/configure.in b/configure.in
index a5c3298a..00b12160 100644
--- a/configure.in
+++ b/configure.in
@@ -429,6 +429,35 @@ AM_CONDITIONAL(INCLUDE_INDIC_XFT,echo $included_modules | egrep '(^|,)indic-xft(
AC_CHECK_FUNCS(flockfile strtok_r)
#
+# Check for the Uniscribe header usp10.h for Win32
+#
+
+AC_ARG_WITH(usp10,
+[ --with-usp10=DIRECTORY where to find the usp10.h header file for Win32
+ (typically the Include directory in the
+ Platform SDK)])
+
+USP10_H=no
+if test "${with_usp10+set}" = set && test "$with_usp10" != no; then
+ AC_MSG_CHECKING([for usp10.h])
+ if test -f "$with_usp10"/usp10.h; then
+ AC_MSG_RESULT(yes)
+ USP10_H="$with_usp10"/usp10.h
+ AC_DEFINE(HAVE_USP10_H)
+ else
+ if test -f "$with_usp10"/include/usp10.h; then
+ AC_MSG_RESULT(yes)
+ USP10_H="$with_usp10"/include/usp10.h
+ AC_DEFINE(HAVE_USP10_H)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+fi
+AC_SUBST(USP10_H)
+AM_CONDITIONAL(HAVE_USP10_H, test "$USP10_H" != no)
+
+#
# Check for Qt - which we use for building the viewer example, if
# present
#
diff --git a/modules/basic/Makefile.am b/modules/basic/Makefile.am
index e03a8f0f..7e41eab3 100644
--- a/modules/basic/Makefile.am
+++ b/modules/basic/Makefile.am
@@ -68,7 +68,7 @@ else
WIN32_INCLUDED=
WIN32_MODULES=pango-basic-win32.la
WIN32_PREFIX=
-basic_win32_libadd=$(pangowin32libs)
+basic_win32_libadd=$(pangowin32libs) -lgdi32
endif
else
WIN32_INCLUDED=
@@ -115,6 +115,14 @@ pango_basic_win32_la_LIBADD = $(basic_win32_libadd)
pango_basic_win32_la_SOURCES = basic-win32.c
libpango_basic_win32_la_SOURCES = basic-win32.c
+if HAVE_USP10_H
+basic-win32.lo: usp10.h
+
+# Do it like this to avoid getting other headers from where usp10.h is
+usp10.h: @USP10_H@
+ cp -p @USP10_H@ usp10.h
+endif
+
EXTRA_DIST = \
basic-common.h \
tables-big.i \
diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
index 2c3f4629..c85c5573 100644
--- a/modules/basic/basic-win32.c
+++ b/modules/basic/basic-win32.c
@@ -20,7 +20,14 @@
* Boston, MA 02111-1307, USA.
*/
+#include "config.h"
+
+#define BASIC_WIN32_DEBUGGING
+
+#include <stdlib.h>
+
#include <glib.h>
+
#include "pangowin32.h"
#include "pango-engine.h"
#include "pango-utils.h"
@@ -29,7 +36,89 @@
#define SCRIPT_ENGINE_NAME "BasicScriptEngineWin32"
+static gboolean pango_win32_debug = FALSE;
+
+#ifdef HAVE_USP10_H
+
+#include "usp10.h"
+
+/* Some languages missing from mingw ("w32api") headers */
+
+#ifndef LANG_INVARIANT
+#define LANG_INVARIANT 0x7f
+#endif
+#ifndef LANG_DIVEHI
+#define LANG_DIVEHI 0x65
+#endif
+#ifndef LANG_GALICIAN
+#define LANG_GALICIAN 0x56
+#endif
+#ifndef LANG_KYRGYZ
+#define LANG_KYRGYZ 0x40
+#endif
+#ifndef LANG_MONGOLIAN
+#define LANG_MONGOLIAN 0x50
+#endif
+#ifndef LANG_SYRIAC
+#define LANG_SYRIAC 0x5a
+#endif
+
+static gboolean have_uniscribe = FALSE;
+
+static PangoWin32FontCache *font_cache;
+
+static HDC hdc;
+
+typedef HRESULT (WINAPI *pScriptGetProperties) (const SCRIPT_PROPERTIES ***,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptItemize) (const WCHAR *,
+ int,
+ int,
+ const SCRIPT_CONTROL *,
+ const SCRIPT_STATE *,
+ SCRIPT_ITEM *,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptShape) (HDC,
+ SCRIPT_CACHE *,
+ const WCHAR *,
+ int,
+ int,
+ SCRIPT_ANALYSIS *,
+ WORD *,
+ WORD *,
+ SCRIPT_VISATTR *,
+ int *);
+
+typedef HRESULT (WINAPI *pScriptPlace) (HDC,
+ SCRIPT_CACHE *,
+ const WORD *,
+ int,
+ const SCRIPT_VISATTR *,
+ SCRIPT_ANALYSIS *,
+ int *,
+ GOFFSET *,
+ ABC *);
+
+typedef HRESULT (WINAPI *pScriptFreeCache) (SCRIPT_CACHE *);
+
+static pScriptGetProperties script_get_properties;
+static pScriptItemize script_itemize;
+static pScriptShape script_shape;
+static pScriptPlace script_place;
+static pScriptFreeCache script_free_cache;
+
+static const SCRIPT_PROPERTIES **scripts;
+int nscripts;
+
+#endif
+
static PangoEngineRange basic_ranges[] = {
+#ifdef HAVE_USP10_H
+ /* We claim to cover everything ;-) */
+ { 0x0020, 0xffee, "*" }
+#else
/* Basic Latin, Latin-1 Supplement, Latin Extended-A, Latin Extended-B,
* IPA Extensions
*/
@@ -96,6 +185,7 @@ static PangoEngineRange basic_ranges[] = {
/* Halfwidth and Fullwidth Forms (partly) */
{ 0xff00, 0xffe3, "*" }
+#endif
};
static PangoEngineInfo script_engines[] = {
@@ -162,6 +252,617 @@ swap_range (PangoGlyphString *glyphs,
}
}
+#ifdef BASIC_WIN32_DEBUGGING
+
+static char *
+charset_name (int charset)
+{
+ static char unk[10];
+
+ switch (charset)
+ {
+#define CASE(n) case n##_CHARSET: return #n
+ CASE (ANSI);
+ CASE (DEFAULT);
+ CASE (SYMBOL);
+ CASE (SHIFTJIS);
+ CASE (HANGEUL);
+ CASE (GB2312);
+ CASE (CHINESEBIG5);
+ CASE (OEM);
+ CASE (JOHAB);
+ CASE (HEBREW);
+ CASE (ARABIC);
+ CASE (GREEK);
+ CASE (TURKISH);
+ CASE (VIETNAMESE);
+ CASE (THAI);
+ CASE (EASTEUROPE);
+ CASE (RUSSIAN);
+ CASE (MAC);
+ CASE (BALTIC);
+#undef CASE
+ default:
+ sprintf (unk, "%d", charset);
+ return unk;
+ }
+}
+
+static char *
+lang_name (int lang)
+{
+ static char unk[10];
+
+ switch (PRIMARYLANGID (lang))
+ {
+#define CASE(n) case LANG_##n: return #n
+ CASE (NEUTRAL);
+ CASE (INVARIANT);
+ CASE (AFRIKAANS);
+ CASE (ALBANIAN);
+ CASE (ARABIC);
+ CASE (ARMENIAN);
+ CASE (ASSAMESE);
+ CASE (AZERI);
+ CASE (BASQUE);
+ CASE (BELARUSIAN);
+ CASE (BENGALI);
+ CASE (BULGARIAN);
+ CASE (CATALAN);
+ CASE (CHINESE);
+ CASE (CROATIAN);
+ CASE (CZECH);
+ CASE (DANISH);
+ CASE (DIVEHI);
+ CASE (DUTCH);
+ CASE (ENGLISH);
+ CASE (ESTONIAN);
+ CASE (FAEROESE);
+ CASE (FARSI);
+ CASE (FINNISH);
+ CASE (FRENCH);
+ CASE (GALICIAN);
+ CASE (GEORGIAN);
+ CASE (GERMAN);
+ CASE (GREEK);
+ CASE (GUJARATI);
+ CASE (HEBREW);
+ CASE (HINDI);
+ CASE (HUNGARIAN);
+ CASE (ICELANDIC);
+ CASE (INDONESIAN);
+ CASE (ITALIAN);
+ CASE (JAPANESE);
+ CASE (KANNADA);
+ CASE (KASHMIRI);
+ CASE (KAZAK);
+ CASE (KONKANI);
+ CASE (KOREAN);
+ CASE (KYRGYZ);
+ CASE (LATVIAN);
+ CASE (LITHUANIAN);
+ CASE (MACEDONIAN);
+ CASE (MALAY);
+ CASE (MALAYALAM);
+ CASE (MANIPURI);
+ CASE (MARATHI);
+ CASE (MONGOLIAN);
+ CASE (NEPALI);
+ CASE (NORWEGIAN);
+ CASE (ORIYA);
+ CASE (POLISH);
+ CASE (PORTUGUESE);
+ CASE (PUNJABI);
+ CASE (ROMANIAN);
+ CASE (RUSSIAN);
+ CASE (SANSKRIT);
+ CASE (SINDHI);
+ CASE (SLOVAK);
+ CASE (SLOVENIAN);
+ CASE (SPANISH);
+ CASE (SWAHILI);
+ CASE (SWEDISH);
+ CASE (SYRIAC);
+ CASE (TAMIL);
+ CASE (TATAR);
+ CASE (TELUGU);
+ CASE (THAI);
+ CASE (TURKISH);
+ CASE (UKRAINIAN);
+ CASE (URDU);
+ CASE (UZBEK);
+ CASE (VIETNAMESE);
+#undef CASE
+ default:
+ sprintf (unk, "%#02x", lang);
+ return unk;
+ }
+}
+
+#endif /* BASIC_WIN32_DEBUGGING */
+
+#ifdef HAVE_USP10_H
+
+static WORD
+make_langid (PangoLanguage *lang)
+{
+#define CASE(t,p,s) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_##p##_##s)
+#define CASEN(t,p) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_NEUTRAL)
+
+ /* Languages that most probably don't affect Uniscribe have been
+ * left out. Presumably still many of those mentioned below don't
+ * have any effect either.
+ */
+
+ CASEN ("sq", ALBANIAN);
+ CASEN ("ar", ARABIC);
+ CASEN ("az", AZERI);
+ CASEN ("hy", ARMENIAN);
+ CASEN ("as", ASSAMESE);
+ CASEN ("az", AZERI);
+ CASEN ("eu", BASQUE);
+ CASEN ("be", BELARUSIAN);
+ CASEN ("bn", BENGALI);
+ CASEN ("bg", BULGARIAN);
+ CASEN ("ca", CATALAN);
+ CASE ("zh-tw", CHINESE, TRADITIONAL);
+ CASE ("zh-cn", CHINESE, SIMPLIFIED);
+ CASE ("zh-hk", CHINESE, HONGKONG);
+ CASE ("zh-sg", CHINESE, SINGAPORE);
+ CASE ("zh-mo", CHINESE, MACAU);
+ CASEN ("hr", CROATIAN);
+ CASE ("sr", SERBIAN, CYRILLIC);
+ CASEN ("dib", DIVEHI);
+ CASEN ("fa", FARSI);
+ CASEN ("ka", GEORGIAN);
+ CASEN ("el", GREEK);
+ CASEN ("gu", GUJARATI);
+ CASEN ("he", HEBREW);
+ CASEN ("hi", HINDI);
+ CASEN ("ja", JAPANESE);
+ CASEN ("kn", KANNADA);
+ CASE ("ks-in", KASHMIRI, INDIA);
+ CASEN ("ks", KASHMIRI);
+ CASEN ("kk", KAZAK);
+ CASEN ("kok", KONKANI);
+ CASEN ("ko", KOREAN);
+ CASEN ("ky", KYRGYZ);
+ CASEN ("ml", MALAYALAM);
+ CASEN ("mni", MANIPURI);
+ CASEN ("mr", MARATHI);
+ CASEN ("mn", MONGOLIAN);
+ CASE ("ne-in", NEPALI, INDIA);
+ CASEN ("ne", NEPALI);
+ CASEN ("or", ORIYA);
+ CASEN ("pa", PUNJABI);
+ CASEN ("sa", SANSKRIT);
+ CASEN ("sd", SINDHI);
+ CASEN ("syr", SYRIAC);
+ CASEN ("ta", TAMIL);
+ CASEN ("tt", TATAR);
+ CASEN ("te", TELUGU);
+ CASEN ("th", THAI);
+ CASEN ("tr", TURKISH);
+ CASEN ("uk", UKRAINIAN);
+ CASE ("ur-pk", URDU, PAKISTAN);
+ CASE ("ur-in", URDU, INDIA);
+ CASEN ("ur", URDU);
+ CASEN ("uz", UZBEK);
+ CASEN ("vi", VIETNAMESE);
+
+#undef CASE
+#undef CASEN
+
+ return MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
+}
+
+static void
+dump_glyphs_and_log_clusters (gboolean rtl,
+ int itemlen,
+ int charix0,
+ WORD *log_clusters,
+ WORD *iglyphs,
+ int nglyphs)
+{
+ if (pango_win32_debug)
+ {
+ int j, k, nclusters, clusterix, charix, ng;
+
+ printf (" ScriptShape: nglyphs=%d: ", nglyphs);
+
+ for (j = 0; j < nglyphs; j++)
+ printf ("%d%s", iglyphs[j], (j < nglyphs-1) ? "," : "");
+ printf ("\n");
+
+ printf (" log_clusters: ");
+ for (j = 0; j < itemlen; j++)
+ printf ("%d ", log_clusters[j]);
+ printf ("\n"); nclusters = 0;
+ for (j = 0; j < itemlen; j++)
+ {
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ nclusters++;
+ }
+ printf (" %d clusters:\n", nclusters);
+
+ /* If RTL, first char is the last in the run, otherwise the
+ * first.
+ */
+ clusterix = 0;
+ if (rtl)
+ {
+ int firstglyphix = 0;
+ for (j = itemlen - 1, charix = charix0 + j; j >= 0; j--, charix--)
+ {
+ if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
+ printf (" Cluster %d: chars %d--",
+ clusterix, charix);
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ {
+ ng = log_clusters[j] - firstglyphix + 1;
+ printf ("%d: %d glyphs: ",
+ charix, ng);
+ for (k = firstglyphix; k <= log_clusters[j]; k++)
+ {
+ printf ("%d", iglyphs[k]);
+ if (k < log_clusters[j])
+ printf (",");
+ }
+ firstglyphix = log_clusters[j] + 1;
+ clusterix++;
+ printf ("\n");
+ }
+ }
+ }
+ else
+ {
+ for (j = 0, charix = charix0; j < itemlen; j++, charix++)
+ {
+ if (j == 0 || log_clusters[j-1] != log_clusters[j])
+ printf (" Cluster %d: chars %d--",
+ clusterix, charix);
+ if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
+ {
+ int klim = ((j == itemlen-1) ? nglyphs : log_clusters[j+1]);
+ ng = klim - log_clusters[j];
+ printf ("%d: %d glyphs: ",
+ charix, ng);
+ for (k = log_clusters[j]; k < klim; k++)
+ {
+ printf ("%d", iglyphs[k]);
+ if (k != klim - 1)
+ printf (",");
+ }
+ clusterix++;
+ printf ("\n");
+ }
+ }
+ }
+ }
+}
+
+static void
+set_up_pango_log_clusters (gboolean rtl,
+ int itemlen,
+ WORD *usp_log_clusters,
+ int nglyphs,
+ gint *pango_log_clusters,
+ int char_offset)
+{
+ int j, k;
+ int first_char_in_cluster;
+
+ if (rtl)
+ {
+ /* RTL. Walk Uniscribe log_clusters array backwards, build Pango
+ * log_clusters array forwards.
+ */
+ int glyph0 = 0;
+ first_char_in_cluster = itemlen - 1;
+ for (j = itemlen - 1; j >= 0; j--)
+ {
+ if (j < itemlen - 1 && usp_log_clusters[j+1] != usp_log_clusters[j])
+ {
+ /* Cluster starts */
+ first_char_in_cluster = j;
+ }
+ if (j == 0)
+ {
+ /* First char, cluster ends */
+ for (k = glyph0; k < nglyphs; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ else if (usp_log_clusters[j-1] == usp_log_clusters[j])
+ {
+ /* Cluster continues */
+ first_char_in_cluster = j-1;
+ }
+ else
+ {
+ /* Cluster ends */
+ for (k = glyph0; k <= usp_log_clusters[j]; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ glyph0 = usp_log_clusters[j] + 1;
+ }
+ }
+ }
+ else
+ {
+ /* LTR. Walk Uniscribe log_clusters array forwards, build Pango
+ * log_clusters array also forwards.
+ */
+ first_char_in_cluster = 0;
+ for (j = 0; j < itemlen; j++)
+ {
+ if (j > 0 && usp_log_clusters[j-1] != usp_log_clusters[j])
+ {
+ /* Cluster starts */
+ first_char_in_cluster = j;
+ }
+ if (j == itemlen - 1)
+ {
+ /* Last char, cluster ends */
+ for (k = usp_log_clusters[j]; k < nglyphs; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ else if (usp_log_clusters[j] == usp_log_clusters[j+1])
+ {
+ /* Cluster continues */
+ }
+ else
+ {
+ /* Cluster ends */
+ for (k = usp_log_clusters[j]; k < usp_log_clusters[j+1]; k++)
+ pango_log_clusters[k] = first_char_in_cluster + char_offset;
+ }
+ }
+ }
+}
+
+static void
+convert_log_clusters_to_byte_offsets (const char *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ const char *p;
+ int charix, glyphix;
+
+ /* Convert char indexes in the log_clusters array to byte offsets in
+ * the UTF-8 text.
+ */
+ p = text;
+ charix = 0;
+ if (analysis->level % 2)
+ {
+ glyphix = glyphs->num_glyphs - 1;
+ while (p < text + length)
+ {
+ while (glyphix >= 0 &&
+ glyphs->log_clusters[glyphix] == charix)
+ {
+ glyphs->log_clusters[glyphix] = p - text;
+ glyphix--;
+ }
+ charix++;
+ p = g_utf8_next_char (p);
+ }
+ }
+ else
+ {
+ glyphix = 0;
+ while (p < text + length)
+ {
+ while (glyphix < glyphs->num_glyphs &&
+ glyphs->log_clusters[glyphix] == charix)
+ {
+ glyphs->log_clusters[glyphix] = p - text;
+ glyphix++;
+ }
+ charix++;
+ p = g_utf8_next_char (p);
+ }
+ }
+}
+
+static gboolean
+itemize_shape_and_place (HDC hdc,
+ wchar_t *wtext,
+ int wlen,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ SCRIPT_CACHE *script_cache)
+{
+ int item, nitems;
+ int itemlen, glyphix, nglyphs;
+ int nc;
+ SCRIPT_CONTROL control;
+ SCRIPT_STATE state;
+ SCRIPT_ITEM items[100];
+
+ memset (&control, 0, sizeof (control));
+ memset (&state, 0, sizeof (state));
+
+ control.uDefaultLanguage = make_langid (analysis->language);
+ state.uBidiLevel = analysis->level;
+
+ if ((*script_itemize) (wtext, wlen, G_N_ELEMENTS (items), &control, NULL,
+ items, &nitems))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf ("pango-basic-win32: ScriptItemize failed\n");
+#endif
+ return FALSE;
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf (G_STRLOC ": ScriptItemize: %d items\n", nitems);
+#endif
+
+ nc = 0;
+ for (item = 0; item < nitems; item++)
+ {
+ WORD iglyphs[1000];
+ WORD log_clusters[1000];
+ SCRIPT_VISATTR visattrs[1000];
+ int advances[1000];
+ GOFFSET offsets[1000];
+ ABC abc;
+ int script = items[item].a.eScript;
+ int ng;
+
+ memset (advances, 0, sizeof (advances));
+ memset (offsets, 0, sizeof (offsets));
+ memset (&abc, 0, sizeof (abc));
+
+ itemlen = items[item+1].iCharPos - items[item].iCharPos;
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf (" Item %d: iCharPos=%d eScript=%d (%s) %s%s%s%s%s%s%s chars %d--%d (%d)\n",
+ item, items[item].iCharPos, script,
+ lang_name (scripts[script]->langid),
+ scripts[script]->fComplex ? "complex" : "simple",
+ items[item].a.fRTL ? " fRTL" : "",
+ items[item].a.fLayoutRTL ? " fLayoutRTL" : "",
+ items[item].a.fLinkBefore ? " fLinkBefore" : "",
+ items[item].a.fLinkAfter ? " fLinkAfter" : "",
+ items[item].a.fLogicalOrder ? " fLogicalOrder" : "",
+ items[item].a.fNoGlyphIndex ? " fNoGlyphIndex" : "",
+ items[item].iCharPos, items[item+1].iCharPos-1, itemlen);
+#endif
+
+ if ((*script_shape) (hdc, &script_cache[script], wtext + items[item].iCharPos, itemlen,
+ G_N_ELEMENTS (iglyphs),
+ &items[item].a,
+ iglyphs,
+ log_clusters,
+ visattrs,
+ &nglyphs))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf ("pango-basic-win32: ScriptShape failed\n");
+#endif
+ return FALSE;
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ dump_glyphs_and_log_clusters (items[item].a.fRTL, itemlen,
+ items[item].iCharPos, log_clusters,
+ iglyphs, nglyphs);
+#endif
+
+ ng = glyphs->num_glyphs;
+ pango_glyph_string_set_size (glyphs, ng + nglyphs);
+
+ set_up_pango_log_clusters (items[item].a.fRTL, itemlen, log_clusters,
+ nglyphs, glyphs->log_clusters + ng, nc);
+
+ if ((*script_place) (hdc, &script_cache[script], iglyphs, nglyphs,
+ visattrs, &items[item].a,
+ advances, offsets, &abc))
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf ("pango-basic-win32: ScriptPlace failed\n");
+#endif
+ return FALSE;
+ }
+
+ for (glyphix = 0; glyphix < nglyphs; glyphix++)
+ {
+ glyphs->glyphs[ng+glyphix].glyph = iglyphs[glyphix];
+ glyphs->glyphs[ng+glyphix].geometry.width = PANGO_SCALE * advances[glyphix];
+ glyphs->glyphs[ng+glyphix].geometry.x_offset = PANGO_SCALE * offsets[glyphix].du;
+ glyphs->glyphs[ng+glyphix].geometry.y_offset = PANGO_SCALE * offsets[glyphix].dv;
+ }
+ nc += itemlen;
+ }
+
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ printf (" Pango log_clusters, char index:");
+ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
+ printf ("%d ", glyphs->log_clusters[glyphix]);
+ printf ("\n");
+ }
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+uniscribe_shape (PangoFont *font,
+ const char *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ wchar_t *wtext;
+ int wlen, i;
+ gboolean retval = TRUE;
+ GError *error;
+ HGDIOBJ old_font;
+ LOGFONT *lf;
+ SCRIPT_CACHE script_cache[100];
+
+ wtext = (wchar_t *) g_convert (text, length, "UTF-16LE", "UTF-8",
+ NULL, &wlen, &error);
+ if (wtext == NULL)
+ return FALSE;
+
+ wlen /= 2;
+
+ lf = pango_win32_font_logfont (font);
+ old_font = SelectObject (hdc, pango_win32_font_cache_load (font_cache, lf));
+ if (old_font == NULL)
+ {
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ printf ("pango-basic-win32: SelectObject for font failed\n");
+#endif
+ retval = FALSE;
+ }
+
+ if (retval)
+ {
+ memset (script_cache, 0, sizeof (script_cache));
+ retval = itemize_shape_and_place (hdc, wtext, wlen, analysis, glyphs, script_cache);
+ for (i = 0; i < G_N_ELEMENTS (script_cache); i++)
+ if (script_cache[i])
+ (*script_free_cache)(&script_cache[i]);
+ }
+
+ if (retval)
+ {
+ convert_log_clusters_to_byte_offsets (text, length, analysis, glyphs);
+#ifdef BASIC_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ int glyphix;
+
+ printf (" Pango log_clusters, byte offsets:");
+ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
+ printf ("%d ", glyphs->log_clusters[glyphix]);
+ printf ("\n");
+ }
+#endif
+
+ }
+
+ g_free (wtext);
+ if (old_font != NULL)
+ SelectObject (hdc, old_font);
+
+ return retval;
+}
+
+#endif /* HAVE_USP10_H */
+
static void
basic_engine_shape (PangoFont *font,
const char *text,
@@ -178,7 +879,15 @@ basic_engine_shape (PangoFont *font,
g_return_if_fail (length >= 0);
g_return_if_fail (analysis != NULL);
+#ifdef HAVE_USP10_H
+
+ if (have_uniscribe && uniscribe_shape (font, text, length, analysis, glyphs))
+ return;
+
+#endif
+
n_chars = g_utf8_strlen (text, length);
+
pango_glyph_string_set_size (glyphs, n_chars);
p = text;
@@ -282,6 +991,41 @@ basic_engine_win32_new (void)
return (PangoEngine *)result;
}
+static void
+init_uniscribe (void)
+{
+#ifdef HAVE_USP10_H
+ HMODULE usp10_dll;
+
+ have_uniscribe = FALSE;
+
+ if (getenv ("PANGO_WIN32_NO_UNISCRIBE") == NULL &&
+ (usp10_dll = LoadLibrary ("usp10.dll")) != NULL)
+ {
+ (script_get_properties = (pScriptGetProperties)
+ GetProcAddress (usp10_dll, "ScriptGetProperties")) &&
+ (script_itemize = (pScriptItemize)
+ GetProcAddress (usp10_dll, "ScriptItemize")) &&
+ (script_shape = (pScriptShape)
+ GetProcAddress (usp10_dll, "ScriptShape")) &&
+ (script_place = (pScriptPlace)
+ GetProcAddress (usp10_dll, "ScriptPlace")) &&
+ (script_free_cache = (pScriptFreeCache)
+ GetProcAddress (usp10_dll, "ScriptFreeCache")) &&
+ (have_uniscribe = TRUE);
+ }
+ if (have_uniscribe)
+ {
+ (*script_get_properties) (&scripts, &nscripts);
+
+ font_cache = pango_win32_font_map_get_font_cache
+ (pango_win32_font_map_for_display ());
+
+ hdc = pango_win32_get_dc ();
+ }
+#endif
+}
+
/* The following three functions provide the public module API for
* Pango
*/
@@ -302,6 +1046,11 @@ MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines,
PangoEngine *
MODULE_ENTRY(script_engine_load) (const char *id)
{
+ init_uniscribe ();
+
+ if (pango_win32_get_debug_flag ())
+ pango_win32_debug = TRUE;
+
if (!strcmp (id, SCRIPT_ENGINE_NAME))
return basic_engine_win32_new ();
else
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index e4b7604d..2ec80599 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -188,8 +188,7 @@ pango_win32_font_map_class_init (PangoFontMapClass *class)
class->load_font = pango_win32_font_map_load_font;
class->list_families = pango_win32_font_map_list_families;
- if (pango_win32_hdc == NULL)
- pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+ pango_win32_get_dc ();
}
static PangoWin32FontMap *fontmap = NULL;
@@ -782,7 +781,7 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
* same entry at the moment and it isn't crashing on g_free () ???
* Maybe a memory leak ...
*/
- switch (lfp->lfPitchAndFamily & (0x0F << 4)) /* bit 4...7 */
+ switch (lfp->lfPitchAndFamily & 0xF0)
{
case FF_MODERN : /* monospace */
PING(("monospace"));
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index dc1f5faa..b1014214 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -24,20 +24,27 @@
#ifndef __PANGOWIN32_PRIVATE_H__
#define __PANGOWIN32_PRIVATE_H__
-/* Define if you want copious debugging output. */
-/* #define PANGO_WIN32_DEBUGGING 1 */
+/* Define if you want the possibility to get copious debugging output.
+ * (You still need to set the PANGO_WIN32_DEBUG environment variable
+ * to get it.)
+ */
+#define PANGO_WIN32_DEBUGGING 1
#ifdef PANGO_WIN32_DEBUGGING
#ifdef __GNUC__
#define PING(printlist) \
-(printf ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \
- printf printlist, \
- printf ("\n"))
+(pango_win32_debug ? \
+ (printf ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \
+ printf printlist, \
+ printf ("\n")) : \
+ 0)
#else
#define PING(printlist) \
-(printf ("%s:%d ", __FILE__, __LINE__), \
- printf printlist, \
- printf ("\n"))
+(pango_win32_debug ? \
+ (printf ("%s:%d ", __FILE__, __LINE__), \
+ printf printlist, \
+ printf ("\n")) : \
+ 0)
#endif
#else /* !PANGO_WIN32_DEBUGGING */
#define PING(printlist)
@@ -72,9 +79,9 @@ struct _PangoWin32Font
/* Written by pango_win32_get_hfont: */
HFONT hfont;
- gint tm_ascent;
- gint tm_descent;
- gint tm_overhang;
+ gint tm_ascent;
+ gint tm_descent;
+ gint tm_overhang;
PangoWin32Face *win32face;
@@ -198,5 +205,6 @@ gboolean pango_win32_get_name_record (HDC hdc,
extern HDC pango_win32_hdc;
extern OSVERSIONINFO pango_win32_os_version_info;
+extern gboolean pango_win32_debug;
#endif /* __PANGOWIN32_PRIVATE_H__ */
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 0f98db1f..bebcf927 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -43,6 +43,7 @@
HDC pango_win32_hdc;
OSVERSIONINFO pango_win32_os_version_info;
+gboolean pango_win32_debug = FALSE;
typedef struct _PangoWin32FontClass PangoWin32FontClass;
@@ -177,6 +178,37 @@ pango_win32_font_init (PangoWin32Font *win32font)
win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);
}
+HDC
+pango_win32_get_dc (void)
+{
+ if (pango_win32_hdc == NULL)
+ {
+ pango_win32_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
+ memset (&pango_win32_os_version_info, 0,
+ sizeof (pango_win32_os_version_info));
+ pango_win32_os_version_info.dwOSVersionInfoSize =
+ sizeof (OSVERSIONINFO);
+ GetVersionEx (&pango_win32_os_version_info);
+
+ /* Also do some generic pangowin32 initialisations... this function
+ * is a suitable place for those as it is called from a couple
+ * of class_init functions.
+ */
+#ifdef PANGO_WIN32_DEBUGGING
+ if (getenv ("PANGO_WIN32_DEBUG") != NULL)
+ pango_win32_debug = TRUE;
+#endif
+ }
+
+ return pango_win32_hdc;
+}
+
+gboolean
+pango_win32_get_debug_flag (void)
+{
+ return pango_win32_debug;
+}
+
static void
pango_win32_font_class_init (PangoWin32FontClass *class)
{
@@ -194,15 +226,7 @@ pango_win32_font_class_init (PangoWin32FontClass *class)
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);
- memset (&pango_win32_os_version_info, 0,
- sizeof (pango_win32_os_version_info));
- pango_win32_os_version_info.dwOSVersionInfoSize =
- sizeof (OSVERSIONINFO);
- GetVersionEx (&pango_win32_os_version_info);
- }
+ pango_win32_get_dc ();
}
PangoWin32Font *
@@ -244,16 +268,34 @@ pango_win32_render (HDC hdc,
int x,
int y)
{
- HFONT old_hfont = NULL;
- HFONT hfont;
- int i, num_valid_glyphs;
+ HFONT hfont, old_hfont = NULL;
+ int i, j, num_valid_glyphs;
guint16 *glyph_indexes;
gint *dX;
- gint last_x = 0;
- PangoGlyphUnit start_x_offset = 0, x_offset = 0;
+ gint this_x;
+ PangoGlyphUnit start_x_offset, x_offset, next_x_offset, cur_y_offset;
g_return_if_fail (glyphs != NULL);
+#ifdef PANGO_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ PING (("num_glyphs:%d", glyphs->num_glyphs));
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ printf (" %d:%d", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);
+ if (glyphs->glyphs[i].geometry.x_offset != 0 ||
+ glyphs->glyphs[i].geometry.y_offset != 0)
+ printf (":%d,%d", glyphs->glyphs[i].geometry.x_offset,
+ glyphs->glyphs[i].geometry.y_offset);
+ }
+ printf ("\n");
+ }
+#endif
+
+ if (glyphs->num_glyphs == 0)
+ return;
+
hfont = pango_win32_get_hfont (font);
if (!hfont)
return;
@@ -263,66 +305,107 @@ pango_win32_render (HDC hdc,
glyph_indexes = g_new (guint16, glyphs->num_glyphs);
dX = g_new (INT, glyphs->num_glyphs);
-#ifdef PANGO_WIN32_DEBUGGING
- PING (("num_glyphs:%d", glyphs->num_glyphs));
- printf (" ");
- for (i = 0; i <glyphs->num_glyphs; i++)
- printf ("%d:%d ", glyphs->glyphs[i].glyph, glyphs->glyphs[i].geometry.width);
- printf ("\n");
-#endif
+ /* Render glyphs using one ExtTextOutW() call for each run of glyphs
+ * that have the same y offset. The big majoroty of glyphs will have
+ * y offset of zero, so in general, the whole glyph string will be
+ * rendered by one call to ExtTextOutW().
+ *
+ * In order to minimize buildup of rounding errors, we keep track of
+ * where the glyphs should be rendered in PangoGlyphUnits, and round
+ * to pixels separately for each glyph,
+ */
+
+ i = 0;
- num_valid_glyphs = 0;
- for (i = 0; i <glyphs->num_glyphs; i++)
+ /* Outer loop through all glyphs in string */
+ while (i < glyphs->num_glyphs)
{
- if (glyphs->glyphs[i].glyph == 0)
+ cur_y_offset = glyphs->glyphs[i].geometry.y_offset;
+ num_valid_glyphs = 0;
+ x_offset = 0;
+ start_x_offset = glyphs->glyphs[i].geometry.x_offset;
+ this_x = PANGO_PIXELS (start_x_offset);
+
+ /* Inner loop through glyphs with the same y offset, or code
+ * point zero (just spacing).
+ */
+ while (i < glyphs->num_glyphs &&
+ (glyphs->glyphs[i].glyph == 0 || cur_y_offset == glyphs->glyphs[i].geometry.y_offset))
{
- /* Code point 0 glyphs should not be rendered, but their
- * indicated width (set up by PangoLayout) should be taken
- * into account.
- */
-
- /* If the string starts with spacing, must shift the
- * starting point for the glyphs actually rendered. For
- * spacing in the middle of the glyph string, add to the dX
- * of the previous glyph to be rendered.
- */
- if (num_valid_glyphs == 0)
- start_x_offset += glyphs->glyphs[i].geometry.width;
- else
+ if (glyphs->glyphs[i].glyph == 0)
{
- x_offset += glyphs->glyphs[i].geometry.width;
- dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - last_x;
- }
- }
- else
- {
- if (glyphs->glyphs[i].glyph & PANGO_WIN32_UNKNOWN_FLAG)
- {
- /* Glyph index is actually the char value that doesn't
- * have any glyph (ORed with the flag). We should really
- * do the same that pango_xft_real_render() does: render
- * a box with the char value in hex inside it in a tiny
- * font. Later. For now, use the TrueType invalid glyph
- * at 0.
+ /* Code point 0 glyphs should not be rendered, but their
+ * indicated width (set up by PangoLayout) should be taken
+ * into account.
+ */
+
+ /* If the string starts with spacing, must shift the
+ * starting point for the glyphs actually rendered. For
+ * spacing in the middle of the glyph string, add to the dX
+ * of the previous glyph to be rendered.
*/
- glyph_indexes[num_valid_glyphs] = 0;
+ if (num_valid_glyphs == 0)
+ start_x_offset += glyphs->glyphs[i].geometry.width;
+ else
+ {
+ x_offset += glyphs->glyphs[i].geometry.width;
+ dX[num_valid_glyphs-1] = PANGO_PIXELS (x_offset) - this_x;
+ }
}
else
- glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;
+ {
+ if (glyphs->glyphs[i].glyph & PANGO_WIN32_UNKNOWN_FLAG)
+ {
+ /* Glyph index is actually the char value that doesn't
+ * have any glyph (ORed with the flag). We should really
+ * do the same that pango_xft_real_render() does: render
+ * a box with the char value in hex inside it in a tiny
+ * font. Later. For now, use the TrueType invalid glyph
+ * at 0.
+ */
+ glyph_indexes[num_valid_glyphs] = 0;
+ }
+ else
+ glyph_indexes[num_valid_glyphs] = glyphs->glyphs[i].glyph;
+
+ x_offset += glyphs->glyphs[i].geometry.width;
+
+ /* If the next glyph has an X offset, take that into consideration now */
+ if (i < glyphs->num_glyphs - 1)
+ next_x_offset = glyphs->glyphs[i+1].geometry.x_offset;
+ else
+ next_x_offset = 0;
+
+ dX[num_valid_glyphs] = PANGO_PIXELS (x_offset + next_x_offset) - this_x;
- if (num_valid_glyphs > 0)
- last_x += dX[num_valid_glyphs-1];
- x_offset += glyphs->glyphs[i].geometry.width;
- dX[num_valid_glyphs] = PANGO_PIXELS (x_offset) - last_x;
- num_valid_glyphs++;
+ /* Prepare for next glyph */
+ this_x += dX[num_valid_glyphs];
+ num_valid_glyphs++;
+ }
+ i++;
+ }
+#ifdef PANGO_WIN32_DEBUGGING
+ if (pango_win32_debug)
+ {
+ printf ("ExtTextOutW at %d,%d deltas:",
+ x + PANGO_PIXELS (start_x_offset),
+ y + PANGO_PIXELS (cur_y_offset));
+ for (j = 0; j < num_valid_glyphs; j++)
+ printf (" %d", dX[j]);
+ printf ("\n");
}
+#endif
+
+ ExtTextOutW (hdc,
+ x + PANGO_PIXELS (start_x_offset),
+ y + PANGO_PIXELS (cur_y_offset),
+ ETO_GLYPH_INDEX,
+ NULL,
+ glyph_indexes, num_valid_glyphs,
+ dX);
+ x += this_x;
}
- ExtTextOutW (hdc, x + PANGO_PIXELS (start_x_offset), y,
- ETO_GLYPH_INDEX,
- NULL,
- glyph_indexes, num_valid_glyphs,
- dX);
SelectObject (hdc, old_hfont); /* restore */
g_free (glyph_indexes);
@@ -581,8 +664,10 @@ pango_win32_font_find_shaper (PangoFont *font,
/**
* pango_win32_get_unknown_glyph:
* @font: a #PangoFont
+ * @wc: the Unicode character for which a glyph is needed.
*
- * Return the index of a glyph suitable for drawing unknown characters.
+ * Returns the index of a glyph suitable for drawing @wc as an
+ * unknown character.
*
* Return value: a glyph index into @font
**/
@@ -1229,10 +1314,13 @@ pango_win32_font_calc_coverage (PangoFont *font,
if (id_range_offset[i] == 0)
{
#ifdef PANGO_WIN32_DEBUGGING
- if (end_count[i] == start_count[i])
- printf ("%04x ", start_count[i]);
- else
- printf ("%04x:%04x ", start_count[i], end_count[i]);
+ if (pango_win32_debug)
+ {
+ if (end_count[i] == start_count[i])
+ printf ("%04x ", start_count[i]);
+ else
+ printf ("%04x:%04x ", start_count[i], end_count[i]);
+ }
#endif
for (ch = start_count[i];
ch <= end_count[i];
@@ -1268,10 +1356,13 @@ pango_win32_font_calc_coverage (PangoFont *font,
#ifdef PANGO_WIN32_DEBUGGING
else if (ch0 < G_MAXUINT)
{
- if (ch > ch0 + 2)
- printf ("%04x:%04x ", ch0, ch - 1);
- else
- printf ("%04x ", ch0);
+ if (pango_win32_debug)
+ {
+ if (ch > ch0 + 2)
+ printf ("%04x:%04x ", ch0, ch - 1);
+ else
+ printf ("%04x ", ch0);
+ }
ch0 = G_MAXUINT;
}
#endif
@@ -1279,15 +1370,19 @@ pango_win32_font_calc_coverage (PangoFont *font,
#ifdef PANGO_WIN32_DEBUGGING
if (ch0 < G_MAXUINT)
{
- if (ch > ch0 + 2)
- printf ("%04x:%04x ", ch0, ch - 1);
- else
- printf ("%04x ", ch0);
+ if (pango_win32_debug)
+ {
+ if (ch > ch0 + 2)
+ printf ("%04x:%04x ", ch0, ch - 1);
+ else
+ printf ("%04x ", ch0);
+ }
}
#endif
}
}
#ifdef PANGO_WIN32_DEBUGGING
- printf ("\n");
+ if (pango_win32_debug)
+ printf ("\n");
#endif
}
diff --git a/pango/pangowin32.def b/pango/pangowin32.def
index 9592753c..0754abcc 100644
--- a/pango/pangowin32.def
+++ b/pango/pangowin32.def
@@ -13,6 +13,8 @@ EXPORTS
pango_win32_fontmap_cache_add
pango_win32_fontmap_cache_remove
pango_win32_get_context
+ pango_win32_get_dc
+ pango_win32_get_debug_flag
pango_win32_get_shaper_map
pango_win32_get_unknown_glyph
pango_win32_make_matching_logfont
diff --git a/pango/pangowin32.h b/pango/pangowin32.h
index 49dcd08a..ece1b829 100644
--- a/pango/pangowin32.h
+++ b/pango/pangowin32.h
@@ -68,6 +68,10 @@ PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font,
gint pango_win32_font_get_glyph_index(PangoFont *font,
gunichar wc);
+HDC pango_win32_get_dc (void);
+
+gboolean pango_win32_get_debug_flag (void);
+
#endif
/* API for libraries that want to use PangoWin32 mixed with classic