4 * Copyright (C) 2011-2013 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
16 /* originally file `afglobal.c' (2011-Mar-28) from FreeType */
18 /* heavily modified 2011 by Werner Lemberg <wl@gnu.org> */
24 /* get writing system specific header files */
26 #define WRITING_SYSTEM(ws, WS) /* empty */
31 #define WRITING_SYSTEM(ws, WS) \
32 &ta_ ## ws ## _writing_system_class,
34 TA_WritingSystemClass
const ta_writing_system_classes
[] =
39 NULL
/* do not remove */
44 #define SCRIPT(s, S, d) \
45 &ta_ ## s ## _script_class,
47 TA_ScriptClass
const ta_script_classes
[] =
50 #include <ttfautohint-scripts.h>
52 NULL
/* do not remove */
59 #define SCRIPT(s, S, d) #s,
61 const char* ta_script_names
[] =
64 #include <ttfautohint-scripts.h>
71 /* Compute the script index of each glyph within a given face. */
74 ta_face_globals_compute_script_coverage(TA_FaceGlobals globals
)
77 FT_Face face
= globals
->face
;
78 FT_CharMap old_charmap
= face
->charmap
;
79 FT_Byte
* gscripts
= globals
->glyph_scripts
;
84 /* the value TA_SCRIPT_NONE means `uncovered glyph' */
85 memset(globals
->glyph_scripts
, TA_SCRIPT_NONE
, globals
->glyph_count
);
87 error
= FT_Select_Charmap(face
, FT_ENCODING_UNICODE
);
90 /* ignore this error; we simply use the fallback script */
91 /* XXX: Shouldn't we rather disable hinting? */
96 /* scan each script in a Unicode charmap */
97 for (ss
= 0; ta_script_classes
[ss
]; ss
++)
99 TA_ScriptClass script_class
= ta_script_classes
[ss
];
100 TA_Script_UniRange range
;
103 if (script_class
->script_uni_ranges
== NULL
)
106 /* scan all Unicode points in the range and */
107 /* set the corresponding glyph script index */
108 for (range
= script_class
->script_uni_ranges
; range
->first
!= 0; range
++)
110 FT_ULong charcode
= range
->first
;
114 gindex
= FT_Get_Char_Index(face
, charcode
);
117 && gindex
< (FT_ULong
)globals
->glyph_count
118 && gscripts
[gindex
] == TA_SCRIPT_NONE
)
119 gscripts
[gindex
] = (FT_Byte
)ss
;
123 charcode
= FT_Get_Next_Char(face
, charcode
, &gindex
);
125 if (gindex
== 0 || charcode
> range
->last
)
128 if (gindex
< (FT_ULong
)globals
->glyph_count
129 && gscripts
[gindex
] == TA_SCRIPT_NONE
)
130 gscripts
[gindex
] = (FT_Byte
)ss
;
135 /* mark ASCII digits */
136 for (i
= 0x30; i
<= 0x39; i
++)
138 FT_UInt gindex
= FT_Get_Char_Index(face
, i
);
142 && gindex
< (FT_ULong
)globals
->glyph_count
)
143 gscripts
[gindex
] |= TA_DIGIT
;
147 /* by default, all uncovered glyphs are set to the fallback script */
148 /* XXX: Shouldn't we disable hinting or do something similar? */
149 if (globals
->font
->fallback_script
!= TA_SCRIPT_NONE
)
154 for (nn
= 0; nn
< globals
->glyph_count
; nn
++)
156 if ((gscripts
[nn
] & ~TA_DIGIT
) == TA_SCRIPT_NONE
)
158 gscripts
[nn
] &= ~TA_SCRIPT_NONE
;
159 gscripts
[nn
] |= globals
->font
->fallback_script
;
164 FT_Set_Charmap(face
, old_charmap
);
170 ta_face_globals_new(FT_Face face
,
171 TA_FaceGlobals
*aglobals
,
175 TA_FaceGlobals globals
;
178 globals
= (TA_FaceGlobals
)calloc(1, sizeof (TA_FaceGlobalsRec
) +
179 face
->num_glyphs
* sizeof (FT_Byte
));
182 error
= FT_Err_Out_Of_Memory
;
186 globals
->face
= face
;
187 globals
->glyph_count
= face
->num_glyphs
;
188 globals
->glyph_scripts
= (FT_Byte
*)(globals
+ 1);
189 globals
->font
= font
;
191 error
= ta_face_globals_compute_script_coverage(globals
);
194 ta_face_globals_free(globals
);
198 globals
->increase_x_height
= TA_PROP_INCREASE_X_HEIGHT_MAX
;
207 ta_face_globals_free(TA_FaceGlobals globals
)
214 for (nn
= 0; nn
< TA_SCRIPT_MAX
; nn
++)
216 if (globals
->metrics
[nn
])
218 TA_ScriptClass script_class
=
219 ta_script_classes
[nn
];
220 TA_WritingSystemClass writing_system_class
=
221 ta_writing_system_classes
[script_class
->writing_system
];
224 if (writing_system_class
->script_metrics_done
)
225 writing_system_class
->script_metrics_done(globals
->metrics
[nn
]);
227 free(globals
->metrics
[nn
]);
228 globals
->metrics
[nn
] = NULL
;
232 globals
->glyph_count
= 0;
233 globals
->glyph_scripts
= NULL
; /* no need to free this one! */
234 globals
->face
= NULL
;
243 ta_face_globals_get_metrics(TA_FaceGlobals globals
,
246 TA_ScriptMetrics
*ametrics
)
248 TA_ScriptMetrics metrics
= NULL
;
249 TA_Script script
= (TA_Script
)(options
& 15);
250 TA_ScriptClass script_class
;
251 TA_WritingSystemClass writing_system_class
;
252 FT_Error error
= FT_Err_Ok
;
255 if (gindex
>= (FT_ULong
)globals
->glyph_count
)
257 error
= FT_Err_Invalid_Argument
;
261 /* if we have a forced script (via `options'), use it, */
262 /* otherwise look into `glyph_scripts' array */
263 if (script
== TA_SCRIPT_DFLT
|| script
+ 1 >= TA_SCRIPT_MAX
)
264 script
= (TA_Script
)(globals
->glyph_scripts
[gindex
] & TA_SCRIPT_NONE
);
267 ta_script_classes
[script
];
268 writing_system_class
=
269 ta_writing_system_classes
[script_class
->writing_system
];
271 metrics
= globals
->metrics
[script
];
274 /* create the global metrics object if necessary */
275 metrics
= (TA_ScriptMetrics
)
276 calloc(1, writing_system_class
->script_metrics_size
);
279 error
= FT_Err_Out_Of_Memory
;
283 metrics
->script_class
= script_class
;
284 metrics
->globals
= globals
;
286 if (writing_system_class
->script_metrics_init
)
288 error
= writing_system_class
->script_metrics_init(metrics
,
292 if (writing_system_class
->script_metrics_done
)
293 writing_system_class
->script_metrics_done(metrics
);
301 globals
->metrics
[script
] = metrics
;
312 ta_face_globals_is_digit(TA_FaceGlobals globals
,
315 if (gindex
< (FT_ULong
)globals
->glyph_count
)
316 return (FT_Bool
)(globals
->glyph_scripts
[gindex
] & TA_DIGIT
);
321 /* end of taglobal.c */