Mercurial > emacs
changeset 97025:e72be8a4fdb8
(uniscribe_shape): Pass NULL for control arg to ScriptItemize. Clean
up return value checking. Remove unused variables.
(uniscribe_encode_char): Encode non-BMP characters with uniscribe
shaping engine.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Fri, 25 Jul 2008 21:53:21 +0000 |
parents | c46e4c1d8339 |
children | aebbea50eef4 |
files | src/ChangeLog src/w32uniscribe.c |
diffstat | 2 files changed, 66 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog Fri Jul 25 21:44:37 2008 +0000 +++ b/src/ChangeLog Fri Jul 25 21:53:21 2008 +0000 @@ -1,3 +1,14 @@ +2008-07-25 Jason Rumney <jasonr@gnu.org> + + * w32uniscribe.c (uniscribe_shape): Pass NULL for control arg to + ScriptItemize. Clean up return value checking. Remove unused + variables. + (uniscribe_encode_char): Encode non-BMP characters with uniscribe + shaping engine. + + * w32font.c (w32font_has_char): Handle the case where we can't + determine the script for a character. + 2008-07-25 Chong Yidong <cyd@stupidchicken.com> * term.c (syms_of_term): Initialize default_orig_pair,
--- a/src/w32uniscribe.c Fri Jul 25 21:44:37 2008 +0000 +++ b/src/w32uniscribe.c Fri Jul 25 21:53:21 2008 +0000 @@ -134,6 +134,7 @@ /* Initialize the cache for this font. */ uniscribe_font->cache = NULL; + /* Mark the format as opentype */ uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype; uniscribe_font->w32_font.font.driver = &uniscribe_font_driver; @@ -150,7 +151,7 @@ = (struct uniscribe_font_info *) font; if (uniscribe_font->cache) - ScriptFreeCache (&uniscribe_font->cache); + ScriptFreeCache (&(uniscribe_font->cache)); w32font_close (f, font); } @@ -206,12 +207,10 @@ wchar_t *chars; WORD *glyphs, *clusters; SCRIPT_ITEM *items; - SCRIPT_CONTROL control; SCRIPT_VISATTR *attributes; int *advances; GOFFSET *offsets; ABC overall_metrics; - MAT2 transform; HDC context; HFONT old_font; HRESULT result; @@ -239,9 +238,8 @@ can be treated together. First try a single run. */ max_items = 2; items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); - bzero (&control, sizeof (control)); - while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL, + while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, items, &nitems)) == E_OUTOFMEMORY) { /* If that wasn't enough, keep trying with one more run. */ @@ -250,8 +248,7 @@ sizeof (SCRIPT_ITEM) * max_items + 1); } - /* 0 = success in Microsoft's backwards world. */ - if (result) + if (!SUCCEEDED (result)) { xfree (items); return Qnil; @@ -269,9 +266,6 @@ attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR)); advances = alloca (max_glyphs * sizeof (int)); offsets = alloca (max_glyphs * sizeof (GOFFSET)); - bzero (&transform, sizeof (transform)); - transform.eM11.value = 1; - transform.eM22.value = 1; for (i = 0; i < nitems; i++) { @@ -304,7 +298,7 @@ result = ScriptPlace (context, &(uniscribe_font->cache), glyphs, nglyphs, attributes, &(items[i].a), advances, offsets, &overall_metrics); - if (result == 0) /* Success. */ + if (SUCCEEDED (result)) { int j, nclusters, from, to; @@ -364,7 +358,7 @@ &(uniscribe_font->cache), glyphs[j], &char_metric); - if (result == 0) /* Success. */ + if (SUCCEEDED (result)) { LGLYPH_SET_LBEARING (lglyph, char_metric.abcA); LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA @@ -411,45 +405,68 @@ struct font *font; int c; { - wchar_t chars[2]; - int len; - WORD indices[1]; HDC context; struct frame *f; HFONT old_font; - DWORD retval; - - if (c > 0xFFFF) - { - DWORD surrogate = c - 0x10000; - - /* High surrogate: U+D800 - U+DBFF. */ - chars[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); - /* Low surrogate: U+DC00 - U+DFFF. */ - chars[1] = 0xDC00 + (surrogate & 0x03FF); - len = 2; - } - else - { - chars[0] = (wchar_t) c; - len = 1; - } + unsigned code = FONT_INVALID_CODE; /* Use selected frame until API is updated to pass the frame. */ f = XFRAME (selected_frame); context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE(font)); - retval = GetGlyphIndicesW (context, chars, len, indices, - GGI_MARK_NONEXISTING_GLYPHS); + /* There are a number of ways to get glyph indices for BMP characters. + The GetGlyphIndices GDI function seems to work best for detecting + non-existing glyphs. */ + if (c < 0x10000) + { + wchar_t ch = (wchar_t) c; + WORD index; + DWORD retval = GetGlyphIndicesW (context, &ch, 1, &index, + GGI_MARK_NONEXISTING_GLYPHS); + if (retval == 1 && index != 0xFFFF) + code = index; + } + + /* Non BMP characters must be handled by the uniscribe shaping + engine as GDI functions (except blindly displaying lines of + unicode text) and the promising looking ScriptGetCMap do not + convert surrogate pairs to glyph indexes correctly. */ + else + { + wchar_t ch[2]; + SCRIPT_ITEM* items; + int nitems; + struct uniscribe_font_info *uniscribe_font + = (struct uniscribe_font_info *)font; + DWORD surrogate = c - 0x10000; + + /* High surrogate: U+D800 - U+DBFF. */ + ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); + /* Low surrogate: U+DC00 - U+DFFF. */ + ch[1] = 0xDC00 + (surrogate & 0x03FF); + + items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); + if (SUCCEEDED (ScriptItemize (ch, 2, 2, NULL, NULL, items, &nitems))) + { + WORD glyphs[2], clusters[2]; + SCRIPT_VISATTR attrs[2]; + int nglyphs; + + if (SUCCEEDED (ScriptShape (context, &(uniscribe_font->cache), + ch, 2, 2, &(items[0].a), + glyphs, clusters, attrs, &nglyphs)) + && nglyphs == 1) + { + code = glyphs[0]; + } + } + } SelectObject (context, old_font); release_frame_dc (f, context); - if (retval == 1) - return indices[0] == 0xFFFF ? FONT_INVALID_CODE : indices[0]; - else - return FONT_INVALID_CODE; + return code; } /*