diff options
author | Tor Lillqvist <tml@iki.fi> | 2002-10-21 23:48:24 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2002-10-21 23:48:24 +0000 |
commit | efe38161780103a7f01e1f241eca4d02e2039326 (patch) | |
tree | 07f9cd08c2af02229fe0cfb32dfee53189f4b889 | |
parent | f1da959cfb199c97e45b2bde9a093205e2405247 (diff) | |
download | pango-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-- | ChangeLog | 41 | ||||
-rw-r--r-- | ChangeLog.pre-1-10 | 41 | ||||
-rw-r--r-- | ChangeLog.pre-1-2 | 41 | ||||
-rw-r--r-- | ChangeLog.pre-1-4 | 41 | ||||
-rw-r--r-- | ChangeLog.pre-1-6 | 41 | ||||
-rw-r--r-- | ChangeLog.pre-1-8 | 41 | ||||
-rw-r--r-- | acconfig.h | 1 | ||||
-rw-r--r-- | configure.in | 29 | ||||
-rw-r--r-- | modules/basic/Makefile.am | 10 | ||||
-rw-r--r-- | modules/basic/basic-win32.c | 749 | ||||
-rw-r--r-- | pango/pangowin32-fontmap.c | 5 | ||||
-rw-r--r-- | pango/pangowin32-private.h | 30 | ||||
-rw-r--r-- | pango/pangowin32.c | 249 | ||||
-rw-r--r-- | pango/pangowin32.def | 2 | ||||
-rw-r--r-- | pango/pangowin32.h | 4 |
15 files changed, 1233 insertions, 92 deletions
@@ -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. @@ -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 |