OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* aflatin2.c */ | 3 /* aflatin2.c */ |
4 /* */ | 4 /* */ |
5 /* Auto-fitter hinting routines for latin script (body). */ | 5 /* Auto-fitter hinting routines for latin script (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 2003-2011 by */ | 7 /* Copyright 2003-2013 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 10 /* This file is part of the FreeType project, and may only be used, */ |
11 /* modified, and distributed under the terms of the FreeType project */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
18 | 18 |
19 #include FT_ADVANCES_H | 19 #include FT_ADVANCES_H |
20 | 20 |
| 21 #include "afglobal.h" |
21 #include "aflatin.h" | 22 #include "aflatin.h" |
22 #include "aflatin2.h" | 23 #include "aflatin2.h" |
23 #include "aferrors.h" | 24 #include "aferrors.h" |
24 | 25 |
25 | 26 |
26 #ifdef AF_CONFIG_OPTION_USE_WARPER | 27 #ifdef AF_CONFIG_OPTION_USE_WARPER |
27 #include "afwarp.h" | 28 #include "afwarp.h" |
28 #endif | 29 #endif |
29 | 30 |
30 | 31 |
(...skipping 18 matching lines...) Expand all Loading... |
49 /*************************************************************************/ | 50 /*************************************************************************/ |
50 /*************************************************************************/ | 51 /*************************************************************************/ |
51 /***** *****/ | 52 /***** *****/ |
52 /***** L A T I N G L O B A L M E T R I C S *****/ | 53 /***** L A T I N G L O B A L M E T R I C S *****/ |
53 /***** *****/ | 54 /***** *****/ |
54 /*************************************************************************/ | 55 /*************************************************************************/ |
55 /*************************************************************************/ | 56 /*************************************************************************/ |
56 | 57 |
57 FT_LOCAL_DEF( void ) | 58 FT_LOCAL_DEF( void ) |
58 af_latin2_metrics_init_widths( AF_LatinMetrics metrics, | 59 af_latin2_metrics_init_widths( AF_LatinMetrics metrics, |
59 FT_Face face, | 60 FT_Face face ) |
60 FT_ULong charcode ) | |
61 { | 61 { |
62 /* scan the array of segments in each direction */ | 62 /* scan the array of segments in each direction */ |
63 AF_GlyphHintsRec hints[1]; | 63 AF_GlyphHintsRec hints[1]; |
64 | 64 |
65 | 65 |
66 af_glyph_hints_init( hints, face->memory ); | 66 af_glyph_hints_init( hints, face->memory ); |
67 | 67 |
68 metrics->axis[AF_DIMENSION_HORZ].width_count = 0; | 68 metrics->axis[AF_DIMENSION_HORZ].width_count = 0; |
69 metrics->axis[AF_DIMENSION_VERT].width_count = 0; | 69 metrics->axis[AF_DIMENSION_VERT].width_count = 0; |
70 | 70 |
71 { | 71 { |
72 FT_Error error; | 72 FT_Error error; |
73 FT_UInt glyph_index; | 73 FT_UInt glyph_index; |
74 int dim; | 74 int dim; |
75 AF_LatinMetricsRec dummy[1]; | 75 AF_LatinMetricsRec dummy[1]; |
76 AF_Scaler scaler = &dummy->root.scaler; | 76 AF_Scaler scaler = &dummy->root.scaler; |
77 | 77 |
78 | 78 |
79 glyph_index = FT_Get_Char_Index( face, charcode ); | 79 glyph_index = FT_Get_Char_Index( face, |
| 80 metrics->root.clazz->standard_char ); |
80 if ( glyph_index == 0 ) | 81 if ( glyph_index == 0 ) |
81 goto Exit; | 82 goto Exit; |
82 | 83 |
83 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); | 84 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); |
84 if ( error || face->glyph->outline.n_points <= 0 ) | 85 if ( error || face->glyph->outline.n_points <= 0 ) |
85 goto Exit; | 86 goto Exit; |
86 | 87 |
87 FT_ZERO( dummy ); | 88 FT_ZERO( dummy ); |
88 | 89 |
89 dummy->units_per_em = metrics->units_per_em; | 90 dummy->units_per_em = metrics->units_per_em; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 AF_LatinBlue blue; | 192 AF_LatinBlue blue; |
192 FT_Error error; | 193 FT_Error error; |
193 AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; | 194 AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; |
194 FT_GlyphSlot glyph = face->glyph; | 195 FT_GlyphSlot glyph = face->glyph; |
195 | 196 |
196 | 197 |
197 /* we compute the blues simply by loading each character from the */ | 198 /* we compute the blues simply by loading each character from the */ |
198 /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */ | 199 /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */ |
199 /* bottom-most points (depending on `AF_IS_TOP_BLUE') */ | 200 /* bottom-most points (depending on `AF_IS_TOP_BLUE') */ |
200 | 201 |
201 FT_TRACE5(( "blue zones computation\n" )); | 202 FT_TRACE5(( "blue zones computation\n" |
202 FT_TRACE5(( "------------------------------------------------\n" )); | 203 "======================\n\n" )); |
203 | 204 |
204 for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) | 205 for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) |
205 { | 206 { |
206 const char* p = af_latin2_blue_chars[bb]; | 207 const char* p = af_latin2_blue_chars[bb]; |
207 const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS; | 208 const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS; |
208 FT_Pos* blue_ref; | 209 FT_Pos* blue_ref; |
209 FT_Pos* blue_shoot; | 210 FT_Pos* blue_shoot; |
210 | 211 |
211 | 212 |
212 FT_TRACE5(( "blue %3d: ", bb )); | 213 FT_TRACE5(( "blue zone %d:\n", bb )); |
213 | 214 |
214 num_flats = 0; | 215 num_flats = 0; |
215 num_rounds = 0; | 216 num_rounds = 0; |
216 | 217 |
217 for ( ; p < limit && *p; p++ ) | 218 for ( ; p < limit && *p; p++ ) |
218 { | 219 { |
219 FT_UInt glyph_index; | 220 FT_UInt glyph_index; |
220 FT_Int best_point, best_y, best_first, best_last; | 221 FT_Int best_point, best_y, best_first, best_last; |
221 FT_Vector* points; | 222 FT_Vector* points; |
222 FT_Bool round; | 223 FT_Bool round; |
223 | 224 |
224 | 225 |
225 FT_TRACE5(( "'%c'", *p )); | |
226 | |
227 /* load the character in the face -- skip unknown or empty ones */ | 226 /* load the character in the face -- skip unknown or empty ones */ |
228 glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); | 227 glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); |
229 if ( glyph_index == 0 ) | 228 if ( glyph_index == 0 ) |
230 continue; | 229 continue; |
231 | 230 |
232 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); | 231 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); |
233 if ( error || glyph->outline.n_points <= 0 ) | 232 if ( error || glyph->outline.n_points <= 0 ) |
234 continue; | 233 continue; |
235 | 234 |
236 /* now compute min or max point indices and coordinates */ | 235 /* now compute min or max point indices and coordinates */ |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 best_y = points[pp].y; | 277 best_y = points[pp].y; |
279 } | 278 } |
280 } | 279 } |
281 | 280 |
282 if ( best_point != old_best_point ) | 281 if ( best_point != old_best_point ) |
283 { | 282 { |
284 best_first = first; | 283 best_first = first; |
285 best_last = last; | 284 best_last = last; |
286 } | 285 } |
287 } | 286 } |
288 FT_TRACE5(( "%5d", best_y )); | 287 FT_TRACE5(( " %c %d", *p, best_y )); |
289 } | 288 } |
290 | 289 |
291 /* now check whether the point belongs to a straight or round */ | 290 /* now check whether the point belongs to a straight or round */ |
292 /* segment; we first need to find in which contour the extremum */ | 291 /* segment; we first need to find in which contour the extremum */ |
293 /* lies, then inspect its previous and next points */ | 292 /* lies, then inspect its previous and next points */ |
294 { | 293 { |
| 294 FT_Pos best_x = points[best_point].x; |
295 FT_Int start, end, prev, next; | 295 FT_Int start, end, prev, next; |
296 FT_Pos dist; | 296 FT_Pos dist; |
297 | 297 |
298 | 298 |
299 /* now look for the previous and next points that are not on the */ | 299 /* now look for the previous and next points that are not on the */ |
300 /* same Y coordinate. Threshold the `closeness'... */ | 300 /* same Y coordinate. Threshold the `closeness'... */ |
301 start = end = best_point; | 301 start = end = best_point; |
302 | 302 |
303 do | 303 do |
304 { | 304 { |
305 prev = start-1; | 305 prev = start - 1; |
306 if ( prev < best_first ) | 306 if ( prev < best_first ) |
307 prev = best_last; | 307 prev = best_last; |
308 | 308 |
309 dist = points[prev].y - best_y; | 309 dist = FT_ABS( points[prev].y - best_y ); |
310 if ( dist < -5 || dist > 5 ) | 310 /* accept a small distance or a small angle (both values are */ |
311 break; | 311 /* heuristic; value 20 corresponds to approx. 2.9 degrees) */ |
| 312 if ( dist > 5 ) |
| 313 if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist ) |
| 314 break; |
312 | 315 |
313 start = prev; | 316 start = prev; |
314 | 317 |
315 } while ( start != best_point ); | 318 } while ( start != best_point ); |
316 | 319 |
317 do | 320 do |
318 { | 321 { |
319 next = end+1; | 322 next = end + 1; |
320 if ( next > best_last ) | 323 if ( next > best_last ) |
321 next = best_first; | 324 next = best_first; |
322 | 325 |
323 dist = points[next].y - best_y; | 326 dist = FT_ABS( points[next].y - best_y ); |
324 if ( dist < -5 || dist > 5 ) | 327 if ( dist > 5 ) |
325 break; | 328 if ( FT_ABS( points[next].x - best_x ) <= 20 * dist ) |
| 329 break; |
326 | 330 |
327 end = next; | 331 end = next; |
328 | 332 |
329 } while ( end != best_point ); | 333 } while ( end != best_point ); |
330 | 334 |
331 /* now, set the `round' flag depending on the segment's kind */ | 335 /* now, set the `round' flag depending on the segment's kind */ |
332 round = FT_BOOL( | 336 round = FT_BOOL( |
333 FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON || | 337 FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON || |
334 FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON ); | 338 FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON ); |
335 | 339 |
336 FT_TRACE5(( "%c ", round ? 'r' : 'f' )); | 340 FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); |
337 } | 341 } |
338 | 342 |
339 if ( round ) | 343 if ( round ) |
340 rounds[num_rounds++] = best_y; | 344 rounds[num_rounds++] = best_y; |
341 else | 345 else |
342 flats[num_flats++] = best_y; | 346 flats[num_flats++] = best_y; |
343 } | 347 } |
344 | 348 |
345 FT_TRACE5(( "\n" )); | |
346 | |
347 if ( num_flats == 0 && num_rounds == 0 ) | 349 if ( num_flats == 0 && num_rounds == 0 ) |
348 { | 350 { |
349 /* | 351 /* |
350 * we couldn't find a single glyph to compute this blue zone, | 352 * we couldn't find a single glyph to compute this blue zone, |
351 * we will simply ignore it then | 353 * we will simply ignore it then |
352 */ | 354 */ |
353 FT_TRACE5(( "empty\n" )); | 355 FT_TRACE5(( " empty\n" )); |
354 continue; | 356 continue; |
355 } | 357 } |
356 | 358 |
357 /* we have computed the contents of the `rounds' and `flats' tables, */ | 359 /* we have computed the contents of the `rounds' and `flats' tables, */ |
358 /* now determine the reference and overshoot position of the blue -- */ | 360 /* now determine the reference and overshoot position of the blue -- */ |
359 /* we simply take the median value after a simple sort */ | 361 /* we simply take the median value after a simple sort */ |
360 af_sort_pos( num_rounds, rounds ); | 362 af_sort_pos( num_rounds, rounds ); |
361 af_sort_pos( num_flats, flats ); | 363 af_sort_pos( num_flats, flats ); |
362 | 364 |
363 blue = & axis->blues[axis->blue_count]; | 365 blue = & axis->blues[axis->blue_count]; |
(...skipping 22 matching lines...) Expand all Loading... |
386 /* zones is under its reference position, or the opposite for bottom */ | 388 /* zones is under its reference position, or the opposite for bottom */ |
387 /* zones. We must thus check everything there and correct the errors */ | 389 /* zones. We must thus check everything there and correct the errors */ |
388 if ( *blue_shoot != *blue_ref ) | 390 if ( *blue_shoot != *blue_ref ) |
389 { | 391 { |
390 FT_Pos ref = *blue_ref; | 392 FT_Pos ref = *blue_ref; |
391 FT_Pos shoot = *blue_shoot; | 393 FT_Pos shoot = *blue_shoot; |
392 FT_Bool over_ref = FT_BOOL( shoot > ref ); | 394 FT_Bool over_ref = FT_BOOL( shoot > ref ); |
393 | 395 |
394 | 396 |
395 if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) | 397 if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) |
396 *blue_shoot = *blue_ref = ( shoot + ref ) / 2; | 398 { |
| 399 *blue_ref = |
| 400 *blue_shoot = ( shoot + ref ) / 2; |
| 401 |
| 402 FT_TRACE5(( " [overshoot smaller than reference," |
| 403 " taking mean value]\n" )); |
| 404 } |
397 } | 405 } |
398 | 406 |
399 blue->flags = 0; | 407 blue->flags = 0; |
400 if ( AF_LATIN_IS_TOP_BLUE( bb ) ) | 408 if ( AF_LATIN_IS_TOP_BLUE( bb ) ) |
401 blue->flags |= AF_LATIN_BLUE_TOP; | 409 blue->flags |= AF_LATIN_BLUE_TOP; |
402 | 410 |
403 /* | 411 /* |
404 * The following flags is used later to adjust the y and x scales | 412 * The following flags is used later to adjust the y and x scales |
405 * in order to optimize the pixel grid alignment of the top of small | 413 * in order to optimize the pixel grid alignment of the top of small |
406 * letters. | 414 * letters. |
407 */ | 415 */ |
408 if ( bb == AF_LATIN_BLUE_SMALL_TOP ) | 416 if ( bb == AF_LATIN_BLUE_SMALL_TOP ) |
409 blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; | 417 blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; |
410 | 418 |
411 FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); | 419 FT_TRACE5(( " -> reference = %ld\n" |
| 420 " overshoot = %ld\n", |
| 421 *blue_ref, *blue_shoot )); |
412 } | 422 } |
413 | 423 |
414 return; | 424 return; |
415 } | 425 } |
416 | 426 |
417 | 427 |
418 FT_LOCAL_DEF( void ) | 428 FT_LOCAL_DEF( void ) |
419 af_latin2_metrics_check_digits( AF_LatinMetrics metrics, | 429 af_latin2_metrics_check_digits( AF_LatinMetrics metrics, |
420 FT_Face face ) | 430 FT_Face face ) |
421 { | 431 { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 } | 468 } |
459 | 469 |
460 metrics->root.digits_have_same_width = same_width; | 470 metrics->root.digits_have_same_width = same_width; |
461 } | 471 } |
462 | 472 |
463 | 473 |
464 FT_LOCAL_DEF( FT_Error ) | 474 FT_LOCAL_DEF( FT_Error ) |
465 af_latin2_metrics_init( AF_LatinMetrics metrics, | 475 af_latin2_metrics_init( AF_LatinMetrics metrics, |
466 FT_Face face ) | 476 FT_Face face ) |
467 { | 477 { |
468 FT_Error error = AF_Err_Ok; | 478 FT_Error error = FT_Err_Ok; |
469 FT_CharMap oldmap = face->charmap; | 479 FT_CharMap oldmap = face->charmap; |
470 FT_UInt ee; | 480 FT_UInt ee; |
471 | 481 |
472 static const FT_Encoding latin_encodings[] = | 482 static const FT_Encoding latin_encodings[] = |
473 { | 483 { |
474 FT_ENCODING_UNICODE, | 484 FT_ENCODING_UNICODE, |
475 FT_ENCODING_APPLE_ROMAN, | 485 FT_ENCODING_APPLE_ROMAN, |
476 FT_ENCODING_ADOBE_STANDARD, | 486 FT_ENCODING_ADOBE_STANDARD, |
477 FT_ENCODING_ADOBE_LATIN_1, | 487 FT_ENCODING_ADOBE_LATIN_1, |
478 FT_ENCODING_NONE /* end of list */ | 488 FT_ENCODING_NONE /* end of list */ |
479 }; | 489 }; |
480 | 490 |
481 | 491 |
482 metrics->units_per_em = face->units_per_EM; | 492 metrics->units_per_em = face->units_per_EM; |
483 | 493 |
484 /* do we have a latin charmap in there? */ | 494 /* do we have a latin charmap in there? */ |
485 for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ ) | 495 for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ ) |
486 { | 496 { |
487 error = FT_Select_Charmap( face, latin_encodings[ee] ); | 497 error = FT_Select_Charmap( face, latin_encodings[ee] ); |
488 if ( !error ) | 498 if ( !error ) |
489 break; | 499 break; |
490 } | 500 } |
491 | 501 |
492 if ( !error ) | 502 if ( !error ) |
493 { | 503 { |
494 /* For now, compute the standard width and height from the `o'. */ | 504 af_latin2_metrics_init_widths( metrics, face ); |
495 af_latin2_metrics_init_widths( metrics, face, 'o' ); | |
496 af_latin2_metrics_init_blues( metrics, face ); | 505 af_latin2_metrics_init_blues( metrics, face ); |
497 af_latin2_metrics_check_digits( metrics, face ); | 506 af_latin2_metrics_check_digits( metrics, face ); |
498 } | 507 } |
499 | 508 |
500 FT_Set_Charmap( face, oldmap ); | 509 FT_Set_Charmap( face, oldmap ); |
501 return AF_Err_Ok; | 510 return FT_Err_Ok; |
502 } | 511 } |
503 | 512 |
504 | 513 |
505 static void | 514 static void |
506 af_latin2_metrics_scale_dim( AF_LatinMetrics metrics, | 515 af_latin2_metrics_scale_dim( AF_LatinMetrics metrics, |
507 AF_Scaler scaler, | 516 AF_Scaler scaler, |
508 AF_Dimension dim ) | 517 AF_Dimension dim ) |
509 { | 518 { |
510 FT_Fixed scale; | 519 FT_Fixed scale; |
511 FT_Pos delta; | 520 FT_Pos delta; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 { | 555 { |
547 if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) | 556 if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) |
548 { | 557 { |
549 blue = &vaxis->blues[nn]; | 558 blue = &vaxis->blues[nn]; |
550 break; | 559 break; |
551 } | 560 } |
552 } | 561 } |
553 | 562 |
554 if ( blue ) | 563 if ( blue ) |
555 { | 564 { |
556 FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); | 565 FT_Pos scaled; |
557 FT_Pos fitted = ( scaled + 40 ) & ~63; | 566 FT_Pos threshold; |
| 567 FT_Pos fitted; |
| 568 FT_UInt limit; |
| 569 FT_UInt ppem; |
| 570 |
| 571 |
| 572 scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); |
| 573 ppem = metrics->root.scaler.face->size->metrics.x_ppem; |
| 574 limit = metrics->root.globals->increase_x_height; |
| 575 threshold = 40; |
| 576 |
| 577 /* if the `increase-x-height' property is active, */ |
| 578 /* we round up much more often */ |
| 579 if ( limit && |
| 580 ppem <= limit && |
| 581 ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN ) |
| 582 threshold = 52; |
| 583 |
| 584 fitted = ( scaled + threshold ) & ~63; |
558 | 585 |
559 #if 1 | 586 #if 1 |
560 if ( scaled != fitted ) | 587 if ( scaled != fitted ) |
561 { | 588 { |
562 scale = FT_MulDiv( scale, fitted, scaled ); | 589 scale = FT_MulDiv( scale, fitted, scaled ); |
563 FT_TRACE5(( "== scaled x-top = %.2g" | 590 FT_TRACE5(( "== scaled x-top = %.2g" |
564 " fitted = %.2g, scaling = %.4g\n", | 591 " fitted = %.2g, scaling = %.4g\n", |
565 scaled / 64.0, fitted / 64.0, | 592 scaled / 64.0, fitted / 64.0, |
566 ( fitted * 1.0 ) / scaled )); | 593 ( fitted * 1.0 ) / scaled )); |
567 } | 594 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 } | 678 } |
652 } | 679 } |
653 | 680 |
654 | 681 |
655 FT_LOCAL_DEF( void ) | 682 FT_LOCAL_DEF( void ) |
656 af_latin2_metrics_scale( AF_LatinMetrics metrics, | 683 af_latin2_metrics_scale( AF_LatinMetrics metrics, |
657 AF_Scaler scaler ) | 684 AF_Scaler scaler ) |
658 { | 685 { |
659 metrics->root.scaler.render_mode = scaler->render_mode; | 686 metrics->root.scaler.render_mode = scaler->render_mode; |
660 metrics->root.scaler.face = scaler->face; | 687 metrics->root.scaler.face = scaler->face; |
| 688 metrics->root.scaler.flags = scaler->flags; |
661 | 689 |
662 af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); | 690 af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); |
663 af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); | 691 af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); |
664 } | 692 } |
665 | 693 |
666 | 694 |
667 /*************************************************************************/ | 695 /*************************************************************************/ |
668 /*************************************************************************/ | 696 /*************************************************************************/ |
669 /***** *****/ | 697 /***** *****/ |
670 /***** L A T I N G L Y P H A N A L Y S I S *****/ | 698 /***** L A T I N G L Y P H A N A L Y S I S *****/ |
671 /***** *****/ | 699 /***** *****/ |
672 /*************************************************************************/ | 700 /*************************************************************************/ |
673 /*************************************************************************/ | 701 /*************************************************************************/ |
674 | 702 |
675 #define SORT_SEGMENTS | 703 #define SORT_SEGMENTS |
676 | 704 |
677 FT_LOCAL_DEF( FT_Error ) | 705 FT_LOCAL_DEF( FT_Error ) |
678 af_latin2_hints_compute_segments( AF_GlyphHints hints, | 706 af_latin2_hints_compute_segments( AF_GlyphHints hints, |
679 AF_Dimension dim ) | 707 AF_Dimension dim ) |
680 { | 708 { |
681 AF_AxisHints axis = &hints->axis[dim]; | 709 AF_AxisHints axis = &hints->axis[dim]; |
682 FT_Memory memory = hints->memory; | 710 FT_Memory memory = hints->memory; |
683 FT_Error error = AF_Err_Ok; | 711 FT_Error error = FT_Err_Ok; |
684 AF_Segment segment = NULL; | 712 AF_Segment segment = NULL; |
685 AF_SegmentRec seg0; | 713 AF_SegmentRec seg0; |
686 AF_Point* contour = hints->contours; | 714 AF_Point* contour = hints->contours; |
687 AF_Point* contour_limit = contour + hints->num_contours; | 715 AF_Point* contour_limit = contour + hints->num_contours; |
688 AF_Direction major_dir, segment_dir; | 716 AF_Direction major_dir, segment_dir; |
689 | 717 |
690 | 718 |
691 FT_ZERO( &seg0 ); | 719 FT_ZERO( &seg0 ); |
692 seg0.score = 32000; | 720 seg0.score = 32000; |
693 seg0.flags = AF_EDGE_NORMAL; | 721 seg0.flags = AF_EDGE_NORMAL; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 817 |
790 /* record new segment */ | 818 /* record new segment */ |
791 error = af_axis_hints_new_segment( axis, memory, &segment ); | 819 error = af_axis_hints_new_segment( axis, memory, &segment ); |
792 if ( error ) | 820 if ( error ) |
793 goto Exit; | 821 goto Exit; |
794 | 822 |
795 segment[0] = seg0; | 823 segment[0] = seg0; |
796 segment->dir = first->out_dir; | 824 segment->dir = first->out_dir; |
797 segment->first = first; | 825 segment->first = first; |
798 segment->last = point; | 826 segment->last = point; |
799 segment->pos = (FT_Short)(( min_u + max_u ) >> 1); | 827 segment->pos = (FT_Short)( ( min_u + max_u ) >> 1 ); |
800 segment->min_coord = (FT_Short) min_v; | 828 segment->min_coord = (FT_Short) min_v; |
801 segment->max_coord = (FT_Short) max_v; | 829 segment->max_coord = (FT_Short) max_v; |
802 segment->height = (FT_Short)(max_v - min_v); | 830 segment->height = (FT_Short)( max_v - min_v ); |
803 | 831 |
804 /* a segment is round if it doesn't have successive */ | 832 /* a segment is round if it doesn't have successive */ |
805 /* on-curve points. */ | 833 /* on-curve points. */ |
806 { | 834 { |
807 AF_Point pt = first; | 835 AF_Point pt = first; |
808 AF_Point last = point; | 836 AF_Point last = point; |
809 AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); | 837 AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
810 AF_Flags f1; | 838 AF_Flags f1; |
811 | 839 |
812 | 840 |
813 segment->flags &= ~AF_EDGE_ROUND; | 841 segment->flags &= ~AF_EDGE_ROUND; |
814 | 842 |
815 for ( ; pt != last; f0 = f1 ) | 843 for ( ; pt != last; f0 = f1 ) |
816 { | 844 { |
817 pt = pt->next; | 845 pt = pt->next; |
818 f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); | 846 f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
819 | 847 |
820 if ( !f0 && !f1 ) | 848 if ( !f0 && !f1 ) |
821 break; | 849 break; |
822 | 850 |
823 if ( pt == last ) | 851 if ( pt == last ) |
824 segment->flags |= AF_EDGE_ROUND; | 852 segment->flags |= AF_EDGE_ROUND; |
825 } | 853 } |
826 } | 854 } |
827 | 855 |
828 /* this can happen in the case of a degenerate contour | 856 /* this can happen in the case of a degenerate contour |
829 * e.g. a 2-point vertical contour | 857 * e.g. a 2-point vertical contour |
830 */ | 858 */ |
831 if ( point == start ) | 859 if ( point == start ) |
832 break; | 860 break; |
833 | 861 |
834 /* jump to the start of the next segment, if any */ | 862 /* jump to the start of the next segment, if any */ |
835 while ( FT_ABS(point->out_dir) != major_dir ) | 863 while ( FT_ABS( point->out_dir ) != major_dir ) |
836 { | 864 { |
837 point = point->next; | 865 point = point->next; |
838 | 866 |
839 if ( point == start ) | 867 if ( point == start ) |
840 goto NextContour; | 868 goto NextContour; |
841 } | 869 } |
842 } | 870 } |
843 | 871 |
844 NextContour: | 872 NextContour: |
845 ; | 873 ; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 | 921 |
894 #ifdef AF_SORT_SEGMENTS | 922 #ifdef AF_SORT_SEGMENTS |
895 /* place all segments with a negative direction to the start | 923 /* place all segments with a negative direction to the start |
896 * of the array, used to speed up segment linking later... | 924 * of the array, used to speed up segment linking later... |
897 */ | 925 */ |
898 { | 926 { |
899 AF_Segment segments = axis->segments; | 927 AF_Segment segments = axis->segments; |
900 FT_UInt count = axis->num_segments; | 928 FT_UInt count = axis->num_segments; |
901 FT_UInt ii, jj; | 929 FT_UInt ii, jj; |
902 | 930 |
903 for (ii = 0; ii < count; ii++) | 931 for ( ii = 0; ii < count; ii++ ) |
904 { | 932 { |
905 if ( segments[ii].dir > 0 ) | 933 if ( segments[ii].dir > 0 ) |
906 { | 934 { |
907 for (jj = ii+1; jj < count; jj++) | 935 for ( jj = ii + 1; jj < count; jj++ ) |
908 { | 936 { |
909 if ( segments[jj].dir < 0 ) | 937 if ( segments[jj].dir < 0 ) |
910 { | 938 { |
911 AF_SegmentRec tmp; | 939 AF_SegmentRec tmp; |
912 | 940 |
| 941 |
913 tmp = segments[ii]; | 942 tmp = segments[ii]; |
914 segments[ii] = segments[jj]; | 943 segments[ii] = segments[jj]; |
915 segments[jj] = tmp; | 944 segments[jj] = tmp; |
916 | 945 |
917 break; | 946 break; |
918 } | 947 } |
919 } | 948 } |
920 | 949 |
921 if ( jj == count ) | 950 if ( jj == count ) |
922 break; | 951 break; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 } | 1058 } |
1030 } | 1059 } |
1031 } | 1060 } |
1032 | 1061 |
1033 | 1062 |
1034 FT_LOCAL_DEF( FT_Error ) | 1063 FT_LOCAL_DEF( FT_Error ) |
1035 af_latin2_hints_compute_edges( AF_GlyphHints hints, | 1064 af_latin2_hints_compute_edges( AF_GlyphHints hints, |
1036 AF_Dimension dim ) | 1065 AF_Dimension dim ) |
1037 { | 1066 { |
1038 AF_AxisHints axis = &hints->axis[dim]; | 1067 AF_AxisHints axis = &hints->axis[dim]; |
1039 FT_Error error = AF_Err_Ok; | 1068 FT_Error error = FT_Err_Ok; |
1040 FT_Memory memory = hints->memory; | 1069 FT_Memory memory = hints->memory; |
1041 AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; | 1070 AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; |
1042 | 1071 |
1043 AF_Segment segments = axis->segments; | 1072 AF_Segment segments = axis->segments; |
1044 AF_Segment segment_limit = segments + axis->num_segments; | 1073 AF_Segment segment_limit = segments + axis->num_segments; |
1045 AF_Segment seg; | 1074 AF_Segment seg; |
1046 | 1075 |
1047 AF_Direction up_dir; | 1076 AF_Direction up_dir; |
1048 FT_Fixed scale; | 1077 FT_Fixed scale; |
1049 FT_Pos edge_distance_threshold; | 1078 FT_Pos edge_distance_threshold; |
(...skipping 13 matching lines...) Expand all Loading... |
1063 * by ignoring those that whose length is less than a given fraction | 1092 * by ignoring those that whose length is less than a given fraction |
1064 * of the standard width. If there is no standard width, we ignore | 1093 * of the standard width. If there is no standard width, we ignore |
1065 * those that are less than a given size in pixels | 1094 * those that are less than a given size in pixels |
1066 * | 1095 * |
1067 * also, unlink serif segments that are linked to segments farther | 1096 * also, unlink serif segments that are linked to segments farther |
1068 * than 50% of the standard width | 1097 * than 50% of the standard width |
1069 */ | 1098 */ |
1070 if ( dim == AF_DIMENSION_HORZ ) | 1099 if ( dim == AF_DIMENSION_HORZ ) |
1071 { | 1100 { |
1072 if ( laxis->width_count > 0 ) | 1101 if ( laxis->width_count > 0 ) |
1073 segment_length_threshold = (laxis->standard_width * 10 ) >> 4; | 1102 segment_length_threshold = ( laxis->standard_width * 10 ) >> 4; |
1074 else | 1103 else |
1075 segment_length_threshold = FT_DivFix( 64, hints->y_scale ); | 1104 segment_length_threshold = FT_DivFix( 64, hints->y_scale ); |
1076 } | 1105 } |
1077 else | 1106 else |
1078 segment_length_threshold = 0; | 1107 segment_length_threshold = 0; |
1079 | 1108 |
1080 /*********************************************************************/ | 1109 /*********************************************************************/ |
1081 /* */ | 1110 /* */ |
1082 /* We will begin by generating a sorted table of edges for the */ | 1111 /* We will begin by generating a sorted table of edges for the */ |
1083 /* current direction. To do so, we simply scan each segment and try */ | 1112 /* current direction. To do so, we simply scan each segment and try */ |
(...skipping 25 matching lines...) Expand all Loading... |
1109 | 1138 |
1110 if ( seg->height < segment_length_threshold ) | 1139 if ( seg->height < segment_length_threshold ) |
1111 continue; | 1140 continue; |
1112 | 1141 |
1113 /* A special case for serif edges: If they are smaller than */ | 1142 /* A special case for serif edges: If they are smaller than */ |
1114 /* 1.5 pixels we ignore them. */ | 1143 /* 1.5 pixels we ignore them. */ |
1115 if ( seg->serif ) | 1144 if ( seg->serif ) |
1116 { | 1145 { |
1117 FT_Pos dist = seg->serif->pos - seg->pos; | 1146 FT_Pos dist = seg->serif->pos - seg->pos; |
1118 | 1147 |
1119 if (dist < 0) | 1148 |
| 1149 if ( dist < 0 ) |
1120 dist = -dist; | 1150 dist = -dist; |
1121 | 1151 |
1122 if (dist >= laxis->standard_width >> 1) | 1152 if ( dist >= laxis->standard_width >> 1 ) |
1123 { | 1153 { |
1124 /* unlink this serif, it is too distant from its reference stem */ | 1154 /* unlink this serif, it is too distant from its reference stem */ |
1125 seg->serif = NULL; | 1155 seg->serif = NULL; |
1126 } | 1156 } |
1127 else if ( 2*seg->height < 3 * segment_length_threshold ) | 1157 else if ( 2*seg->height < 3 * segment_length_threshold ) |
1128 continue; | 1158 continue; |
1129 } | 1159 } |
1130 | 1160 |
1131 /* look for an edge corresponding to the segment */ | 1161 /* look for an edge corresponding to the segment */ |
1132 for ( ee = 0; ee < axis->num_edges; ee++ ) | 1162 for ( ee = 0; ee < axis->num_edges; ee++ ) |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1410 | 1440 |
1411 | 1441 |
1412 /* if it's a rounded edge, compare it to the overshoot position */ | 1442 /* if it's a rounded edge, compare it to the overshoot position */ |
1413 /* if it's a flat edge, compare it to the reference position */ | 1443 /* if it's a flat edge, compare it to the reference position */ |
1414 if ( edge->flags & AF_EDGE_ROUND ) | 1444 if ( edge->flags & AF_EDGE_ROUND ) |
1415 compare = &blue->shoot; | 1445 compare = &blue->shoot; |
1416 else | 1446 else |
1417 compare = &blue->ref; | 1447 compare = &blue->ref; |
1418 | 1448 |
1419 dist = edge->fpos - compare->org; | 1449 dist = edge->fpos - compare->org; |
1420 if (dist < 0) | 1450 if ( dist < 0 ) |
1421 dist = -dist; | 1451 dist = -dist; |
1422 | 1452 |
1423 dist = FT_MulFix( dist, scale ); | 1453 dist = FT_MulFix( dist, scale ); |
1424 if ( dist < best_dist ) | 1454 if ( dist < best_dist ) |
1425 { | 1455 { |
1426 best_dist = dist; | 1456 best_dist = dist; |
1427 best_blue = compare; | 1457 best_blue = compare; |
1428 } | 1458 } |
1429 | 1459 |
1430 #if 0 | 1460 #if 0 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 if ( mode != FT_RENDER_MODE_LIGHT ) | 1544 if ( mode != FT_RENDER_MODE_LIGHT ) |
1515 other_flags |= AF_LATIN_HINTS_STEM_ADJUST; | 1545 other_flags |= AF_LATIN_HINTS_STEM_ADJUST; |
1516 | 1546 |
1517 if ( mode == FT_RENDER_MODE_MONO ) | 1547 if ( mode == FT_RENDER_MODE_MONO ) |
1518 other_flags |= AF_LATIN_HINTS_MONO; | 1548 other_flags |= AF_LATIN_HINTS_MONO; |
1519 | 1549 |
1520 /* | 1550 /* |
1521 * In `light' hinting mode we disable horizontal hinting completely. | 1551 * In `light' hinting mode we disable horizontal hinting completely. |
1522 * We also do it if the face is italic. | 1552 * We also do it if the face is italic. |
1523 */ | 1553 */ |
1524 if ( mode == FT_RENDER_MODE_LIGHT || | 1554 if ( mode == FT_RENDER_MODE_LIGHT || |
1525 (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 ) | 1555 ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) |
1526 scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; | 1556 scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; |
1527 | 1557 |
1528 hints->scaler_flags = scaler_flags; | 1558 hints->scaler_flags = scaler_flags; |
1529 hints->other_flags = other_flags; | 1559 hints->other_flags = other_flags; |
1530 | 1560 |
1531 return 0; | 1561 return 0; |
1532 } | 1562 } |
1533 | 1563 |
1534 | 1564 |
1535 /*************************************************************************/ | 1565 /*************************************************************************/ |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 FT_Pos width, | 1626 FT_Pos width, |
1597 AF_Edge_Flags base_flags, | 1627 AF_Edge_Flags base_flags, |
1598 AF_Edge_Flags stem_flags ) | 1628 AF_Edge_Flags stem_flags ) |
1599 { | 1629 { |
1600 AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics; | 1630 AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics; |
1601 AF_LatinAxis axis = & metrics->axis[dim]; | 1631 AF_LatinAxis axis = & metrics->axis[dim]; |
1602 FT_Pos dist = width; | 1632 FT_Pos dist = width; |
1603 FT_Int sign = 0; | 1633 FT_Int sign = 0; |
1604 FT_Int vertical = ( dim == AF_DIMENSION_VERT ); | 1634 FT_Int vertical = ( dim == AF_DIMENSION_VERT ); |
1605 | 1635 |
| 1636 FT_UNUSED( base_flags ); |
1606 | 1637 |
1607 FT_UNUSED(base_flags); | |
1608 | 1638 |
1609 if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || | 1639 if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || |
1610 axis->extra_light ) | 1640 axis->extra_light ) |
1611 return width; | 1641 return width; |
1612 | 1642 |
1613 if ( dist < 0 ) | 1643 if ( dist < 0 ) |
1614 { | 1644 { |
1615 dist = -width; | 1645 dist = -width; |
1616 sign = 1; | 1646 sign = 1; |
1617 } | 1647 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 /* vertical stems. */ | 1757 /* vertical stems. */ |
1728 | 1758 |
1729 FT_Int delta; | 1759 FT_Int delta; |
1730 | 1760 |
1731 | 1761 |
1732 dist = ( dist + 22 ) & ~63; | 1762 dist = ( dist + 22 ) & ~63; |
1733 delta = dist - org_dist; | 1763 delta = dist - org_dist; |
1734 if ( delta < 0 ) | 1764 if ( delta < 0 ) |
1735 delta = -delta; | 1765 delta = -delta; |
1736 | 1766 |
1737 if (delta >= 16) | 1767 if ( delta >= 16 ) |
1738 { | 1768 { |
1739 dist = org_dist; | 1769 dist = org_dist; |
1740 if ( dist < 48 ) | 1770 if ( dist < 48 ) |
1741 dist = ( dist + 64 ) >> 1; | 1771 dist = ( dist + 64 ) >> 1; |
1742 } | 1772 } |
1743 } | 1773 } |
1744 else | 1774 else |
1745 /* round otherwise to prevent color fringes in LCD mode */ | 1775 /* round otherwise to prevent color fringes in LCD mode */ |
1746 dist = ( dist + 32 ) & ~63; | 1776 dist = ( dist + 32 ) & ~63; |
1747 } | 1777 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1781 } | 1811 } |
1782 | 1812 |
1783 | 1813 |
1784 static void | 1814 static void |
1785 af_latin2_align_serif_edge( AF_GlyphHints hints, | 1815 af_latin2_align_serif_edge( AF_GlyphHints hints, |
1786 AF_Edge base, | 1816 AF_Edge base, |
1787 AF_Edge serif ) | 1817 AF_Edge serif ) |
1788 { | 1818 { |
1789 FT_UNUSED( hints ); | 1819 FT_UNUSED( hints ); |
1790 | 1820 |
1791 serif->pos = base->pos + (serif->opos - base->opos); | 1821 serif->pos = base->pos + ( serif->opos - base->opos ); |
1792 } | 1822 } |
1793 | 1823 |
1794 | 1824 |
1795 /*************************************************************************/ | 1825 /*************************************************************************/ |
1796 /*************************************************************************/ | 1826 /*************************************************************************/ |
1797 /*************************************************************************/ | 1827 /*************************************************************************/ |
1798 /**** ****/ | 1828 /**** ****/ |
1799 /**** E D G E H I N T I N G ****/ | 1829 /**** E D G E H I N T I N G ****/ |
1800 /**** ****/ | 1830 /**** ****/ |
1801 /*************************************************************************/ | 1831 /*************************************************************************/ |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 if ( edge2 && !edge2->blue_edge ) | 1893 if ( edge2 && !edge2->blue_edge ) |
1864 { | 1894 { |
1865 af_latin2_align_linked_edge( hints, dim, edge1, edge2 ); | 1895 af_latin2_align_linked_edge( hints, dim, edge1, edge2 ); |
1866 edge2->flags |= AF_EDGE_DONE; | 1896 edge2->flags |= AF_EDGE_DONE; |
1867 } | 1897 } |
1868 | 1898 |
1869 if ( !anchor ) | 1899 if ( !anchor ) |
1870 { | 1900 { |
1871 anchor = edge; | 1901 anchor = edge; |
1872 | 1902 |
1873 anchor_drift = (anchor->pos - anchor->opos); | 1903 anchor_drift = ( anchor->pos - anchor->opos ); |
1874 if (edge2) | 1904 if ( edge2 ) |
1875 anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1; | 1905 anchor_drift = ( anchor_drift + |
| 1906 ( edge2->pos - edge2->opos ) ) >> 1; |
1876 } | 1907 } |
1877 } | 1908 } |
1878 } | 1909 } |
1879 | 1910 |
1880 /* now we will align all stem edges, trying to maintain the */ | 1911 /* now we will align all stem edges, trying to maintain the */ |
1881 /* relative order of stems in the glyph */ | 1912 /* relative order of stems in the glyph */ |
1882 for ( edge = edges; edge < edge_limit; edge++ ) | 1913 for ( edge = edges; edge < edge_limit; edge++ ) |
1883 { | 1914 { |
1884 AF_Edge edge2; | 1915 AF_Edge edge2; |
1885 | 1916 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1957 edge2-edges, edge2->opos / 64.0, | 1988 edge2-edges, edge2->opos / 64.0, |
1958 edge->pos / 64.0, edge2->pos / 64.0 )); | 1989 edge->pos / 64.0, edge2->pos / 64.0 )); |
1959 anchor = edge; | 1990 anchor = edge; |
1960 | 1991 |
1961 edge->flags |= AF_EDGE_DONE; | 1992 edge->flags |= AF_EDGE_DONE; |
1962 | 1993 |
1963 af_latin2_align_linked_edge( hints, dim, edge, edge2 ); | 1994 af_latin2_align_linked_edge( hints, dim, edge, edge2 ); |
1964 | 1995 |
1965 edge2->flags |= AF_EDGE_DONE; | 1996 edge2->flags |= AF_EDGE_DONE; |
1966 | 1997 |
1967 anchor_drift = ( (anchor->pos - anchor->opos) + | 1998 anchor_drift = ( ( anchor->pos - anchor->opos ) + |
1968 (edge2->pos - edge2->opos)) >> 1; | 1999 ( edge2->pos - edge2->opos ) ) >> 1; |
1969 | 2000 |
1970 FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 )); | 2001 FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 )); |
1971 } | 2002 } |
1972 else | 2003 else |
1973 { | 2004 { |
1974 FT_Pos org_pos, org_len, org_center, cur_center, cur_len; | 2005 FT_Pos org_pos, org_len, org_center, cur_center, cur_len; |
1975 FT_Pos org_left, org_right; | 2006 FT_Pos org_left, org_right; |
1976 | 2007 |
1977 | 2008 |
1978 org_pos = edge->opos + anchor_drift; | 2009 org_pos = edge->opos + anchor_drift; |
1979 org_len = edge2->opos - edge->opos; | 2010 org_len = edge2->opos - edge->opos; |
1980 org_center = org_pos + ( org_len >> 1 ); | 2011 org_center = org_pos + ( org_len >> 1 ); |
1981 | 2012 |
1982 cur_len = af_latin2_compute_stem_width( | 2013 cur_len = af_latin2_compute_stem_width( |
1983 hints, dim, org_len, | 2014 hints, dim, org_len, |
1984 (AF_Edge_Flags)edge->flags, | 2015 (AF_Edge_Flags)edge->flags, |
1985 (AF_Edge_Flags)edge2->flags ); | 2016 (AF_Edge_Flags)edge2->flags ); |
1986 | 2017 |
1987 org_left = org_pos + ((org_len - cur_len) >> 1); | 2018 org_left = org_pos + ( ( org_len - cur_len ) >> 1 ); |
1988 org_right = org_pos + ((org_len + cur_len) >> 1); | 2019 org_right = org_pos + ( ( org_len + cur_len ) >> 1 ); |
1989 | 2020 |
1990 FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ", | 2021 FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ", |
1991 org_left / 64.0, org_right / 64.0 )); | 2022 org_left / 64.0, org_right / 64.0 )); |
1992 cur_center = org_center; | 2023 cur_center = org_center; |
1993 | 2024 |
1994 if ( edge2->flags & AF_EDGE_DONE ) | 2025 if ( edge2->flags & AF_EDGE_DONE ) |
1995 { | 2026 { |
1996 FT_TRACE5(( "\n" )); | 2027 FT_TRACE5(( "\n" )); |
1997 edge->pos = edge2->pos - cur_len; | 2028 edge->pos = edge2->pos - cur_len; |
1998 } | 2029 } |
1999 else | 2030 else |
2000 { | 2031 { |
2001 /* we want to compare several displacement, and choose | 2032 /* we want to compare several displacement, and choose |
2002 * the one that increases fitness while minimizing | 2033 * the one that increases fitness while minimizing |
2003 * distortion as well | 2034 * distortion as well |
2004 */ | 2035 */ |
2005 FT_Pos displacements[6], scores[6], org, fit, delta; | 2036 FT_Pos displacements[6], scores[6], org, fit, delta; |
2006 FT_UInt count = 0; | 2037 FT_UInt count = 0; |
2007 | 2038 |
2008 /* note: don't even try to fit tiny stems */ | 2039 /* note: don't even try to fit tiny stems */ |
2009 if ( cur_len < 32 ) | 2040 if ( cur_len < 32 ) |
2010 { | 2041 { |
2011 FT_TRACE5(( "tiny stem\n" )); | 2042 FT_TRACE5(( "tiny stem\n" )); |
2012 goto AlignStem; | 2043 goto AlignStem; |
2013 } | 2044 } |
2014 | 2045 |
2015 /* if the span is within a single pixel, don't touch it */ | 2046 /* if the span is within a single pixel, don't touch it */ |
2016 if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) ) | 2047 if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) ) |
2017 { | 2048 { |
2018 FT_TRACE5(( "single pixel stem\n" )); | 2049 FT_TRACE5(( "single pixel stem\n" )); |
2019 goto AlignStem; | 2050 goto AlignStem; |
2020 } | 2051 } |
2021 | 2052 |
2022 if (cur_len <= 96) | 2053 if ( cur_len <= 96 ) |
2023 { | 2054 { |
2024 /* we want to avoid the absolute worst case which is | 2055 /* we want to avoid the absolute worst case which is |
2025 * when the left and right edges of the span each represent | 2056 * when the left and right edges of the span each represent |
2026 * about 50% of the gray. we'd better want to change this | 2057 * about 50% of the gray. we'd better want to change this |
2027 * to 25/75%, since this is much more pleasant to the eye with | 2058 * to 25/75%, since this is much more pleasant to the eye with |
2028 * very acceptable distortion | 2059 * very acceptable distortion |
2029 */ | 2060 */ |
2030 FT_Pos frac_left = (org_left) & 63; | 2061 FT_Pos frac_left = org_left & 63; |
2031 FT_Pos frac_right = (org_right) & 63; | 2062 FT_Pos frac_right = org_right & 63; |
2032 | 2063 |
2033 if ( frac_left >= 22 && frac_left <= 42 && | 2064 if ( frac_left >= 22 && frac_left <= 42 && |
2034 frac_right >= 22 && frac_right <= 42 ) | 2065 frac_right >= 22 && frac_right <= 42 ) |
2035 { | 2066 { |
2036 org = frac_left; | 2067 org = frac_left; |
2037 fit = (org <= 32) ? 16 : 48; | 2068 fit = ( org <= 32 ) ? 16 : 48; |
2038 delta = FT_ABS(fit - org); | 2069 delta = FT_ABS( fit - org ); |
2039 displacements[count] = fit - org; | 2070 displacements[count] = fit - org; |
2040 scores[count++] = delta; | 2071 scores[count++] = delta; |
2041 FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta )); | 2072 FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
2042 | 2073 |
2043 org = frac_right; | 2074 org = frac_right; |
2044 fit = (org <= 32) ? 16 : 48; | 2075 fit = ( org <= 32 ) ? 16 : 48; |
2045 delta = FT_ABS(fit - org); | 2076 delta = FT_ABS( fit - org ); |
2046 displacements[count] = fit - org; | 2077 displacements[count] = fit - org; |
2047 scores[count++] = delta; | 2078 scores[count++] = delta; |
2048 FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta )); | 2079 FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
2049 } | 2080 } |
2050 } | 2081 } |
2051 | 2082 |
2052 /* snapping the left edge to the grid */ | 2083 /* snapping the left edge to the grid */ |
2053 org = org_left; | 2084 org = org_left; |
2054 fit = FT_PIX_ROUND(org); | 2085 fit = FT_PIX_ROUND( org ); |
2055 delta = FT_ABS(fit - org); | 2086 delta = FT_ABS( fit - org ); |
2056 displacements[count] = fit - org; | 2087 displacements[count] = fit - org; |
2057 scores[count++] = delta; | 2088 scores[count++] = delta; |
2058 FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta )); | 2089 FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
2059 | 2090 |
2060 /* snapping the right edge to the grid */ | 2091 /* snapping the right edge to the grid */ |
2061 org = org_right; | 2092 org = org_right; |
2062 fit = FT_PIX_ROUND(org); | 2093 fit = FT_PIX_ROUND( org ); |
2063 delta = FT_ABS(fit - org); | 2094 delta = FT_ABS( fit - org ); |
2064 displacements[count] = fit - org; | 2095 displacements[count] = fit - org; |
2065 scores[count++] = delta; | 2096 scores[count++] = delta; |
2066 FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta )); | 2097 FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
2067 | 2098 |
2068 /* now find the best displacement */ | 2099 /* now find the best displacement */ |
2069 { | 2100 { |
2070 FT_Pos best_score = scores[0]; | 2101 FT_Pos best_score = scores[0]; |
2071 FT_Pos best_disp = displacements[0]; | 2102 FT_Pos best_disp = displacements[0]; |
2072 FT_UInt nn; | 2103 FT_UInt nn; |
2073 | 2104 |
2074 for (nn = 1; nn < count; nn++) | 2105 for ( nn = 1; nn < count; nn++ ) |
2075 { | 2106 { |
2076 if (scores[nn] < best_score) | 2107 if ( scores[nn] < best_score ) |
2077 { | 2108 { |
2078 best_score = scores[nn]; | 2109 best_score = scores[nn]; |
2079 best_disp = displacements[nn]; | 2110 best_disp = displacements[nn]; |
2080 } | 2111 } |
2081 } | 2112 } |
2082 | 2113 |
2083 cur_center = org_center + best_disp; | 2114 cur_center = org_center + best_disp; |
2084 } | 2115 } |
2085 FT_TRACE5(( "\n" )); | 2116 FT_TRACE5(( "\n" )); |
2086 } | 2117 } |
2087 | 2118 |
2088 AlignStem: | 2119 AlignStem: |
2089 edge->pos = cur_center - (cur_len >> 1); | 2120 edge->pos = cur_center - ( cur_len >> 1 ); |
2090 edge2->pos = edge->pos + cur_len; | 2121 edge2->pos = edge->pos + cur_len; |
2091 | 2122 |
2092 FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)" | 2123 FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)" |
2093 " snapped to (%.2f) and (%.2f)," | 2124 " snapped to (%.2f) and (%.2f)," |
2094 " org_len=%.2f cur_len=%.2f\n", | 2125 " org_len=%.2f cur_len=%.2f\n", |
2095 edge-edges, edge->opos / 64.0, | 2126 edge-edges, edge->opos / 64.0, |
2096 edge2-edges, edge2->opos / 64.0, | 2127 edge2-edges, edge2->opos / 64.0, |
2097 edge->pos / 64.0, edge2->pos / 64.0, | 2128 edge->pos / 64.0, edge2->pos / 64.0, |
2098 org_len / 64.0, cur_len / 64.0 )); | 2129 org_len / 64.0, cur_len / 64.0 )); |
2099 | 2130 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2352 { | 2383 { |
2353 AF_UNIRANGE_REC( 32UL, 127UL ), /* TODO: Add new Unicode ranges here! */ | 2384 AF_UNIRANGE_REC( 32UL, 127UL ), /* TODO: Add new Unicode ranges here! */ |
2354 AF_UNIRANGE_REC( 160UL, 255UL ), | 2385 AF_UNIRANGE_REC( 160UL, 255UL ), |
2355 AF_UNIRANGE_REC( 0UL, 0UL ) | 2386 AF_UNIRANGE_REC( 0UL, 0UL ) |
2356 }; | 2387 }; |
2357 | 2388 |
2358 | 2389 |
2359 AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class, | 2390 AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class, |
2360 AF_SCRIPT_LATIN2, | 2391 AF_SCRIPT_LATIN2, |
2361 af_latin2_uniranges, | 2392 af_latin2_uniranges, |
| 2393 'o', |
2362 | 2394 |
2363 sizeof ( AF_LatinMetricsRec ), | 2395 sizeof ( AF_LatinMetricsRec ), |
2364 | 2396 |
2365 (AF_Script_InitMetricsFunc) af_latin2_metrics_init, | 2397 (AF_Script_InitMetricsFunc) af_latin2_metrics_init, |
2366 (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale, | 2398 (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale, |
2367 (AF_Script_DoneMetricsFunc) NULL, | 2399 (AF_Script_DoneMetricsFunc) NULL, |
2368 | 2400 |
2369 (AF_Script_InitHintsFunc) af_latin2_hints_init, | 2401 (AF_Script_InitHintsFunc) af_latin2_hints_init, |
2370 (AF_Script_ApplyHintsFunc) af_latin2_hints_apply | 2402 (AF_Script_ApplyHintsFunc) af_latin2_hints_apply |
2371 ) | 2403 ) |
2372 | 2404 |
2373 | 2405 |
2374 /* END */ | 2406 /* END */ |
OLD | NEW |