3 /* originally file `afglobal.c' (2011-Mar-28) from FreeType */
5 /* heavily modified 2011 by Werner Lemberg <wl@gnu.org> */
18 #ifdef FT_OPTION_AUTOFIT2
23 /* populate this list when you add new scripts */
24 static TA_ScriptClass
const ta_script_classes
[] =
26 &ta_dummy_script_class
,
27 #ifdef FT_OPTION_AUTOFIT2
28 &ta_latin2_script_class
,
30 &ta_latin_script_class
,
33 &ta_indic_script_class
,
35 NULL
/* do not remove */
39 /* XXX index of default script in `ta_script_classes' */
40 #define TA_SCRIPT_LIST_DEFAULT 0
41 /* a bit mask indicating an uncovered glyph */
42 #define TA_SCRIPT_LIST_NONE 0x7F
43 /* if this flag is set, we have an ASCII digit */
47 /* note that glyph_scripts[] is used to map each glyph into */
48 /* an index into the `ta_script_classes' array. */
49 typedef struct TA_FaceGlobalsRec_
52 FT_Long glyph_count
; /* same as face->num_glyphs */
53 FT_Byte
* glyph_scripts
;
55 TA_ScriptMetrics metrics
[TA_SCRIPT_MAX
];
59 /* Compute the script index of each glyph within a given face. */
62 ta_face_globals_compute_script_coverage(TA_FaceGlobals globals
)
64 FT_Error error
= FT_Err_Ok
;
65 FT_Face face
= globals
->face
;
66 FT_CharMap old_charmap
= face
->charmap
;
67 FT_Byte
* gscripts
= globals
->glyph_scripts
;
72 /* the value TA_SCRIPT_LIST_NONE means `uncovered glyph' */
73 memset(globals
->glyph_scripts
, TA_SCRIPT_LIST_NONE
, globals
->glyph_count
);
75 error
= FT_Select_Charmap(face
, FT_ENCODING_UNICODE
);
78 /* ignore this error; we simply use the default script */
79 /* XXX: Shouldn't we rather disable hinting? */
84 /* scan each script in a Unicode charmap */
85 for (ss
= 0; ta_script_classes
[ss
]; ss
++)
87 TA_ScriptClass clazz
= ta_script_classes
[ss
];
88 TA_Script_UniRange range
;
91 if (clazz
->script_uni_ranges
== NULL
)
94 /* scan all Unicode points in the range and */
95 /* set the corresponding glyph script index */
96 for (range
= clazz
->script_uni_ranges
; range
->first
!= 0; range
++)
98 FT_ULong charcode
= range
->first
;
102 gindex
= FT_Get_Char_Index(face
, charcode
);
105 && gindex
< (FT_ULong
)globals
->glyph_count
106 && gscripts
[gindex
] == TA_SCRIPT_LIST_NONE
)
107 gscripts
[gindex
] = (FT_Byte
)ss
;
111 charcode
= FT_Get_Next_Char(face
, charcode
, &gindex
);
113 if (gindex
== 0 || charcode
> range
->last
)
116 if (gindex
< (FT_ULong
)globals
->glyph_count
117 && gscripts
[gindex
] == TA_SCRIPT_LIST_NONE
)
118 gscripts
[gindex
] = (FT_Byte
)ss
;
123 /* mark ASCII digits */
124 for (i
= 0x30; i
<= 0x39; i
++)
126 FT_UInt gindex
= FT_Get_Char_Index(face
, i
);
130 && gindex
< (FT_ULong
)globals
->glyph_count
)
131 gscripts
[gindex
] |= TA_DIGIT
;
135 /* by default, all uncovered glyphs are set to the latin script */
136 /* XXX: Shouldn't we disable hinting or do something similar? */
141 for (nn
= 0; nn
< globals
->glyph_count
; nn
++)
143 if ((gscripts
[nn
] & ~TA_DIGIT
) == TA_SCRIPT_LIST_NONE
)
145 gscripts
[nn
] &= ~TA_SCRIPT_LIST_NONE
;
146 gscripts
[nn
] |= TA_SCRIPT_LIST_DEFAULT
;
151 FT_Set_Charmap(face
, old_charmap
);
157 ta_face_globals_new(FT_Face face
,
158 TA_FaceGlobals
*aglobals
)
161 TA_FaceGlobals globals
;
164 globals
= (TA_FaceGlobals
)calloc(1, sizeof (TA_FaceGlobalsRec
) +
165 face
->num_glyphs
* sizeof (FT_Byte
));
168 error
= FT_Err_Out_Of_Memory
;
172 globals
->face
= face
;
173 globals
->glyph_count
= face
->num_glyphs
;
174 globals
->glyph_scripts
= (FT_Byte
*)(globals
+ 1);
176 error
= ta_face_globals_compute_script_coverage(globals
);
179 ta_face_globals_free(globals
);
190 ta_face_globals_free(TA_FaceGlobals globals
)
197 for (nn
= 0; nn
< TA_SCRIPT_MAX
; nn
++)
199 if (globals
->metrics
[nn
])
201 TA_ScriptClass clazz
= ta_script_classes
[nn
];
205 FT_ASSERT(globals
->metrics
[nn
]->clazz
== clazz
);
208 if (clazz
->script_metrics_done
)
209 clazz
->script_metrics_done(globals
->metrics
[nn
]);
211 free(globals
->metrics
[nn
]);
212 globals
->metrics
[nn
] = NULL
;
216 globals
->glyph_count
= 0;
217 globals
->glyph_scripts
= NULL
; /* no need to free this one! */
218 globals
->face
= NULL
;
227 ta_face_globals_get_metrics(TA_FaceGlobals globals
,
230 TA_ScriptMetrics
*ametrics
)
232 TA_ScriptMetrics metrics
= NULL
;
234 TA_ScriptClass clazz
;
235 FT_UInt script
= options
& 15;
236 const FT_Offset script_max
= sizeof (ta_script_classes
)
237 / sizeof (ta_script_classes
[0]);
238 FT_Error error
= FT_Err_Ok
;
241 if (gindex
>= (FT_ULong
)globals
->glyph_count
)
243 error
= FT_Err_Invalid_Argument
;
249 || gidx
+ 1 >= script_max
)
250 gidx
= globals
->glyph_scripts
[gindex
] & TA_SCRIPT_LIST_NONE
;
252 clazz
= ta_script_classes
[gidx
];
254 script
= clazz
->script
;
256 metrics
= globals
->metrics
[clazz
->script
];
259 /* create the global metrics object if necessary */
260 metrics
= (TA_ScriptMetrics
)calloc(1, clazz
->script_metrics_size
);
263 error
= FT_Err_Out_Of_Memory
;
267 metrics
->clazz
= clazz
;
269 if (clazz
->script_metrics_init
)
271 error
= clazz
->script_metrics_init(metrics
, globals
->face
);
274 if (clazz
->script_metrics_done
)
275 clazz
->script_metrics_done(metrics
);
283 globals
->metrics
[clazz
->script
] = metrics
;
294 ta_face_globals_is_digit(TA_FaceGlobals globals
,
297 if (gindex
< (FT_ULong
)globals
->glyph_count
)
298 return (FT_Bool
)(globals
->glyph_scripts
[gindex
] & TA_DIGIT
);
303 /* end of taglobal.c */