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