1 /***************************************************************************/
5 /* Auto-fitter routines to compute global hinting values (body). */
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2008 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 /***************************************************************************/
27 #ifdef FT_OPTION_AUTOFIT2
31 /* populate this list when you add new scripts */
32 static AF_ScriptClass
const af_script_classes
[] =
34 &af_dummy_script_class
,
35 #ifdef FT_OPTION_AUTOFIT2
36 &af_latin2_script_class
,
38 &af_latin_script_class
,
40 &af_indic_script_class
,
41 NULL
/* do not remove */
44 /* index of default script in `af_script_classes' */
45 #define AF_SCRIPT_LIST_DEFAULT 2
46 /* indicates an uncovered glyph */
47 #define AF_SCRIPT_LIST_NONE 255
51 * Note that glyph_scripts[] is used to map each glyph into
52 * an index into the `af_script_classes' array.
55 typedef struct AF_FaceGlobalsRec_
58 FT_UInt glyph_count
; /* same as face->num_glyphs */
59 FT_Byte
* glyph_scripts
;
61 AF_ScriptMetrics metrics
[AF_SCRIPT_MAX
];
66 /* Compute the script index of each glyph within a given face. */
69 af_face_globals_compute_script_coverage( AF_FaceGlobals globals
)
71 FT_Error error
= AF_Err_Ok
;
72 FT_Face face
= globals
->face
;
73 FT_CharMap old_charmap
= face
->charmap
;
74 FT_Byte
* gscripts
= globals
->glyph_scripts
;
78 /* the value 255 means `uncovered glyph' */
79 FT_MEM_SET( globals
->glyph_scripts
,
81 globals
->glyph_count
);
83 error
= FT_Select_Charmap( face
, FT_ENCODING_UNICODE
);
87 * Ignore this error; we simply use the default script.
88 * XXX: Shouldn't we rather disable hinting?
94 /* scan each script in a Unicode charmap */
95 for ( ss
= 0; af_script_classes
[ss
]; ss
++ )
97 AF_ScriptClass clazz
= af_script_classes
[ss
];
98 AF_Script_UniRange range
;
101 if ( clazz
->script_uni_ranges
== NULL
)
105 * Scan all unicode points in the range and set the corresponding
106 * glyph script index.
108 for ( range
= clazz
->script_uni_ranges
; range
->first
!= 0; range
++ )
110 FT_ULong charcode
= range
->first
;
114 gindex
= FT_Get_Char_Index( face
, charcode
);
117 gindex
< globals
->glyph_count
&&
118 gscripts
[gindex
] == AF_SCRIPT_LIST_NONE
)
120 gscripts
[gindex
] = (FT_Byte
)ss
;
125 charcode
= FT_Get_Next_Char( face
, charcode
, &gindex
);
127 if ( gindex
== 0 || charcode
> range
->last
)
130 if ( gindex
< globals
->glyph_count
&&
131 gscripts
[gindex
] == AF_SCRIPT_LIST_NONE
)
133 gscripts
[gindex
] = (FT_Byte
)ss
;
141 * By default, all uncovered glyphs are set to the latin script.
142 * XXX: Shouldn't we disable hinting or do something similar?
148 for ( nn
= 0; nn
< globals
->glyph_count
; nn
++ )
150 if ( gscripts
[nn
] == AF_SCRIPT_LIST_NONE
)
151 gscripts
[nn
] = AF_SCRIPT_LIST_DEFAULT
;
155 FT_Set_Charmap( face
, old_charmap
);
160 FT_LOCAL_DEF( FT_Error
)
161 af_face_globals_new( FT_Face face
,
162 AF_FaceGlobals
*aglobals
)
166 AF_FaceGlobals globals
;
169 memory
= face
->memory
;
171 if ( !FT_ALLOC( globals
, sizeof ( *globals
) +
172 face
->num_glyphs
* sizeof ( FT_Byte
) ) )
174 globals
->face
= face
;
175 globals
->glyph_count
= face
->num_glyphs
;
176 globals
->glyph_scripts
= (FT_Byte
*)( globals
+ 1 );
178 error
= af_face_globals_compute_script_coverage( globals
);
181 af_face_globals_free( globals
);
192 af_face_globals_free( AF_FaceGlobals globals
)
196 FT_Memory memory
= globals
->face
->memory
;
200 for ( nn
= 0; nn
< AF_SCRIPT_MAX
; nn
++ )
202 if ( globals
->metrics
[nn
] )
204 AF_ScriptClass clazz
= af_script_classes
[nn
];
207 FT_ASSERT( globals
->metrics
[nn
]->clazz
== clazz
);
209 if ( clazz
->script_metrics_done
)
210 clazz
->script_metrics_done( globals
->metrics
[nn
] );
212 FT_FREE( globals
->metrics
[nn
] );
216 globals
->glyph_count
= 0;
217 globals
->glyph_scripts
= NULL
; /* no need to free this one! */
218 globals
->face
= NULL
;
225 FT_LOCAL_DEF( FT_Error
)
226 af_face_globals_get_metrics( AF_FaceGlobals globals
,
229 AF_ScriptMetrics
*ametrics
)
231 AF_ScriptMetrics metrics
= NULL
;
233 AF_ScriptClass clazz
;
234 FT_UInt script
= options
& 15;
235 const FT_UInt script_max
= sizeof ( af_script_classes
) /
236 sizeof ( af_script_classes
[0] );
237 FT_Error error
= AF_Err_Ok
;
240 if ( gindex
>= globals
->glyph_count
)
242 error
= AF_Err_Invalid_Argument
;
247 if ( gidx
== 0 || gidx
+ 1 >= script_max
)
248 gidx
= globals
->glyph_scripts
[gindex
];
250 clazz
= af_script_classes
[gidx
];
252 script
= clazz
->script
;
254 metrics
= globals
->metrics
[clazz
->script
];
255 if ( metrics
== NULL
)
257 /* create the global metrics object when needed */
258 FT_Memory memory
= globals
->face
->memory
;
261 if ( FT_ALLOC( metrics
, clazz
->script_metrics_size
) )
264 metrics
->clazz
= clazz
;
266 if ( clazz
->script_metrics_init
)
268 error
= clazz
->script_metrics_init( metrics
, globals
->face
);
271 if ( clazz
->script_metrics_done
)
272 clazz
->script_metrics_done( metrics
);
279 globals
->metrics
[clazz
->script
] = metrics
;