OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* afcjk.c */ | 3 /* afcjk.c */ |
4 /* */ | 4 /* */ |
5 /* Auto-fitter hinting routines for CJK script (body). */ | 5 /* Auto-fitter hinting routines for CJK script (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 2006-2012 by */ | 7 /* Copyright 2006-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 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 /***** *****/ | 60 /***** *****/ |
61 /*************************************************************************/ | 61 /*************************************************************************/ |
62 /*************************************************************************/ | 62 /*************************************************************************/ |
63 | 63 |
64 | 64 |
65 /* Basically the Latin version with AF_CJKMetrics */ | 65 /* Basically the Latin version with AF_CJKMetrics */ |
66 /* to replace AF_LatinMetrics. */ | 66 /* to replace AF_LatinMetrics. */ |
67 | 67 |
68 FT_LOCAL_DEF( void ) | 68 FT_LOCAL_DEF( void ) |
69 af_cjk_metrics_init_widths( AF_CJKMetrics metrics, | 69 af_cjk_metrics_init_widths( AF_CJKMetrics metrics, |
70 FT_Face face, | 70 FT_Face face ) |
71 FT_ULong charcode ) | |
72 { | 71 { |
73 /* scan the array of segments in each direction */ | 72 /* scan the array of segments in each direction */ |
74 AF_GlyphHintsRec hints[1]; | 73 AF_GlyphHintsRec hints[1]; |
75 | 74 |
76 | 75 |
77 af_glyph_hints_init( hints, face->memory ); | 76 af_glyph_hints_init( hints, face->memory ); |
78 | 77 |
79 metrics->axis[AF_DIMENSION_HORZ].width_count = 0; | 78 metrics->axis[AF_DIMENSION_HORZ].width_count = 0; |
80 metrics->axis[AF_DIMENSION_VERT].width_count = 0; | 79 metrics->axis[AF_DIMENSION_VERT].width_count = 0; |
81 | 80 |
82 { | 81 { |
83 FT_Error error; | 82 FT_Error error; |
84 FT_UInt glyph_index; | 83 FT_UInt glyph_index; |
85 int dim; | 84 int dim; |
86 AF_CJKMetricsRec dummy[1]; | 85 AF_CJKMetricsRec dummy[1]; |
87 AF_Scaler scaler = &dummy->root.scaler; | 86 AF_Scaler scaler = &dummy->root.scaler; |
88 | 87 |
89 | 88 |
90 glyph_index = FT_Get_Char_Index( face, charcode ); | 89 glyph_index = FT_Get_Char_Index( face, |
| 90 metrics->root.clazz->standard_char ); |
91 if ( glyph_index == 0 ) | 91 if ( glyph_index == 0 ) |
92 goto Exit; | 92 goto Exit; |
93 | 93 |
94 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); | 94 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); |
95 if ( error || face->glyph->outline.n_points <= 0 ) | 95 if ( error || face->glyph->outline.n_points <= 0 ) |
96 goto Exit; | 96 goto Exit; |
97 | 97 |
98 FT_ZERO( dummy ); | 98 FT_ZERO( dummy ); |
99 | 99 |
100 dummy->units_per_em = metrics->units_per_em; | 100 dummy->units_per_em = metrics->units_per_em; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 | 143 |
144 dist = seg->pos - link->pos; | 144 dist = seg->pos - link->pos; |
145 if ( dist < 0 ) | 145 if ( dist < 0 ) |
146 dist = -dist; | 146 dist = -dist; |
147 | 147 |
148 if ( num_widths < AF_CJK_MAX_WIDTHS ) | 148 if ( num_widths < AF_CJK_MAX_WIDTHS ) |
149 axis->widths[num_widths++].org = dist; | 149 axis->widths[num_widths++].org = dist; |
150 } | 150 } |
151 } | 151 } |
152 | 152 |
153 af_sort_widths( num_widths, axis->widths ); | 153 /* this also replaces multiple almost identical stem widths */ |
| 154 /* with a single one (the value 100 is heuristic) */ |
| 155 af_sort_and_quantize_widths( &num_widths, axis->widths, |
| 156 dummy->units_per_em / 100 ); |
154 axis->width_count = num_widths; | 157 axis->width_count = num_widths; |
155 } | 158 } |
156 | 159 |
157 Exit: | 160 Exit: |
158 for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) | 161 for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) |
159 { | 162 { |
160 AF_CJKAxis axis = &metrics->axis[dim]; | 163 AF_CJKAxis axis = &metrics->axis[dim]; |
161 FT_Pos stdw; | 164 FT_Pos stdw; |
162 | 165 |
163 | 166 |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 | 474 |
472 /* make sure blue_ref >= blue_shoot for top/right or */ | 475 /* make sure blue_ref >= blue_shoot for top/right or */ |
473 /* vice versa for bottom/left */ | 476 /* vice versa for bottom/left */ |
474 if ( *blue_shoot != *blue_ref ) | 477 if ( *blue_shoot != *blue_ref ) |
475 { | 478 { |
476 FT_Pos ref = *blue_ref; | 479 FT_Pos ref = *blue_ref; |
477 FT_Pos shoot = *blue_shoot; | 480 FT_Pos shoot = *blue_shoot; |
478 FT_Bool under_ref = FT_BOOL( shoot < ref ); | 481 FT_Bool under_ref = FT_BOOL( shoot < ref ); |
479 | 482 |
480 | 483 |
481 if ( (AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_RIGHT == bb) ^ under_ref ) | 484 if ( ( AF_CJK_BLUE_TOP == bb || |
| 485 AF_CJK_BLUE_RIGHT == bb ) ^ under_ref ) |
482 *blue_shoot = *blue_ref = ( shoot + ref ) / 2; | 486 *blue_shoot = *blue_ref = ( shoot + ref ) / 2; |
483 } | 487 } |
484 | 488 |
485 blue->flags = 0; | 489 blue->flags = 0; |
486 if ( AF_CJK_BLUE_TOP == bb ) | 490 if ( AF_CJK_BLUE_TOP == bb ) |
487 blue->flags |= AF_CJK_BLUE_IS_TOP; | 491 blue->flags |= AF_CJK_BLUE_IS_TOP; |
488 else if ( AF_CJK_BLUE_RIGHT == bb ) | 492 else if ( AF_CJK_BLUE_RIGHT == bb ) |
489 blue->flags |= AF_CJK_BLUE_IS_RIGHT; | 493 blue->flags |= AF_CJK_BLUE_IS_RIGHT; |
490 | 494 |
491 FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n", | 495 FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n", |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 { | 553 { |
550 FT_CharMap oldmap = face->charmap; | 554 FT_CharMap oldmap = face->charmap; |
551 | 555 |
552 | 556 |
553 metrics->units_per_em = face->units_per_EM; | 557 metrics->units_per_em = face->units_per_EM; |
554 | 558 |
555 if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) | 559 if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) |
556 face->charmap = NULL; | 560 face->charmap = NULL; |
557 else | 561 else |
558 { | 562 { |
559 af_cjk_metrics_init_widths( metrics, face, 0x7530 ); | 563 af_cjk_metrics_init_widths( metrics, face ); |
560 af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars ); | 564 af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars ); |
561 af_cjk_metrics_check_digits( metrics, face ); | 565 af_cjk_metrics_check_digits( metrics, face ); |
562 } | 566 } |
563 | 567 |
564 FT_Set_Charmap( face, oldmap ); | 568 FT_Set_Charmap( face, oldmap ); |
565 | 569 |
566 return AF_Err_Ok; | 570 return FT_Err_Ok; |
567 } | 571 } |
568 | 572 |
569 | 573 |
570 static void | 574 static void |
571 af_cjk_metrics_scale_dim( AF_CJKMetrics metrics, | 575 af_cjk_metrics_scale_dim( AF_CJKMetrics metrics, |
572 AF_Scaler scaler, | 576 AF_Scaler scaler, |
573 AF_Dimension dim ) | 577 AF_Dimension dim ) |
574 { | 578 { |
575 FT_Fixed scale; | 579 FT_Fixed scale; |
576 FT_Pos delta; | 580 FT_Pos delta; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 error = af_latin_hints_compute_segments( hints, dim ); | 696 error = af_latin_hints_compute_segments( hints, dim ); |
693 if ( error ) | 697 if ( error ) |
694 return error; | 698 return error; |
695 | 699 |
696 /* a segment is round if it doesn't have successive */ | 700 /* a segment is round if it doesn't have successive */ |
697 /* on-curve points. */ | 701 /* on-curve points. */ |
698 for ( seg = segments; seg < segment_limit; seg++ ) | 702 for ( seg = segments; seg < segment_limit; seg++ ) |
699 { | 703 { |
700 AF_Point pt = seg->first; | 704 AF_Point pt = seg->first; |
701 AF_Point last = seg->last; | 705 AF_Point last = seg->last; |
702 AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); | 706 AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
703 AF_Flags f1; | 707 AF_Flags f1; |
704 | 708 |
705 | 709 |
706 seg->flags &= ~AF_EDGE_ROUND; | 710 seg->flags &= ~AF_EDGE_ROUND; |
707 | 711 |
708 for ( ; pt != last; f0 = f1 ) | 712 for ( ; pt != last; f0 = f1 ) |
709 { | 713 { |
710 pt = pt->next; | 714 pt = pt->next; |
711 f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); | 715 f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
712 | 716 |
713 if ( !f0 && !f1 ) | 717 if ( !f0 && !f1 ) |
714 break; | 718 break; |
715 | 719 |
716 if ( pt == last ) | 720 if ( pt == last ) |
717 seg->flags |= AF_EDGE_ROUND; | 721 seg->flags |= AF_EDGE_ROUND; |
718 } | 722 } |
719 } | 723 } |
720 | 724 |
721 return AF_Err_Ok; | 725 return FT_Err_Ok; |
722 } | 726 } |
723 | 727 |
724 | 728 |
725 static void | 729 static void |
726 af_cjk_hints_link_segments( AF_GlyphHints hints, | 730 af_cjk_hints_link_segments( AF_GlyphHints hints, |
727 AF_Dimension dim ) | 731 AF_Dimension dim ) |
728 { | 732 { |
729 AF_AxisHints axis = &hints->axis[dim]; | 733 AF_AxisHints axis = &hints->axis[dim]; |
730 AF_Segment segments = axis->segments; | 734 AF_Segment segments = axis->segments; |
731 AF_Segment segment_limit = segments + axis->num_segments; | 735 AF_Segment segment_limit = segments + axis->num_segments; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 } | 889 } |
886 } | 890 } |
887 } | 891 } |
888 | 892 |
889 | 893 |
890 static FT_Error | 894 static FT_Error |
891 af_cjk_hints_compute_edges( AF_GlyphHints hints, | 895 af_cjk_hints_compute_edges( AF_GlyphHints hints, |
892 AF_Dimension dim ) | 896 AF_Dimension dim ) |
893 { | 897 { |
894 AF_AxisHints axis = &hints->axis[dim]; | 898 AF_AxisHints axis = &hints->axis[dim]; |
895 FT_Error error = AF_Err_Ok; | 899 FT_Error error = FT_Err_Ok; |
896 FT_Memory memory = hints->memory; | 900 FT_Memory memory = hints->memory; |
897 AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; | 901 AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; |
898 | 902 |
899 AF_Segment segments = axis->segments; | 903 AF_Segment segments = axis->segments; |
900 AF_Segment segment_limit = segments + axis->num_segments; | 904 AF_Segment segment_limit = segments + axis->num_segments; |
901 AF_Segment seg; | 905 AF_Segment seg; |
902 | 906 |
903 FT_Fixed scale; | 907 FT_Fixed scale; |
904 FT_Pos edge_distance_threshold; | 908 FT_Pos edge_distance_threshold; |
905 | 909 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 | 959 |
956 if ( dist < edge_distance_threshold && dist < best ) | 960 if ( dist < edge_distance_threshold && dist < best ) |
957 { | 961 { |
958 AF_Segment link = seg->link; | 962 AF_Segment link = seg->link; |
959 | 963 |
960 | 964 |
961 /* check whether all linked segments of the candidate edge */ | 965 /* check whether all linked segments of the candidate edge */ |
962 /* can make a single edge. */ | 966 /* can make a single edge. */ |
963 if ( link ) | 967 if ( link ) |
964 { | 968 { |
965 AF_Segment seg1 = edge->first; | 969 AF_Segment seg1 = edge->first; |
966 AF_Segment link1; | |
967 FT_Pos dist2 = 0; | 970 FT_Pos dist2 = 0; |
968 | 971 |
969 | 972 |
970 do | 973 do |
971 { | 974 { |
972 link1 = seg1->link; | 975 AF_Segment link1 = seg1->link; |
| 976 |
| 977 |
973 if ( link1 ) | 978 if ( link1 ) |
974 { | 979 { |
975 dist2 = AF_SEGMENT_DIST( link, link1 ); | 980 dist2 = AF_SEGMENT_DIST( link, link1 ); |
976 if ( dist2 >= edge_distance_threshold ) | 981 if ( dist2 >= edge_distance_threshold ) |
977 break; | 982 break; |
978 } | 983 } |
979 | 984 |
980 } while ( ( seg1 = seg1->edge_next ) != edge->first ); | 985 } while ( ( seg1 = seg1->edge_next ) != edge->first ); |
981 | 986 |
982 if ( dist2 >= edge_distance_threshold ) | 987 if ( dist2 >= edge_distance_threshold ) |
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2183 /***** C J K S C R I P T C L A S S *****/ | 2188 /***** C J K S C R I P T C L A S S *****/ |
2184 /***** *****/ | 2189 /***** *****/ |
2185 /*************************************************************************/ | 2190 /*************************************************************************/ |
2186 /*************************************************************************/ | 2191 /*************************************************************************/ |
2187 | 2192 |
2188 | 2193 |
2189 /* this corresponds to Unicode 6.0 */ | 2194 /* this corresponds to Unicode 6.0 */ |
2190 | 2195 |
2191 static const AF_Script_UniRangeRec af_cjk_uniranges[] = | 2196 static const AF_Script_UniRangeRec af_cjk_uniranges[] = |
2192 { | 2197 { |
| 2198 AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo
*/ |
2193 AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement
*/ | 2199 AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement
*/ |
2194 AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals
*/ | 2200 AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals
*/ |
2195 AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Charact
ers */ | 2201 AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Charact
ers */ |
2196 AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation
*/ | 2202 AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation
*/ |
2197 AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana
*/ | 2203 AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana
*/ |
2198 AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana
*/ | 2204 AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana
*/ |
2199 AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo
*/ | 2205 AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo
*/ |
2200 AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo
*/ | 2206 AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo
*/ |
2201 AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun
*/ | 2207 AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun
*/ |
2202 AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended
*/ | 2208 AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended
*/ |
(...skipping 18 matching lines...) Expand all Loading... |
2221 AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extensio
n C */ | 2227 AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extensio
n C */ |
2222 AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extensio
n D */ | 2228 AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extensio
n D */ |
2223 AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Su
pplement */ | 2229 AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Su
pplement */ |
2224 AF_UNIRANGE_REC( 0UL, 0UL ) | 2230 AF_UNIRANGE_REC( 0UL, 0UL ) |
2225 }; | 2231 }; |
2226 | 2232 |
2227 | 2233 |
2228 AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, | 2234 AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, |
2229 AF_SCRIPT_CJK, | 2235 AF_SCRIPT_CJK, |
2230 af_cjk_uniranges, | 2236 af_cjk_uniranges, |
| 2237 0x7530, /* 田 */ |
2231 | 2238 |
2232 sizeof ( AF_CJKMetricsRec ), | 2239 sizeof ( AF_CJKMetricsRec ), |
2233 | 2240 |
2234 (AF_Script_InitMetricsFunc) af_cjk_metrics_init, | 2241 (AF_Script_InitMetricsFunc) af_cjk_metrics_init, |
2235 (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale, | 2242 (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale, |
2236 (AF_Script_DoneMetricsFunc) NULL, | 2243 (AF_Script_DoneMetricsFunc) NULL, |
2237 | 2244 |
2238 (AF_Script_InitHintsFunc) af_cjk_hints_init, | 2245 (AF_Script_InitHintsFunc) af_cjk_hints_init, |
2239 (AF_Script_ApplyHintsFunc) af_cjk_hints_apply | 2246 (AF_Script_ApplyHintsFunc) af_cjk_hints_apply |
2240 ) | 2247 ) |
2241 | 2248 |
2242 #else /* !AF_CONFIG_OPTION_CJK */ | 2249 #else /* !AF_CONFIG_OPTION_CJK */ |
2243 | 2250 |
2244 static const AF_Script_UniRangeRec af_cjk_uniranges[] = | 2251 static const AF_Script_UniRangeRec af_cjk_uniranges[] = |
2245 { | 2252 { |
2246 AF_UNIRANGE_REC( 0UL, 0UL ) | 2253 AF_UNIRANGE_REC( 0UL, 0UL ) |
2247 }; | 2254 }; |
2248 | 2255 |
2249 | 2256 |
2250 AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, | 2257 AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, |
2251 AF_SCRIPT_CJK, | 2258 AF_SCRIPT_CJK, |
2252 af_cjk_uniranges, | 2259 af_cjk_uniranges, |
| 2260 0, |
2253 | 2261 |
2254 sizeof ( AF_CJKMetricsRec ), | 2262 sizeof ( AF_CJKMetricsRec ), |
2255 | 2263 |
2256 (AF_Script_InitMetricsFunc) NULL, | 2264 (AF_Script_InitMetricsFunc) NULL, |
2257 (AF_Script_ScaleMetricsFunc)NULL, | 2265 (AF_Script_ScaleMetricsFunc)NULL, |
2258 (AF_Script_DoneMetricsFunc) NULL, | 2266 (AF_Script_DoneMetricsFunc) NULL, |
2259 | 2267 |
2260 (AF_Script_InitHintsFunc) NULL, | 2268 (AF_Script_InitHintsFunc) NULL, |
2261 (AF_Script_ApplyHintsFunc) NULL | 2269 (AF_Script_ApplyHintsFunc) NULL |
2262 ) | 2270 ) |
2263 | 2271 |
2264 #endif /* !AF_CONFIG_OPTION_CJK */ | 2272 #endif /* !AF_CONFIG_OPTION_CJK */ |
2265 | 2273 |
2266 | 2274 |
2267 /* END */ | 2275 /* END */ |
OLD | NEW |