📄 basic-win32.c
字号:
{ byte_offset[charix] = p - text; charix++; p = g_utf8_next_char (p); } /* Convert char indexes in the log_clusters array to byte offsets. */ for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) { g_assert (glyphs->log_clusters[glyphix] < n_chars); glyphs->log_clusters[glyphix] = byte_offset[glyphs->log_clusters[glyphix]]; } g_free (byte_offset);}static gbooleanitemize_shape_and_place (PangoFont *font, HDC hdc, wchar_t *wtext, int wlen, const PangoAnalysis *analysis, PangoGlyphString *glyphs, SCRIPT_CACHE *script_cache){ int i; int item, nitems, item_step; int itemlen, glyphix, nglyphs; SCRIPT_CONTROL control; SCRIPT_STATE state; SCRIPT_ITEM items[100]; double scale = pango_win32_font_get_metrics_factor (font); memset (&control, 0, sizeof (control)); memset (&state, 0, sizeof (state)); control.uDefaultLanguage = make_langid (analysis->language); state.uBidiLevel = analysis->level;#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print (G_STRLOC ": ScriptItemize: uDefaultLanguage:%04x uBidiLevel:%d\n", control.uDefaultLanguage, state.uBidiLevel);#endif if ((*script_itemize) (wtext, wlen, G_N_ELEMENTS (items), &control, NULL, items, &nitems)) {#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print ("ScriptItemize failed\n");#endif return FALSE; }#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print ("%d items:\n", nitems);#endif if (analysis->level % 2) { item = nitems - 1; item_step = -1; } else { item = 0; item_step = 1; } for (i = 0; i < nitems; i++, item += item_step) { 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; int char_offset; memset (advances, 0, sizeof (advances)); memset (offsets, 0, sizeof (offsets)); memset (&abc, 0, sizeof (abc)); /* Note that itemlen is number of wchar_t's i.e. surrogate pairs * count as two! */ itemlen = items[item+1].iCharPos - items[item].iCharPos; char_offset = unichar_index (wtext, items[item].iCharPos);#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print (" Item %d: iCharPos=%d eScript=%d (%s) %s%s%s%s%s%s%s wchar_t %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 items[item].a.fRTL = analysis->level % 2; 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) g_print ("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 (wtext + items[item].iCharPos, items[item].a.fRTL, itemlen, log_clusters, nglyphs, glyphs->log_clusters + ng, char_offset); if ((*script_place) (hdc, &script_cache[script], iglyphs, nglyphs, visattrs, &items[item].a, advances, offsets, &abc)) {#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print ("pango-basic-win32: ScriptPlace failed\n");#endif return FALSE; } for (glyphix = 0; glyphix < nglyphs; glyphix++) { if (iglyphs[glyphix] != 0) { glyphs->glyphs[ng+glyphix].glyph = iglyphs[glyphix]; glyphs->glyphs[ng+glyphix].geometry.width = floor (0.5 + scale * advances[glyphix]); glyphs->glyphs[ng+glyphix].geometry.x_offset = floor (0.5 + scale * offsets[glyphix].du); glyphs->glyphs[ng+glyphix].geometry.y_offset = floor (0.5 + scale * offsets[glyphix].dv); } else { PangoRectangle logical_rect; /* Should pass actual char that was not found to * PANGO_GET_UNKNOWN_GLYPH(), but a bit hard to * find out that at this point, so cheat and use 0. */ PangoGlyph unk = PANGO_GET_UNKNOWN_GLYPH (0); glyphs->glyphs[ng+glyphix].glyph = unk; pango_font_get_glyph_extents (font, unk, NULL, &logical_rect); glyphs->glyphs[ng+glyphix].geometry.width = logical_rect.width; glyphs->glyphs[ng+glyphix].geometry.x_offset = 0; glyphs->glyphs[ng+glyphix].geometry.y_offset = 0; } } }#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) { g_print (" Pango log_clusters (level:%d), char index:", analysis->level); for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) g_print ("%d ", glyphs->log_clusters[glyphix]); g_print ("\n"); }#endif return TRUE;}static gbooleanuniscribe_shape (PangoFont *font, const char *text, gint length, const PangoAnalysis *analysis, PangoGlyphString *glyphs){ wchar_t *wtext; long wlen; int i; gboolean retval = TRUE; SCRIPT_CACHE script_cache[100]; if (!pango_win32_font_select_font (font, hdc)) return FALSE; wtext = g_utf8_to_utf16 (text, length, NULL, &wlen, NULL); if (wtext == NULL) retval = FALSE; if (retval) { memset (script_cache, 0, sizeof (script_cache)); retval = itemize_shape_and_place (font, 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, glyphs);#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) { int glyphix; g_print (" Pango log_clusters, byte offsets:"); for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) g_print ("%d ", glyphs->log_clusters[glyphix]); g_print ("\n"); }#endif } pango_win32_font_done_font (font); g_free (wtext); return retval && glyphs->num_glyphs > 0;}static gbooleantext_is_simple (const char *text, gint length){ gboolean retval; wchar_t *wtext; long wlen; wtext = (wchar_t *) g_utf8_to_utf16 (text, length, NULL, &wlen, NULL); if (wtext == NULL) return TRUE; retval = ((*script_is_complex) (wtext, wlen, SIC_COMPLEX) == S_FALSE); g_free (wtext);#ifdef BASIC_WIN32_DEBUGGING if (pango_win32_debug) g_print ("text_is_simple: %.*s (%ld wchar_t): %s\n", MIN (length, 10), text, wlen, retval ? "YES" : "NO");#endif return retval;}static voidbasic_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, int length, const PangoAnalysis *analysis, PangoGlyphString *glyphs){ int n_chars; int i; const char *p; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); if (have_uniscribe && !text_is_simple (text, length) && uniscribe_shape (font, text, length, analysis, glyphs)) return; n_chars = g_utf8_strlen (text, length); pango_glyph_string_set_size (glyphs, n_chars); p = text; for (i = 0; i < n_chars; i++) { gunichar wc; gunichar mirrored_ch; PangoGlyph index; wc = g_utf8_get_char (p); if (analysis->level % 2) if (pango_get_mirror_char (wc, &mirrored_ch)) wc = mirrored_ch; if (wc == 0xa0) /* non-break-space */ wc = 0x20; if (pango_is_zero_width (wc)) { set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY); } else { index = find_char (font, wc); if (index) { set_glyph (font, glyphs, i, p - text, index); if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK) { if (i > 0) { PangoRectangle logical_rect, ink_rect; glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width, glyphs->glyphs[i].geometry.width); glyphs->glyphs[i-1].geometry.width = 0; glyphs->log_clusters[i] = glyphs->log_clusters[i-1]; /* Some heuristics to try to guess how overstrike glyphs are * done and compensate */ /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect); if (logical_rect.width == 0 && ink_rect.x == 0) glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2; } } } else set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc)); } p = g_utf8_next_char (p); } /* Simple bidi support... may have separate modules later */ if (analysis->level % 2) { int start, end; /* Swap all glyphs */ swap_range (glyphs, 0, n_chars); /* Now reorder glyphs within each cluster back to LTR */ for (start = 0; start < n_chars;) { end = start; while (end < n_chars && glyphs->log_clusters[end] == glyphs->log_clusters[start]) end++; swap_range (glyphs, start, end); start = end; } }}static voidinit_uniscribe (void){ HMODULE usp10_dll; have_uniscribe = FALSE; if ((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")) && (script_is_complex = (pScriptIsComplex) GetProcAddress (usp10_dll, "ScriptIsComplex")) && (have_uniscribe = TRUE); } if (have_uniscribe) {#ifdef BASIC_WIN32_DEBUGGING (*script_get_properties) (&scripts, &nscripts);#endif hdc = pango_win32_get_dc (); }}static voidbasic_engine_win32_class_init (PangoEngineShapeClass *class){ class->script_shape = basic_engine_shape;}PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineWin32, basic_engine_win32, basic_engine_win32_class_init, NULL);voidPANGO_MODULE_ENTRY(init) (GTypeModule *module){ init_uniscribe (); if (pango_win32_get_debug_flag ()) pango_win32_debug = TRUE; basic_engine_win32_register_type (module);}voidPANGO_MODULE_ENTRY(exit) (void){}voidPANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines, int *n_engines){ init_uniscribe (); script_engines[0].scripts = basic_scripts; script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts); if (have_uniscribe) {#if 0 int i; GArray *ranges = g_array_new (FALSE, FALSE, sizeof (PangoEngineRange)); /* Walk through scripts supported by the Uniscribe implementation on this * machine, and mark corresponding Unicode ranges. */ for (i = 0; i < nscripts; i++) { } /* Sort range array */ g_array_sort (ranges, compare_range); script_engines[0].ranges = ranges; script_engines[0].n_ranges = ranges->len;#else script_engines[0].scripts = uniscribe_scripts; script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);#endif } *engines = script_engines; *n_engines = G_N_ELEMENTS (script_engines);}PangoEngine *PANGO_MODULE_ENTRY(create) (const char *id){ if (!strcmp (id, SCRIPT_ENGINE_NAME)) return g_object_new (basic_engine_win32_type, NULL); else return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -