| 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 |