58 |
FT_UInt num_widths = 0; |
FT_UInt num_widths = 0; |
59 |
FT_Pos edge_distance_threshold = 32000; |
FT_Pos edge_distance_threshold = 32000; |
60 |
|
|
61 |
af_latin_hints_compute_segments( hints, dim ); |
error = af_latin_hints_compute_segments( hints, dim ); |
62 |
|
if ( error ) |
63 |
|
goto Exit; |
64 |
|
|
65 |
af_latin_hints_link_segments ( hints, dim ); |
af_latin_hints_link_segments ( hints, dim ); |
66 |
|
|
67 |
seg = axhints->segments; |
seg = axhints->segments; |
509 |
af_latin_metrics_scale( AF_LatinMetrics metrics, |
af_latin_metrics_scale( AF_LatinMetrics metrics, |
510 |
AF_Scaler scaler ) |
AF_Scaler scaler ) |
511 |
{ |
{ |
|
if ( AF_SCALER_EQUAL_SCALES( scaler, &metrics->root.scaler ) ) |
|
|
return; |
|
|
|
|
512 |
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); |
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); |
513 |
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); |
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); |
514 |
} |
} |
522 |
/***************************************************************************/ |
/***************************************************************************/ |
523 |
/***************************************************************************/ |
/***************************************************************************/ |
524 |
|
|
525 |
FT_LOCAL_DEF( void ) |
FT_LOCAL_DEF( FT_Error ) |
526 |
af_latin_hints_compute_segments( AF_GlyphHints hints, |
af_latin_hints_compute_segments( AF_GlyphHints hints, |
527 |
AF_Dimension dim ) |
AF_Dimension dim ) |
528 |
{ |
{ |
529 |
AF_AxisHints axis = &hints->axis[dim]; |
AF_AxisHints axis = &hints->axis[dim]; |
530 |
AF_Segment segments = axis->segments; |
FT_Memory memory = hints->memory; |
531 |
AF_Segment segment = segments; |
FT_Error error = 0; |
532 |
FT_Int num_segments = 0; |
AF_Segment segment = NULL; |
533 |
AF_Point* contour = hints->contours; |
AF_Point* contour = hints->contours; |
534 |
AF_Point* contour_limit = contour + hints->num_contours; |
AF_Point* contour_limit = contour + hints->num_contours; |
535 |
AF_Direction major_dir, segment_dir; |
AF_Direction major_dir, segment_dir; |
544 |
major_dir = FT_ABS( axis->major_dir ); |
major_dir = FT_ABS( axis->major_dir ); |
545 |
segment_dir = major_dir; |
segment_dir = major_dir; |
546 |
|
|
547 |
|
axis->num_segments = 0; |
548 |
|
|
549 |
/* set up (u,v) in each point */ |
/* set up (u,v) in each point */ |
550 |
if ( dim == AF_DIMENSION_HORZ ) |
if ( dim == AF_DIMENSION_HORZ ) |
551 |
{ |
{ |
658 |
segment->max_coord = max_pos; |
segment->max_coord = max_pos; |
659 |
|
|
660 |
on_edge = 0; |
on_edge = 0; |
661 |
num_segments++; |
segment = NULL; |
|
segment++; |
|
662 |
/* fallthrough */ |
/* fallthrough */ |
663 |
} |
} |
664 |
} |
} |
677 |
segment_dir = point->out_dir; |
segment_dir = point->out_dir; |
678 |
|
|
679 |
/* clear all segment fields */ |
/* clear all segment fields */ |
680 |
FT_ZERO( segment ); |
error = af_axis_hints_new_segment( axis, memory, &segment ); |
681 |
|
if ( error ) |
682 |
|
goto Exit; |
683 |
|
|
684 |
segment->dir = segment_dir; |
segment->dir = segment_dir; |
685 |
segment->flags = AF_EDGE_NORMAL; |
segment->flags = AF_EDGE_NORMAL; |
743 |
if ( min_point ) |
if ( min_point ) |
744 |
{ |
{ |
745 |
/* clear all segment fields */ |
/* clear all segment fields */ |
746 |
FT_ZERO( segment ); |
error = af_axis_hints_new_segment( axis, memory, &segment ); |
747 |
|
if ( error ) |
748 |
|
goto Exit; |
749 |
|
|
750 |
segment->dir = segment_dir; |
segment->dir = segment_dir; |
751 |
segment->flags = AF_EDGE_NORMAL; |
segment->flags = AF_EDGE_NORMAL; |
755 |
segment->score = 32000; |
segment->score = 32000; |
756 |
segment->link = NULL; |
segment->link = NULL; |
757 |
|
|
758 |
num_segments++; |
segment = NULL; |
|
segment++; |
|
759 |
} |
} |
760 |
|
|
761 |
/* insert maximum segment */ |
/* insert maximum segment */ |
762 |
if ( max_point ) |
if ( max_point ) |
763 |
{ |
{ |
764 |
/* clear all segment fields */ |
/* clear all segment fields */ |
765 |
FT_ZERO( segment ); |
error = af_axis_hints_new_segment( axis, memory, &segment ); |
766 |
|
if ( error) |
767 |
|
goto Exit; |
768 |
|
|
769 |
segment->dir = segment_dir; |
segment->dir = segment_dir; |
770 |
segment->flags = AF_EDGE_NORMAL; |
segment->flags = AF_EDGE_NORMAL; |
774 |
segment->score = 32000; |
segment->score = 32000; |
775 |
segment->link = NULL; |
segment->link = NULL; |
776 |
|
|
777 |
num_segments++; |
segment = NULL; |
|
segment++; |
|
778 |
} |
} |
779 |
} |
} |
780 |
#endif /* AF_HINT_METRICS */ |
#endif /* AF_HINT_METRICS */ |
781 |
|
|
782 |
axis->num_segments = num_segments; |
Exit: |
783 |
|
return error; |
784 |
} |
} |
785 |
|
|
786 |
|
|
864 |
} |
} |
865 |
|
|
866 |
|
|
867 |
FT_LOCAL_DEF( void ) |
FT_LOCAL_DEF( FT_Error ) |
868 |
af_latin_hints_compute_edges( AF_GlyphHints hints, |
af_latin_hints_compute_edges( AF_GlyphHints hints, |
869 |
AF_Dimension dim ) |
AF_Dimension dim ) |
870 |
{ |
{ |
871 |
AF_AxisHints axis = &hints->axis[dim]; |
AF_AxisHints axis = &hints->axis[dim]; |
872 |
|
FT_Error error = 0; |
873 |
|
FT_Memory memory = hints->memory; |
874 |
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; |
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; |
|
AF_Edge edges = axis->edges; |
|
|
AF_Edge edge, edge_limit; |
|
875 |
|
|
876 |
AF_Segment segments = axis->segments; |
AF_Segment segments = axis->segments; |
877 |
AF_Segment segment_limit = segments + axis->num_segments; |
AF_Segment segment_limit = segments + axis->num_segments; |
881 |
FT_Fixed scale; |
FT_Fixed scale; |
882 |
FT_Pos edge_distance_threshold; |
FT_Pos edge_distance_threshold; |
883 |
|
|
884 |
|
axis->num_edges = 0; |
885 |
|
|
886 |
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale |
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale |
887 |
: hints->y_scale; |
: hints->y_scale; |
913 |
edge_distance_threshold = FT_DivFix( edge_distance_threshold, |
edge_distance_threshold = FT_DivFix( edge_distance_threshold, |
914 |
scale ); |
scale ); |
915 |
|
|
|
edge_limit = edges; |
|
916 |
for ( seg = segments; seg < segment_limit; seg++ ) |
for ( seg = segments; seg < segment_limit; seg++ ) |
917 |
{ |
{ |
918 |
AF_Edge found = 0; |
AF_Edge found = 0; |
919 |
|
FT_Int ee; |
920 |
|
|
921 |
/* look for an edge corresponding to the segment */ |
/* look for an edge corresponding to the segment */ |
922 |
for ( edge = edges; edge < edge_limit; edge++ ) |
for ( ee = 0; ee < axis->num_edges; ee++ ) |
923 |
{ |
{ |
924 |
FT_Pos dist; |
AF_Edge edge = axis->edges + ee; |
925 |
|
FT_Pos dist; |
926 |
|
|
927 |
|
|
928 |
dist = seg->pos - edge->fpos; |
dist = seg->pos - edge->fpos; |
938 |
|
|
939 |
if ( !found ) |
if ( !found ) |
940 |
{ |
{ |
941 |
|
AF_Edge edge; |
942 |
|
|
943 |
/* insert a new edge in the list and */ |
/* insert a new edge in the list and */ |
944 |
/* sort according to the position */ |
/* sort according to the position */ |
945 |
while ( edge > edges && edge[-1].fpos > seg->pos ) |
error = af_axis_hints_new_edge( axis, seg->pos, memory, &edge ); |
946 |
{ |
if ( error ) |
947 |
edge[0] = edge[-1]; |
goto Exit; |
|
edge--; |
|
|
} |
|
|
edge_limit++; |
|
|
|
|
|
/* clear all edge fields */ |
|
|
FT_ZERO( edge ); |
|
948 |
|
|
949 |
/* add the segment to the new edge's list */ |
/* add the segment to the new edge's list */ |
950 |
|
FT_ZERO(edge); |
951 |
|
|
952 |
edge->first = seg; |
edge->first = seg; |
953 |
edge->last = seg; |
edge->last = seg; |
954 |
edge->fpos = seg->pos; |
edge->fpos = seg->pos; |
959 |
{ |
{ |
960 |
/* if an edge was found, simply add the segment to the edge's */ |
/* if an edge was found, simply add the segment to the edge's */ |
961 |
/* list */ |
/* list */ |
962 |
seg->edge_next = edge->first; |
seg->edge_next = found->first; |
963 |
edge->last->edge_next = seg; |
found->last->edge_next = seg; |
964 |
edge->last = seg; |
found->last = seg; |
965 |
} |
} |
966 |
} |
} |
|
axis->num_edges = (FT_Int)( edge_limit - edges ); |
|
967 |
|
|
968 |
|
|
969 |
/*********************************************************************/ |
/*********************************************************************/ |
986 |
* code above. For some reason, it slows down execution |
* code above. For some reason, it slows down execution |
987 |
* speed -- on a Sun. |
* speed -- on a Sun. |
988 |
*/ |
*/ |
|
for ( edge = edges; edge < edge_limit; edge++ ) |
|
|
{ |
|
|
seg = edge->first; |
|
|
if ( seg ) |
|
|
do |
|
|
{ |
|
|
seg->edge = edge; |
|
|
seg = seg->edge_next; |
|
|
} |
|
|
while ( seg != edge->first ); |
|
|
} |
|
|
|
|
|
/* now, compute each edge properties */ |
|
|
for ( edge = edges; edge < edge_limit; edge++ ) |
|
989 |
{ |
{ |
990 |
FT_Int is_round = 0; /* does it contain round segments? */ |
AF_Edge edges = axis->edges; |
991 |
FT_Int is_straight = 0; /* does it contain straight segments? */ |
AF_Edge edge_limit = edges + axis->num_edges; |
992 |
FT_Pos ups = 0; /* number of upwards segments */ |
AF_Edge edge; |
|
FT_Pos downs = 0; /* number of downwards segments */ |
|
993 |
|
|
994 |
|
for ( edge = edges; edge < edge_limit; edge++ ) |
995 |
|
{ |
996 |
|
seg = edge->first; |
997 |
|
if ( seg ) |
998 |
|
do |
999 |
|
{ |
1000 |
|
seg->edge = edge; |
1001 |
|
seg = seg->edge_next; |
1002 |
|
} |
1003 |
|
while ( seg != edge->first ); |
1004 |
|
} |
1005 |
|
|
1006 |
seg = edge->first; |
/* now, compute each edge properties */ |
1007 |
|
for ( edge = edges; edge < edge_limit; edge++ ) |
|
do |
|
1008 |
{ |
{ |
1009 |
FT_Bool is_serif; |
FT_Int is_round = 0; /* does it contain round segments? */ |
1010 |
|
FT_Int is_straight = 0; /* does it contain straight segments? */ |
1011 |
|
FT_Pos ups = 0; /* number of upwards segments */ |
1012 |
|
FT_Pos downs = 0; /* number of downwards segments */ |
1013 |
|
|
1014 |
|
|
1015 |
/* check for roundness of segment */ |
seg = edge->first; |
|
if ( seg->flags & AF_EDGE_ROUND ) |
|
|
is_round++; |
|
|
else |
|
|
is_straight++; |
|
1016 |
|
|
1017 |
/* check for segment direction */ |
do |
1018 |
if ( seg->dir == up_dir ) |
{ |
1019 |
ups += seg->max_coord-seg->min_coord; |
FT_Bool is_serif; |
|
else |
|
|
downs += seg->max_coord-seg->min_coord; |
|
1020 |
|
|
|
/* check for links -- if seg->serif is set, then seg->link must */ |
|
|
/* be ignored */ |
|
|
is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); |
|
1021 |
|
|
1022 |
if ( seg->link || is_serif ) |
/* check for roundness of segment */ |
1023 |
{ |
if ( seg->flags & AF_EDGE_ROUND ) |
1024 |
AF_Edge edge2; |
is_round++; |
1025 |
AF_Segment seg2; |
else |
1026 |
|
is_straight++; |
1027 |
|
|
1028 |
|
/* check for segment direction */ |
1029 |
|
if ( seg->dir == up_dir ) |
1030 |
|
ups += seg->max_coord-seg->min_coord; |
1031 |
|
else |
1032 |
|
downs += seg->max_coord-seg->min_coord; |
1033 |
|
|
1034 |
edge2 = edge->link; |
/* check for links -- if seg->serif is set, then seg->link must */ |
1035 |
seg2 = seg->link; |
/* be ignored */ |
1036 |
|
is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); |
1037 |
|
|
1038 |
if ( is_serif ) |
if ( seg->link || is_serif ) |
1039 |
{ |
{ |
1040 |
seg2 = seg->serif; |
AF_Edge edge2; |
1041 |
edge2 = edge->serif; |
AF_Segment seg2; |
|
} |
|
1042 |
|
|
|
if ( edge2 ) |
|
|
{ |
|
|
FT_Pos edge_delta; |
|
|
FT_Pos seg_delta; |
|
1043 |
|
|
1044 |
|
edge2 = edge->link; |
1045 |
|
seg2 = seg->link; |
1046 |
|
|
1047 |
edge_delta = edge->fpos - edge2->fpos; |
if ( is_serif ) |
1048 |
if ( edge_delta < 0 ) |
{ |
1049 |
edge_delta = -edge_delta; |
seg2 = seg->serif; |
1050 |
|
edge2 = edge->serif; |
1051 |
|
} |
1052 |
|
|
1053 |
seg_delta = seg->pos - seg2->pos; |
if ( edge2 ) |
1054 |
if ( seg_delta < 0 ) |
{ |
1055 |
seg_delta = -seg_delta; |
FT_Pos edge_delta; |
1056 |
|
FT_Pos seg_delta; |
1057 |
|
|
1058 |
|
|
1059 |
|
edge_delta = edge->fpos - edge2->fpos; |
1060 |
|
if ( edge_delta < 0 ) |
1061 |
|
edge_delta = -edge_delta; |
1062 |
|
|
1063 |
if ( seg_delta < edge_delta ) |
seg_delta = seg->pos - seg2->pos; |
1064 |
|
if ( seg_delta < 0 ) |
1065 |
|
seg_delta = -seg_delta; |
1066 |
|
|
1067 |
|
if ( seg_delta < edge_delta ) |
1068 |
|
edge2 = seg2->edge; |
1069 |
|
} |
1070 |
|
else |
1071 |
edge2 = seg2->edge; |
edge2 = seg2->edge; |
|
} |
|
|
else |
|
|
edge2 = seg2->edge; |
|
1072 |
|
|
1073 |
if ( is_serif ) |
if ( is_serif ) |
1074 |
{ |
{ |
1075 |
edge->serif = edge2; |
edge->serif = edge2; |
1076 |
edge2->flags |= AF_EDGE_SERIF; |
edge2->flags |= AF_EDGE_SERIF; |
1077 |
|
} |
1078 |
|
else |
1079 |
|
edge->link = edge2; |
1080 |
} |
} |
|
else |
|
|
edge->link = edge2; |
|
|
} |
|
1081 |
|
|
1082 |
seg = seg->edge_next; |
seg = seg->edge_next; |
1083 |
|
|
1084 |
} while ( seg != edge->first ); |
} while ( seg != edge->first ); |
1085 |
|
|
1086 |
/* set the round/straight flags */ |
/* set the round/straight flags */ |
1087 |
edge->flags = AF_EDGE_NORMAL; |
edge->flags = AF_EDGE_NORMAL; |
1088 |
|
|
1089 |
if ( is_round > 0 && is_round >= is_straight ) |
if ( is_round > 0 && is_round >= is_straight ) |
1090 |
edge->flags |= AF_EDGE_ROUND; |
edge->flags |= AF_EDGE_ROUND; |
1091 |
|
|
1092 |
/* set the edge's main direction */ |
/* set the edge's main direction */ |
1093 |
edge->dir = AF_DIR_NONE; |
edge->dir = AF_DIR_NONE; |
1094 |
|
|
1095 |
if ( ups > downs ) |
if ( ups > downs ) |
1096 |
edge->dir = up_dir; |
edge->dir = up_dir; |
1097 |
|
|
1098 |
else if ( ups < downs ) |
else if ( ups < downs ) |
1099 |
edge->dir = -up_dir; |
edge->dir = -up_dir; |
1100 |
|
|
1101 |
else if ( ups == downs ) |
else if ( ups == downs ) |
1102 |
edge->dir = 0; /* both up and down! */ |
edge->dir = 0; /* both up and down! */ |
1103 |
|
|
1104 |
/* gets rid of serifs if link is set */ |
/* gets rid of serifs if link is set */ |
1105 |
/* XXX: This gets rid of many unpleasant artefacts! */ |
/* XXX: This gets rid of many unpleasant artefacts! */ |
1106 |
/* Example: the `c' in cour.pfa at size 13 */ |
/* Example: the `c' in cour.pfa at size 13 */ |
1107 |
|
|
1108 |
if ( edge->serif && edge->link ) |
if ( edge->serif && edge->link ) |
1109 |
edge->serif = 0; |
edge->serif = 0; |
1110 |
|
} |
1111 |
} |
} |
1112 |
|
|
1113 |
|
Exit: |
1114 |
|
return error; |
1115 |
} |
} |
1116 |
|
|
1117 |
|
|
1118 |
FT_LOCAL_DEF( void ) |
FT_LOCAL_DEF( FT_Error ) |
1119 |
af_latin_hints_detect_features( AF_GlyphHints hints, |
af_latin_hints_detect_features( AF_GlyphHints hints, |
1120 |
AF_Dimension dim ) |
AF_Dimension dim ) |
1121 |
{ |
{ |
1122 |
af_latin_hints_compute_segments( hints, dim ); |
FT_Error error; |
1123 |
af_latin_hints_link_segments ( hints, dim ); |
|
1124 |
af_latin_hints_compute_edges ( hints, dim ); |
error = af_latin_hints_compute_segments( hints, dim ); |
1125 |
|
if ( !error ) |
1126 |
|
{ |
1127 |
|
af_latin_hints_link_segments ( hints, dim ); |
1128 |
|
error = af_latin_hints_compute_edges ( hints, dim ); |
1129 |
|
} |
1130 |
|
return error; |
1131 |
} |
} |
1132 |
|
|
1133 |
|
|
1831 |
/* analyze glyph outline |
/* analyze glyph outline |
1832 |
*/ |
*/ |
1833 |
if ( AF_HINTS_DO_HORIZONTAL(hints) ) |
if ( AF_HINTS_DO_HORIZONTAL(hints) ) |
1834 |
af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ ); |
{ |
1835 |
|
error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ ); |
1836 |
|
if ( error ) |
1837 |
|
goto Exit; |
1838 |
|
} |
1839 |
|
|
1840 |
if ( AF_HINTS_DO_VERTICAL(hints) ) |
if ( AF_HINTS_DO_VERTICAL(hints) ) |
1841 |
{ |
{ |
1842 |
af_latin_hints_detect_features( hints, AF_DIMENSION_VERT ); |
error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT ); |
1843 |
|
if ( error ) |
1844 |
|
goto Exit; |
1845 |
|
|
1846 |
af_latin_hints_compute_blue_edges( hints, metrics ); |
af_latin_hints_compute_blue_edges( hints, metrics ); |
1847 |
} |
} |
1848 |
|
|