# HG changeset patch # User Jason Rumney # Date 1216985143 0 # Node ID 1b8d15c8653f3c8c3bca5794b114062360c88bc8 # Parent 1c0b739f899d13942a98893e71c3867bdcdd5505 * w32font.c (w32font_encode_char): Encode characters outside BMP as surrogates before looking up glyph index. (w32font_text_extents): Encode as surrogates if falling back to functions that need UTF-16 wide chars. * w32uniscribe.c (uniscribe_encode_char): Encode characters outside BMP as surrogates before looking up glyph index. diff -r 1c0b739f899d -r 1b8d15c8653f src/ChangeLog --- a/src/ChangeLog Fri Jul 25 05:51:24 2008 +0000 +++ b/src/ChangeLog Fri Jul 25 11:25:43 2008 +0000 @@ -1,3 +1,13 @@ +2008-07-25 Jason Rumney + + * w32font.c (w32font_encode_char): Encode characters outside BMP as + surrogates before looking up glyph index. + (w32font_text_extents): Encode as surrogates if falling back to + functions that need UTF-16 wide chars. + + * w32uniscribe.c (uniscribe_encode_char): Encode characters outside + BMP as surrogates before looking up glyph index. + 2008-07-25 Chong Yidong * image.c (svg_load_image): Check for failure in return value of diff -r 1c0b739f899d -r 1b8d15c8653f src/w32font.c --- a/src/w32font.c Fri Jul 25 05:51:24 2008 +0000 +++ b/src/w32font.c Fri Jul 25 11:25:43 2008 +0000 @@ -327,8 +327,13 @@ if (c > 0xFFFF) { - /* TODO: Encode as surrogate pair and lookup the glyph. */ - return FONT_INVALID_CODE; + DWORD surrogate = c - 0x10000; + + /* High surrogate: U+D800 - U+DBFF. */ + in[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); + /* Low surrogate: U+DC00 - U+DFFF. */ + in[1] = 0xDC00 + (surrogate & 0x03FF); + len = 2; } else { @@ -394,7 +399,7 @@ HDC dc = NULL; struct frame * f; int total_width = 0; - WORD *wcode = NULL; + WORD *wcode; SIZE size; struct w32font_info *w32_font = (struct w32font_info *) font; @@ -484,19 +489,27 @@ /* For non-truetype fonts, GetGlyphOutlineW is not supported, so fallback on other methods that will at least give some of the metric information. */ - if (!wcode) { - wcode = alloca (nglyphs * sizeof (WORD)); - for (i = 0; i < nglyphs; i++) - { - if (code[i] < 0x10000) - wcode[i] = code[i]; - else - { - /* TODO: Convert to surrogate, reallocating array if needed */ - wcode[i] = 0xffff; - } - } - } + + /* Make array big enough to hold surrogates. */ + wcode = alloca (nglyphs * sizeof (WORD) * 2); + for (i = 0; i < nglyphs; i++) + { + if (code[i] < 0x10000) + wcode[i] = code[i]; + else + { + DWORD surrogate = code[i] - 0x10000; + + /* High surrogate: U+D800 - U+DBFF. */ + wcode[i++] = 0xD800 + ((surrogate >> 10) & 0x03FF); + /* Low surrogate: U+DC00 - U+DFFF. */ + wcode[i] = 0xDC00 + (surrogate & 0x03FF); + /* An extra glyph. wcode is already double the size of code to + cope with this. */ + nglyphs++; + } + } + if (dc == NULL) { /* TODO: Frames can come and go, and their fonts outlive diff -r 1c0b739f899d -r 1b8d15c8653f src/w32uniscribe.c --- a/src/w32uniscribe.c Fri Jul 25 05:51:24 2008 +0000 +++ b/src/w32uniscribe.c Fri Jul 25 11:25:43 2008 +0000 @@ -411,25 +411,36 @@ struct font *font; int c; { - wchar_t chars[1]; + wchar_t chars[2]; + int len; WORD indices[1]; HDC context; struct frame *f; HFONT old_font; DWORD retval; - /* TODO: surrogates. */ if (c > 0xFFFF) - return FONT_INVALID_CODE; + { + DWORD surrogate = c - 0x10000; - chars[0] = (wchar_t) c; + /* 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; + } /* 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, 1, indices, + retval = GetGlyphIndicesW (context, chars, len, indices, GGI_MARK_NONEXISTING_GLYPHS); SelectObject (context, old_font);