diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/w32uniscribe.c | 186 |
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 @@ | |||
| 1 | 2008-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 | |||
| 1 | 2008-04-05 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 9 | 2008-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 | ||
| 60 | 2008-04-04 Jason Rumney <jasonr@gnu.org> | 68 | 2008-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. |