| OLD | NEW |
| 1 /***************************************************************************/ | 1 /***************************************************************************/ |
| 2 /* */ | 2 /* */ |
| 3 /* ftoutln.c */ | 3 /* ftoutln.c */ |
| 4 /* */ | 4 /* */ |
| 5 /* FreeType outline management (body). */ | 5 /* FreeType outline management (body). */ |
| 6 /* */ | 6 /* */ |
| 7 /* Copyright 1996-2008, 2010, 2012 by */ | 7 /* Copyright 1996-2008, 2010, 2012-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 /*************************************************************************/ | 19 /*************************************************************************/ |
| 20 /* */ | 20 /* */ |
| 21 /* All functions are declared in freetype.h. */ | 21 /* All functions are declared in freetype.h. */ |
| 22 /* */ | 22 /* */ |
| 23 /*************************************************************************/ | 23 /*************************************************************************/ |
| 24 | 24 |
| 25 | 25 |
| 26 #include <ft2build.h> | 26 #include <ft2build.h> |
| 27 #include FT_OUTLINE_H | 27 #include FT_OUTLINE_H |
| 28 #include FT_INTERNAL_OBJECTS_H | 28 #include FT_INTERNAL_OBJECTS_H |
| 29 #include FT_INTERNAL_CALC_H |
| 29 #include FT_INTERNAL_DEBUG_H | 30 #include FT_INTERNAL_DEBUG_H |
| 30 #include FT_TRIGONOMETRY_H | 31 #include FT_TRIGONOMETRY_H |
| 31 | 32 |
| 32 | 33 |
| 33 /*************************************************************************/ | 34 /*************************************************************************/ |
| 34 /* */ | 35 /* */ |
| 35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| 36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| 37 /* messages during execution. */ | 38 /* messages during execution. */ |
| 38 /* */ | 39 /* */ |
| (...skipping 27 matching lines...) Expand all Loading... |
| 66 | 67 |
| 67 FT_Int n; /* index of contour in outline */ | 68 FT_Int n; /* index of contour in outline */ |
| 68 FT_UInt first; /* index of first point in contour */ | 69 FT_UInt first; /* index of first point in contour */ |
| 69 FT_Int tag; /* current point's state */ | 70 FT_Int tag; /* current point's state */ |
| 70 | 71 |
| 71 FT_Int shift; | 72 FT_Int shift; |
| 72 FT_Pos delta; | 73 FT_Pos delta; |
| 73 | 74 |
| 74 | 75 |
| 75 if ( !outline || !func_interface ) | 76 if ( !outline || !func_interface ) |
| 76 return FT_Err_Invalid_Argument; | 77 return FT_THROW( Invalid_Argument ); |
| 77 | 78 |
| 78 shift = func_interface->shift; | 79 shift = func_interface->shift; |
| 79 delta = func_interface->delta; | 80 delta = func_interface->delta; |
| 80 first = 0; | 81 first = 0; |
| 81 | 82 |
| 82 for ( n = 0; n < outline->n_contours; n++ ) | 83 for ( n = 0; n < outline->n_contours; n++ ) |
| 83 { | 84 { |
| 84 FT_Int last; /* index of last point in contour */ | 85 FT_Int last; /* index of last point in contour */ |
| 85 | 86 |
| 86 | 87 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 280 } |
| 280 | 281 |
| 281 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); | 282 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); |
| 282 return FT_Err_Ok; | 283 return FT_Err_Ok; |
| 283 | 284 |
| 284 Exit: | 285 Exit: |
| 285 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); | 286 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); |
| 286 return error; | 287 return error; |
| 287 | 288 |
| 288 Invalid_Outline: | 289 Invalid_Outline: |
| 289 return FT_Err_Invalid_Outline; | 290 return FT_THROW( Invalid_Outline ); |
| 290 } | 291 } |
| 291 | 292 |
| 292 | 293 |
| 293 FT_EXPORT_DEF( FT_Error ) | 294 FT_EXPORT_DEF( FT_Error ) |
| 294 FT_Outline_New_Internal( FT_Memory memory, | 295 FT_Outline_New_Internal( FT_Memory memory, |
| 295 FT_UInt numPoints, | 296 FT_UInt numPoints, |
| 296 FT_Int numContours, | 297 FT_Int numContours, |
| 297 FT_Outline *anoutline ) | 298 FT_Outline *anoutline ) |
| 298 { | 299 { |
| 299 FT_Error error; | 300 FT_Error error; |
| 300 | 301 |
| 301 | 302 |
| 302 if ( !anoutline || !memory ) | 303 if ( !anoutline || !memory ) |
| 303 return FT_Err_Invalid_Argument; | 304 return FT_THROW( Invalid_Argument ); |
| 304 | 305 |
| 305 *anoutline = null_outline; | 306 *anoutline = null_outline; |
| 306 | 307 |
| 308 if ( numContours < 0 || |
| 309 (FT_UInt)numContours > numPoints ) |
| 310 return FT_THROW( Invalid_Argument ); |
| 311 |
| 312 if ( numPoints > FT_OUTLINE_POINTS_MAX ) |
| 313 return FT_THROW( Array_Too_Large ); |
| 314 |
| 307 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || | 315 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || |
| 308 FT_NEW_ARRAY( anoutline->tags, numPoints ) || | 316 FT_NEW_ARRAY( anoutline->tags, numPoints ) || |
| 309 FT_NEW_ARRAY( anoutline->contours, numContours ) ) | 317 FT_NEW_ARRAY( anoutline->contours, numContours ) ) |
| 310 goto Fail; | 318 goto Fail; |
| 311 | 319 |
| 312 anoutline->n_points = (FT_UShort)numPoints; | 320 anoutline->n_points = (FT_UShort)numPoints; |
| 313 anoutline->n_contours = (FT_Short)numContours; | 321 anoutline->n_contours = (FT_Short)numContours; |
| 314 anoutline->flags |= FT_OUTLINE_OWNER; | 322 anoutline->flags |= FT_OUTLINE_OWNER; |
| 315 | 323 |
| 316 return FT_Err_Ok; | 324 return FT_Err_Ok; |
| 317 | 325 |
| 318 Fail: | 326 Fail: |
| 319 anoutline->flags |= FT_OUTLINE_OWNER; | 327 anoutline->flags |= FT_OUTLINE_OWNER; |
| 320 FT_Outline_Done_Internal( memory, anoutline ); | 328 FT_Outline_Done_Internal( memory, anoutline ); |
| 321 | 329 |
| 322 return error; | 330 return error; |
| 323 } | 331 } |
| 324 | 332 |
| 325 | 333 |
| 326 /* documentation is in ftoutln.h */ | 334 /* documentation is in ftoutln.h */ |
| 327 | 335 |
| 328 FT_EXPORT_DEF( FT_Error ) | 336 FT_EXPORT_DEF( FT_Error ) |
| 329 FT_Outline_New( FT_Library library, | 337 FT_Outline_New( FT_Library library, |
| 330 FT_UInt numPoints, | 338 FT_UInt numPoints, |
| 331 FT_Int numContours, | 339 FT_Int numContours, |
| 332 FT_Outline *anoutline ) | 340 FT_Outline *anoutline ) |
| 333 { | 341 { |
| 334 if ( !library ) | 342 if ( !library ) |
| 335 return FT_Err_Invalid_Library_Handle; | 343 return FT_THROW( Invalid_Library_Handle ); |
| 336 | 344 |
| 337 return FT_Outline_New_Internal( library->memory, numPoints, | 345 return FT_Outline_New_Internal( library->memory, numPoints, |
| 338 numContours, anoutline ); | 346 numContours, anoutline ); |
| 339 } | 347 } |
| 340 | 348 |
| 341 | 349 |
| 342 /* documentation is in ftoutln.h */ | 350 /* documentation is in ftoutln.h */ |
| 343 | 351 |
| 344 FT_EXPORT_DEF( FT_Error ) | 352 FT_EXPORT_DEF( FT_Error ) |
| 345 FT_Outline_Check( FT_Outline* outline ) | 353 FT_Outline_Check( FT_Outline* outline ) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 373 } | 381 } |
| 374 | 382 |
| 375 if ( end != n_points - 1 ) | 383 if ( end != n_points - 1 ) |
| 376 goto Bad; | 384 goto Bad; |
| 377 | 385 |
| 378 /* XXX: check the tags array */ | 386 /* XXX: check the tags array */ |
| 379 return 0; | 387 return 0; |
| 380 } | 388 } |
| 381 | 389 |
| 382 Bad: | 390 Bad: |
| 383 return FT_Err_Invalid_Argument; | 391 return FT_THROW( Invalid_Argument ); |
| 384 } | 392 } |
| 385 | 393 |
| 386 | 394 |
| 387 /* documentation is in ftoutln.h */ | 395 /* documentation is in ftoutln.h */ |
| 388 | 396 |
| 389 FT_EXPORT_DEF( FT_Error ) | 397 FT_EXPORT_DEF( FT_Error ) |
| 390 FT_Outline_Copy( const FT_Outline* source, | 398 FT_Outline_Copy( const FT_Outline* source, |
| 391 FT_Outline *target ) | 399 FT_Outline *target ) |
| 392 { | 400 { |
| 393 FT_Int is_owner; | 401 FT_Int is_owner; |
| 394 | 402 |
| 395 | 403 |
| 396 if ( !source || !target || | 404 if ( !source || !target || |
| 397 source->n_points != target->n_points || | 405 source->n_points != target->n_points || |
| 398 source->n_contours != target->n_contours ) | 406 source->n_contours != target->n_contours ) |
| 399 return FT_Err_Invalid_Argument; | 407 return FT_THROW( Invalid_Argument ); |
| 400 | 408 |
| 401 if ( source == target ) | 409 if ( source == target ) |
| 402 return FT_Err_Ok; | 410 return FT_Err_Ok; |
| 403 | 411 |
| 404 FT_ARRAY_COPY( target->points, source->points, source->n_points ); | 412 FT_ARRAY_COPY( target->points, source->points, source->n_points ); |
| 405 | 413 |
| 406 FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); | 414 FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); |
| 407 | 415 |
| 408 FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); | 416 FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); |
| 409 | 417 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 428 { | 436 { |
| 429 FT_FREE( outline->points ); | 437 FT_FREE( outline->points ); |
| 430 FT_FREE( outline->tags ); | 438 FT_FREE( outline->tags ); |
| 431 FT_FREE( outline->contours ); | 439 FT_FREE( outline->contours ); |
| 432 } | 440 } |
| 433 *outline = null_outline; | 441 *outline = null_outline; |
| 434 | 442 |
| 435 return FT_Err_Ok; | 443 return FT_Err_Ok; |
| 436 } | 444 } |
| 437 else | 445 else |
| 438 return FT_Err_Invalid_Argument; | 446 return FT_THROW( Invalid_Argument ); |
| 439 } | 447 } |
| 440 | 448 |
| 441 | 449 |
| 442 /* documentation is in ftoutln.h */ | 450 /* documentation is in ftoutln.h */ |
| 443 | 451 |
| 444 FT_EXPORT_DEF( FT_Error ) | 452 FT_EXPORT_DEF( FT_Error ) |
| 445 FT_Outline_Done( FT_Library library, | 453 FT_Outline_Done( FT_Library library, |
| 446 FT_Outline* outline ) | 454 FT_Outline* outline ) |
| 447 { | 455 { |
| 448 /* check for valid `outline' in FT_Outline_Done_Internal() */ | 456 /* check for valid `outline' in FT_Outline_Done_Internal() */ |
| 449 | 457 |
| 450 if ( !library ) | 458 if ( !library ) |
| 451 return FT_Err_Invalid_Library_Handle; | 459 return FT_THROW( Invalid_Library_Handle ); |
| 452 | 460 |
| 453 return FT_Outline_Done_Internal( library->memory, outline ); | 461 return FT_Outline_Done_Internal( library->memory, outline ); |
| 454 } | 462 } |
| 455 | 463 |
| 456 | 464 |
| 457 /* documentation is in ftoutln.h */ | 465 /* documentation is in ftoutln.h */ |
| 458 | 466 |
| 459 FT_EXPORT_DEF( void ) | 467 FT_EXPORT_DEF( void ) |
| 460 FT_Outline_Get_CBox( const FT_Outline* outline, | 468 FT_Outline_Get_CBox( const FT_Outline* outline, |
| 461 FT_BBox *acbox ) | 469 FT_BBox *acbox ) |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 FT_Outline* outline, | 603 FT_Outline* outline, |
| 596 FT_Raster_Params* params ) | 604 FT_Raster_Params* params ) |
| 597 { | 605 { |
| 598 FT_Error error; | 606 FT_Error error; |
| 599 FT_Bool update = FALSE; | 607 FT_Bool update = FALSE; |
| 600 FT_Renderer renderer; | 608 FT_Renderer renderer; |
| 601 FT_ListNode node; | 609 FT_ListNode node; |
| 602 | 610 |
| 603 | 611 |
| 604 if ( !library ) | 612 if ( !library ) |
| 605 return FT_Err_Invalid_Library_Handle; | 613 return FT_THROW( Invalid_Library_Handle ); |
| 606 | 614 |
| 607 if ( !outline || !params ) | 615 if ( !outline || !params ) |
| 608 return FT_Err_Invalid_Argument; | 616 return FT_THROW( Invalid_Argument ); |
| 609 | 617 |
| 610 renderer = library->cur_renderer; | 618 renderer = library->cur_renderer; |
| 611 node = library->renderers.head; | 619 node = library->renderers.head; |
| 612 | 620 |
| 613 params->source = (void*)outline; | 621 params->source = (void*)outline; |
| 614 | 622 |
| 615 error = FT_Err_Cannot_Render_Glyph; | 623 error = FT_ERR( Cannot_Render_Glyph ); |
| 616 while ( renderer ) | 624 while ( renderer ) |
| 617 { | 625 { |
| 618 error = renderer->raster_render( renderer->raster, params ); | 626 error = renderer->raster_render( renderer->raster, params ); |
| 619 if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) | 627 if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) |
| 620 break; | 628 break; |
| 621 | 629 |
| 622 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ | 630 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ |
| 623 /* is unsupported by the current renderer for this glyph image */ | 631 /* is unsupported by the current renderer for this glyph image */ |
| 624 /* format */ | 632 /* format */ |
| 625 | 633 |
| 626 /* now, look for another renderer that supports the same */ | 634 /* now, look for another renderer that supports the same */ |
| 627 /* format */ | 635 /* format */ |
| 628 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, | 636 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, |
| 629 &node ); | 637 &node ); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 643 | 651 |
| 644 FT_EXPORT_DEF( FT_Error ) | 652 FT_EXPORT_DEF( FT_Error ) |
| 645 FT_Outline_Get_Bitmap( FT_Library library, | 653 FT_Outline_Get_Bitmap( FT_Library library, |
| 646 FT_Outline* outline, | 654 FT_Outline* outline, |
| 647 const FT_Bitmap *abitmap ) | 655 const FT_Bitmap *abitmap ) |
| 648 { | 656 { |
| 649 FT_Raster_Params params; | 657 FT_Raster_Params params; |
| 650 | 658 |
| 651 | 659 |
| 652 if ( !abitmap ) | 660 if ( !abitmap ) |
| 653 return FT_Err_Invalid_Argument; | 661 return FT_THROW( Invalid_Argument ); |
| 654 | 662 |
| 655 /* other checks are delayed to FT_Outline_Render() */ | 663 /* other checks are delayed to FT_Outline_Render() */ |
| 656 | 664 |
| 657 params.target = abitmap; | 665 params.target = abitmap; |
| 658 params.flags = 0; | 666 params.flags = 0; |
| 659 | 667 |
| 660 if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || | 668 if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || |
| 661 abitmap->pixel_mode == FT_PIXEL_MODE_LCD || | 669 abitmap->pixel_mode == FT_PIXEL_MODE_LCD || |
| 662 abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) | 670 abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) |
| 663 params.flags |= FT_RASTER_FLAG_AA; | 671 params.flags |= FT_RASTER_FLAG_AA; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 | 883 |
| 876 #endif /* 0 */ | 884 #endif /* 0 */ |
| 877 | 885 |
| 878 | 886 |
| 879 /* documentation is in ftoutln.h */ | 887 /* documentation is in ftoutln.h */ |
| 880 | 888 |
| 881 FT_EXPORT_DEF( FT_Error ) | 889 FT_EXPORT_DEF( FT_Error ) |
| 882 FT_Outline_Embolden( FT_Outline* outline, | 890 FT_Outline_Embolden( FT_Outline* outline, |
| 883 FT_Pos strength ) | 891 FT_Pos strength ) |
| 884 { | 892 { |
| 893 return FT_Outline_EmboldenXY( outline, strength, strength ); |
| 894 } |
| 895 |
| 896 |
| 897 /* documentation is in ftoutln.h */ |
| 898 |
| 899 FT_EXPORT_DEF( FT_Error ) |
| 900 FT_Outline_EmboldenXY( FT_Outline* outline, |
| 901 FT_Pos xstrength, |
| 902 FT_Pos ystrength ) |
| 903 { |
| 885 FT_Vector* points; | 904 FT_Vector* points; |
| 886 FT_Vector v_prev, v_first, v_next, v_cur; | 905 FT_Vector v_prev, v_first, v_next, v_cur; |
| 887 FT_Angle rotate, angle_in, angle_out; | |
| 888 FT_Int c, n, first; | 906 FT_Int c, n, first; |
| 889 FT_Int orientation; | 907 FT_Int orientation; |
| 890 | 908 |
| 891 | 909 |
| 892 if ( !outline ) | 910 if ( !outline ) |
| 893 return FT_Err_Invalid_Argument; | 911 return FT_THROW( Invalid_Argument ); |
| 894 | 912 |
| 895 strength /= 2; | 913 xstrength /= 2; |
| 896 if ( strength == 0 ) | 914 ystrength /= 2; |
| 915 if ( xstrength == 0 && ystrength == 0 ) |
| 897 return FT_Err_Ok; | 916 return FT_Err_Ok; |
| 898 | 917 |
| 899 orientation = FT_Outline_Get_Orientation( outline ); | 918 orientation = FT_Outline_Get_Orientation( outline ); |
| 900 if ( orientation == FT_ORIENTATION_NONE ) | 919 if ( orientation == FT_ORIENTATION_NONE ) |
| 901 { | 920 { |
| 902 if ( outline->n_contours ) | 921 if ( outline->n_contours ) |
| 903 return FT_Err_Invalid_Argument; | 922 return FT_THROW( Invalid_Argument ); |
| 904 else | 923 else |
| 905 return FT_Err_Ok; | 924 return FT_Err_Ok; |
| 906 } | 925 } |
| 907 | 926 |
| 908 if ( orientation == FT_ORIENTATION_TRUETYPE ) | |
| 909 rotate = -FT_ANGLE_PI2; | |
| 910 else | |
| 911 rotate = FT_ANGLE_PI2; | |
| 912 | |
| 913 points = outline->points; | 927 points = outline->points; |
| 914 | 928 |
| 915 first = 0; | 929 first = 0; |
| 916 for ( c = 0; c < outline->n_contours; c++ ) | 930 for ( c = 0; c < outline->n_contours; c++ ) |
| 917 { | 931 { |
| 918 int last = outline->contours[c]; | 932 FT_Vector in, out, shift; |
| 933 FT_Fixed l_in, l_out, l, q, d; |
| 934 int last = outline->contours[c]; |
| 919 | 935 |
| 920 | 936 |
| 921 v_first = points[first]; | 937 v_first = points[first]; |
| 922 v_prev = points[last]; | 938 v_prev = points[last]; |
| 923 v_cur = v_first; | 939 v_cur = v_first; |
| 924 | 940 |
| 941 /* compute incoming normalized vector */ |
| 942 in.x = v_cur.x - v_prev.x; |
| 943 in.y = v_cur.y - v_prev.y; |
| 944 l_in = FT_Vector_Length( &in ); |
| 945 if ( l_in ) |
| 946 { |
| 947 in.x = FT_DivFix( in.x, l_in ); |
| 948 in.y = FT_DivFix( in.y, l_in ); |
| 949 } |
| 950 |
| 925 for ( n = first; n <= last; n++ ) | 951 for ( n = first; n <= last; n++ ) |
| 926 { | 952 { |
| 927 FT_Vector in, out; | |
| 928 FT_Angle angle_diff; | |
| 929 FT_Pos d; | |
| 930 FT_Fixed scale; | |
| 931 | |
| 932 | |
| 933 if ( n < last ) | 953 if ( n < last ) |
| 934 v_next = points[n + 1]; | 954 v_next = points[n + 1]; |
| 935 else | 955 else |
| 936 v_next = v_first; | 956 v_next = v_first; |
| 937 | 957 |
| 938 /* compute the in and out vectors */ | 958 /* compute outgoing normalized vector */ |
| 939 in.x = v_cur.x - v_prev.x; | |
| 940 in.y = v_cur.y - v_prev.y; | |
| 941 | |
| 942 out.x = v_next.x - v_cur.x; | 959 out.x = v_next.x - v_cur.x; |
| 943 out.y = v_next.y - v_cur.y; | 960 out.y = v_next.y - v_cur.y; |
| 944 | 961 l_out = FT_Vector_Length( &out ); |
| 945 angle_in = FT_Atan2( in.x, in.y ); | 962 if ( l_out ) |
| 946 angle_out = FT_Atan2( out.x, out.y ); | |
| 947 angle_diff = FT_Angle_Diff( angle_in, angle_out ); | |
| 948 scale = FT_Cos( angle_diff / 2 ); | |
| 949 | |
| 950 if ( scale < 0x4000L && scale > -0x4000L ) | |
| 951 in.x = in.y = 0; | |
| 952 else | |
| 953 { | 963 { |
| 954 d = FT_DivFix( strength, scale ); | 964 out.x = FT_DivFix( out.x, l_out ); |
| 955 | 965 out.y = FT_DivFix( out.y, l_out ); |
| 956 FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate ); | |
| 957 } | 966 } |
| 958 | 967 |
| 959 outline->points[n].x = v_cur.x + strength + in.x; | 968 d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); |
| 960 outline->points[n].y = v_cur.y + strength + in.y; | |
| 961 | 969 |
| 962 v_prev = v_cur; | 970 /* shift only if turn is less than ~160 degrees */ |
| 963 v_cur = v_next; | 971 if ( d > -0xF000L ) |
| 972 { |
| 973 d = d + 0x10000L; |
| 974 |
| 975 /* shift components are aligned along lateral bisector */ |
| 976 /* and directed according to the outline orientation. */ |
| 977 shift.x = in.y + out.y; |
| 978 shift.y = in.x + out.x; |
| 979 |
| 980 if ( orientation == FT_ORIENTATION_TRUETYPE ) |
| 981 shift.x = -shift.x; |
| 982 else |
| 983 shift.y = -shift.y; |
| 984 |
| 985 /* restrict shift magnitude to better handle collapsing segments */ |
| 986 q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); |
| 987 if ( orientation == FT_ORIENTATION_TRUETYPE ) |
| 988 q = -q; |
| 989 |
| 990 l = FT_MIN( l_in, l_out ); |
| 991 |
| 992 /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ |
| 993 if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) ) |
| 994 shift.x = FT_MulDiv( shift.x, xstrength, d ); |
| 995 else |
| 996 shift.x = FT_MulDiv( shift.x, l, q ); |
| 997 |
| 998 |
| 999 if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) ) |
| 1000 shift.y = FT_MulDiv( shift.y, ystrength, d ); |
| 1001 else |
| 1002 shift.y = FT_MulDiv( shift.y, l, q ); |
| 1003 } |
| 1004 else |
| 1005 shift.x = shift.y = 0; |
| 1006 |
| 1007 outline->points[n].x = v_cur.x + xstrength + shift.x; |
| 1008 outline->points[n].y = v_cur.y + ystrength + shift.y; |
| 1009 |
| 1010 in = out; |
| 1011 l_in = l_out; |
| 1012 v_cur = v_next; |
| 964 } | 1013 } |
| 965 | 1014 |
| 966 first = last + 1; | 1015 first = last + 1; |
| 967 } | 1016 } |
| 968 | 1017 |
| 969 return FT_Err_Ok; | 1018 return FT_Err_Ok; |
| 970 } | 1019 } |
| 971 | 1020 |
| 972 | 1021 |
| 973 /* documentation is in ftoutln.h */ | 1022 /* documentation is in ftoutln.h */ |
| 974 | 1023 |
| 975 FT_EXPORT_DEF( FT_Orientation ) | 1024 FT_EXPORT_DEF( FT_Orientation ) |
| 976 FT_Outline_Get_Orientation( FT_Outline* outline ) | 1025 FT_Outline_Get_Orientation( FT_Outline* outline ) |
| 977 { | 1026 { |
| 978 FT_Pos xmin = 32768L; | 1027 FT_BBox cbox; |
| 979 FT_Pos xmin_ymin = 32768L; | 1028 FT_Int xshift, yshift; |
| 980 FT_Pos xmin_ymax = -32768L; | 1029 FT_Vector* points; |
| 981 FT_Vector* xmin_first = NULL; | 1030 FT_Vector v_prev, v_cur; |
| 982 FT_Vector* xmin_last = NULL; | 1031 FT_Int c, n, first; |
| 983 | 1032 FT_Pos area = 0; |
| 984 short* contour; | |
| 985 | |
| 986 FT_Vector* first; | |
| 987 FT_Vector* last; | |
| 988 FT_Vector* prev; | |
| 989 FT_Vector* point; | |
| 990 | |
| 991 int i; | |
| 992 FT_Pos ray_y[3]; | |
| 993 FT_Orientation result[3] = | |
| 994 { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE }; | |
| 995 | 1033 |
| 996 | 1034 |
| 997 if ( !outline || outline->n_points <= 0 ) | 1035 if ( !outline || outline->n_points <= 0 ) |
| 998 return FT_ORIENTATION_TRUETYPE; | 1036 return FT_ORIENTATION_TRUETYPE; |
| 999 | 1037 |
| 1000 /* We use the nonzero winding rule to find the orientation. */ | 1038 /* We use the nonzero winding rule to find the orientation. */ |
| 1001 /* Since glyph outlines behave much more `regular' than arbitrary */ | 1039 /* Since glyph outlines behave much more `regular' than arbitrary */ |
| 1002 /* cubic or quadratic curves, this test deals with the polygon */ | 1040 /* cubic or quadratic curves, this test deals with the polygon */ |
| 1003 /* only which is spanned up by the control points. */ | 1041 /* only which is spanned up by the control points. */ |
| 1004 | 1042 |
| 1005 first = outline->points; | 1043 FT_Outline_Get_CBox( outline, &cbox ); |
| 1006 for ( contour = outline->contours; | 1044 |
| 1007 contour < outline->contours + outline->n_contours; | 1045 xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14; |
| 1008 contour++, first = last + 1 ) | 1046 xshift = FT_MAX( xshift, 0 ); |
| 1047 |
| 1048 yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14; |
| 1049 yshift = FT_MAX( yshift, 0 ); |
| 1050 |
| 1051 points = outline->points; |
| 1052 |
| 1053 first = 0; |
| 1054 for ( c = 0; c < outline->n_contours; c++ ) |
| 1009 { | 1055 { |
| 1010 FT_Pos contour_xmin = 32768L; | 1056 FT_Int last = outline->contours[c]; |
| 1011 FT_Pos contour_xmax = -32768L; | |
| 1012 FT_Pos contour_ymin = 32768L; | |
| 1013 FT_Pos contour_ymax = -32768L; | |
| 1014 | 1057 |
| 1015 | 1058 |
| 1016 last = outline->points + *contour; | 1059 v_prev = points[last]; |
| 1017 | 1060 |
| 1018 /* skip degenerate contours */ | 1061 for ( n = first; n <= last; n++ ) |
| 1019 if ( last < first + 2 ) | |
| 1020 continue; | |
| 1021 | |
| 1022 for ( point = first; point <= last; ++point ) | |
| 1023 { | 1062 { |
| 1024 if ( point->x < contour_xmin ) | 1063 v_cur = points[n]; |
| 1025 contour_xmin = point->x; | 1064 area += ( ( v_cur.y - v_prev.y ) >> yshift ) * |
| 1026 | 1065 ( ( v_cur.x + v_prev.x ) >> xshift ); |
| 1027 if ( point->x > contour_xmax ) | 1066 v_prev = v_cur; |
| 1028 contour_xmax = point->x; | |
| 1029 | |
| 1030 if ( point->y < contour_ymin ) | |
| 1031 contour_ymin = point->y; | |
| 1032 | |
| 1033 if ( point->y > contour_ymax ) | |
| 1034 contour_ymax = point->y; | |
| 1035 } | 1067 } |
| 1036 | 1068 |
| 1037 if ( contour_xmin < xmin && | 1069 first = last + 1; |
| 1038 contour_xmin != contour_xmax && | |
| 1039 contour_ymin != contour_ymax ) | |
| 1040 { | |
| 1041 xmin = contour_xmin; | |
| 1042 xmin_ymin = contour_ymin; | |
| 1043 xmin_ymax = contour_ymax; | |
| 1044 xmin_first = first; | |
| 1045 xmin_last = last; | |
| 1046 } | |
| 1047 } | 1070 } |
| 1048 | 1071 |
| 1049 if ( xmin == 32768L ) | 1072 if ( area > 0 ) |
| 1073 return FT_ORIENTATION_POSTSCRIPT; |
| 1074 else if ( area < 0 ) |
| 1050 return FT_ORIENTATION_TRUETYPE; | 1075 return FT_ORIENTATION_TRUETYPE; |
| 1051 | 1076 else |
| 1052 ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2; | 1077 return FT_ORIENTATION_NONE; |
| 1053 ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1; | |
| 1054 ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2; | |
| 1055 | |
| 1056 for ( i = 0; i < 3; i++ ) | |
| 1057 { | |
| 1058 FT_Pos left_x; | |
| 1059 FT_Pos right_x; | |
| 1060 FT_Vector* left1; | |
| 1061 FT_Vector* left2; | |
| 1062 FT_Vector* right1; | |
| 1063 FT_Vector* right2; | |
| 1064 | |
| 1065 | |
| 1066 RedoRay: | |
| 1067 left_x = 32768L; | |
| 1068 right_x = -32768L; | |
| 1069 | |
| 1070 left1 = left2 = right1 = right2 = NULL; | |
| 1071 | |
| 1072 prev = xmin_last; | |
| 1073 for ( point = xmin_first; point <= xmin_last; prev = point, ++point ) | |
| 1074 { | |
| 1075 FT_Pos tmp_x; | |
| 1076 | |
| 1077 | |
| 1078 if ( point->y == ray_y[i] || prev->y == ray_y[i] ) | |
| 1079 { | |
| 1080 ray_y[i]++; | |
| 1081 goto RedoRay; | |
| 1082 } | |
| 1083 | |
| 1084 if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) || | |
| 1085 ( point->y > ray_y[i] && prev->y > ray_y[i] ) ) | |
| 1086 continue; | |
| 1087 | |
| 1088 tmp_x = FT_MulDiv( point->x - prev->x, | |
| 1089 ray_y[i] - prev->y, | |
| 1090 point->y - prev->y ) + prev->x; | |
| 1091 | |
| 1092 if ( tmp_x < left_x ) | |
| 1093 { | |
| 1094 left_x = tmp_x; | |
| 1095 left1 = prev; | |
| 1096 left2 = point; | |
| 1097 } | |
| 1098 | |
| 1099 if ( tmp_x > right_x ) | |
| 1100 { | |
| 1101 right_x = tmp_x; | |
| 1102 right1 = prev; | |
| 1103 right2 = point; | |
| 1104 } | |
| 1105 } | |
| 1106 | |
| 1107 if ( left1 && right1 ) | |
| 1108 { | |
| 1109 if ( left1->y < left2->y && right1->y > right2->y ) | |
| 1110 result[i] = FT_ORIENTATION_TRUETYPE; | |
| 1111 else if ( left1->y > left2->y && right1->y < right2->y ) | |
| 1112 result[i] = FT_ORIENTATION_POSTSCRIPT; | |
| 1113 else | |
| 1114 result[i] = FT_ORIENTATION_NONE; | |
| 1115 } | |
| 1116 } | |
| 1117 | |
| 1118 if ( result[0] != FT_ORIENTATION_NONE && | |
| 1119 ( result[0] == result[1] || result[0] == result[2] ) ) | |
| 1120 return result[0]; | |
| 1121 | |
| 1122 if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] ) | |
| 1123 return result[1]; | |
| 1124 | |
| 1125 return FT_ORIENTATION_TRUETYPE; | |
| 1126 } | 1078 } |
| 1127 | 1079 |
| 1128 | 1080 |
| 1129 /* END */ | 1081 /* END */ |
| OLD | NEW |