aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog11
-rw-r--r--src/w32uniscribe.c186
2 files changed, 116 insertions, 81 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c683d77ad17..f9bb5b9c3c8 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12008-04-06 Jason Rumney <jasonr@gnu.org>
2
3 * w32uniscribe.c (uniscribe_shape): Increase items buffer size.
4 Give up if glyph indices not supported. Use uniscribe obtained
5 ABC widths for individual metrics. Map glyph clusters back to
6 characters using fClusterStart flag. Return number of glyphs
7 produced, not chars processed.
8
12008-04-05 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> 92008-04-05 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2 10
3 * macmenu.c (fill_menu) [TARGET_API_MAC_CARBON]: Use 11 * macmenu.c (fill_menu) [TARGET_API_MAC_CARBON]: Use
@@ -59,6 +67,9 @@
59 67
602008-04-04 Jason Rumney <jasonr@gnu.org> 682008-04-04 Jason Rumney <jasonr@gnu.org>
61 69
70 * w32font.c (w32font_text_extents): Use font's ascent and descent.
71 (recompute_cached_metrics): Don't set ascent and descent per char.
72
62 * w32uniscribe.c (uniscribe_check_otf): Fix last change. 73 * w32uniscribe.c (uniscribe_check_otf): Fix last change.
63 (uniscribe_check_otf): Add GC protection before consing. 74 (uniscribe_check_otf): Add GC protection before consing.
64 Rearrange loop for counting features. 75 Rearrange loop for counting features.
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 320862167ec..9f78e01082a 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -202,7 +202,7 @@ uniscribe_shape (lgstring)
202 struct font * font; 202 struct font * font;
203 struct uniscribe_font_info * uniscribe_font; 203 struct uniscribe_font_info * uniscribe_font;
204 EMACS_UINT nchars; 204 EMACS_UINT nchars;
205 int nitems, max_items, i, max_glyphs, done_glyphs, done_chars; 205 int nitems, max_items, i, max_glyphs, done_glyphs;
206 wchar_t *chars; 206 wchar_t *chars;
207 WORD *glyphs, *clusters; 207 WORD *glyphs, *clusters;
208 SCRIPT_ITEM *items; 208 SCRIPT_ITEM *items;
@@ -222,7 +222,7 @@ uniscribe_shape (lgstring)
222 222
223 /* Get the chars from lgstring in a form we can use with uniscribe. */ 223 /* Get the chars from lgstring in a form we can use with uniscribe. */
224 max_glyphs = nchars = LGSTRING_LENGTH (lgstring); 224 max_glyphs = nchars = LGSTRING_LENGTH (lgstring);
225 done_glyphs = done_chars = 0; 225 done_glyphs = 0;
226 chars = (wchar_t *) alloca (nchars * sizeof (wchar_t)); 226 chars = (wchar_t *) alloca (nchars * sizeof (wchar_t));
227 for (i = 0; i < nchars; i++) 227 for (i = 0; i < nchars; i++)
228 { 228 {
@@ -238,7 +238,7 @@ uniscribe_shape (lgstring)
238 /* First we need to break up the glyph string into runs of glyphs that 238 /* First we need to break up the glyph string into runs of glyphs that
239 can be treated together. First try a single run. */ 239 can be treated together. First try a single run. */
240 max_items = 2; 240 max_items = 2;
241 items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items); 241 items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
242 bzero (&control, sizeof (control)); 242 bzero (&control, sizeof (control));
243 243
244 while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL, 244 while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL,
@@ -247,7 +247,7 @@ uniscribe_shape (lgstring)
247 /* If that wasn't enough, keep trying with one more run. */ 247 /* If that wasn't enough, keep trying with one more run. */
248 max_items++; 248 max_items++;
249 items = (SCRIPT_ITEM *) xrealloc (items, 249 items = (SCRIPT_ITEM *) xrealloc (items,
250 sizeof (SCRIPT_ITEM) * max_items); 250 sizeof (SCRIPT_ITEM) * max_items + 1);
251 } 251 }
252 252
253 /* 0 = success in Microsoft's backwards world. */ 253 /* 0 = success in Microsoft's backwards world. */
@@ -257,6 +257,9 @@ uniscribe_shape (lgstring)
257 return Qnil; 257 return Qnil;
258 } 258 }
259 259
260 /* TODO: When we get BIDI support, we need to call ScriptLayout here.
261 Requires that we know the surrounding context. */
262
260 f = XFRAME (selected_frame); 263 f = XFRAME (selected_frame);
261 context = get_frame_dc (f); 264 context = get_frame_dc (f);
262 old_font = SelectObject (context, 265 old_font = SelectObject (context,
@@ -273,7 +276,7 @@ uniscribe_shape (lgstring)
273 276
274 for (i = 0; i < nitems; i++) 277 for (i = 0; i < nitems; i++)
275 { 278 {
276 int nglyphs, nchars_in_run; 279 int nglyphs, nchars_in_run, rtl = items[i].a.fRTL ? -1 : 1;
277 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos; 280 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
278 281
279 result = ScriptShape (context, &(uniscribe_font->cache), 282 result = ScriptShape (context, &(uniscribe_font->cache),
@@ -286,25 +289,36 @@ uniscribe_shape (lgstring)
286 lgstring = Qnil; 289 lgstring = Qnil;
287 break; 290 break;
288 } 291 }
289 else if (result) 292 else if (result) /* Failure. */
290 { 293 {
291 /* Can't shape this run - return results so far if any. */ 294 /* Can't shape this run - return results so far if any. */
292 break; 295 break;
293 } 296 }
297 else if (items[i].a.fNoGlyphIndex)
298 {
299 /* Glyph indices not supported by this font (or OS), means we
300 can't really do any meaningful shaping. */
301 break;
302 }
294 else 303 else
295 { 304 {
296 result = ScriptPlace (context, &(uniscribe_font->cache), 305 result = ScriptPlace (context, &(uniscribe_font->cache),
297 glyphs, nglyphs, attributes, &(items[i].a), 306 glyphs, nglyphs, attributes, &(items[i].a),
298 advances, offsets, &overall_metrics); 307 advances, offsets, &overall_metrics);
299 if (!result) 308 if (result == 0) /* Success. */
300 { 309 {
301 int j, nclusters; 310 int j, nclusters, from = 0, to = 0;
311 /* For tracking our mapping of characters to glyphs.
312 Special value -1 means not yet initialized, -2 means
313 we've run off the end. Anything else is an index
314 into the chars and clusters arrays. */
315 int my_char = -1;
302 316
303 for (j = 0; j < nglyphs; j++) 317 for (j = 0; j < nglyphs; j++)
304 { 318 {
305 int lglyph_index = j + done_glyphs; 319 int lglyph_index = j + done_glyphs;
306 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index); 320 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index);
307 GLYPHMETRICS metrics; 321 ABC char_metric;
308 322
309 if (NILP (lglyph)) 323 if (NILP (lglyph))
310 { 324 {
@@ -312,93 +326,103 @@ uniscribe_shape (lgstring)
312 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph); 326 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
313 } 327 }
314 LGLYPH_SET_CODE (lglyph, glyphs[j]); 328 LGLYPH_SET_CODE (lglyph, glyphs[j]);
315 LGLYPH_SET_WIDTH (lglyph, advances[j]); 329
316 if (offsets[j].du || offsets[j].dv) 330 /* Detect clusters, for linking codes back to characters. */
331 if (attributes[j].fClusterStart)
317 { 332 {
318 Lisp_Object vec; 333 /* First time, set to appropriate end of run. */
319 /* Convert from logical inches. */ 334 if (my_char == -1)
320 int dpi = FRAME_W32_DISPLAY_INFO (f)->resy; 335 my_char = rtl > 0 ? 0 : nchars_in_run - 1;
321 int dx = (int)(offsets[j].du * dpi / 72.27 + 0.5); 336 else if (my_char >= 0)
322 int dy = (int)(offsets[j].dv * dpi / 72.27 + 0.5); 337 my_char += rtl;
323 vec = Fmake_vector (make_number (3), Qnil); 338 while (my_char >= 0 && my_char < nchars_in_run
324 ASET (vec, 0, make_number (dx)); 339 && clusters[my_char] < j)
325 ASET (vec, 1, make_number (dy)); 340 my_char += rtl;
326 /* Based on what ftfont.c does... */ 341
327 ASET (vec, 2, make_number (advances[j])); 342 if (my_char < 0 || my_char >= nchars_in_run)
328 LGLYPH_SET_ADJUSTMENT (lglyph, vec); 343 my_char = -2;
344
345 /* FROM and TO as char indices. This produces
346 much better results at small font sizes than
347 earlier attempts at using glyph indices for
348 FROM and TO, but the output still isn't quite
349 right. For example, on the first South Asia
350 line of etc/HELLO, the third example
351 (Kannada) is missing the last glyph. This
352 seems to be caused by the fact that more
353 glyphs are produced than there are characters
354 in the output (other scripts on that line
355 result in the same or fewer glyphs). */
356 if (my_char < 0)
357 from = to = rtl > 0 ? nchars_in_run - 1: 0;
358 else
359 {
360 int k;
361 from = my_char;
362 to = rtl > 0 ? nchars_in_run : 0;
363 for (k = my_char + rtl; k >= 0 && k < nchars_in_run;
364 k += rtl)
365 {
366 if (clusters[k] > j)
367 {
368 to = k;
369 break;
370 }
371 }
372 }
329 } 373 }
330 else
331 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
332 374
333 if (GetGlyphOutlineW (context, glyphs[j], 375 if (my_char < 0 || clusters[my_char] > j)
334 GGO_METRICS | GGO_GLYPH_INDEX,
335 &metrics, 0, NULL, &transform)
336 != GDI_ERROR)
337 { 376 {
338 LGLYPH_SET_LBEARING (lglyph, metrics.gmptGlyphOrigin.x); 377 /* No mapping. */
339 LGLYPH_SET_RBEARING (lglyph, 378 LGLYPH_SET_CHAR (lglyph, 0);
340 metrics.gmBlackBoxX 379 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
341 + metrics.gmptGlyphOrigin.x); 380 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
342 LGLYPH_SET_ASCENT (lglyph, metrics.gmBlackBoxY);
343 LGLYPH_SET_DESCENT (lglyph,
344 (metrics.gmCellIncY
345 - metrics.gmptGlyphOrigin.y
346 - metrics.gmBlackBoxY));
347 } 381 }
348 else 382 else
349 { 383 {
350 /* Defaults based on what we know from elsewhere. */ 384 LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos
351 LGLYPH_SET_LBEARING (lglyph, 0); 385 + my_char]);
352 LGLYPH_SET_RBEARING (lglyph, advances[j]); 386 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
353 LGLYPH_SET_ASCENT (lglyph, font->ascent); 387 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
354 LGLYPH_SET_DESCENT (lglyph, font->descent);
355 } 388 }
356 }
357 389
358 /* Set character codes as indicated in clusters. */ 390 /* Metrics. */
359 for (j = 0; j < nchars_in_run - 1; j++) 391 LGLYPH_SET_WIDTH (lglyph, advances[j]);
360 { 392 LGLYPH_SET_ASCENT (lglyph, font->ascent);
361 int k, start, end; 393 LGLYPH_SET_DESCENT (lglyph, font->descent);
362 wchar_t this_char = *(chars + items[i].iCharPos + j); 394
395 result = ScriptGetGlyphABCWidth (context,
396 &(uniscribe_font->cache),
397 glyphs[j], &char_metric);
363 398
364 start = clusters[i]; 399 if (result == 0) /* Success. */
365 end = clusters[i+1];
366 if (start > end)
367 { 400 {
368 int temp = start; 401 LGLYPH_SET_LBEARING (lglyph, char_metric.abcA);
369 start = end; 402 LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA
370 end = temp; 403 + char_metric.abcB));
371 } 404 }
372 for (k = start; k < end; k++) 405 else
373 { 406 {
374 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, 407 LGLYPH_SET_LBEARING (lglyph, 0);
375 done_glyphs + k); 408 LGLYPH_SET_RBEARING (lglyph, advances[j]);
376 LGLYPH_SET_CHAR (lglyph, this_char);
377 } 409 }
378 } 410
379 /* Last one until end (or beginning) of string. */ 411 if (offsets[j].du || offsets[j].dv)
380 { 412 {
381 int k, start, end; 413 Lisp_Object vec;
382 wchar_t last_char = *(chars + items[i].iCharPos 414 vec = Fmake_vector (make_number (3), Qnil);
383 + nchars_in_run - 1); 415 ASET (vec, 0, make_number (offsets[j].du));
384 start = clusters[nchars_in_run - 1]; 416 ASET (vec, 1, make_number (offsets[j].dv));
385 end = nglyphs; 417 /* Based on what ftfont.c does... */
386 if (start < clusters[nchars_in_run - 2]) 418 ASET (vec, 2, make_number (advances[j]));
387 { 419 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
388 end = start + 1; 420 }
389 start = 0; 421 else
390 } 422 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
391 for (k = start; k < end; k++) 423 } }
392 {
393 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring,
394 done_glyphs + k);
395 LGLYPH_SET_CHAR (lglyph, last_char);
396 }
397 }
398 }
399 } 424 }
400 done_glyphs += nglyphs; 425 done_glyphs += nglyphs;
401 done_chars += nchars_in_run;
402 } 426 }
403 427
404 xfree (items); 428 xfree (items);
@@ -408,7 +432,7 @@ uniscribe_shape (lgstring)
408 if (NILP (lgstring)) 432 if (NILP (lgstring))
409 return Qnil; 433 return Qnil;
410 else 434 else
411 return make_number (done_chars); 435 return make_number (done_glyphs);
412} 436}
413 437
414/* Uniscribe implementation of encode_char for font backend. 438/* Uniscribe implementation of encode_char for font backend.