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-2014 by */ | 7 /* Copyright 1996-2015 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 |
(...skipping 27 matching lines...) Expand all Loading... |
45 const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; | 45 const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; |
46 | 46 |
47 | 47 |
48 /* documentation is in ftoutln.h */ | 48 /* documentation is in ftoutln.h */ |
49 | 49 |
50 FT_EXPORT_DEF( FT_Error ) | 50 FT_EXPORT_DEF( FT_Error ) |
51 FT_Outline_Decompose( FT_Outline* outline, | 51 FT_Outline_Decompose( FT_Outline* outline, |
52 const FT_Outline_Funcs* func_interface, | 52 const FT_Outline_Funcs* func_interface, |
53 void* user ) | 53 void* user ) |
54 { | 54 { |
55 #undef SCALED | 55 #undef SCALED |
56 #define SCALED( x ) ( ( (x) << shift ) - delta ) | 56 #define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \ |
| 57 : ( (x) << shift ) ) - delta ) |
57 | 58 |
58 FT_Vector v_last; | 59 FT_Vector v_last; |
59 FT_Vector v_control; | 60 FT_Vector v_control; |
60 FT_Vector v_start; | 61 FT_Vector v_start; |
61 | 62 |
62 FT_Vector* point; | 63 FT_Vector* point; |
63 FT_Vector* limit; | 64 FT_Vector* limit; |
64 char* tags; | 65 char* tags; |
65 | 66 |
66 FT_Error error; | 67 FT_Error error; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 273 |
273 /* close the contour with a line segment */ | 274 /* close the contour with a line segment */ |
274 FT_TRACE5(( " line to (%.2f, %.2f)\n", | 275 FT_TRACE5(( " line to (%.2f, %.2f)\n", |
275 v_start.x / 64.0, v_start.y / 64.0 )); | 276 v_start.x / 64.0, v_start.y / 64.0 )); |
276 error = func_interface->line_to( &v_start, user ); | 277 error = func_interface->line_to( &v_start, user ); |
277 | 278 |
278 Close: | 279 Close: |
279 if ( error ) | 280 if ( error ) |
280 goto Exit; | 281 goto Exit; |
281 | 282 |
282 first = last + 1; | 283 first = (FT_UInt)last + 1; |
283 } | 284 } |
284 | 285 |
285 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); | 286 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); |
286 return FT_Err_Ok; | 287 return FT_Err_Ok; |
287 | 288 |
288 Exit: | 289 Exit: |
289 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); | 290 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); |
290 return error; | 291 return error; |
291 | 292 |
292 Invalid_Outline: | 293 Invalid_Outline: |
(...skipping 20 matching lines...) Expand all Loading... |
313 return FT_THROW( Invalid_Argument ); | 314 return FT_THROW( Invalid_Argument ); |
314 | 315 |
315 if ( numPoints > FT_OUTLINE_POINTS_MAX ) | 316 if ( numPoints > FT_OUTLINE_POINTS_MAX ) |
316 return FT_THROW( Array_Too_Large ); | 317 return FT_THROW( Array_Too_Large ); |
317 | 318 |
318 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || | 319 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || |
319 FT_NEW_ARRAY( anoutline->tags, numPoints ) || | 320 FT_NEW_ARRAY( anoutline->tags, numPoints ) || |
320 FT_NEW_ARRAY( anoutline->contours, numContours ) ) | 321 FT_NEW_ARRAY( anoutline->contours, numContours ) ) |
321 goto Fail; | 322 goto Fail; |
322 | 323 |
323 anoutline->n_points = (FT_UShort)numPoints; | 324 anoutline->n_points = (FT_Short)numPoints; |
324 anoutline->n_contours = (FT_Short)numContours; | 325 anoutline->n_contours = (FT_Short)numContours; |
325 anoutline->flags |= FT_OUTLINE_OWNER; | 326 anoutline->flags |= FT_OUTLINE_OWNER; |
326 | 327 |
327 return FT_Err_Ok; | 328 return FT_Err_Ok; |
328 | 329 |
329 Fail: | 330 Fail: |
330 anoutline->flags |= FT_OUTLINE_OWNER; | 331 anoutline->flags |= FT_OUTLINE_OWNER; |
331 FT_Outline_Done_Internal( memory, anoutline ); | 332 FT_Outline_Done_Internal( memory, anoutline ); |
332 | 333 |
333 return error; | 334 return error; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 606 |
606 | 607 |
607 /* documentation is in ftoutln.h */ | 608 /* documentation is in ftoutln.h */ |
608 | 609 |
609 FT_EXPORT_DEF( FT_Error ) | 610 FT_EXPORT_DEF( FT_Error ) |
610 FT_Outline_Render( FT_Library library, | 611 FT_Outline_Render( FT_Library library, |
611 FT_Outline* outline, | 612 FT_Outline* outline, |
612 FT_Raster_Params* params ) | 613 FT_Raster_Params* params ) |
613 { | 614 { |
614 FT_Error error; | 615 FT_Error error; |
615 FT_Bool update = FALSE; | |
616 FT_Renderer renderer; | 616 FT_Renderer renderer; |
617 FT_ListNode node; | 617 FT_ListNode node; |
618 | 618 |
619 | 619 |
620 if ( !library ) | 620 if ( !library ) |
621 return FT_THROW( Invalid_Library_Handle ); | 621 return FT_THROW( Invalid_Library_Handle ); |
622 | 622 |
623 if ( !outline ) | 623 if ( !outline ) |
624 return FT_THROW( Invalid_Outline ); | 624 return FT_THROW( Invalid_Outline ); |
625 | 625 |
(...skipping 13 matching lines...) Expand all Loading... |
639 break; | 639 break; |
640 | 640 |
641 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ | 641 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ |
642 /* is unsupported by the current renderer for this glyph image */ | 642 /* is unsupported by the current renderer for this glyph image */ |
643 /* format */ | 643 /* format */ |
644 | 644 |
645 /* now, look for another renderer that supports the same */ | 645 /* now, look for another renderer that supports the same */ |
646 /* format */ | 646 /* format */ |
647 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, | 647 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, |
648 &node ); | 648 &node ); |
649 update = TRUE; | |
650 } | 649 } |
651 | 650 |
652 /* if we changed the current renderer for the glyph image format */ | |
653 /* we need to select it as the next current one */ | |
654 if ( !error && update && renderer ) | |
655 error = FT_Set_Renderer( library, renderer, 0, 0 ); | |
656 | |
657 return error; | 651 return error; |
658 } | 652 } |
659 | 653 |
660 | 654 |
661 /* documentation is in ftoutln.h */ | 655 /* documentation is in ftoutln.h */ |
662 | 656 |
663 FT_EXPORT_DEF( FT_Error ) | 657 FT_EXPORT_DEF( FT_Error ) |
664 FT_Outline_Get_Bitmap( FT_Library library, | 658 FT_Outline_Get_Bitmap( FT_Library library, |
665 FT_Outline* outline, | 659 FT_Outline* outline, |
666 const FT_Bitmap *abitmap ) | 660 const FT_Bitmap *abitmap ) |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 | 901 |
908 | 902 |
909 /* documentation is in ftoutln.h */ | 903 /* documentation is in ftoutln.h */ |
910 | 904 |
911 FT_EXPORT_DEF( FT_Error ) | 905 FT_EXPORT_DEF( FT_Error ) |
912 FT_Outline_EmboldenXY( FT_Outline* outline, | 906 FT_Outline_EmboldenXY( FT_Outline* outline, |
913 FT_Pos xstrength, | 907 FT_Pos xstrength, |
914 FT_Pos ystrength ) | 908 FT_Pos ystrength ) |
915 { | 909 { |
916 FT_Vector* points; | 910 FT_Vector* points; |
917 FT_Vector v_prev, v_first, v_next, v_cur; | 911 FT_Int c, first, last; |
918 FT_Int c, n, first; | |
919 FT_Int orientation; | 912 FT_Int orientation; |
920 | 913 |
921 | 914 |
922 if ( !outline ) | 915 if ( !outline ) |
923 return FT_THROW( Invalid_Outline ); | 916 return FT_THROW( Invalid_Outline ); |
924 | 917 |
925 xstrength /= 2; | 918 xstrength /= 2; |
926 ystrength /= 2; | 919 ystrength /= 2; |
927 if ( xstrength == 0 && ystrength == 0 ) | 920 if ( xstrength == 0 && ystrength == 0 ) |
928 return FT_Err_Ok; | 921 return FT_Err_Ok; |
929 | 922 |
930 orientation = FT_Outline_Get_Orientation( outline ); | 923 orientation = FT_Outline_Get_Orientation( outline ); |
931 if ( orientation == FT_ORIENTATION_NONE ) | 924 if ( orientation == FT_ORIENTATION_NONE ) |
932 { | 925 { |
933 if ( outline->n_contours ) | 926 if ( outline->n_contours ) |
934 return FT_THROW( Invalid_Argument ); | 927 return FT_THROW( Invalid_Argument ); |
935 else | 928 else |
936 return FT_Err_Ok; | 929 return FT_Err_Ok; |
937 } | 930 } |
938 | 931 |
939 points = outline->points; | 932 points = outline->points; |
940 | 933 |
941 first = 0; | 934 first = 0; |
942 for ( c = 0; c < outline->n_contours; c++ ) | 935 for ( c = 0; c < outline->n_contours; c++ ) |
943 { | 936 { |
944 FT_Vector in, out, shift; | 937 FT_Vector in, out, anchor, shift; |
945 FT_Fixed l_in, l_out, l, q, d; | 938 FT_Fixed l_in, l_out, l_anchor = 0, l, q, d; |
946 int last = outline->contours[c]; | 939 FT_Int i, j, k; |
947 | 940 |
948 | 941 |
949 v_first = points[first]; | 942 l_in = 0; |
950 v_prev = points[last]; | 943 last = outline->contours[c]; |
951 v_cur = v_first; | |
952 | 944 |
953 /* compute incoming normalized vector */ | 945 /* Counter j cycles though the points; counter i advances only */ |
954 in.x = v_cur.x - v_prev.x; | 946 /* when points are moved; anchor k marks the first moved point. */ |
955 in.y = v_cur.y - v_prev.y; | 947 for ( i = last, j = first, k = -1; |
956 l_in = FT_Vector_Length( &in ); | 948 j != i && i != k; |
957 if ( l_in ) | 949 j = j < last ? j + 1 : first ) |
958 { | 950 { |
959 in.x = FT_DivFix( in.x, l_in ); | 951 if ( j != k ) |
960 in.y = FT_DivFix( in.y, l_in ); | 952 { |
961 } | 953 out.x = points[j].x - points[i].x; |
| 954 out.y = points[j].y - points[i].y; |
| 955 l_out = (FT_Fixed)FT_Vector_NormLen( &out ); |
962 | 956 |
963 for ( n = first; n <= last; n++ ) | 957 if ( l_out == 0 ) |
964 { | 958 continue; |
965 if ( n < last ) | 959 } |
966 v_next = points[n + 1]; | |
967 else | 960 else |
968 v_next = v_first; | |
969 | |
970 /* compute outgoing normalized vector */ | |
971 out.x = v_next.x - v_cur.x; | |
972 out.y = v_next.y - v_cur.y; | |
973 l_out = FT_Vector_Length( &out ); | |
974 if ( l_out ) | |
975 { | 961 { |
976 out.x = FT_DivFix( out.x, l_out ); | 962 out = anchor; |
977 out.y = FT_DivFix( out.y, l_out ); | 963 l_out = l_anchor; |
978 } | 964 } |
979 | 965 |
980 d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); | 966 if ( l_in != 0 ) |
| 967 { |
| 968 if ( k < 0 ) |
| 969 { |
| 970 k = i; |
| 971 anchor = in; |
| 972 l_anchor = l_in; |
| 973 } |
981 | 974 |
982 /* shift only if turn is less than ~160 degrees */ | 975 d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); |
983 if ( d > -0xF000L ) | |
984 { | |
985 d = d + 0x10000L; | |
986 | 976 |
987 /* shift components are aligned along lateral bisector */ | 977 /* shift only if turn is less than ~160 degrees */ |
988 /* and directed according to the outline orientation. */ | 978 if ( d > -0xF000L ) |
989 shift.x = in.y + out.y; | 979 { |
990 shift.y = in.x + out.x; | 980 d = d + 0x10000L; |
991 | 981 |
992 if ( orientation == FT_ORIENTATION_TRUETYPE ) | 982 /* shift components along lateral bisector in proper orientation */ |
993 shift.x = -shift.x; | 983 shift.x = in.y + out.y; |
994 else | 984 shift.y = in.x + out.x; |
995 shift.y = -shift.y; | |
996 | 985 |
997 /* restrict shift magnitude to better handle collapsing segments */ | 986 if ( orientation == FT_ORIENTATION_TRUETYPE ) |
998 q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); | 987 shift.x = -shift.x; |
999 if ( orientation == FT_ORIENTATION_TRUETYPE ) | 988 else |
1000 q = -q; | 989 shift.y = -shift.y; |
1001 | 990 |
1002 l = FT_MIN( l_in, l_out ); | 991 /* restrict shift magnitude to better handle collapsing segments */ |
| 992 q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); |
| 993 if ( orientation == FT_ORIENTATION_TRUETYPE ) |
| 994 q = -q; |
1003 | 995 |
1004 /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ | 996 l = FT_MIN( l_in, l_out ); |
1005 if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) ) | 997 |
1006 shift.x = FT_MulDiv( shift.x, xstrength, d ); | 998 /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ |
1007 else | 999 if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) ) |
1008 shift.x = FT_MulDiv( shift.x, l, q ); | 1000 shift.x = FT_MulDiv( shift.x, xstrength, d ); |
| 1001 else |
| 1002 shift.x = FT_MulDiv( shift.x, l, q ); |
1009 | 1003 |
1010 | 1004 |
1011 if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) ) | 1005 if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) ) |
1012 shift.y = FT_MulDiv( shift.y, ystrength, d ); | 1006 shift.y = FT_MulDiv( shift.y, ystrength, d ); |
| 1007 else |
| 1008 shift.y = FT_MulDiv( shift.y, l, q ); |
| 1009 } |
1013 else | 1010 else |
1014 shift.y = FT_MulDiv( shift.y, l, q ); | 1011 shift.x = shift.y = 0; |
| 1012 |
| 1013 for ( ; |
| 1014 i != j; |
| 1015 i = i < last ? i + 1 : first ) |
| 1016 { |
| 1017 points[i].x += xstrength + shift.x; |
| 1018 points[i].y += ystrength + shift.y; |
| 1019 } |
1015 } | 1020 } |
1016 else | 1021 else |
1017 shift.x = shift.y = 0; | 1022 i = j; |
1018 | 1023 |
1019 outline->points[n].x = v_cur.x + xstrength + shift.x; | 1024 in = out; |
1020 outline->points[n].y = v_cur.y + ystrength + shift.y; | 1025 l_in = l_out; |
1021 | |
1022 in = out; | |
1023 l_in = l_out; | |
1024 v_cur = v_next; | |
1025 } | 1026 } |
1026 | 1027 |
1027 first = last + 1; | 1028 first = last + 1; |
1028 } | 1029 } |
1029 | 1030 |
1030 return FT_Err_Ok; | 1031 return FT_Err_Ok; |
1031 } | 1032 } |
1032 | 1033 |
1033 | 1034 |
1034 /* documentation is in ftoutln.h */ | 1035 /* documentation is in ftoutln.h */ |
1035 | 1036 |
1036 FT_EXPORT_DEF( FT_Orientation ) | 1037 FT_EXPORT_DEF( FT_Orientation ) |
1037 FT_Outline_Get_Orientation( FT_Outline* outline ) | 1038 FT_Outline_Get_Orientation( FT_Outline* outline ) |
1038 { | 1039 { |
1039 FT_BBox cbox; | 1040 FT_BBox cbox; |
1040 FT_Int xshift, yshift; | 1041 FT_Int xshift, yshift; |
1041 FT_Vector* points; | 1042 FT_Vector* points; |
1042 FT_Vector v_prev, v_cur; | 1043 FT_Vector v_prev, v_cur; |
1043 FT_Int c, n, first; | 1044 FT_Int c, n, first; |
1044 FT_Pos area = 0; | 1045 FT_Pos area = 0; |
1045 | 1046 |
1046 | 1047 |
1047 if ( !outline || outline->n_points <= 0 ) | 1048 if ( !outline || outline->n_points <= 0 ) |
1048 return FT_ORIENTATION_TRUETYPE; | 1049 return FT_ORIENTATION_TRUETYPE; |
1049 | 1050 |
1050 /* We use the nonzero winding rule to find the orientation. */ | 1051 /* We use the nonzero winding rule to find the orientation. */ |
1051 /* Since glyph outlines behave much more `regular' than arbitrary */ | 1052 /* Since glyph outlines behave much more `regular' than arbitrary */ |
1052 /* cubic or quadratic curves, this test deals with the polygon */ | 1053 /* cubic or quadratic curves, this test deals with the polygon */ |
1053 /* only which is spanned up by the control points. */ | 1054 /* only that is spanned up by the control points. */ |
1054 | 1055 |
1055 FT_Outline_Get_CBox( outline, &cbox ); | 1056 FT_Outline_Get_CBox( outline, &cbox ); |
1056 | 1057 |
1057 /* Handle collapsed outlines to avoid undefined FT_MSB. */ | 1058 /* Handle collapsed outlines to avoid undefined FT_MSB. */ |
1058 if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax ) | 1059 if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax ) |
1059 return FT_ORIENTATION_NONE; | 1060 return FT_ORIENTATION_NONE; |
1060 | 1061 |
1061 xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14; | 1062 xshift = FT_MSB( (FT_UInt32)( FT_ABS( cbox.xMax ) | |
| 1063 FT_ABS( cbox.xMin ) ) ) - 14; |
1062 xshift = FT_MAX( xshift, 0 ); | 1064 xshift = FT_MAX( xshift, 0 ); |
1063 | 1065 |
1064 yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14; | 1066 yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14; |
1065 yshift = FT_MAX( yshift, 0 ); | 1067 yshift = FT_MAX( yshift, 0 ); |
1066 | 1068 |
1067 points = outline->points; | 1069 points = outline->points; |
1068 | 1070 |
1069 first = 0; | 1071 first = 0; |
1070 for ( c = 0; c < outline->n_contours; c++ ) | 1072 for ( c = 0; c < outline->n_contours; c++ ) |
1071 { | 1073 { |
1072 FT_Int last = outline->contours[c]; | 1074 FT_Int last = outline->contours[c]; |
1073 | 1075 |
1074 | 1076 |
(...skipping 13 matching lines...) Expand all Loading... |
1088 if ( area > 0 ) | 1090 if ( area > 0 ) |
1089 return FT_ORIENTATION_POSTSCRIPT; | 1091 return FT_ORIENTATION_POSTSCRIPT; |
1090 else if ( area < 0 ) | 1092 else if ( area < 0 ) |
1091 return FT_ORIENTATION_TRUETYPE; | 1093 return FT_ORIENTATION_TRUETYPE; |
1092 else | 1094 else |
1093 return FT_ORIENTATION_NONE; | 1095 return FT_ORIENTATION_NONE; |
1094 } | 1096 } |
1095 | 1097 |
1096 | 1098 |
1097 /* END */ | 1099 /* END */ |
OLD | NEW |