afglobal.c revision ec0bab5697bb31ba980810145f62e3799946ec60
1/***************************************************************************/ 2/* */ 3/* afglobal.c */ 4/* */ 5/* Auto-fitter routines to compute global hinting values (body). */ 6/* */ 7/* Copyright 2003-2013 by */ 8/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9/* */ 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 */ 12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13/* this file you indicate that you have read the license and */ 14/* understand and accept it fully. */ 15/* */ 16/***************************************************************************/ 17 18 19#include "afglobal.h" 20 21 /* get writing system specific header files */ 22#undef WRITING_SYSTEM 23#define WRITING_SYSTEM( ws, WS ) /* empty */ 24#include "afwrtsys.h" 25 26#include "aferrors.h" 27#include "afpic.h" 28 29 30#ifndef FT_CONFIG_OPTION_PIC 31 32#undef WRITING_SYSTEM 33#define WRITING_SYSTEM( ws, WS ) \ 34 &af_ ## ws ## _writing_system_class, 35 36 FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass ) 37 af_writing_system_classes[] = 38 { 39 40#include "afwrtsys.h" 41 42 NULL /* do not remove */ 43 }; 44 45 46#undef SCRIPT 47#define SCRIPT( s, S, d ) \ 48 &af_ ## s ## _script_class, 49 50 FT_LOCAL_ARRAY_DEF( AF_ScriptClass ) 51 af_script_classes[] = 52 { 53 54#include "afscript.h" 55 56 NULL /* do not remove */ 57 }; 58 59#endif /* !FT_CONFIG_OPTION_PIC */ 60 61 62#ifdef FT_DEBUG_LEVEL_TRACE 63 64#undef SCRIPT 65#define SCRIPT( s, S, d ) #s, 66 67 FT_LOCAL_ARRAY_DEF( char* ) 68 af_script_names[] = 69 { 70 71#include "afscript.h" 72 73 }; 74 75#endif /* FT_DEBUG_LEVEL_TRACE */ 76 77 78 /* Compute the script index of each glyph within a given face. */ 79 80 static FT_Error 81 af_face_globals_compute_script_coverage( AF_FaceGlobals globals ) 82 { 83 FT_Error error; 84 FT_Face face = globals->face; 85 FT_CharMap old_charmap = face->charmap; 86 FT_Byte* gscripts = globals->glyph_scripts; 87 FT_UInt ss; 88 FT_UInt i; 89 90 91 /* the value AF_SCRIPT_UNASSIGNED means `uncovered glyph' */ 92 FT_MEM_SET( globals->glyph_scripts, 93 AF_SCRIPT_UNASSIGNED, 94 globals->glyph_count ); 95 96 error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); 97 if ( error ) 98 { 99 /* 100 * Ignore this error; we simply use the fallback script. 101 * XXX: Shouldn't we rather disable hinting? 102 */ 103 error = FT_Err_Ok; 104 goto Exit; 105 } 106 107 /* scan each script in a Unicode charmap */ 108 for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ ) 109 { 110 AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET[ss]; 111 AF_Script_UniRange range; 112 113 114 if ( script_class->script_uni_ranges == NULL ) 115 continue; 116 117 /* 118 * Scan all Unicode points in the range and set the corresponding 119 * glyph script index. 120 */ 121 for ( range = script_class->script_uni_ranges; 122 range->first != 0; 123 range++ ) 124 { 125 FT_ULong charcode = range->first; 126 FT_UInt gindex; 127 128 129 gindex = FT_Get_Char_Index( face, charcode ); 130 131 if ( gindex != 0 && 132 gindex < (FT_ULong)globals->glyph_count && 133 gscripts[gindex] == AF_SCRIPT_UNASSIGNED ) 134 gscripts[gindex] = (FT_Byte)ss; 135 136 for (;;) 137 { 138 charcode = FT_Get_Next_Char( face, charcode, &gindex ); 139 140 if ( gindex == 0 || charcode > range->last ) 141 break; 142 143 if ( gindex < (FT_ULong)globals->glyph_count && 144 gscripts[gindex] == AF_SCRIPT_UNASSIGNED ) 145 gscripts[gindex] = (FT_Byte)ss; 146 } 147 } 148 } 149 150 /* mark ASCII digits */ 151 for ( i = 0x30; i <= 0x39; i++ ) 152 { 153 FT_UInt gindex = FT_Get_Char_Index( face, i ); 154 155 156 if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count ) 157 gscripts[gindex] |= AF_DIGIT; 158 } 159 160 Exit: 161 /* 162 * By default, all uncovered glyphs are set to the fallback script. 163 * XXX: Shouldn't we disable hinting or do something similar? 164 */ 165 if ( globals->module->fallback_script != AF_SCRIPT_UNASSIGNED ) 166 { 167 FT_Long nn; 168 169 170 for ( nn = 0; nn < globals->glyph_count; nn++ ) 171 { 172 if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_UNASSIGNED ) 173 { 174 gscripts[nn] &= ~AF_SCRIPT_UNASSIGNED; 175 gscripts[nn] |= globals->module->fallback_script; 176 } 177 } 178 } 179 180 FT_Set_Charmap( face, old_charmap ); 181 return error; 182 } 183 184 185 FT_LOCAL_DEF( FT_Error ) 186 af_face_globals_new( FT_Face face, 187 AF_FaceGlobals *aglobals, 188 AF_Module module ) 189 { 190 FT_Error error; 191 FT_Memory memory; 192 AF_FaceGlobals globals = NULL; 193 194 195 memory = face->memory; 196 197 if ( FT_ALLOC( globals, sizeof ( *globals ) + 198 face->num_glyphs * sizeof ( FT_Byte ) ) ) 199 goto Exit; 200 201 globals->face = face; 202 globals->glyph_count = face->num_glyphs; 203 globals->glyph_scripts = (FT_Byte*)( globals + 1 ); 204 globals->module = module; 205 206 error = af_face_globals_compute_script_coverage( globals ); 207 if ( error ) 208 { 209 af_face_globals_free( globals ); 210 globals = NULL; 211 } 212 213 globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; 214 215 Exit: 216 *aglobals = globals; 217 return error; 218 } 219 220 221 FT_LOCAL_DEF( void ) 222 af_face_globals_free( AF_FaceGlobals globals ) 223 { 224 if ( globals ) 225 { 226 FT_Memory memory = globals->face->memory; 227 FT_UInt nn; 228 229 230 for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ ) 231 { 232 if ( globals->metrics[nn] ) 233 { 234 AF_ScriptClass script_class = 235 AF_SCRIPT_CLASSES_GET[nn]; 236 AF_WritingSystemClass writing_system_class = 237 AF_WRITING_SYSTEM_CLASSES_GET[script_class->writing_system]; 238 239 240 if ( writing_system_class->script_metrics_done ) 241 writing_system_class->script_metrics_done( globals->metrics[nn] ); 242 243 FT_FREE( globals->metrics[nn] ); 244 } 245 } 246 247 globals->glyph_count = 0; 248 globals->glyph_scripts = NULL; /* no need to free this one! */ 249 globals->face = NULL; 250 251 FT_FREE( globals ); 252 } 253 } 254 255 256 FT_LOCAL_DEF( FT_Error ) 257 af_face_globals_get_metrics( AF_FaceGlobals globals, 258 FT_UInt gindex, 259 FT_UInt options, 260 AF_ScriptMetrics *ametrics ) 261 { 262 AF_ScriptMetrics metrics = NULL; 263 264 AF_Script script = (AF_Script)( options & 15 ); 265 AF_WritingSystemClass writing_system_class; 266 AF_ScriptClass script_class; 267 268 FT_Error error = FT_Err_Ok; 269 270 271 if ( gindex >= (FT_ULong)globals->glyph_count ) 272 { 273 error = FT_THROW( Invalid_Argument ); 274 goto Exit; 275 } 276 277 /* if we have a forced script (via `options'), use it, */ 278 /* otherwise look into `glyph_scripts' array */ 279 if ( script == AF_SCRIPT_NONE || script + 1 >= AF_SCRIPT_MAX ) 280 script = (AF_Script)( globals->glyph_scripts[gindex] & 281 AF_SCRIPT_UNASSIGNED ); 282 283 script_class = AF_SCRIPT_CLASSES_GET[script]; 284 writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET 285 [script_class->writing_system]; 286 287 metrics = globals->metrics[script]; 288 if ( metrics == NULL ) 289 { 290 /* create the global metrics object if necessary */ 291 FT_Memory memory = globals->face->memory; 292 293 294 if ( FT_ALLOC( metrics, writing_system_class->script_metrics_size ) ) 295 goto Exit; 296 297 metrics->script_class = script_class; 298 metrics->globals = globals; 299 300 if ( writing_system_class->script_metrics_init ) 301 { 302 error = writing_system_class->script_metrics_init( metrics, 303 globals->face ); 304 if ( error ) 305 { 306 if ( writing_system_class->script_metrics_done ) 307 writing_system_class->script_metrics_done( metrics ); 308 309 FT_FREE( metrics ); 310 goto Exit; 311 } 312 } 313 314 globals->metrics[script] = metrics; 315 } 316 317 Exit: 318 *ametrics = metrics; 319 320 return error; 321 } 322 323 324 FT_LOCAL_DEF( FT_Bool ) 325 af_face_globals_is_digit( AF_FaceGlobals globals, 326 FT_UInt gindex ) 327 { 328 if ( gindex < (FT_ULong)globals->glyph_count ) 329 return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT ); 330 331 return (FT_Bool)0; 332 } 333 334 335/* END */ 336