summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Rumney <jasonr@gnu.org>2008-07-25 11:25:43 +0000
committerJason Rumney <jasonr@gnu.org>2008-07-25 11:25:43 +0000
commitf31cf550ca95e76bbff474487c68bb36992f96c3 (patch)
tree05a8e5b42151bc213d212609a3ce603fe6924dd8 /src
parent6f79c90b19ef0fa073a07e515db7639a2a81fb03 (diff)
downloademacs-f31cf550ca95e76bbff474487c68bb36992f96c3.tar.gz
* 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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog10
-rw-r--r--src/w32font.c45
-rw-r--r--src/w32uniscribe.c21
3 files changed, 55 insertions, 21 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d0daa9412ac..d8583efd915 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
+2008-07-25 Jason Rumney <jasonr@gnu.org>
+
+ * 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 <cyd@stupidchicken.com>
* image.c (svg_load_image): Check for failure in return value of
diff --git a/src/w32font.c b/src/w32font.c
index 4a4c7625787..380bead2e74 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -327,8 +327,13 @@ w32font_encode_char (font, c)
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 @@ w32font_text_extents (font, code, nglyphs, metrics)
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 @@ w32font_text_extents (font, code, nglyphs, metrics)
/* 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 --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 0e0a4e8d143..fc9f48b3a17 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -411,25 +411,36 @@ uniscribe_encode_char (font, c)
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);