"Fossies" - the Fresh Open Source Software Archive 
Member "SDL2_ttf-2.20.2/external/freetype/src/autofit/afglobal.c" (25 May 2022, 13819 Bytes) of package /linux/misc/SDL2_ttf-2.20.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "afglobal.c" see the
Fossies "Dox" file reference documentation.
1 /****************************************************************************
2 *
3 * afglobal.c
4 *
5 * Auto-fitter routines to compute global hinting values (body).
6 *
7 * Copyright (C) 2003-2022 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
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.
15 *
16 */
17
18
19 #include "afglobal.h"
20 #include "afranges.h"
21 #include "afshaper.h"
22 #include "afws-decl.h"
23 #include <freetype/internal/ftdebug.h>
24
25
26 /**************************************************************************
27 *
28 * The macro FT_COMPONENT is used in trace mode. It is an implicit
29 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
30 * messages during execution.
31 */
32 #undef FT_COMPONENT
33 #define FT_COMPONENT afglobal
34
35
36 #include "aferrors.h"
37
38
39 #undef SCRIPT
40 #define SCRIPT( s, S, d, h, H, ss ) \
41 AF_DEFINE_SCRIPT_CLASS( \
42 af_ ## s ## _script_class, \
43 AF_SCRIPT_ ## S, \
44 af_ ## s ## _uniranges, \
45 af_ ## s ## _nonbase_uniranges, \
46 AF_ ## H, \
47 ss )
48
49 #include "afscript.h"
50
51
52 #undef STYLE
53 #define STYLE( s, S, d, ws, sc, ss, c ) \
54 AF_DEFINE_STYLE_CLASS( \
55 af_ ## s ## _style_class, \
56 AF_STYLE_ ## S, \
57 ws, \
58 sc, \
59 ss, \
60 c )
61
62 #include "afstyles.h"
63
64
65 #undef WRITING_SYSTEM
66 #define WRITING_SYSTEM( ws, WS ) \
67 &af_ ## ws ## _writing_system_class,
68
69 FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass )
70 af_writing_system_classes[] =
71 {
72
73 #include "afws-iter.h"
74
75 NULL /* do not remove */
76 };
77
78
79 #undef SCRIPT
80 #define SCRIPT( s, S, d, h, H, ss ) \
81 &af_ ## s ## _script_class,
82
83 FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
84 af_script_classes[] =
85 {
86
87 #include "afscript.h"
88
89 NULL /* do not remove */
90 };
91
92
93 #undef STYLE
94 #define STYLE( s, S, d, ws, sc, ss, c ) \
95 &af_ ## s ## _style_class,
96
97 FT_LOCAL_ARRAY_DEF( AF_StyleClass )
98 af_style_classes[] =
99 {
100
101 #include "afstyles.h"
102
103 NULL /* do not remove */
104 };
105
106
107 #ifdef FT_DEBUG_LEVEL_TRACE
108
109 #undef STYLE
110 #define STYLE( s, S, d, ws, sc, ss, c ) #s,
111
112 FT_LOCAL_ARRAY_DEF( char* )
113 af_style_names[] =
114 {
115
116 #include "afstyles.h"
117
118 };
119
120 #endif /* FT_DEBUG_LEVEL_TRACE */
121
122
123 /* Compute the style index of each glyph within a given face. */
124
125 static FT_Error
126 af_face_globals_compute_style_coverage( AF_FaceGlobals globals )
127 {
128 FT_Error error;
129 FT_Face face = globals->face;
130 FT_CharMap old_charmap = face->charmap;
131 FT_UShort* gstyles = globals->glyph_styles;
132 FT_UInt ss;
133 FT_UInt i;
134 FT_UInt dflt = ~0U; /* a non-valid value */
135
136
137 /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
138 for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
139 gstyles[i] = AF_STYLE_UNASSIGNED;
140
141 error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
142 if ( error )
143 {
144 /*
145 * Ignore this error; we simply use the fallback style.
146 * XXX: Shouldn't we rather disable hinting?
147 */
148 error = FT_Err_Ok;
149 goto Exit;
150 }
151
152 /* scan each style in a Unicode charmap */
153 for ( ss = 0; af_style_classes[ss]; ss++ )
154 {
155 AF_StyleClass style_class =
156 af_style_classes[ss];
157 AF_ScriptClass script_class =
158 af_script_classes[style_class->script];
159 AF_Script_UniRange range;
160
161
162 if ( !script_class->script_uni_ranges )
163 continue;
164
165 /*
166 * Scan all Unicode points in the range and set the corresponding
167 * glyph style index.
168 */
169 if ( style_class->coverage == AF_COVERAGE_DEFAULT )
170 {
171 if ( (FT_UInt)style_class->script ==
172 globals->module->default_script )
173 dflt = ss;
174
175 for ( range = script_class->script_uni_ranges;
176 range->first != 0;
177 range++ )
178 {
179 FT_ULong charcode = range->first;
180 FT_UInt gindex;
181
182
183 gindex = FT_Get_Char_Index( face, charcode );
184
185 if ( gindex != 0 &&
186 gindex < (FT_ULong)globals->glyph_count &&
187 ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
188 gstyles[gindex] = (FT_UShort)ss;
189
190 for (;;)
191 {
192 charcode = FT_Get_Next_Char( face, charcode, &gindex );
193
194 if ( gindex == 0 || charcode > range->last )
195 break;
196
197 if ( gindex < (FT_ULong)globals->glyph_count &&
198 ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
199 gstyles[gindex] = (FT_UShort)ss;
200 }
201 }
202
203 /* do the same for the script's non-base characters */
204 for ( range = script_class->script_uni_nonbase_ranges;
205 range->first != 0;
206 range++ )
207 {
208 FT_ULong charcode = range->first;
209 FT_UInt gindex;
210
211
212 gindex = FT_Get_Char_Index( face, charcode );
213
214 if ( gindex != 0 &&
215 gindex < (FT_ULong)globals->glyph_count &&
216 ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
217 gstyles[gindex] |= AF_NONBASE;
218
219 for (;;)
220 {
221 charcode = FT_Get_Next_Char( face, charcode, &gindex );
222
223 if ( gindex == 0 || charcode > range->last )
224 break;
225
226 if ( gindex < (FT_ULong)globals->glyph_count &&
227 ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
228 gstyles[gindex] |= AF_NONBASE;
229 }
230 }
231 }
232 else
233 {
234 /* get glyphs not directly addressable by cmap */
235 af_shaper_get_coverage( globals, style_class, gstyles, 0 );
236 }
237 }
238
239 /* handle the remaining default OpenType features ... */
240 for ( ss = 0; af_style_classes[ss]; ss++ )
241 {
242 AF_StyleClass style_class = af_style_classes[ss];
243
244
245 if ( style_class->coverage == AF_COVERAGE_DEFAULT )
246 af_shaper_get_coverage( globals, style_class, gstyles, 0 );
247 }
248
249 /* ... and finally the default OpenType features of the default script */
250 af_shaper_get_coverage( globals, af_style_classes[dflt], gstyles, 1 );
251
252 /* mark ASCII digits */
253 for ( i = 0x30; i <= 0x39; i++ )
254 {
255 FT_UInt gindex = FT_Get_Char_Index( face, i );
256
257
258 if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
259 gstyles[gindex] |= AF_DIGIT;
260 }
261
262 Exit:
263 /*
264 * By default, all uncovered glyphs are set to the fallback style.
265 * XXX: Shouldn't we disable hinting or do something similar?
266 */
267 if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
268 {
269 FT_Long nn;
270
271
272 for ( nn = 0; nn < globals->glyph_count; nn++ )
273 {
274 if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
275 {
276 gstyles[nn] &= ~AF_STYLE_MASK;
277 gstyles[nn] |= globals->module->fallback_style;
278 }
279 }
280 }
281
282 #ifdef FT_DEBUG_LEVEL_TRACE
283
284 FT_TRACE4(( "\n" ));
285 FT_TRACE4(( "style coverage\n" ));
286 FT_TRACE4(( "==============\n" ));
287 FT_TRACE4(( "\n" ));
288
289 for ( ss = 0; af_style_classes[ss]; ss++ )
290 {
291 AF_StyleClass style_class = af_style_classes[ss];
292 FT_UInt count = 0;
293 FT_Long idx;
294
295
296 FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));
297
298 for ( idx = 0; idx < globals->glyph_count; idx++ )
299 {
300 if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
301 {
302 if ( !( count % 10 ) )
303 FT_TRACE4(( " " ));
304
305 FT_TRACE4(( " %ld", idx ));
306 count++;
307
308 if ( !( count % 10 ) )
309 FT_TRACE4(( "\n" ));
310 }
311 }
312
313 if ( !count )
314 FT_TRACE4(( " (none)\n" ));
315 if ( count % 10 )
316 FT_TRACE4(( "\n" ));
317 }
318
319 #endif /* FT_DEBUG_LEVEL_TRACE */
320
321 FT_Set_Charmap( face, old_charmap );
322 return error;
323 }
324
325
326 FT_LOCAL_DEF( FT_Error )
327 af_face_globals_new( FT_Face face,
328 AF_FaceGlobals *aglobals,
329 AF_Module module )
330 {
331 FT_Error error;
332 FT_Memory memory;
333 AF_FaceGlobals globals = NULL;
334
335
336 memory = face->memory;
337
338 /* we allocate an AF_FaceGlobals structure together */
339 /* with the glyph_styles array */
340 if ( FT_QALLOC( globals,
341 sizeof ( *globals ) +
342 (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
343 goto Exit;
344
345 FT_ZERO( &globals->metrics );
346
347 globals->face = face;
348 globals->glyph_count = face->num_glyphs;
349 /* right after the globals structure come the glyph styles */
350 globals->glyph_styles = (FT_UShort*)( globals + 1 );
351 globals->module = module;
352 globals->stem_darkening_for_ppem = 0;
353 globals->darken_x = 0;
354 globals->darken_y = 0;
355 globals->standard_vertical_width = 0;
356 globals->standard_horizontal_width = 0;
357 globals->scale_down_factor = 0;
358
359 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
360 globals->hb_font = hb_ft_font_create( face, NULL );
361 globals->hb_buf = hb_buffer_create();
362 #endif
363
364 error = af_face_globals_compute_style_coverage( globals );
365 if ( error )
366 {
367 af_face_globals_free( globals );
368 globals = NULL;
369 }
370 else
371 globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
372
373 Exit:
374 *aglobals = globals;
375 return error;
376 }
377
378
379 FT_LOCAL_DEF( void )
380 af_face_globals_free( AF_FaceGlobals globals )
381 {
382 if ( globals )
383 {
384 FT_Memory memory = globals->face->memory;
385 FT_UInt nn;
386
387
388 for ( nn = 0; nn < AF_STYLE_MAX; nn++ )
389 {
390 if ( globals->metrics[nn] )
391 {
392 AF_StyleClass style_class =
393 af_style_classes[nn];
394 AF_WritingSystemClass writing_system_class =
395 af_writing_system_classes[style_class->writing_system];
396
397
398 if ( writing_system_class->style_metrics_done )
399 writing_system_class->style_metrics_done( globals->metrics[nn] );
400
401 FT_FREE( globals->metrics[nn] );
402 }
403 }
404
405 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
406 hb_font_destroy( globals->hb_font );
407 hb_buffer_destroy( globals->hb_buf );
408 #endif
409
410 /* no need to free `globals->glyph_styles'; */
411 /* it is part of the `globals' array */
412 FT_FREE( globals );
413 }
414 }
415
416
417 FT_LOCAL_DEF( FT_Error )
418 af_face_globals_get_metrics( AF_FaceGlobals globals,
419 FT_UInt gindex,
420 FT_UInt options,
421 AF_StyleMetrics *ametrics )
422 {
423 AF_StyleMetrics metrics = NULL;
424
425 AF_Style style = (AF_Style)options;
426 AF_WritingSystemClass writing_system_class;
427 AF_StyleClass style_class;
428
429 FT_Error error = FT_Err_Ok;
430
431
432 if ( gindex >= (FT_ULong)globals->glyph_count )
433 {
434 error = FT_THROW( Invalid_Argument );
435 goto Exit;
436 }
437
438 /* if we have a forced style (via `options'), use it, */
439 /* otherwise look into `glyph_styles' array */
440 if ( style == AF_STYLE_NONE_DFLT || style + 1 >= AF_STYLE_MAX )
441 style = (AF_Style)( globals->glyph_styles[gindex] &
442 AF_STYLE_UNASSIGNED );
443
444 Again:
445 style_class = af_style_classes[style];
446 writing_system_class = af_writing_system_classes
447 [style_class->writing_system];
448
449 metrics = globals->metrics[style];
450 if ( !metrics )
451 {
452 /* create the global metrics object if necessary */
453 FT_Memory memory = globals->face->memory;
454
455
456 if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) )
457 goto Exit;
458
459 metrics->style_class = style_class;
460 metrics->globals = globals;
461
462 if ( writing_system_class->style_metrics_init )
463 {
464 error = writing_system_class->style_metrics_init( metrics,
465 globals->face );
466 if ( error )
467 {
468 if ( writing_system_class->style_metrics_done )
469 writing_system_class->style_metrics_done( metrics );
470
471 FT_FREE( metrics );
472
473 /* internal error code -1 indicates */
474 /* that no blue zones have been found */
475 if ( error == -1 )
476 {
477 style = (AF_Style)( globals->glyph_styles[gindex] &
478 AF_STYLE_UNASSIGNED );
479 /* IMPORTANT: Clear the error code, see
480 * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
481 */
482 error = FT_Err_Ok;
483 goto Again;
484 }
485
486 goto Exit;
487 }
488 }
489
490 globals->metrics[style] = metrics;
491 }
492
493 Exit:
494 *ametrics = metrics;
495
496 return error;
497 }
498
499
500 FT_LOCAL_DEF( FT_Bool )
501 af_face_globals_is_digit( AF_FaceGlobals globals,
502 FT_UInt gindex )
503 {
504 if ( gindex < (FT_ULong)globals->glyph_count )
505 return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );
506
507 return FT_BOOL( 0 );
508 }
509
510
511 /* END */