1 /***************************************************************************/
5 /* Auto-fitter routines to compute global hinting values (body). */
7 /* Copyright 2003-2014 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 /***************************************************************************/
22 #include FT_INTERNAL_DEBUG_H
25 /*************************************************************************/
27 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
28 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
29 /* messages during execution. */
32 #define FT_COMPONENT trace_afglobal
35 /* get writing system specific header files */
37 #define WRITING_SYSTEM( ws, WS ) /* empty */
45 #define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
46 AF_DEFINE_SCRIPT_CLASS( \
47 af_ ## s ## _script_class, \
49 af_ ## s ## _uniranges, \
56 #define STYLE( s, S, d, ws, sc, ss, c ) \
57 AF_DEFINE_STYLE_CLASS( \
58 af_ ## s ## _style_class, \
68 #ifndef FT_CONFIG_OPTION_PIC
71 #define WRITING_SYSTEM( ws, WS ) \
72 &af_ ## ws ## _writing_system_class,
74 FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass
)
75 af_writing_system_classes
[] =
80 NULL
/* do not remove */
85 #define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
86 &af_ ## s ## _script_class,
88 FT_LOCAL_ARRAY_DEF( AF_ScriptClass
)
94 NULL
/* do not remove */
99 #define STYLE( s, S, d, ws, sc, ss, c ) \
100 &af_ ## s ## _style_class,
102 FT_LOCAL_ARRAY_DEF( AF_StyleClass
)
106 #include "afstyles.h"
108 NULL
/* do not remove */
111 #endif /* !FT_CONFIG_OPTION_PIC */
114 #ifdef FT_DEBUG_LEVEL_TRACE
117 #define STYLE( s, S, d, ws, sc, ss, c ) #s,
119 FT_LOCAL_ARRAY_DEF( char* )
123 #include "afstyles.h"
127 #endif /* FT_DEBUG_LEVEL_TRACE */
130 /* Compute the style index of each glyph within a given face. */
133 af_face_globals_compute_style_coverage( AF_FaceGlobals globals
)
136 FT_Face face
= globals
->face
;
137 FT_CharMap old_charmap
= face
->charmap
;
138 FT_Byte
* gstyles
= globals
->glyph_styles
;
141 FT_UInt dflt
= ~0U; /* a non-valid value */
144 /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
145 FT_MEM_SET( globals
->glyph_styles
,
147 globals
->glyph_count
);
149 error
= FT_Select_Charmap( face
, FT_ENCODING_UNICODE
);
153 * Ignore this error; we simply use the fallback style.
154 * XXX: Shouldn't we rather disable hinting?
160 /* scan each style in a Unicode charmap */
161 for ( ss
= 0; AF_STYLE_CLASSES_GET
[ss
]; ss
++ )
163 AF_StyleClass style_class
=
164 AF_STYLE_CLASSES_GET
[ss
];
165 AF_ScriptClass script_class
=
166 AF_SCRIPT_CLASSES_GET
[style_class
->script
];
167 AF_Script_UniRange range
;
170 if ( script_class
->script_uni_ranges
== NULL
)
174 * Scan all Unicode points in the range and set the corresponding
177 if ( style_class
->coverage
== AF_COVERAGE_DEFAULT
)
179 if ( (FT_UInt
)style_class
->script
==
180 globals
->module
->default_script
)
183 for ( range
= script_class
->script_uni_ranges
;
187 FT_ULong charcode
= range
->first
;
191 gindex
= FT_Get_Char_Index( face
, charcode
);
194 gindex
< (FT_ULong
)globals
->glyph_count
&&
195 gstyles
[gindex
] == AF_STYLE_UNASSIGNED
)
196 gstyles
[gindex
] = (FT_Byte
)ss
;
200 charcode
= FT_Get_Next_Char( face
, charcode
, &gindex
);
202 if ( gindex
== 0 || charcode
> range
->last
)
205 if ( gindex
< (FT_ULong
)globals
->glyph_count
&&
206 gstyles
[gindex
] == AF_STYLE_UNASSIGNED
)
207 gstyles
[gindex
] = (FT_Byte
)ss
;
213 /* get glyphs not directly addressable by cmap */
214 af_get_coverage( globals
, style_class
, gstyles
);
218 /* handle the default OpenType features of the default script ... */
219 af_get_coverage( globals
, AF_STYLE_CLASSES_GET
[dflt
], gstyles
);
221 /* ... and the remaining default OpenType features */
222 for ( ss
= 0; AF_STYLE_CLASSES_GET
[ss
]; ss
++ )
224 AF_StyleClass style_class
= AF_STYLE_CLASSES_GET
[ss
];
227 if ( ss
!= dflt
&& style_class
->coverage
== AF_COVERAGE_DEFAULT
)
228 af_get_coverage( globals
, style_class
, gstyles
);
231 /* mark ASCII digits */
232 for ( i
= 0x30; i
<= 0x39; i
++ )
234 FT_UInt gindex
= FT_Get_Char_Index( face
, i
);
237 if ( gindex
!= 0 && gindex
< (FT_ULong
)globals
->glyph_count
)
238 gstyles
[gindex
] |= AF_DIGIT
;
243 * By default, all uncovered glyphs are set to the fallback style.
244 * XXX: Shouldn't we disable hinting or do something similar?
246 if ( globals
->module
->fallback_style
!= AF_STYLE_UNASSIGNED
)
251 for ( nn
= 0; nn
< globals
->glyph_count
; nn
++ )
253 if ( ( gstyles
[nn
] & ~AF_DIGIT
) == AF_STYLE_UNASSIGNED
)
255 gstyles
[nn
] &= ~AF_STYLE_UNASSIGNED
;
256 gstyles
[nn
] |= globals
->module
->fallback_style
;
261 #ifdef FT_DEBUG_LEVEL_TRACE
268 for ( ss
= 0; AF_STYLE_CLASSES_GET
[ss
]; ss
++ )
270 AF_StyleClass style_class
= AF_STYLE_CLASSES_GET
[ss
];
275 FT_TRACE4(( "%s:\n", af_style_names
[style_class
->style
] ));
277 for ( idx
= 0; idx
< globals
->glyph_count
; idx
++ )
279 if ( ( gstyles
[idx
] & ~AF_DIGIT
) == style_class
->style
)
281 if ( !( count
% 10 ) )
284 FT_TRACE4(( " %d", idx
));
287 if ( !( count
% 10 ) )
293 FT_TRACE4(( " (none)\n" ));
298 #endif /* FT_DEBUG_LEVEL_TRACE */
300 FT_Set_Charmap( face
, old_charmap
);
305 FT_LOCAL_DEF( FT_Error
)
306 af_face_globals_new( FT_Face face
,
307 AF_FaceGlobals
*aglobals
,
312 AF_FaceGlobals globals
= NULL
;
315 memory
= face
->memory
;
317 if ( FT_ALLOC( globals
, sizeof ( *globals
) +
318 face
->num_glyphs
* sizeof ( FT_Byte
) ) )
321 globals
->face
= face
;
322 globals
->glyph_count
= face
->num_glyphs
;
323 globals
->glyph_styles
= (FT_Byte
*)( globals
+ 1 );
324 globals
->module
= module
;
326 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
327 globals
->hb_font
= hb_ft_font_create( face
, NULL
);
330 error
= af_face_globals_compute_style_coverage( globals
);
333 af_face_globals_free( globals
);
337 globals
->increase_x_height
= AF_PROP_INCREASE_X_HEIGHT_MAX
;
346 af_face_globals_free( AF_FaceGlobals globals
)
350 FT_Memory memory
= globals
->face
->memory
;
354 for ( nn
= 0; nn
< AF_STYLE_MAX
; nn
++ )
356 if ( globals
->metrics
[nn
] )
358 AF_StyleClass style_class
=
359 AF_STYLE_CLASSES_GET
[nn
];
360 AF_WritingSystemClass writing_system_class
=
361 AF_WRITING_SYSTEM_CLASSES_GET
[style_class
->writing_system
];
364 if ( writing_system_class
->style_metrics_done
)
365 writing_system_class
->style_metrics_done( globals
->metrics
[nn
] );
367 FT_FREE( globals
->metrics
[nn
] );
371 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
372 hb_font_destroy( globals
->hb_font
);
373 globals
->hb_font
= NULL
;
376 globals
->glyph_count
= 0;
377 globals
->glyph_styles
= NULL
; /* no need to free this one! */
378 globals
->face
= NULL
;
385 FT_LOCAL_DEF( FT_Error
)
386 af_face_globals_get_metrics( AF_FaceGlobals globals
,
389 AF_StyleMetrics
*ametrics
)
391 AF_StyleMetrics metrics
= NULL
;
393 AF_Style style
= (AF_Style
)options
;
394 AF_WritingSystemClass writing_system_class
;
395 AF_StyleClass style_class
;
397 FT_Error error
= FT_Err_Ok
;
400 if ( gindex
>= (FT_ULong
)globals
->glyph_count
)
402 error
= FT_THROW( Invalid_Argument
);
406 /* if we have a forced style (via `options'), use it, */
407 /* otherwise look into `glyph_styles' array */
408 if ( style
== AF_STYLE_NONE_DFLT
|| style
+ 1 >= AF_STYLE_MAX
)
409 style
= (AF_Style
)( globals
->glyph_styles
[gindex
] &
410 AF_STYLE_UNASSIGNED
);
412 style_class
= AF_STYLE_CLASSES_GET
[style
];
413 writing_system_class
= AF_WRITING_SYSTEM_CLASSES_GET
414 [style_class
->writing_system
];
416 metrics
= globals
->metrics
[style
];
417 if ( metrics
== NULL
)
419 /* create the global metrics object if necessary */
420 FT_Memory memory
= globals
->face
->memory
;
423 if ( FT_ALLOC( metrics
, writing_system_class
->style_metrics_size
) )
426 metrics
->style_class
= style_class
;
427 metrics
->globals
= globals
;
429 if ( writing_system_class
->style_metrics_init
)
431 error
= writing_system_class
->style_metrics_init( metrics
,
435 if ( writing_system_class
->style_metrics_done
)
436 writing_system_class
->style_metrics_done( metrics
);
443 globals
->metrics
[style
] = metrics
;
453 FT_LOCAL_DEF( FT_Bool
)
454 af_face_globals_is_digit( AF_FaceGlobals globals
,
457 if ( gindex
< (FT_ULong
)globals
->glyph_count
)
458 return (FT_Bool
)( globals
->glyph_styles
[gindex
] & AF_DIGIT
);