diff options
| author | Jason Rumney | 2008-07-25 21:53:21 +0000 |
|---|---|---|
| committer | Jason Rumney | 2008-07-25 21:53:21 +0000 |
| commit | 11856d4d74e6670f2b60c277fab8a323588461a1 (patch) | |
| tree | bb2145c1bdd347970253e21898790add80aa78cf | |
| parent | 6a8082b5d4574f44a40c6c03c56d023f17a8ab3a (diff) | |
| download | emacs-11856d4d74e6670f2b60c277fab8a323588461a1.tar.gz emacs-11856d4d74e6670f2b60c277fab8a323588461a1.zip | |
(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.
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/w32uniscribe.c | 91 |
2 files changed, 65 insertions, 37 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 32129795587..c23aadee7d8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2008-07-25 Jason Rumney <jasonr@gnu.org> | ||
| 2 | |||
| 3 | * w32uniscribe.c (uniscribe_shape): Pass NULL for control arg to | ||
| 4 | ScriptItemize. Clean up return value checking. Remove unused | ||
| 5 | variables. | ||
| 6 | (uniscribe_encode_char): Encode non-BMP characters with uniscribe | ||
| 7 | shaping engine. | ||
| 8 | |||
| 9 | * w32font.c (w32font_has_char): Handle the case where we can't | ||
| 10 | determine the script for a character. | ||
| 11 | |||
| 1 | 2008-07-25 Chong Yidong <cyd@stupidchicken.com> | 12 | 2008-07-25 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 13 | ||
| 3 | * term.c (syms_of_term): Initialize default_orig_pair, | 14 | * term.c (syms_of_term): Initialize default_orig_pair, |
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index fc9f48b3a17..8315f8814ad 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c | |||
| @@ -134,6 +134,7 @@ uniscribe_open (f, font_entity, pixel_size) | |||
| 134 | 134 | ||
| 135 | /* Initialize the cache for this font. */ | 135 | /* Initialize the cache for this font. */ |
| 136 | uniscribe_font->cache = NULL; | 136 | uniscribe_font->cache = NULL; |
| 137 | |||
| 137 | /* Mark the format as opentype */ | 138 | /* Mark the format as opentype */ |
| 138 | uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype; | 139 | uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype; |
| 139 | uniscribe_font->w32_font.font.driver = &uniscribe_font_driver; | 140 | uniscribe_font->w32_font.font.driver = &uniscribe_font_driver; |
| @@ -150,7 +151,7 @@ uniscribe_close (f, font) | |||
| 150 | = (struct uniscribe_font_info *) font; | 151 | = (struct uniscribe_font_info *) font; |
| 151 | 152 | ||
| 152 | if (uniscribe_font->cache) | 153 | if (uniscribe_font->cache) |
| 153 | ScriptFreeCache (&uniscribe_font->cache); | 154 | ScriptFreeCache (&(uniscribe_font->cache)); |
| 154 | 155 | ||
| 155 | w32font_close (f, font); | 156 | w32font_close (f, font); |
| 156 | } | 157 | } |
| @@ -206,12 +207,10 @@ uniscribe_shape (lgstring) | |||
| 206 | wchar_t *chars; | 207 | wchar_t *chars; |
| 207 | WORD *glyphs, *clusters; | 208 | WORD *glyphs, *clusters; |
| 208 | SCRIPT_ITEM *items; | 209 | SCRIPT_ITEM *items; |
| 209 | SCRIPT_CONTROL control; | ||
| 210 | SCRIPT_VISATTR *attributes; | 210 | SCRIPT_VISATTR *attributes; |
| 211 | int *advances; | 211 | int *advances; |
| 212 | GOFFSET *offsets; | 212 | GOFFSET *offsets; |
| 213 | ABC overall_metrics; | 213 | ABC overall_metrics; |
| 214 | MAT2 transform; | ||
| 215 | HDC context; | 214 | HDC context; |
| 216 | HFONT old_font; | 215 | HFONT old_font; |
| 217 | HRESULT result; | 216 | HRESULT result; |
| @@ -239,9 +238,8 @@ uniscribe_shape (lgstring) | |||
| 239 | can be treated together. First try a single run. */ | 238 | can be treated together. First try a single run. */ |
| 240 | max_items = 2; | 239 | max_items = 2; |
| 241 | items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); | 240 | items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); |
| 242 | bzero (&control, sizeof (control)); | ||
| 243 | 241 | ||
| 244 | while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL, | 242 | while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, |
| 245 | items, &nitems)) == E_OUTOFMEMORY) | 243 | items, &nitems)) == E_OUTOFMEMORY) |
| 246 | { | 244 | { |
| 247 | /* If that wasn't enough, keep trying with one more run. */ | 245 | /* If that wasn't enough, keep trying with one more run. */ |
| @@ -250,8 +248,7 @@ uniscribe_shape (lgstring) | |||
| 250 | sizeof (SCRIPT_ITEM) * max_items + 1); | 248 | sizeof (SCRIPT_ITEM) * max_items + 1); |
| 251 | } | 249 | } |
| 252 | 250 | ||
| 253 | /* 0 = success in Microsoft's backwards world. */ | 251 | if (!SUCCEEDED (result)) |
| 254 | if (result) | ||
| 255 | { | 252 | { |
| 256 | xfree (items); | 253 | xfree (items); |
| 257 | return Qnil; | 254 | return Qnil; |
| @@ -269,9 +266,6 @@ uniscribe_shape (lgstring) | |||
| 269 | attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR)); | 266 | attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR)); |
| 270 | advances = alloca (max_glyphs * sizeof (int)); | 267 | advances = alloca (max_glyphs * sizeof (int)); |
| 271 | offsets = alloca (max_glyphs * sizeof (GOFFSET)); | 268 | offsets = alloca (max_glyphs * sizeof (GOFFSET)); |
| 272 | bzero (&transform, sizeof (transform)); | ||
| 273 | transform.eM11.value = 1; | ||
| 274 | transform.eM22.value = 1; | ||
| 275 | 269 | ||
| 276 | for (i = 0; i < nitems; i++) | 270 | for (i = 0; i < nitems; i++) |
| 277 | { | 271 | { |
| @@ -304,7 +298,7 @@ uniscribe_shape (lgstring) | |||
| 304 | result = ScriptPlace (context, &(uniscribe_font->cache), | 298 | result = ScriptPlace (context, &(uniscribe_font->cache), |
| 305 | glyphs, nglyphs, attributes, &(items[i].a), | 299 | glyphs, nglyphs, attributes, &(items[i].a), |
| 306 | advances, offsets, &overall_metrics); | 300 | advances, offsets, &overall_metrics); |
| 307 | if (result == 0) /* Success. */ | 301 | if (SUCCEEDED (result)) |
| 308 | { | 302 | { |
| 309 | int j, nclusters, from, to; | 303 | int j, nclusters, from, to; |
| 310 | 304 | ||
| @@ -364,7 +358,7 @@ uniscribe_shape (lgstring) | |||
| 364 | &(uniscribe_font->cache), | 358 | &(uniscribe_font->cache), |
| 365 | glyphs[j], &char_metric); | 359 | glyphs[j], &char_metric); |
| 366 | 360 | ||
| 367 | if (result == 0) /* Success. */ | 361 | if (SUCCEEDED (result)) |
| 368 | { | 362 | { |
| 369 | LGLYPH_SET_LBEARING (lglyph, char_metric.abcA); | 363 | LGLYPH_SET_LBEARING (lglyph, char_metric.abcA); |
| 370 | LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA | 364 | LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA |
| @@ -411,45 +405,68 @@ uniscribe_encode_char (font, c) | |||
| 411 | struct font *font; | 405 | struct font *font; |
| 412 | int c; | 406 | int c; |
| 413 | { | 407 | { |
| 414 | wchar_t chars[2]; | ||
| 415 | int len; | ||
| 416 | WORD indices[1]; | ||
| 417 | HDC context; | 408 | HDC context; |
| 418 | struct frame *f; | 409 | struct frame *f; |
| 419 | HFONT old_font; | 410 | HFONT old_font; |
| 420 | DWORD retval; | 411 | unsigned code = FONT_INVALID_CODE; |
| 412 | |||
| 413 | /* Use selected frame until API is updated to pass the frame. */ | ||
| 414 | f = XFRAME (selected_frame); | ||
| 415 | context = get_frame_dc (f); | ||
| 416 | old_font = SelectObject (context, FONT_HANDLE(font)); | ||
| 421 | 417 | ||
| 422 | if (c > 0xFFFF) | 418 | /* There are a number of ways to get glyph indices for BMP characters. |
| 419 | The GetGlyphIndices GDI function seems to work best for detecting | ||
| 420 | non-existing glyphs. */ | ||
| 421 | if (c < 0x10000) | ||
| 422 | { | ||
| 423 | wchar_t ch = (wchar_t) c; | ||
| 424 | WORD index; | ||
| 425 | DWORD retval = GetGlyphIndicesW (context, &ch, 1, &index, | ||
| 426 | GGI_MARK_NONEXISTING_GLYPHS); | ||
| 427 | if (retval == 1 && index != 0xFFFF) | ||
| 428 | code = index; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Non BMP characters must be handled by the uniscribe shaping | ||
| 432 | engine as GDI functions (except blindly displaying lines of | ||
| 433 | unicode text) and the promising looking ScriptGetCMap do not | ||
| 434 | convert surrogate pairs to glyph indexes correctly. */ | ||
| 435 | else | ||
| 423 | { | 436 | { |
| 437 | wchar_t ch[2]; | ||
| 438 | SCRIPT_ITEM* items; | ||
| 439 | int nitems; | ||
| 440 | struct uniscribe_font_info *uniscribe_font | ||
| 441 | = (struct uniscribe_font_info *)font; | ||
| 424 | DWORD surrogate = c - 0x10000; | 442 | DWORD surrogate = c - 0x10000; |
| 425 | 443 | ||
| 426 | /* High surrogate: U+D800 - U+DBFF. */ | 444 | /* High surrogate: U+D800 - U+DBFF. */ |
| 427 | chars[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); | 445 | ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); |
| 428 | /* Low surrogate: U+DC00 - U+DFFF. */ | 446 | /* Low surrogate: U+DC00 - U+DFFF. */ |
| 429 | chars[1] = 0xDC00 + (surrogate & 0x03FF); | 447 | ch[1] = 0xDC00 + (surrogate & 0x03FF); |
| 430 | len = 2; | 448 | |
| 449 | items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); | ||
| 450 | if (SUCCEEDED (ScriptItemize (ch, 2, 2, NULL, NULL, items, &nitems))) | ||
| 451 | { | ||
| 452 | WORD glyphs[2], clusters[2]; | ||
| 453 | SCRIPT_VISATTR attrs[2]; | ||
| 454 | int nglyphs; | ||
| 455 | |||
| 456 | if (SUCCEEDED (ScriptShape (context, &(uniscribe_font->cache), | ||
| 457 | ch, 2, 2, &(items[0].a), | ||
| 458 | glyphs, clusters, attrs, &nglyphs)) | ||
| 459 | && nglyphs == 1) | ||
| 460 | { | ||
| 461 | code = glyphs[0]; | ||
| 462 | } | ||
| 463 | } | ||
| 431 | } | 464 | } |
| 432 | else | ||
| 433 | { | ||
| 434 | chars[0] = (wchar_t) c; | ||
| 435 | len = 1; | ||
| 436 | } | ||
| 437 | |||
| 438 | /* Use selected frame until API is updated to pass the frame. */ | ||
| 439 | f = XFRAME (selected_frame); | ||
| 440 | context = get_frame_dc (f); | ||
| 441 | old_font = SelectObject (context, FONT_HANDLE(font)); | ||
| 442 | |||
| 443 | retval = GetGlyphIndicesW (context, chars, len, indices, | ||
| 444 | GGI_MARK_NONEXISTING_GLYPHS); | ||
| 445 | 465 | ||
| 446 | SelectObject (context, old_font); | 466 | SelectObject (context, old_font); |
| 447 | release_frame_dc (f, context); | 467 | release_frame_dc (f, context); |
| 448 | 468 | ||
| 449 | if (retval == 1) | 469 | return code; |
| 450 | return indices[0] == 0xFFFF ? FONT_INVALID_CODE : indices[0]; | ||
| 451 | else | ||
| 452 | return FONT_INVALID_CODE; | ||
| 453 | } | 470 | } |
| 454 | 471 | ||
| 455 | /* | 472 | /* |