• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  afglobal.c                                                             */
4 /*                                                                         */
5 /*    Auto-fitter routines to compute global hinting values (body).        */
6 /*                                                                         */
7 /*  Copyright 2003-2013 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 "afdummy.h"
21 #include "aflatin.h"
22 #include "afcjk.h"
23 #include "afindic.h"
24 #include "afpic.h"
25 
26 #include "aferrors.h"
27 
28 #ifdef FT_OPTION_AUTOFIT2
29 #include "aflatin2.h"
30 #endif
31 
32 #ifndef FT_CONFIG_OPTION_PIC
33 
34   /* when updating this table, don't forget to update          */
35   /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
36 
37   /* populate this list when you add new scripts */
38   static AF_ScriptClass const  af_script_classes[] =
39   {
40     &af_dummy_script_class,
41 #ifdef FT_OPTION_AUTOFIT2
42     &af_latin2_script_class,
43 #endif
44     &af_latin_script_class,
45     &af_cjk_script_class,
46     &af_indic_script_class,
47     NULL  /* do not remove */
48   };
49 
50 #endif /* !FT_CONFIG_OPTION_PIC */
51 
52 
53   /* Compute the script index of each glyph within a given face. */
54 
55   static FT_Error
af_face_globals_compute_script_coverage(AF_FaceGlobals globals)56   af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
57   {
58     FT_Error    error;
59     FT_Face     face        = globals->face;
60     FT_CharMap  old_charmap = face->charmap;
61     FT_Byte*    gscripts    = globals->glyph_scripts;
62     FT_UInt     ss;
63     FT_UInt     i;
64 
65 
66     /* the value AF_SCRIPT_NONE means `uncovered glyph' */
67     FT_MEM_SET( globals->glyph_scripts,
68                 AF_SCRIPT_NONE,
69                 globals->glyph_count );
70 
71     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
72     if ( error )
73     {
74      /*
75       *  Ignore this error; we simply use the fallback script.
76       *  XXX: Shouldn't we rather disable hinting?
77       */
78       error = FT_Err_Ok;
79       goto Exit;
80     }
81 
82     /* scan each script in a Unicode charmap */
83     for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
84     {
85       AF_ScriptClass      clazz = AF_SCRIPT_CLASSES_GET[ss];
86       AF_Script_UniRange  range;
87 
88 
89       if ( clazz->script_uni_ranges == NULL )
90         continue;
91 
92       /*
93        *  Scan all Unicode points in the range and set the corresponding
94        *  glyph script index.
95        */
96       for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
97       {
98         FT_ULong  charcode = range->first;
99         FT_UInt   gindex;
100 
101 
102         gindex = FT_Get_Char_Index( face, charcode );
103 
104         if ( gindex != 0                             &&
105              gindex < (FT_ULong)globals->glyph_count &&
106              gscripts[gindex] == AF_SCRIPT_NONE )
107           gscripts[gindex] = (FT_Byte)ss;
108 
109         for (;;)
110         {
111           charcode = FT_Get_Next_Char( face, charcode, &gindex );
112 
113           if ( gindex == 0 || charcode > range->last )
114             break;
115 
116           if ( gindex < (FT_ULong)globals->glyph_count &&
117                gscripts[gindex] == AF_SCRIPT_NONE )
118             gscripts[gindex] = (FT_Byte)ss;
119         }
120       }
121     }
122 
123     /* mark ASCII digits */
124     for ( i = 0x30; i <= 0x39; i++ )
125     {
126       FT_UInt  gindex = FT_Get_Char_Index( face, i );
127 
128 
129       if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
130         gscripts[gindex] |= AF_DIGIT;
131     }
132 
133   Exit:
134     /*
135      *  By default, all uncovered glyphs are set to the fallback script.
136      *  XXX: Shouldn't we disable hinting or do something similar?
137      */
138     if ( globals->module->fallback_script != AF_SCRIPT_NONE )
139     {
140       FT_Long  nn;
141 
142 
143       for ( nn = 0; nn < globals->glyph_count; nn++ )
144       {
145         if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_NONE )
146         {
147           gscripts[nn] &= ~AF_SCRIPT_NONE;
148           gscripts[nn] |= globals->module->fallback_script;
149         }
150       }
151     }
152 
153     FT_Set_Charmap( face, old_charmap );
154     return error;
155   }
156 
157 
158   FT_LOCAL_DEF( FT_Error )
af_face_globals_new(FT_Face face,AF_FaceGlobals * aglobals,AF_Module module)159   af_face_globals_new( FT_Face          face,
160                        AF_FaceGlobals  *aglobals,
161                        AF_Module        module )
162   {
163     FT_Error        error;
164     FT_Memory       memory;
165     AF_FaceGlobals  globals = NULL;
166 
167 
168     memory = face->memory;
169 
170     if ( FT_ALLOC( globals, sizeof ( *globals ) +
171                             face->num_glyphs * sizeof ( FT_Byte ) ) )
172       goto Exit;
173 
174     globals->face          = face;
175     globals->glyph_count   = face->num_glyphs;
176     globals->glyph_scripts = (FT_Byte*)( globals + 1 );
177     globals->module        = module;
178 
179     error = af_face_globals_compute_script_coverage( globals );
180     if ( error )
181     {
182       af_face_globals_free( globals );
183       globals = NULL;
184     }
185 
186     globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
187 
188   Exit:
189     *aglobals = globals;
190     return error;
191   }
192 
193 
194   FT_LOCAL_DEF( void )
af_face_globals_free(AF_FaceGlobals globals)195   af_face_globals_free( AF_FaceGlobals  globals )
196   {
197     if ( globals )
198     {
199       FT_Memory  memory = globals->face->memory;
200       FT_UInt    nn;
201 
202 
203       for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
204       {
205         if ( globals->metrics[nn] )
206         {
207           AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
208 
209 
210           FT_ASSERT( globals->metrics[nn]->clazz == clazz );
211 
212           if ( clazz->script_metrics_done )
213             clazz->script_metrics_done( globals->metrics[nn] );
214 
215           FT_FREE( globals->metrics[nn] );
216         }
217       }
218 
219       globals->glyph_count   = 0;
220       globals->glyph_scripts = NULL;  /* no need to free this one! */
221       globals->face          = NULL;
222 
223       FT_FREE( globals );
224     }
225   }
226 
227 
228   FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics(AF_FaceGlobals globals,FT_UInt gindex,FT_UInt options,AF_ScriptMetrics * ametrics)229   af_face_globals_get_metrics( AF_FaceGlobals     globals,
230                                FT_UInt            gindex,
231                                FT_UInt            options,
232                                AF_ScriptMetrics  *ametrics )
233   {
234     AF_ScriptMetrics  metrics = NULL;
235     FT_UInt           gidx;
236     AF_ScriptClass    clazz;
237     FT_UInt           script     = options & 15;
238     const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
239                                      sizeof ( AF_SCRIPT_CLASSES_GET[0] );
240     FT_Error          error      = FT_Err_Ok;
241 
242 
243     if ( gindex >= (FT_ULong)globals->glyph_count )
244     {
245       error = FT_THROW( Invalid_Argument );
246       goto Exit;
247     }
248 
249     gidx = script;
250     if ( gidx == 0 || gidx + 1 >= script_max )
251       gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_NONE;
252 
253     clazz = AF_SCRIPT_CLASSES_GET[gidx];
254     if ( script == 0 )
255       script = clazz->script;
256 
257     metrics = globals->metrics[clazz->script];
258     if ( metrics == NULL )
259     {
260       /* create the global metrics object if necessary */
261       FT_Memory  memory = globals->face->memory;
262 
263 
264       if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
265         goto Exit;
266 
267       metrics->clazz   = clazz;
268       metrics->globals = globals;
269 
270       if ( clazz->script_metrics_init )
271       {
272         error = clazz->script_metrics_init( metrics, globals->face );
273         if ( error )
274         {
275           if ( clazz->script_metrics_done )
276             clazz->script_metrics_done( metrics );
277 
278           FT_FREE( metrics );
279           goto Exit;
280         }
281       }
282 
283       globals->metrics[clazz->script] = metrics;
284     }
285 
286   Exit:
287     *ametrics = metrics;
288 
289     return error;
290   }
291 
292 
293   FT_LOCAL_DEF( FT_Bool )
af_face_globals_is_digit(AF_FaceGlobals globals,FT_UInt gindex)294   af_face_globals_is_digit( AF_FaceGlobals  globals,
295                             FT_UInt         gindex )
296   {
297     if ( gindex < (FT_ULong)globals->glyph_count )
298       return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
299 
300     return (FT_Bool)0;
301   }
302 
303 
304 /* END */
305