1 /***************************************************************************/
5 /* Auto-fitter routines to compute global hinting values (body). */
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 /***************************************************************************/
28 #ifdef FT_OPTION_AUTOFIT2
32 #ifndef FT_CONFIG_OPTION_PIC
34 /* when updating this table, don't forget to update
35 AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
37 /* populate this list when you add new scripts */
38 static AF_ScriptClass
const af_script_classes
[] =
40 &af_dummy_script_class
,
41 #ifdef FT_OPTION_AUTOFIT2
42 &af_latin2_script_class
,
44 &af_latin_script_class
,
46 &af_indic_script_class
,
47 NULL
/* do not remove */
50 #endif /* FT_CONFIG_OPTION_PIC */
52 /* index of default script in `af_script_classes' */
53 #define AF_SCRIPT_LIST_DEFAULT 2
54 /* a bit mask indicating an uncovered glyph */
55 #define AF_SCRIPT_LIST_NONE 0x7F
56 /* if this flag is set, we have an ASCII digit */
61 * Note that glyph_scripts[] is used to map each glyph into
62 * an index into the `af_script_classes' array.
65 typedef struct AF_FaceGlobalsRec_
68 FT_Long glyph_count
; /* same as face->num_glyphs */
69 FT_Byte
* glyph_scripts
;
71 AF_ScriptMetrics metrics
[AF_SCRIPT_MAX
];
76 /* Compute the script index of each glyph within a given face. */
79 af_face_globals_compute_script_coverage( AF_FaceGlobals globals
)
81 FT_Error error
= AF_Err_Ok
;
82 FT_Face face
= globals
->face
;
83 FT_CharMap old_charmap
= face
->charmap
;
84 FT_Byte
* gscripts
= globals
->glyph_scripts
;
88 /* the value 255 means `uncovered glyph' */
89 FT_MEM_SET( globals
->glyph_scripts
,
91 globals
->glyph_count
);
93 error
= FT_Select_Charmap( face
, FT_ENCODING_UNICODE
);
97 * Ignore this error; we simply use the default script.
98 * XXX: Shouldn't we rather disable hinting?
104 /* scan each script in a Unicode charmap */
105 for ( ss
= 0; AF_SCRIPT_CLASSES_GET
[ss
]; ss
++ )
107 AF_ScriptClass clazz
= AF_SCRIPT_CLASSES_GET
[ss
];
108 AF_Script_UniRange range
;
111 if ( clazz
->script_uni_ranges
== NULL
)
115 * Scan all unicode points in the range and set the corresponding
116 * glyph script index.
118 for ( range
= clazz
->script_uni_ranges
; range
->first
!= 0; range
++ )
120 FT_ULong charcode
= range
->first
;
124 gindex
= FT_Get_Char_Index( face
, charcode
);
127 gindex
< (FT_ULong
)globals
->glyph_count
&&
128 gscripts
[gindex
] == AF_SCRIPT_LIST_NONE
)
130 gscripts
[gindex
] = (FT_Byte
)ss
;
135 charcode
= FT_Get_Next_Char( face
, charcode
, &gindex
);
137 if ( gindex
== 0 || charcode
> range
->last
)
140 if ( gindex
< (FT_ULong
)globals
->glyph_count
&&
141 gscripts
[gindex
] == AF_SCRIPT_LIST_NONE
)
143 gscripts
[gindex
] = (FT_Byte
)ss
;
149 /* mark ASCII digits */
150 for ( i
= 0x30; i
<= 0x39; i
++ )
152 FT_UInt gindex
= FT_Get_Char_Index( face
, i
);
155 if ( gindex
!= 0 && gindex
< (FT_ULong
)globals
->glyph_count
)
156 gscripts
[gindex
] |= AF_DIGIT
;
161 * By default, all uncovered glyphs are set to the latin script.
162 * XXX: Shouldn't we disable hinting or do something similar?
168 for ( nn
= 0; nn
< globals
->glyph_count
; nn
++ )
170 if ( gscripts
[nn
] == AF_SCRIPT_LIST_NONE
)
171 gscripts
[nn
] = AF_SCRIPT_LIST_DEFAULT
;
175 FT_Set_Charmap( face
, old_charmap
);
180 FT_LOCAL_DEF( FT_Error
)
181 af_face_globals_new( FT_Face face
,
182 AF_FaceGlobals
*aglobals
)
186 AF_FaceGlobals globals
;
189 memory
= face
->memory
;
191 if ( !FT_ALLOC( globals
, sizeof ( *globals
) +
192 face
->num_glyphs
* sizeof ( FT_Byte
) ) )
194 globals
->face
= face
;
195 globals
->glyph_count
= face
->num_glyphs
;
196 globals
->glyph_scripts
= (FT_Byte
*)( globals
+ 1 );
198 error
= af_face_globals_compute_script_coverage( globals
);
201 af_face_globals_free( globals
);
212 af_face_globals_free( AF_FaceGlobals globals
)
216 FT_Memory memory
= globals
->face
->memory
;
220 for ( nn
= 0; nn
< AF_SCRIPT_MAX
; nn
++ )
222 if ( globals
->metrics
[nn
] )
224 AF_ScriptClass clazz
= AF_SCRIPT_CLASSES_GET
[nn
];
227 FT_ASSERT( globals
->metrics
[nn
]->clazz
== clazz
);
229 if ( clazz
->script_metrics_done
)
230 clazz
->script_metrics_done( globals
->metrics
[nn
] );
232 FT_FREE( globals
->metrics
[nn
] );
236 globals
->glyph_count
= 0;
237 globals
->glyph_scripts
= NULL
; /* no need to free this one! */
238 globals
->face
= NULL
;
245 FT_LOCAL_DEF( FT_Error
)
246 af_face_globals_get_metrics( AF_FaceGlobals globals
,
249 AF_ScriptMetrics
*ametrics
)
251 AF_ScriptMetrics metrics
= NULL
;
253 AF_ScriptClass clazz
;
254 FT_UInt script
= options
& 15;
255 const FT_Offset script_max
= sizeof ( AF_SCRIPT_CLASSES_GET
) /
256 sizeof ( AF_SCRIPT_CLASSES_GET
[0] );
257 FT_Error error
= AF_Err_Ok
;
260 if ( gindex
>= (FT_ULong
)globals
->glyph_count
)
262 error
= AF_Err_Invalid_Argument
;
267 if ( gidx
== 0 || gidx
+ 1 >= script_max
)
268 gidx
= globals
->glyph_scripts
[gindex
] & AF_SCRIPT_LIST_NONE
;
270 clazz
= AF_SCRIPT_CLASSES_GET
[gidx
];
272 script
= clazz
->script
;
274 metrics
= globals
->metrics
[clazz
->script
];
275 if ( metrics
== NULL
)
277 /* create the global metrics object when needed */
278 FT_Memory memory
= globals
->face
->memory
;
281 if ( FT_ALLOC( metrics
, clazz
->script_metrics_size
) )
284 metrics
->clazz
= clazz
;
286 if ( clazz
->script_metrics_init
)
288 error
= clazz
->script_metrics_init( metrics
, globals
->face
);
291 if ( clazz
->script_metrics_done
)
292 clazz
->script_metrics_done( metrics
);
299 globals
->metrics
[clazz
->script
] = metrics
;
309 FT_LOCAL_DEF( FT_Bool
)
310 af_face_globals_is_digit( AF_FaceGlobals globals
,
313 if ( gindex
< (FT_ULong
)globals
->glyph_count
)
314 return (FT_Bool
)( globals
->glyph_scripts
[gindex
] & AF_DIGIT
);