00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "afglobal.h"
00020 #include "afdummy.h"
00021 #include "aflatin.h"
00022 #include "afcjk.h"
00023 #include "afindic.h"
00024 #include "afpic.h"
00025
00026 #include "aferrors.h"
00027
00028 #ifdef FT_OPTION_AUTOFIT2
00029 #include "aflatin2.h"
00030 #endif
00031
00032 #ifndef FT_CONFIG_OPTION_PIC
00033
00034
00035
00036
00037
00038 static AF_ScriptClass const af_script_classes[] =
00039 {
00040 &af_dummy_script_class,
00041 #ifdef FT_OPTION_AUTOFIT2
00042 &af_latin2_script_class,
00043 #endif
00044 &af_latin_script_class,
00045 &af_cjk_script_class,
00046 &af_indic_script_class,
00047 NULL
00048 };
00049
00050 #endif
00051
00052
00053 #define AF_SCRIPT_LIST_DEFAULT 2
00054
00055 #define AF_SCRIPT_LIST_NONE 0x7F
00056
00057 #define AF_DIGIT 0x80
00058
00059
00060
00061
00062
00063
00064
00065 typedef struct AF_FaceGlobalsRec_
00066 {
00067 FT_Face face;
00068 FT_Long glyph_count;
00069 FT_Byte* glyph_scripts;
00070
00071 AF_ScriptMetrics metrics[AF_SCRIPT_MAX];
00072
00073 } AF_FaceGlobalsRec;
00074
00075
00076
00077
00078 static FT_Error
00079 af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
00080 {
00081 FT_Error error = AF_Err_Ok;
00082 FT_Face face = globals->face;
00083 FT_CharMap old_charmap = face->charmap;
00084 FT_Byte* gscripts = globals->glyph_scripts;
00085 FT_UInt ss, i;
00086
00087
00088
00089 FT_MEM_SET( globals->glyph_scripts,
00090 AF_SCRIPT_LIST_NONE,
00091 globals->glyph_count );
00092
00093 error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
00094 if ( error )
00095 {
00096
00097
00098
00099
00100 error = AF_Err_Ok;
00101 goto Exit;
00102 }
00103
00104
00105 for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
00106 {
00107 AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[ss];
00108 AF_Script_UniRange range;
00109
00110
00111 if ( clazz->script_uni_ranges == NULL )
00112 continue;
00113
00114
00115
00116
00117
00118 for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
00119 {
00120 FT_ULong charcode = range->first;
00121 FT_UInt gindex;
00122
00123
00124 gindex = FT_Get_Char_Index( face, charcode );
00125
00126 if ( gindex != 0 &&
00127 gindex < (FT_ULong)globals->glyph_count &&
00128 gscripts[gindex] == AF_SCRIPT_LIST_NONE )
00129 {
00130 gscripts[gindex] = (FT_Byte)ss;
00131 }
00132
00133 for (;;)
00134 {
00135 charcode = FT_Get_Next_Char( face, charcode, &gindex );
00136
00137 if ( gindex == 0 || charcode > range->last )
00138 break;
00139
00140 if ( gindex < (FT_ULong)globals->glyph_count &&
00141 gscripts[gindex] == AF_SCRIPT_LIST_NONE )
00142 {
00143 gscripts[gindex] = (FT_Byte)ss;
00144 }
00145 }
00146 }
00147 }
00148
00149
00150 for ( i = 0x30; i <= 0x39; i++ )
00151 {
00152 FT_UInt gindex = FT_Get_Char_Index( face, i );
00153
00154
00155 if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
00156 gscripts[gindex] |= AF_DIGIT;
00157 }
00158
00159 Exit:
00160
00161
00162
00163
00164 {
00165 FT_Long nn;
00166
00167
00168 for ( nn = 0; nn < globals->glyph_count; nn++ )
00169 {
00170 if ( gscripts[nn] == AF_SCRIPT_LIST_NONE )
00171 gscripts[nn] = AF_SCRIPT_LIST_DEFAULT;
00172 }
00173 }
00174
00175 FT_Set_Charmap( face, old_charmap );
00176 return error;
00177 }
00178
00179
00180 FT_LOCAL_DEF( FT_Error )
00181 af_face_globals_new( FT_Face face,
00182 AF_FaceGlobals *aglobals )
00183 {
00184 FT_Error error;
00185 FT_Memory memory;
00186 AF_FaceGlobals globals;
00187
00188
00189 memory = face->memory;
00190
00191 if ( !FT_ALLOC( globals, sizeof ( *globals ) +
00192 face->num_glyphs * sizeof ( FT_Byte ) ) )
00193 {
00194 globals->face = face;
00195 globals->glyph_count = face->num_glyphs;
00196 globals->glyph_scripts = (FT_Byte*)( globals + 1 );
00197
00198 error = af_face_globals_compute_script_coverage( globals );
00199 if ( error )
00200 {
00201 af_face_globals_free( globals );
00202 globals = NULL;
00203 }
00204 }
00205
00206 *aglobals = globals;
00207 return error;
00208 }
00209
00210
00211 FT_LOCAL_DEF( void )
00212 af_face_globals_free( AF_FaceGlobals globals )
00213 {
00214 if ( globals )
00215 {
00216 FT_Memory memory = globals->face->memory;
00217 FT_UInt nn;
00218
00219
00220 for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
00221 {
00222 if ( globals->metrics[nn] )
00223 {
00224 AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[nn];
00225
00226
00227 FT_ASSERT( globals->metrics[nn]->clazz == clazz );
00228
00229 if ( clazz->script_metrics_done )
00230 clazz->script_metrics_done( globals->metrics[nn] );
00231
00232 FT_FREE( globals->metrics[nn] );
00233 }
00234 }
00235
00236 globals->glyph_count = 0;
00237 globals->glyph_scripts = NULL;
00238 globals->face = NULL;
00239
00240 FT_FREE( globals );
00241 }
00242 }
00243
00244
00245 FT_LOCAL_DEF( FT_Error )
00246 af_face_globals_get_metrics( AF_FaceGlobals globals,
00247 FT_UInt gindex,
00248 FT_UInt options,
00249 AF_ScriptMetrics *ametrics )
00250 {
00251 AF_ScriptMetrics metrics = NULL;
00252 FT_UInt gidx;
00253 AF_ScriptClass clazz;
00254 FT_UInt script = options & 15;
00255 const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
00256 sizeof ( AF_SCRIPT_CLASSES_GET[0] );
00257 FT_Error error = AF_Err_Ok;
00258
00259
00260 if ( gindex >= (FT_ULong)globals->glyph_count )
00261 {
00262 error = AF_Err_Invalid_Argument;
00263 goto Exit;
00264 }
00265
00266 gidx = script;
00267 if ( gidx == 0 || gidx + 1 >= script_max )
00268 gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
00269
00270 clazz = AF_SCRIPT_CLASSES_GET[gidx];
00271 if ( script == 0 )
00272 script = clazz->script;
00273
00274 metrics = globals->metrics[clazz->script];
00275 if ( metrics == NULL )
00276 {
00277
00278 FT_Memory memory = globals->face->memory;
00279
00280
00281 if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
00282 goto Exit;
00283
00284 metrics->clazz = clazz;
00285
00286 if ( clazz->script_metrics_init )
00287 {
00288 error = clazz->script_metrics_init( metrics, globals->face );
00289 if ( error )
00290 {
00291 if ( clazz->script_metrics_done )
00292 clazz->script_metrics_done( metrics );
00293
00294 FT_FREE( metrics );
00295 goto Exit;
00296 }
00297 }
00298
00299 globals->metrics[clazz->script] = metrics;
00300 }
00301
00302 Exit:
00303 *ametrics = metrics;
00304
00305 return error;
00306 }
00307
00308
00309 FT_LOCAL_DEF( FT_Bool )
00310 af_face_globals_is_digit( AF_FaceGlobals globals,
00311 FT_UInt gindex )
00312 {
00313 if ( gindex < (FT_ULong)globals->glyph_count )
00314 return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
00315
00316 return (FT_Bool)0;
00317 }
00318
00319
00320