4 * Copyright (C) 1999 Red Hat Software
5 * Copyright (C) 2001 Alexander Larsson
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 #define BASIC_WIN32_DEBUGGING
32 #include "pangowin32.h"
33 #include "pango-engine.h"
34 #include "pango-utils.h"
36 /* No extra fields needed */
37 typedef PangoEngineShape BasicEngineWin32;
38 typedef PangoEngineShapeClass BasicEngineWin32Class ;
40 #define SCRIPT_ENGINE_NAME "BasicScriptEngineWin32"
42 static gboolean pango_win32_debug = FALSE;
46 static gboolean have_uniscribe = FALSE;
50 typedef HRESULT (WINAPI *pScriptGetProperties) (const SCRIPT_PROPERTIES ***,
53 typedef HRESULT (WINAPI *pScriptItemize) (const WCHAR *,
56 const SCRIPT_CONTROL *,
61 typedef HRESULT (WINAPI *pScriptShape) (HDC,
72 typedef HRESULT (WINAPI *pScriptPlace) (HDC,
76 const SCRIPT_VISATTR *,
82 typedef HRESULT (WINAPI *pScriptFreeCache) (SCRIPT_CACHE *);
84 typedef HRESULT (WINAPI *pScriptIsComplex) (WCHAR *,
88 static pScriptGetProperties script_get_properties;
89 static pScriptItemize script_itemize;
90 static pScriptShape script_shape;
91 static pScriptPlace script_place;
92 static pScriptFreeCache script_free_cache;
93 static pScriptIsComplex script_is_complex;
95 #ifdef BASIC_WIN32_DEBUGGING
96 static const SCRIPT_PROPERTIES **scripts;
100 static PangoEngineScriptInfo uniscribe_scripts[] = {
101 /* We claim to cover everything ;-) */
102 { PANGO_SCRIPT_COMMON, "" },
105 static PangoEngineScriptInfo basic_scripts[] = {
106 /* Those characters that can be rendered legibly without Uniscribe.
107 * I am not certain this list is correct.
109 { PANGO_SCRIPT_ARMENIAN, "*" },
110 { PANGO_SCRIPT_BOPOMOFO, "*" },
111 { PANGO_SCRIPT_CHEROKEE, "*" },
112 { PANGO_SCRIPT_COPTIC, "*" },
113 { PANGO_SCRIPT_CYRILLIC, "*" },
114 { PANGO_SCRIPT_DESERET, "*" },
115 { PANGO_SCRIPT_ETHIOPIC, "*" },
116 { PANGO_SCRIPT_GEORGIAN, "*" },
117 { PANGO_SCRIPT_GOTHIC, "*" },
118 { PANGO_SCRIPT_GREEK, "*" },
119 { PANGO_SCRIPT_HAN, "*" },
120 { PANGO_SCRIPT_HANGUL, "*" },
121 { PANGO_SCRIPT_HIRAGANA, "*" },
122 { PANGO_SCRIPT_KATAKANA, "*" },
123 { PANGO_SCRIPT_LATIN, "*" },
124 { PANGO_SCRIPT_OGHAM, "*" },
125 { PANGO_SCRIPT_OLD_ITALIC, "*" },
126 { PANGO_SCRIPT_RUNIC, "*" },
127 { PANGO_SCRIPT_THAI, "*" },
128 { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
129 { PANGO_SCRIPT_YI, "*" },
130 { PANGO_SCRIPT_BRAILLE, "*" },
131 { PANGO_SCRIPT_CYPRIOT, "*" },
132 { PANGO_SCRIPT_LIMBU, "*" },
133 { PANGO_SCRIPT_OSMANYA, "*" },
134 { PANGO_SCRIPT_SHAVIAN, "*" },
135 { PANGO_SCRIPT_LINEAR_B, "*" },
136 { PANGO_SCRIPT_UGARITIC, "*" },
138 /* Claim to handle everything as a fallback */
139 { PANGO_SCRIPT_COMMON, "" }
142 static PangoEngineInfo script_engines[] = {
145 PANGO_ENGINE_TYPE_SHAPE,
146 PANGO_RENDER_TYPE_WIN32,
152 find_char (PangoFont *font,
155 return pango_win32_font_get_glyph_index (font, wc);
159 set_glyph (PangoFont *font,
160 PangoGlyphString *glyphs,
165 PangoRectangle logical_rect;
167 glyphs->glyphs[i].glyph = glyph;
169 glyphs->glyphs[i].geometry.x_offset = 0;
170 glyphs->glyphs[i].geometry.y_offset = 0;
172 glyphs->log_clusters[i] = offset;
174 pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
175 glyphs->glyphs[i].geometry.width = logical_rect.width;
179 swap_range (PangoGlyphString *glyphs,
185 for (i = start, j = end - 1; i < j; i++, j--)
187 PangoGlyphInfo glyph_info;
190 glyph_info = glyphs->glyphs[i];
191 glyphs->glyphs[i] = glyphs->glyphs[j];
192 glyphs->glyphs[j] = glyph_info;
194 log_cluster = glyphs->log_clusters[i];
195 glyphs->log_clusters[i] = glyphs->log_clusters[j];
196 glyphs->log_clusters[j] = log_cluster;
200 #ifdef BASIC_WIN32_DEBUGGING
205 LCID lcid = MAKELCID (lang, SORT_DEFAULT);
206 static char retval[10];
208 if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, retval, G_N_ELEMENTS (retval)))
209 sprintf (retval, "%#02x", lang);
214 #endif /* BASIC_WIN32_DEBUGGING */
217 make_langid (PangoLanguage *lang)
219 #define CASE(t,p,s) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_##p##_##s)
220 #define CASEN(t,p) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_NEUTRAL)
222 /* Languages that most probably don't affect Uniscribe have been
223 * left out. Uniscribe is documented to use
224 * SCRIPT_CONTROL::uDefaultLanguage only to select digit shapes, so
225 * just leave languages with own digits.
228 CASEN ("ar", ARABIC);
229 CASEN ("hy", ARMENIAN);
230 CASEN ("as", ASSAMESE);
232 CASEN ("bn", BENGALI);
233 CASE ("zh-tw", CHINESE, TRADITIONAL);
234 CASE ("zh-cn", CHINESE, SIMPLIFIED);
235 CASE ("zh-hk", CHINESE, HONGKONG);
236 CASE ("zh-sg", CHINESE, SINGAPORE);
237 CASE ("zh-mo", CHINESE, MACAU);
238 CASEN ("dib", DIVEHI);
240 CASEN ("ka", GEORGIAN);
241 CASEN ("gu", GUJARATI);
242 CASEN ("he", HEBREW);
244 CASEN ("ja", JAPANESE);
245 CASEN ("kn", KANNADA);
246 CASE ("ks-in", KASHMIRI, INDIA);
247 CASEN ("ks", KASHMIRI);
249 CASEN ("kok", KONKANI);
250 CASEN ("ko", KOREAN);
251 CASEN ("ky", KYRGYZ);
252 CASEN ("ml", MALAYALAM);
253 CASEN ("mni", MANIPURI);
254 CASEN ("mr", MARATHI);
255 CASEN ("mn", MONGOLIAN);
256 CASE ("ne-in", NEPALI, INDIA);
257 CASEN ("ne", NEPALI);
259 CASEN ("pa", PUNJABI);
260 CASEN ("sa", SANSKRIT);
261 CASEN ("sd", SINDHI);
262 CASEN ("syr", SYRIAC);
265 CASEN ("te", TELUGU);
267 CASE ("ur-pk", URDU, PAKISTAN);
268 CASE ("ur-in", URDU, INDIA);
275 return MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
278 #ifdef BASIC_WIN32_DEBUGGING
281 dump_glyphs_and_log_clusters (gboolean rtl,
288 if (pango_win32_debug)
290 int j, k, nclusters, clusterix, charix, ng;
292 g_print (" ScriptShape: nglyphs=%d: ", nglyphs);
294 for (j = 0; j < nglyphs; j++)
295 g_print ("%d%s", iglyphs[j], (j < nglyphs-1) ? "," : "");
298 g_print (" log_clusters: ");
299 for (j = 0; j < itemlen; j++)
300 g_print ("%d ", log_clusters[j]);
303 for (j = 0; j < itemlen; j++)
305 if (j == 0 || log_clusters[j-1] != log_clusters[j])
308 g_print (" %d clusters:\n", nclusters);
310 /* If RTL, first char is the last in the run, otherwise the
316 int firstglyphix = 0;
317 for (j = itemlen - 1, charix = charix0 + j; j >= 0; j--, charix--)
319 if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
320 g_print (" Cluster %d: chars %d--",
322 if (j == 0 || log_clusters[j-1] != log_clusters[j])
324 ng = log_clusters[j] - firstglyphix + 1;
325 g_print ("%d: %d glyphs: ",
327 for (k = firstglyphix; k <= log_clusters[j]; k++)
329 g_print ("%d", iglyphs[k]);
330 if (k < log_clusters[j])
333 firstglyphix = log_clusters[j] + 1;
341 for (j = 0, charix = charix0; j < itemlen; j++, charix++)
343 if (j == 0 || log_clusters[j-1] != log_clusters[j])
344 g_print (" Cluster %d: wchar_t %d--",
346 if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1])
348 int klim = ((j == itemlen-1) ? nglyphs : log_clusters[j+1]);
349 ng = klim - log_clusters[j];
350 g_print ("%d: %d glyphs: ",
352 for (k = log_clusters[j]; k < klim; k++)
354 g_print ("%d", iglyphs[k]);
366 #endif /* BASIC_WIN32_DEBUGGING */
369 unichar_index (wchar_t *wtext,
375 for (i = 0; i < ix; i++)
376 /* Ignore the low surrogate */
377 if (!(wtext[i] >= 0xDC00 && wtext[i] < 0xE000))
384 set_up_pango_log_clusters (wchar_t *wtext,
387 WORD *usp_log_clusters,
389 gint *pango_log_clusters,
393 int first_char_in_cluster;
397 /* RTL. Walk Uniscribe log_clusters array backwards, build Pango
398 * log_clusters array forwards.
401 first_char_in_cluster = unichar_index (wtext, itemlen - 1);
402 for (j = itemlen - 1; j >= 0; j--)
404 if (j < itemlen - 1 && usp_log_clusters[j+1] != usp_log_clusters[j])
407 first_char_in_cluster = unichar_index (wtext, j);
411 /* First char, cluster ends */
412 for (k = glyph0; k < nglyphs; k++)
413 pango_log_clusters[k] = first_char_in_cluster + char_offset;
415 else if (usp_log_clusters[j-1] == usp_log_clusters[j])
417 /* Cluster continues */
418 first_char_in_cluster = unichar_index (wtext, j-1);
423 for (k = glyph0; k <= usp_log_clusters[j]; k++)
424 pango_log_clusters[k] = first_char_in_cluster + char_offset;
425 glyph0 = usp_log_clusters[j] + 1;
431 /* LTR. Walk Uniscribe log_clusters array forwards, build Pango
432 * log_clusters array also forwards.
434 first_char_in_cluster = 0;
435 for (j = 0; j < itemlen; j++)
437 if (j > 0 && usp_log_clusters[j-1] != usp_log_clusters[j])
440 first_char_in_cluster = unichar_index (wtext, j);
442 if (j == itemlen - 1)
444 /* Last char, cluster ends */
445 for (k = usp_log_clusters[j]; k < nglyphs; k++)
446 pango_log_clusters[k] = first_char_in_cluster + char_offset;
448 else if (usp_log_clusters[j] == usp_log_clusters[j+1])
450 /* Cluster continues */
455 for (k = usp_log_clusters[j]; k < usp_log_clusters[j+1]; k++)
456 pango_log_clusters[k] = first_char_in_cluster + char_offset;
463 convert_log_clusters_to_byte_offsets (const char *text,
465 PangoGlyphString *glyphs)
469 int n_chars = g_utf8_strlen (text, length);
470 int *byte_offset = g_new (int, n_chars);
474 while (p < text + length)
476 byte_offset[charix] = p - text;
478 p = g_utf8_next_char (p);
481 /* Convert char indexes in the log_clusters array to byte offsets.
483 for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
485 g_assert (glyphs->log_clusters[glyphix] < n_chars);
486 glyphs->log_clusters[glyphix] = byte_offset[glyphs->log_clusters[glyphix]];
489 g_free (byte_offset);
493 itemize_shape_and_place (PangoFont *font,
497 const PangoAnalysis *analysis,
498 PangoGlyphString *glyphs,
499 SCRIPT_CACHE *script_cache)
502 int item, nitems, item_step;
503 int itemlen, glyphix, nglyphs;
504 SCRIPT_CONTROL control;
506 SCRIPT_ITEM items[100];
507 double scale = pango_win32_font_get_metrics_factor (font);
509 memset (&control, 0, sizeof (control));
510 memset (&state, 0, sizeof (state));
512 control.uDefaultLanguage = make_langid (analysis->language);
513 state.uBidiLevel = analysis->level;
515 #ifdef BASIC_WIN32_DEBUGGING
516 if (pango_win32_debug)
517 g_print (G_STRLOC ": ScriptItemize: uDefaultLanguage:%04x uBidiLevel:%d\n",
518 control.uDefaultLanguage, state.uBidiLevel);
520 if ((*script_itemize) (wtext, wlen, G_N_ELEMENTS (items), &control, NULL,
523 #ifdef BASIC_WIN32_DEBUGGING
524 if (pango_win32_debug)
525 g_print ("ScriptItemize failed\n");
530 #ifdef BASIC_WIN32_DEBUGGING
531 if (pango_win32_debug)
532 g_print ("%d items:\n", nitems);
535 if (analysis->level % 2)
546 for (i = 0; i < nitems; i++, item += item_step)
549 WORD log_clusters[1000];
550 SCRIPT_VISATTR visattrs[1000];
552 GOFFSET offsets[1000];
554 int script = items[item].a.eScript;
558 memset (advances, 0, sizeof (advances));
559 memset (offsets, 0, sizeof (offsets));
560 memset (&abc, 0, sizeof (abc));
562 /* Note that itemlen is number of wchar_t's i.e. surrogate pairs
565 itemlen = items[item+1].iCharPos - items[item].iCharPos;
566 char_offset = unichar_index (wtext, items[item].iCharPos);
568 #ifdef BASIC_WIN32_DEBUGGING
569 if (pango_win32_debug)
570 g_print (" Item %d: iCharPos=%d eScript=%d (%s) %s%s%s%s%s%s%s wchar_t %d--%d (%d)\n",
571 item, items[item].iCharPos, script,
572 lang_name (scripts[script]->langid),
573 scripts[script]->fComplex ? "complex" : "simple",
574 items[item].a.fRTL ? " fRTL" : "",
575 items[item].a.fLayoutRTL ? " fLayoutRTL" : "",
576 items[item].a.fLinkBefore ? " fLinkBefore" : "",
577 items[item].a.fLinkAfter ? " fLinkAfter" : "",
578 items[item].a.fLogicalOrder ? " fLogicalOrder" : "",
579 items[item].a.fNoGlyphIndex ? " fNoGlyphIndex" : "",
580 items[item].iCharPos, items[item+1].iCharPos-1, itemlen);
583 items[item].a.fRTL = analysis->level % 2;
584 if ((*script_shape) (hdc, &script_cache[script],
585 wtext + items[item].iCharPos, itemlen,
586 G_N_ELEMENTS (iglyphs),
593 #ifdef BASIC_WIN32_DEBUGGING
594 if (pango_win32_debug)
595 g_print ("pango-basic-win32: ScriptShape failed\n");
600 #ifdef BASIC_WIN32_DEBUGGING
601 dump_glyphs_and_log_clusters (items[item].a.fRTL, itemlen,
602 items[item].iCharPos, log_clusters,
606 ng = glyphs->num_glyphs;
607 pango_glyph_string_set_size (glyphs, ng + nglyphs);
609 set_up_pango_log_clusters (wtext + items[item].iCharPos,
610 items[item].a.fRTL, itemlen, log_clusters,
611 nglyphs, glyphs->log_clusters + ng,
614 if ((*script_place) (hdc, &script_cache[script], iglyphs, nglyphs,
615 visattrs, &items[item].a,
616 advances, offsets, &abc))
618 #ifdef BASIC_WIN32_DEBUGGING
619 if (pango_win32_debug)
620 g_print ("pango-basic-win32: ScriptPlace failed\n");
625 for (glyphix = 0; glyphix < nglyphs; glyphix++)
627 if (iglyphs[glyphix] != 0)
629 glyphs->glyphs[ng+glyphix].glyph = iglyphs[glyphix];
630 glyphs->glyphs[ng+glyphix].geometry.width = floor (0.5 + scale * advances[glyphix]);
631 glyphs->glyphs[ng+glyphix].geometry.x_offset = floor (0.5 + scale * offsets[glyphix].du);
632 glyphs->glyphs[ng+glyphix].geometry.y_offset = floor (0.5 + scale * offsets[glyphix].dv);
636 PangoRectangle logical_rect;
637 /* Should pass actual char that was not found to
638 * PANGO_GET_UNKNOWN_GLYPH(), but a bit hard to
639 * find out that at this point, so cheat and use 0.
641 PangoGlyph unk = PANGO_GET_UNKNOWN_GLYPH (0);
643 glyphs->glyphs[ng+glyphix].glyph = unk;
644 pango_font_get_glyph_extents (font, unk, NULL, &logical_rect);
645 glyphs->glyphs[ng+glyphix].geometry.width = logical_rect.width;
646 glyphs->glyphs[ng+glyphix].geometry.x_offset = 0;
647 glyphs->glyphs[ng+glyphix].geometry.y_offset = 0;
652 #ifdef BASIC_WIN32_DEBUGGING
653 if (pango_win32_debug)
655 g_print (" Pango log_clusters (level:%d), char index:", analysis->level);
656 for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
657 g_print ("%d ", glyphs->log_clusters[glyphix]);
666 uniscribe_shape (PangoFont *font,
669 const PangoAnalysis *analysis,
670 PangoGlyphString *glyphs)
675 gboolean retval = TRUE;
676 SCRIPT_CACHE script_cache[100];
678 if (!pango_win32_font_select_font (font, hdc))
681 wtext = g_utf8_to_utf16 (text, length, NULL, &wlen, NULL);
687 memset (script_cache, 0, sizeof (script_cache));
688 retval = itemize_shape_and_place (font, hdc, wtext, wlen, analysis, glyphs, script_cache);
689 for (i = 0; i < G_N_ELEMENTS (script_cache); i++)
691 (*script_free_cache)(&script_cache[i]);
696 convert_log_clusters_to_byte_offsets (text, length, glyphs);
697 #ifdef BASIC_WIN32_DEBUGGING
698 if (pango_win32_debug)
702 g_print (" Pango log_clusters, byte offsets:");
703 for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++)
704 g_print ("%d ", glyphs->log_clusters[glyphix]);
710 pango_win32_font_done_font (font);
714 return retval && glyphs->num_glyphs > 0;
718 text_is_simple (const char *text,
725 wtext = (wchar_t *) g_utf8_to_utf16 (text, length, NULL, &wlen, NULL);
729 retval = ((*script_is_complex) (wtext, wlen, SIC_COMPLEX) == S_FALSE);
733 #ifdef BASIC_WIN32_DEBUGGING
734 if (pango_win32_debug)
735 g_print ("text_is_simple: %.*s (%ld wchar_t): %s\n",
736 MIN (length, 10), text, wlen, retval ? "YES" : "NO");
743 basic_engine_shape (PangoEngineShape *engine,
747 const PangoAnalysis *analysis,
748 PangoGlyphString *glyphs)
754 g_return_if_fail (font != NULL);
755 g_return_if_fail (text != NULL);
756 g_return_if_fail (length >= 0);
757 g_return_if_fail (analysis != NULL);
759 if (have_uniscribe &&
760 !text_is_simple (text, length) &&
761 uniscribe_shape (font, text, length, analysis, glyphs))
764 n_chars = g_utf8_strlen (text, length);
766 pango_glyph_string_set_size (glyphs, n_chars);
769 for (i = 0; i < n_chars; i++)
772 gunichar mirrored_ch;
775 wc = g_utf8_get_char (p);
777 if (analysis->level % 2)
778 if (pango_get_mirror_char (wc, &mirrored_ch))
781 if (wc == 0xa0) /* non-break-space */
784 if (pango_is_zero_width (wc))
786 set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
790 index = find_char (font, wc);
793 set_glyph (font, glyphs, i, p - text, index);
795 if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
799 PangoRectangle logical_rect, ink_rect;
801 glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
802 glyphs->glyphs[i].geometry.width);
803 glyphs->glyphs[i-1].geometry.width = 0;
804 glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
806 /* Some heuristics to try to guess how overstrike glyphs are
807 * done and compensate
809 /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */
810 pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
811 if (logical_rect.width == 0 && ink_rect.x == 0)
812 glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
817 set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc));
820 p = g_utf8_next_char (p);
823 /* Simple bidi support... may have separate modules later */
825 if (analysis->level % 2)
829 /* Swap all glyphs */
830 swap_range (glyphs, 0, n_chars);
832 /* Now reorder glyphs within each cluster back to LTR */
833 for (start = 0; start < n_chars;)
836 while (end < n_chars &&
837 glyphs->log_clusters[end] == glyphs->log_clusters[start])
840 swap_range (glyphs, start, end);
847 init_uniscribe (void)
851 have_uniscribe = FALSE;
853 if ((usp10_dll = LoadLibrary ("usp10.dll")) != NULL)
855 (script_get_properties = (pScriptGetProperties)
856 GetProcAddress (usp10_dll, "ScriptGetProperties")) &&
857 (script_itemize = (pScriptItemize)
858 GetProcAddress (usp10_dll, "ScriptItemize")) &&
859 (script_shape = (pScriptShape)
860 GetProcAddress (usp10_dll, "ScriptShape")) &&
861 (script_place = (pScriptPlace)
862 GetProcAddress (usp10_dll, "ScriptPlace")) &&
863 (script_free_cache = (pScriptFreeCache)
864 GetProcAddress (usp10_dll, "ScriptFreeCache")) &&
865 (script_is_complex = (pScriptIsComplex)
866 GetProcAddress (usp10_dll, "ScriptIsComplex")) &&
867 (have_uniscribe = TRUE);
871 #ifdef BASIC_WIN32_DEBUGGING
872 (*script_get_properties) (&scripts, &nscripts);
874 hdc = pango_win32_get_dc ();
879 basic_engine_win32_class_init (PangoEngineShapeClass *class)
881 class->script_shape = basic_engine_shape;
884 PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineWin32, basic_engine_win32,
885 basic_engine_win32_class_init, NULL);
888 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
892 if (pango_win32_get_debug_flag ())
893 pango_win32_debug = TRUE;
895 basic_engine_win32_register_type (module);
899 PANGO_MODULE_ENTRY(exit) (void)
904 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
909 script_engines[0].scripts = basic_scripts;
910 script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts);
916 GArray *ranges = g_array_new (FALSE, FALSE, sizeof (PangoEngineRange));
918 /* Walk through scripts supported by the Uniscribe implementation on this
919 * machine, and mark corresponding Unicode ranges.
921 for (i = 0; i < nscripts; i++)
925 /* Sort range array */
926 g_array_sort (ranges, compare_range);
927 script_engines[0].ranges = ranges;
928 script_engines[0].n_ranges = ranges->len;
930 script_engines[0].scripts = uniscribe_scripts;
931 script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);
935 *engines = script_engines;
936 *n_engines = G_N_ELEMENTS (script_engines);
940 PANGO_MODULE_ENTRY(create) (const char *id)
942 if (!strcmp (id, SCRIPT_ENGINE_NAME))
943 return g_object_new (basic_engine_win32_type, NULL);