4 * Copyright (C) 2011-2014 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 #include "taharfbuzz.h"
28 #define SCRIPT(s, S, d, h, dc) \
29 const TA_ScriptClassRec ta_ ## s ## _script_class = \
32 ta_ ## s ## _uniranges, \
36 #include <ttfautohint-scripts.h>
40 #define STYLE(s, S, d, ws, sc, ss, c) \
41 const TA_StyleClassRec ta_ ## s ## _style_class = \
53 /* get writing system specific header files */
55 #define WRITING_SYSTEM(ws, WS) /* empty */
60 #define WRITING_SYSTEM(ws, WS) \
61 &ta_ ## ws ## _writing_system_class,
63 TA_WritingSystemClass
const ta_writing_system_classes
[] =
68 NULL
/* do not remove */
73 #define SCRIPT(s, S, d, h, dc) \
74 &ta_ ## s ## _script_class,
76 TA_ScriptClass
const ta_script_classes
[] =
79 #include <ttfautohint-scripts.h>
81 NULL
/* do not remove */
86 #define STYLE(s, S, d, ws, sc, ss, c) \
87 &ta_ ## s ## _style_class,
89 TA_StyleClass
const ta_style_classes
[] =
94 NULL
/* do not remove */
101 #define STYLE(s, S, d, ws, sc, ss, c) #s,
103 const char* ta_style_names
[] =
106 #include <tastyles.h>
110 #endif /* TA_DEBUG */
113 /* Compute the style index of each glyph within a given face. */
116 ta_face_globals_compute_style_coverage(TA_FaceGlobals globals
)
119 FT_Face face
= globals
->face
;
120 FT_CharMap old_charmap
= face
->charmap
;
121 FT_Byte
* gstyles
= globals
->glyph_styles
;
127 /* the value TA_STYLE_UNASSIGNED means `uncovered glyph' */
128 memset(globals
->glyph_styles
, TA_STYLE_UNASSIGNED
, globals
->glyph_count
);
130 error
= FT_Select_Charmap(face
, FT_ENCODING_UNICODE
);
133 /* ignore this error; we simply use the fallback style */
134 /* XXX: Shouldn't we rather disable hinting? */
139 /* scan each style in a Unicode charmap */
140 for (ss
= 0; ta_style_classes
[ss
]; ss
++)
142 TA_StyleClass style_class
= ta_style_classes
[ss
];
143 TA_ScriptClass script_class
= ta_script_classes
[style_class
->script
];
144 TA_Script_UniRange range
;
147 if (script_class
->script_uni_ranges
== NULL
)
150 /* scan all Unicode points in the range and */
151 /* set the corresponding glyph style index */
152 if (style_class
->coverage
== TA_COVERAGE_DEFAULT
)
154 if (style_class
->script
== globals
->font
->default_script
)
157 for (range
= script_class
->script_uni_ranges
; range
->first
!= 0; range
++)
159 FT_ULong charcode
= range
->first
;
163 gindex
= FT_Get_Char_Index(face
, charcode
);
166 && gindex
< (FT_ULong
)globals
->glyph_count
167 && gstyles
[gindex
] == TA_STYLE_UNASSIGNED
)
168 gstyles
[gindex
] = (FT_Byte
)ss
;
172 charcode
= FT_Get_Next_Char(face
, charcode
, &gindex
);
174 if (gindex
== 0 || charcode
> range
->last
)
177 if (gindex
< (FT_ULong
)globals
->glyph_count
178 && gstyles
[gindex
] == TA_STYLE_UNASSIGNED
)
179 gstyles
[gindex
] = (FT_Byte
)ss
;
185 /* get glyphs not directly addressable by cmap */
186 ta_get_coverage(globals
, style_class
, gstyles
);
190 /* handle the default OpenType features of the default script ... */
191 ta_get_coverage(globals
, ta_style_classes
[dflt
], gstyles
);
193 /* ... and the remaining default OpenType features */
194 for (ss
= 0; ta_style_classes
[ss
]; ss
++)
196 TA_StyleClass style_class
= ta_style_classes
[ss
];
199 if (ss
!= dflt
&& style_class
->coverage
== TA_COVERAGE_DEFAULT
)
200 ta_get_coverage(globals
, style_class
, gstyles
);
203 /* mark ASCII digits */
204 for (i
= 0x30; i
<= 0x39; i
++)
206 FT_UInt gindex
= FT_Get_Char_Index(face
, i
);
210 && gindex
< (FT_ULong
)globals
->glyph_count
)
211 gstyles
[gindex
] |= TA_DIGIT
;
215 /* by default, all uncovered glyphs are set to the fallback style */
216 /* XXX: Shouldn't we disable hinting or do something similar? */
217 if (globals
->font
->fallback_style
!= TA_STYLE_UNASSIGNED
)
222 for (nn
= 0; nn
< globals
->glyph_count
; nn
++)
224 if ((gstyles
[nn
] & ~TA_DIGIT
) == TA_STYLE_UNASSIGNED
)
226 gstyles
[nn
] &= ~TA_STYLE_UNASSIGNED
;
227 gstyles
[nn
] |= globals
->font
->fallback_style
;
239 for (ss
= 0; ta_style_classes
[ss
]; ss
++)
241 TA_StyleClass style_class
= ta_style_classes
[ss
];
246 TA_LOG_GLOBAL(("%s:\n", ta_style_names
[style_class
->style
]));
248 for (idx
= 0; idx
< globals
->glyph_count
; idx
++)
250 if ((gstyles
[idx
] & ~TA_DIGIT
) == style_class
->style
)
253 TA_LOG_GLOBAL((" "));
255 TA_LOG_GLOBAL((" %d", idx
));
259 TA_LOG_GLOBAL(("\n"));
264 TA_LOG_GLOBAL((" (none)\n"));
266 TA_LOG_GLOBAL(("\n"));
269 #endif /* TA_DEBUG */
271 FT_Set_Charmap(face
, old_charmap
);
277 ta_face_globals_new(FT_Face face
,
278 TA_FaceGlobals
*aglobals
,
282 TA_FaceGlobals globals
;
285 globals
= (TA_FaceGlobals
)calloc(1, sizeof (TA_FaceGlobalsRec
) +
286 face
->num_glyphs
* sizeof (FT_Byte
));
289 error
= FT_Err_Out_Of_Memory
;
293 globals
->face
= face
;
294 globals
->glyph_count
= face
->num_glyphs
;
295 globals
->glyph_styles
= (FT_Byte
*)(globals
+ 1);
296 globals
->font
= font
;
297 globals
->hb_font
= hb_ft_font_create(face
, NULL
);
299 error
= ta_face_globals_compute_style_coverage(globals
);
302 ta_face_globals_free(globals
);
306 globals
->increase_x_height
= TA_PROP_INCREASE_X_HEIGHT_MAX
;
315 ta_face_globals_free(TA_FaceGlobals globals
)
322 for (nn
= 0; nn
< TA_STYLE_MAX
; nn
++)
324 if (globals
->metrics
[nn
])
326 TA_StyleClass style_class
=
327 ta_style_classes
[nn
];
328 TA_WritingSystemClass writing_system_class
=
329 ta_writing_system_classes
[style_class
->writing_system
];
332 if (writing_system_class
->style_metrics_done
)
333 writing_system_class
->style_metrics_done(globals
->metrics
[nn
]);
335 free(globals
->metrics
[nn
]);
336 globals
->metrics
[nn
] = NULL
;
340 hb_font_destroy(globals
->hb_font
);
342 globals
->hb_font
= NULL
;
343 globals
->glyph_count
= 0;
344 globals
->glyph_styles
= NULL
; /* no need to free this one! */
345 globals
->face
= NULL
;
354 ta_face_globals_get_metrics(TA_FaceGlobals globals
,
357 TA_StyleMetrics
*ametrics
)
359 TA_StyleMetrics metrics
= NULL
;
360 TA_Style style
= (TA_Style
)options
;
361 TA_WritingSystemClass writing_system_class
;
362 TA_StyleClass style_class
;
363 FT_Error error
= FT_Err_Ok
;
366 if (gindex
>= (FT_ULong
)globals
->glyph_count
)
368 error
= FT_Err_Invalid_Argument
;
372 /* if we have a forced style (via `options'), use it, */
373 /* otherwise look into `glyph_styles' array */
374 if (style
== TA_STYLE_NONE_DFLT
|| style
+ 1 >= TA_STYLE_MAX
)
375 style
= (TA_Style
)(globals
->glyph_styles
[gindex
]
376 & TA_STYLE_UNASSIGNED
);
379 ta_style_classes
[style
];
380 writing_system_class
=
381 ta_writing_system_classes
[style_class
->writing_system
];
383 metrics
= globals
->metrics
[style
];
386 /* create the global metrics object if necessary */
387 metrics
= (TA_StyleMetrics
)
388 calloc(1, writing_system_class
->style_metrics_size
);
391 error
= FT_Err_Out_Of_Memory
;
395 metrics
->style_class
= style_class
;
396 metrics
->globals
= globals
;
398 if (writing_system_class
->style_metrics_init
)
400 error
= writing_system_class
->style_metrics_init(metrics
,
404 if (writing_system_class
->style_metrics_done
)
405 writing_system_class
->style_metrics_done(metrics
);
413 globals
->metrics
[style
] = metrics
;
424 ta_face_globals_is_digit(TA_FaceGlobals globals
,
427 if (gindex
< (FT_ULong
)globals
->glyph_count
)
428 return (FT_Bool
)(globals
->glyph_styles
[gindex
] & TA_DIGIT
);
433 /* end of taglobal.c */