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 |