summaryrefslogtreecommitdiff
path: root/modules
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 /modules
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.
Diffstat (limited to 'modules')
-rw-r--r--modules/basic/Makefile.am10
-rw-r--r--modules/basic/basic-win32.c749
2 files changed, 758 insertions, 1 deletions
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