aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2008-07-29 16:24:24 +0000
committerJason Rumney2008-07-29 16:24:24 +0000
commitc320e90a79d4b7e92aa091b1ed02d65dd388e54c (patch)
tree1ae24c4773cef65fea5fda79402898b10500e9d9 /src
parent838d78d411955dbe3ef5d75ff404ced8ca832c5a (diff)
downloademacs-c320e90a79d4b7e92aa091b1ed02d65dd388e54c.tar.gz
emacs-c320e90a79d4b7e92aa091b1ed02d65dd388e54c.zip
(uniscribe_shape): Avoid using context if cache
is populated. (uniscribe_encode_char): Always use uniscribe. Avoid using context if cache is populated.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/w32uniscribe.c168
2 files changed, 122 insertions, 53 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index ad37435c1d5..a0ba987005e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12008-07-29 Jason Rumney <jasonr@gnu.org>
2
3 * w32uniscribe.c (uniscribe_shape): Avoid using context if cache
4 is populated.
5 (uniscribe_encode_char): Always use uniscribe.
6 Avoid using context if cache is populated.
7
12008-07-29 Jan Djärv <jan.h.d@swipnet.se> 82008-07-29 Jan Djärv <jan.h.d@swipnet.se>
2 9
3 * xmenu.c (Fx_menu_bar_open_internal): Use activate_item signal to 10 * xmenu.c (Fx_menu_bar_open_internal): Use activate_item signal to
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 8315f8814ad..42047c3d3c7 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -211,10 +211,10 @@ uniscribe_shape (lgstring)
211 int *advances; 211 int *advances;
212 GOFFSET *offsets; 212 GOFFSET *offsets;
213 ABC overall_metrics; 213 ABC overall_metrics;
214 HDC context;
215 HFONT old_font;
216 HRESULT result; 214 HRESULT result;
217 struct frame * f; 215 struct frame * f = NULL;
216 HDC context = NULL;
217 HFONT old_font = NULL;
218 218
219 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font); 219 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
220 uniscribe_font = (struct uniscribe_font_info *) font; 220 uniscribe_font = (struct uniscribe_font_info *) font;
@@ -248,7 +248,7 @@ uniscribe_shape (lgstring)
248 sizeof (SCRIPT_ITEM) * max_items + 1); 248 sizeof (SCRIPT_ITEM) * max_items + 1);
249 } 249 }
250 250
251 if (!SUCCEEDED (result)) 251 if (FAILED (result))
252 { 252 {
253 xfree (items); 253 xfree (items);
254 return Qnil; 254 return Qnil;
@@ -257,10 +257,6 @@ uniscribe_shape (lgstring)
257 /* TODO: When we get BIDI support, we need to call ScriptLayout here. 257 /* TODO: When we get BIDI support, we need to call ScriptLayout here.
258 Requires that we know the surrounding context. */ 258 Requires that we know the surrounding context. */
259 259
260 f = XFRAME (selected_frame);
261 context = get_frame_dc (f);
262 old_font = SelectObject (context, FONT_HANDLE(font));
263
264 glyphs = alloca (max_glyphs * sizeof (WORD)); 260 glyphs = alloca (max_glyphs * sizeof (WORD));
265 clusters = alloca (nchars * sizeof (WORD)); 261 clusters = alloca (nchars * sizeof (WORD));
266 attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR)); 262 attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR));
@@ -272,17 +268,35 @@ uniscribe_shape (lgstring)
272 int nglyphs, nchars_in_run, rtl = items[i].a.fRTL ? -1 : 1; 268 int nglyphs, nchars_in_run, rtl = items[i].a.fRTL ? -1 : 1;
273 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos; 269 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
274 270
271 /* Context may be NULL here, in which case the cache should be
272 used without needing to select the font. */
275 result = ScriptShape (context, &(uniscribe_font->cache), 273 result = ScriptShape (context, &(uniscribe_font->cache),
276 chars + items[i].iCharPos, nchars_in_run, 274 chars + items[i].iCharPos, nchars_in_run,
277 max_glyphs - done_glyphs, &(items[i].a), 275 max_glyphs - done_glyphs, &(items[i].a),
278 glyphs, clusters, attributes, &nglyphs); 276 glyphs, clusters, attributes, &nglyphs);
277
278 if (result == E_PENDING && !context)
279 {
280 /* This assumes the selected frame is on the same display as the
281 one we are drawing. It would be better for the frame to be
282 passed in. */
283 f = XFRAME (selected_frame);
284 context = get_frame_dc (f);
285 old_font = SelectObject (context, FONT_HANDLE(font));
286
287 result = ScriptShape (context, &(uniscribe_font->cache),
288 chars + items[i].iCharPos, nchars_in_run,
289 max_glyphs - done_glyphs, &(items[i].a),
290 glyphs, clusters, attributes, &nglyphs);
291 }
292
279 if (result == E_OUTOFMEMORY) 293 if (result == E_OUTOFMEMORY)
280 { 294 {
281 /* Need a bigger lgstring. */ 295 /* Need a bigger lgstring. */
282 lgstring = Qnil; 296 lgstring = Qnil;
283 break; 297 break;
284 } 298 }
285 else if (result) /* Failure. */ 299 else if (FAILED (result))
286 { 300 {
287 /* Can't shape this run - return results so far if any. */ 301 /* Can't shape this run - return results so far if any. */
288 break; 302 break;
@@ -298,7 +312,18 @@ uniscribe_shape (lgstring)
298 result = ScriptPlace (context, &(uniscribe_font->cache), 312 result = ScriptPlace (context, &(uniscribe_font->cache),
299 glyphs, nglyphs, attributes, &(items[i].a), 313 glyphs, nglyphs, attributes, &(items[i].a),
300 advances, offsets, &overall_metrics); 314 advances, offsets, &overall_metrics);
301 if (SUCCEEDED (result)) 315 if (result == E_PENDING && !context)
316 {
317 /* Cache not complete... */
318 f = XFRAME (selected_frame);
319 context = get_frame_dc (f);
320 old_font = SelectObject (context, FONT_HANDLE(font));
321
322 result = ScriptPlace (context, &(uniscribe_font->cache),
323 glyphs, nglyphs, attributes, &(items[i].a),
324 advances, offsets, &overall_metrics);
325 }
326 if (SUCCEEDED (result))
302 { 327 {
303 int j, nclusters, from, to; 328 int j, nclusters, from, to;
304 329
@@ -357,6 +382,16 @@ uniscribe_shape (lgstring)
357 result = ScriptGetGlyphABCWidth (context, 382 result = ScriptGetGlyphABCWidth (context,
358 &(uniscribe_font->cache), 383 &(uniscribe_font->cache),
359 glyphs[j], &char_metric); 384 glyphs[j], &char_metric);
385 if (result == E_PENDING && !context)
386 {
387 /* Cache incomplete... */
388 f = XFRAME (selected_frame);
389 context = get_frame_dc (f);
390 old_font = SelectObject (context, FONT_HANDLE(font));
391 result = ScriptGetGlyphABCWidth (context,
392 &(uniscribe_font->cache),
393 glyphs[j], &char_metric);
394 }
360 395
361 if (SUCCEEDED (result)) 396 if (SUCCEEDED (result))
362 { 397 {
@@ -382,14 +417,19 @@ uniscribe_shape (lgstring)
382 } 417 }
383 else 418 else
384 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil); 419 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
385 } } 420 }
421 }
386 } 422 }
387 done_glyphs += nglyphs; 423 done_glyphs += nglyphs;
388 } 424 }
389 425
390 xfree (items); 426 xfree (items);
391 SelectObject (context, old_font); 427
392 release_frame_dc (f, context); 428 if (context)
429 {
430 SelectObject (context, old_font);
431 release_frame_dc (f, context);
432 }
393 433
394 if (NILP (lgstring)) 434 if (NILP (lgstring))
395 return Qnil; 435 return Qnil;
@@ -405,68 +445,90 @@ uniscribe_encode_char (font, c)
405 struct font *font; 445 struct font *font;
406 int c; 446 int c;
407{ 447{
408 HDC context; 448 HDC context = NULL;
409 struct frame *f; 449 struct frame *f = NULL;
410 HFONT old_font; 450 HFONT old_font = NULL;
411 unsigned code = FONT_INVALID_CODE; 451 unsigned code = FONT_INVALID_CODE;
452 wchar_t ch[2];
453 int len;
454 SCRIPT_ITEM* items;
455 int nitems;
456 struct uniscribe_font_info *uniscribe_font
457 = (struct uniscribe_font_info *)font;
412 458
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));
417
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) 459 if (c < 0x10000)
422 { 460 {
423 wchar_t ch = (wchar_t) c; 461 ch[0] = (wchar_t) c;
424 WORD index; 462 len = 1;
425 DWORD retval = GetGlyphIndicesW (context, &ch, 1, &index,
426 GGI_MARK_NONEXISTING_GLYPHS);
427 if (retval == 1 && index != 0xFFFF)
428 code = index;
429 } 463 }
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 464 else
436 { 465 {
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;
442 DWORD surrogate = c - 0x10000; 466 DWORD surrogate = c - 0x10000;
443 467
444 /* High surrogate: U+D800 - U+DBFF. */ 468 /* High surrogate: U+D800 - U+DBFF. */
445 ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF); 469 ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
446 /* Low surrogate: U+DC00 - U+DFFF. */ 470 /* Low surrogate: U+DC00 - U+DFFF. */
447 ch[1] = 0xDC00 + (surrogate & 0x03FF); 471 ch[1] = 0xDC00 + (surrogate & 0x03FF);
472 len = 2;
473 }
448 474
475 /* Non BMP characters must be handled by the uniscribe shaping
476 engine as GDI functions (except blindly displaying lines of
477 unicode text) and the promising looking ScriptGetCMap do not
478 convert surrogate pairs to glyph indexes correctly. */
479 {
449 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); 480 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
450 if (SUCCEEDED (ScriptItemize (ch, 2, 2, NULL, NULL, items, &nitems))) 481 if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems)))
451 { 482 {
452 WORD glyphs[2], clusters[2]; 483 HRESULT result;
453 SCRIPT_VISATTR attrs[2]; 484 /* Some Indic characters result in more than 1 glyph. */
485 WORD glyphs[1], clusters[1];
486 SCRIPT_VISATTR attrs[1];
454 int nglyphs; 487 int nglyphs;
455 488
456 if (SUCCEEDED (ScriptShape (context, &(uniscribe_font->cache), 489 result = ScriptShape (context, &(uniscribe_font->cache),
457 ch, 2, 2, &(items[0].a), 490 ch, len, 20, &(items[0].a),
458 glyphs, clusters, attrs, &nglyphs)) 491 glyphs, clusters, attrs, &nglyphs);
459 && nglyphs == 1) 492
493 if (result == E_PENDING)
494 {
495 /* Use selected frame until API is updated to pass
496 the frame. */
497 f = XFRAME (selected_frame);
498 context = get_frame_dc (f);
499 old_font = SelectObject (context, FONT_HANDLE(font));
500 result = ScriptShape (context, &(uniscribe_font->cache),
501 ch, len, 2, &(items[0].a),
502 glyphs, clusters, attrs, &nglyphs);
503 }
504
505 if (SUCCEEDED (result) && nglyphs == 1)
460 { 506 {
461 code = glyphs[0]; 507 code = glyphs[0];
462 } 508 }
463 } 509 else if (SUCCEEDED (result) || result == E_OUTOFMEMORY)
510 {
511 /* This character produces zero or more than one glyph
512 when shaped. But we still need the return from here
513 to be valid for the shaping engine to be invoked
514 later. */
515 result = ScriptGetCMap (context, &(uniscribe_font->cache),
516 ch, len, 0, glyphs);
517 if (SUCCEEDED (result))
518 return glyphs[0];
519 else
520 return 0; /* notdef - enough in some cases to get the script
521 engine working, but not others... */
522 }
523 }
464 } 524 }
525 if (context)
526 {
527 SelectObject (context, old_font);
528 release_frame_dc (f, context);
529 }
465 530
466 SelectObject (context, old_font); 531 return code;
467 release_frame_dc (f, context);
468
469 return code;
470} 532}
471 533
472/* 534/*