1 /***************************************************************************/
5 /* Auto-fitter routines to compute global hinting values (body). */
7 /* Copyright 2003-2013 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
21 /* get writing system specific header files */
23 #define WRITING_SYSTEM( ws, WS ) /* empty */
30 #ifndef FT_CONFIG_OPTION_PIC
33 #define WRITING_SYSTEM( ws, WS ) \
34 &af_ ## ws ## _writing_system_class,
36 FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass
)
37 af_writing_system_classes
[] =
42 NULL
/* do not remove */
47 #define SCRIPT( s, S, d ) \
48 &af_ ## s ## _script_class,
50 FT_LOCAL_ARRAY_DEF( AF_ScriptClass
)
56 NULL
/* do not remove */
59 #endif /* !FT_CONFIG_OPTION_PIC */
62 #ifdef FT_DEBUG_LEVEL_TRACE
65 #define SCRIPT( s, S, d ) #s,
67 FT_LOCAL_ARRAY_DEF( char* )
75 #endif /* FT_DEBUG_LEVEL_TRACE */
78 /* Compute the script index of each glyph within a given face. */
81 af_face_globals_compute_script_coverage( AF_FaceGlobals globals
)
84 FT_Face face
= globals
->face
;
85 FT_CharMap old_charmap
= face
->charmap
;
86 FT_Byte
* gscripts
= globals
->glyph_scripts
;
91 /* the value AF_SCRIPT_NONE means `uncovered glyph' */
92 FT_MEM_SET( globals
->glyph_scripts
,
94 globals
->glyph_count
);
96 error
= FT_Select_Charmap( face
, FT_ENCODING_UNICODE
);
100 * Ignore this error; we simply use the fallback script.
101 * XXX: Shouldn't we rather disable hinting?
107 /* scan each script in a Unicode charmap */
108 for ( ss
= 0; AF_SCRIPT_CLASSES_GET
[ss
]; ss
++ )
110 AF_ScriptClass script_class
= AF_SCRIPT_CLASSES_GET
[ss
];
111 AF_Script_UniRange range
;
114 if ( script_class
->script_uni_ranges
== NULL
)
118 * Scan all Unicode points in the range and set the corresponding
119 * glyph script index.
121 for ( range
= script_class
->script_uni_ranges
;
125 FT_ULong charcode
= range
->first
;
129 gindex
= FT_Get_Char_Index( face
, charcode
);
132 gindex
< (FT_ULong
)globals
->glyph_count
&&
133 gscripts
[gindex
] == AF_SCRIPT_NONE
)
134 gscripts
[gindex
] = (FT_Byte
)ss
;
138 charcode
= FT_Get_Next_Char( face
, charcode
, &gindex
);
140 if ( gindex
== 0 || charcode
> range
->last
)
143 if ( gindex
< (FT_ULong
)globals
->glyph_count
&&
144 gscripts
[gindex
] == AF_SCRIPT_NONE
)
145 gscripts
[gindex
] = (FT_Byte
)ss
;
150 /* mark ASCII digits */
151 for ( i
= 0x30; i
<= 0x39; i
++ )
153 FT_UInt gindex
= FT_Get_Char_Index( face
, i
);
156 if ( gindex
!= 0 && gindex
< (FT_ULong
)globals
->glyph_count
)
157 gscripts
[gindex
] |= AF_DIGIT
;
162 * By default, all uncovered glyphs are set to the fallback script.
163 * XXX: Shouldn't we disable hinting or do something similar?
165 if ( globals
->module
->fallback_script
!= AF_SCRIPT_NONE
)
170 for ( nn
= 0; nn
< globals
->glyph_count
; nn
++ )
172 if ( ( gscripts
[nn
] & ~AF_DIGIT
) == AF_SCRIPT_NONE
)
174 gscripts
[nn
] &= ~AF_SCRIPT_NONE
;
175 gscripts
[nn
] |= globals
->module
->fallback_script
;
180 FT_Set_Charmap( face
, old_charmap
);
185 FT_LOCAL_DEF( FT_Error
)
186 af_face_globals_new( FT_Face face
,
187 AF_FaceGlobals
*aglobals
,
192 AF_FaceGlobals globals
= NULL
;
195 memory
= face
->memory
;
197 if ( FT_ALLOC( globals
, sizeof ( *globals
) +
198 face
->num_glyphs
* sizeof ( FT_Byte
) ) )
201 globals
->face
= face
;
202 globals
->glyph_count
= face
->num_glyphs
;
203 globals
->glyph_scripts
= (FT_Byte
*)( globals
+ 1 );
204 globals
->module
= module
;
206 error
= af_face_globals_compute_script_coverage( globals
);
209 af_face_globals_free( globals
);
213 globals
->increase_x_height
= AF_PROP_INCREASE_X_HEIGHT_MAX
;
222 af_face_globals_free( AF_FaceGlobals globals
)
226 FT_Memory memory
= globals
->face
->memory
;
230 for ( nn
= 0; nn
< AF_SCRIPT_MAX
; nn
++ )
232 if ( globals
->metrics
[nn
] )
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
];
240 if ( writing_system_class
->script_metrics_done
)
241 writing_system_class
->script_metrics_done( globals
->metrics
[nn
] );
243 FT_FREE( globals
->metrics
[nn
] );
247 globals
->glyph_count
= 0;
248 globals
->glyph_scripts
= NULL
; /* no need to free this one! */
249 globals
->face
= NULL
;
256 FT_LOCAL_DEF( FT_Error
)
257 af_face_globals_get_metrics( AF_FaceGlobals globals
,
260 AF_ScriptMetrics
*ametrics
)
262 AF_ScriptMetrics metrics
= NULL
;
264 AF_Script script
= (AF_Script
)( options
& 15 );
265 AF_WritingSystemClass writing_system_class
;
266 AF_ScriptClass script_class
;
268 FT_Error error
= FT_Err_Ok
;
271 if ( gindex
>= (FT_ULong
)globals
->glyph_count
)
273 error
= FT_THROW( Invalid_Argument
);
277 /* if we have a forced script (via `options'), use it, */
278 /* otherwise look into `glyph_scripts' array */
279 if ( script
== AF_SCRIPT_DFLT
|| script
+ 1 >= AF_SCRIPT_MAX
)
280 script
= (AF_Script
)( globals
->glyph_scripts
[gindex
] & AF_SCRIPT_NONE
);
282 script_class
= AF_SCRIPT_CLASSES_GET
[script
];
283 writing_system_class
= AF_WRITING_SYSTEM_CLASSES_GET
284 [script_class
->writing_system
];
286 metrics
= globals
->metrics
[script
];
287 if ( metrics
== NULL
)
289 /* create the global metrics object if necessary */
290 FT_Memory memory
= globals
->face
->memory
;
293 if ( FT_ALLOC( metrics
, writing_system_class
->script_metrics_size
) )
296 metrics
->script_class
= script_class
;
297 metrics
->globals
= globals
;
299 if ( writing_system_class
->script_metrics_init
)
301 error
= writing_system_class
->script_metrics_init( metrics
,
305 if ( writing_system_class
->script_metrics_done
)
306 writing_system_class
->script_metrics_done( metrics
);
313 globals
->metrics
[script
] = metrics
;
323 FT_LOCAL_DEF( FT_Bool
)
324 af_face_globals_is_digit( AF_FaceGlobals globals
,
327 if ( gindex
< (FT_ULong
)globals
->glyph_count
)
328 return (FT_Bool
)( globals
->glyph_scripts
[gindex
] & AF_DIGIT
);