|
Lines 933-950
Link Here
|
| 933 |
FT_EXPORT_DEF( FT_Orientation ) |
933 |
FT_EXPORT_DEF( FT_Orientation ) |
| 934 |
FT_Outline_Get_Orientation( FT_Outline* outline ) |
934 |
FT_Outline_Get_Orientation( FT_Outline* outline ) |
| 935 |
{ |
935 |
{ |
| 936 |
FT_Pos xmin = 32768L; |
936 |
FT_Vector xmin = { 32768L, 32768L }; |
| 937 |
FT_Vector* xmin_point = NULL; |
937 |
FT_Vector xmin_p; |
| 938 |
FT_Vector* xmin_first = NULL; |
938 |
FT_Vector xmin_n; |
| 939 |
FT_Vector* xmin_last = NULL; |
939 |
|
|
|
940 |
FT_Vector* xmin_prev = NULL; |
| 941 |
FT_Vector* xmin_next = NULL; |
| 942 |
FT_Vector* xmin_first = NULL; |
| 943 |
FT_Vector* xmin_last = NULL; |
| 944 |
|
| 945 |
int xmin_points = 0; |
| 940 |
|
946 |
|
| 941 |
short* contour; |
947 |
short* contour; |
| 942 |
|
948 |
|
| 943 |
FT_Vector* first; |
949 |
FT_Vector* first; |
| 944 |
FT_Vector* last; |
950 |
FT_Vector* last; |
| 945 |
FT_Vector* prev; |
|
|
| 946 |
FT_Vector* next; |
| 947 |
|
| 948 |
|
951 |
|
| 949 |
if ( !outline || outline->n_points <= 0 ) |
952 |
if ( !outline || outline->n_points <= 0 ) |
| 950 |
return FT_ORIENTATION_TRUETYPE; |
953 |
return FT_ORIENTATION_TRUETYPE; |
|
Lines 955-964
Link Here
|
| 955 |
contour++, first = last + 1 ) |
958 |
contour++, first = last + 1 ) |
| 956 |
{ |
959 |
{ |
| 957 |
FT_Vector* point; |
960 |
FT_Vector* point; |
| 958 |
FT_Int on_curve; |
961 |
FT_Vector* prev; |
| 959 |
FT_Int on_curve_count = 0; |
962 |
FT_Vector* next; |
| 960 |
FT_Pos tmp_xmin = 32768L; |
963 |
|
| 961 |
FT_Vector* tmp_xmin_point = NULL; |
964 |
FT_Vector contour_xmin = { 32768L, 32768L }; |
|
|
965 |
FT_Vector* contour_xmin_prev; |
| 966 |
FT_Vector* contour_xmin_next; |
| 967 |
int contour_count = 0; |
| 962 |
|
968 |
|
| 963 |
last = outline->points + *contour; |
969 |
last = outline->points + *contour; |
| 964 |
|
970 |
|
|
Lines 966-1019
Link Here
|
| 966 |
if ( last < first + 2 ) |
972 |
if ( last < first + 2 ) |
| 967 |
continue; |
973 |
continue; |
| 968 |
|
974 |
|
|
|
975 |
prev = last; |
| 969 |
for ( point = first; point <= last; ++point ) |
976 |
for ( point = first; point <= last; ++point ) |
| 970 |
{ |
977 |
{ |
| 971 |
/* Count on-curve points. If there are less than 3 on-curve */ |
978 |
FT_Vector tmp_xmin = { 32768L, 32768L }; |
| 972 |
/* points, just bypass this contour. */ |
979 |
FT_Vector* tmp_prev; |
| 973 |
on_curve = outline->tags[point - outline->points] & 1; |
980 |
FT_Vector* tmp_next; |
| 974 |
on_curve_count += on_curve; |
981 |
|
|
|
982 |
if ( point == last ) |
| 983 |
next = first; |
| 984 |
else |
| 985 |
next = point + 1; |
| 986 |
|
| 987 |
/* If it's a on-curve point, then just use it */ |
| 988 |
if ( outline->tags[point - outline->points] & 1 ) |
| 989 |
{ |
| 990 |
tmp_xmin = *point; |
| 991 |
tmp_prev = prev; |
| 992 |
tmp_next = next; |
| 993 |
} |
| 994 |
/* If it's an off-curve point and the prev point is also an |
| 995 |
of-curve point, then use the implicit on-curve point between |
| 996 |
them. */ |
| 997 |
else if ( (outline->tags[prev - outline->points] & 1) == 0 ) |
| 998 |
{ |
| 999 |
tmp_xmin.x = ((point->x + prev->x) >> 1); |
| 1000 |
tmp_xmin.y = ((point->y + prev->y) >> 1); |
| 1001 |
tmp_prev = prev; |
| 1002 |
tmp_next = point; |
| 1003 |
} |
| 1004 |
|
| 1005 |
if ( tmp_xmin.x != 32768L ) |
| 1006 |
++contour_count; |
| 975 |
|
1007 |
|
| 976 |
if ( point->x < tmp_xmin && on_curve ) |
1008 |
if ( tmp_xmin.x < contour_xmin.x ) |
| 977 |
{ |
1009 |
{ |
| 978 |
tmp_xmin = point->x; |
1010 |
contour_xmin = tmp_xmin; |
| 979 |
tmp_xmin_point = point; |
1011 |
contour_xmin_prev = tmp_prev; |
|
|
1012 |
contour_xmin_next = tmp_next; |
| 980 |
} |
1013 |
} |
|
|
1014 |
|
| 1015 |
prev = point; |
| 981 |
} |
1016 |
} |
| 982 |
|
1017 |
|
| 983 |
if ( on_curve_count > 2 && tmp_xmin < xmin ) |
1018 |
if ( contour_xmin.x < xmin.x ) |
| 984 |
{ |
1019 |
{ |
| 985 |
xmin = tmp_xmin; |
1020 |
xmin = contour_xmin; |
| 986 |
xmin_point = tmp_xmin_point; |
1021 |
xmin_prev = contour_xmin_prev; |
| 987 |
xmin_first = first; |
1022 |
xmin_next = contour_xmin_next; |
| 988 |
xmin_last = last; |
1023 |
xmin_first = first; |
|
|
1024 |
xmin_last = last; |
| 1025 |
xmin_points = contour_count; |
| 989 |
} |
1026 |
} |
| 990 |
} |
1027 |
} |
| 991 |
|
1028 |
|
| 992 |
if ( !xmin_point ) |
1029 |
if ( xmin.x == 32768L ) |
| 993 |
return FT_ORIENTATION_TRUETYPE; |
1030 |
return FT_ORIENTATION_TRUETYPE; |
| 994 |
|
1031 |
|
| 995 |
prev = ( xmin_point == xmin_first ) ? xmin_last : xmin_point - 1; |
1032 |
/* if there are less than 3 on-curve points, then just use |
| 996 |
next = ( xmin_point == xmin_last ) ? xmin_first : xmin_point + 1; |
1033 |
the prev and next points, no matter whether they are on-curve |
| 997 |
|
1034 |
points or not. */ |
| 998 |
/* Skip off-curve points */ |
1035 |
if ( xmin_points < 3 ) |
| 999 |
while ( ( outline->tags[prev - outline->points] & 1 ) == 0 ) |
|
|
| 1000 |
{ |
1036 |
{ |
| 1001 |
if ( prev == xmin_first ) |
1037 |
xmin_p = *xmin_prev; |
| 1002 |
prev = xmin_last; |
1038 |
xmin_n = *xmin_next; |
| 1003 |
else |
|
|
| 1004 |
--prev; |
| 1005 |
} |
1039 |
} |
| 1006 |
|
1040 |
/* If there are 3 or more on-curve points, then try to find |
| 1007 |
while ( ( outline->tags[next - outline->points] & 1 ) == 0 ) |
1041 |
better prev and next points. */ |
|
|
1042 |
else |
| 1008 |
{ |
1043 |
{ |
| 1009 |
if ( next == xmin_last ) |
1044 |
/* Find a valid prev point */ |
| 1010 |
next = xmin_first; |
1045 |
if ( outline->tags[xmin_prev - outline->points] & 1 ) |
|
|
1046 |
xmin_p = *xmin_prev; |
| 1011 |
else |
1047 |
else |
| 1012 |
++next; |
1048 |
{ |
|
|
1049 |
FT_Vector *prev2 = ( xmin_prev == xmin_first ) ? xmin_last : xmin_prev - 1; |
| 1050 |
/* If the second prev point is an on-curve point, then use it */ |
| 1051 |
if ( outline->tags[prev2 - outline->points] & 1 ) |
| 1052 |
xmin_p = *prev2; |
| 1053 |
/* If the second prev point is also an off-curve point, then use |
| 1054 |
the middle point between prev and prev2. */ |
| 1055 |
else |
| 1056 |
{ |
| 1057 |
xmin_p.x = ((xmin_prev->x + prev2->x) >> 1); |
| 1058 |
xmin_p.y = ((xmin_prev->y + prev2->y) >> 1); |
| 1059 |
} |
| 1060 |
} |
| 1061 |
|
| 1062 |
/* Find a valid next point. */ |
| 1063 |
if ( outline->tags[xmin_next - outline->points] & 1 ) |
| 1064 |
xmin_n = *xmin_next; |
| 1065 |
else |
| 1066 |
{ |
| 1067 |
FT_Vector *next2 = ( xmin_next == xmin_last ) ? xmin_first : xmin_next + 1; |
| 1068 |
/* If the second next point is an on-curve point, then use it */ |
| 1069 |
if ( outline->tags[next2 - outline->points] & 1 ) |
| 1070 |
xmin_n = *next2; |
| 1071 |
/* If the second next point is also an off-curve point, then use |
| 1072 |
the middle point between next and next2. */ |
| 1073 |
else |
| 1074 |
{ |
| 1075 |
xmin_n.x = ((xmin_next->x + next2->x) >> 1); |
| 1076 |
xmin_n.y = ((xmin_next->y + next2->y) >> 1); |
| 1077 |
} |
| 1078 |
} |
| 1013 |
} |
1079 |
} |
| 1014 |
|
1080 |
|
| 1015 |
if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) > |
1081 |
if ( FT_Atan2( xmin_p.x - xmin.x, xmin_p.y - xmin.y ) > |
| 1016 |
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) ) |
1082 |
FT_Atan2( xmin_n.x - xmin.x, xmin_n.y - xmin.y ) ) |
| 1017 |
return FT_ORIENTATION_POSTSCRIPT; |
1083 |
return FT_ORIENTATION_POSTSCRIPT; |
| 1018 |
else |
1084 |
else |
| 1019 |
return FT_ORIENTATION_TRUETYPE; |
1085 |
return FT_ORIENTATION_TRUETYPE; |