- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / freetype2 / src / src / autofit / afglobal.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  afglobal.c                                                             */
4 /*                                                                         */
5 /*    Auto-fitter routines to compute global hinting values (body).        */
6 /*                                                                         */
7 /*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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   /* index of default script in `af_script_classes' */
53 #define AF_SCRIPT_LIST_DEFAULT  2
54   /* a bit mask indicating an uncovered glyph       */
55 #define AF_SCRIPT_LIST_NONE     0x7F
56   /* if this flag is set, we have an ASCII digit    */
57 #define AF_DIGIT                0x80
58
59
60   /*
61    *  Note that glyph_scripts[] is used to map each glyph into
62    *  an index into the `af_script_classes' array.
63    *
64    */
65   typedef struct  AF_FaceGlobalsRec_
66   {
67     FT_Face           face;
68     FT_Long           glyph_count;    /* same as face->num_glyphs */
69     FT_Byte*          glyph_scripts;
70
71     AF_ScriptMetrics  metrics[AF_SCRIPT_MAX];
72
73   } AF_FaceGlobalsRec;
74
75
76   /* Compute the script index of each glyph within a given face. */
77
78   static FT_Error
79   af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
80   {
81     FT_Error    error       = AF_Err_Ok;
82     FT_Face     face        = globals->face;
83     FT_CharMap  old_charmap = face->charmap;
84     FT_Byte*    gscripts    = globals->glyph_scripts;
85     FT_UInt     ss, i;
86
87
88     /* the value 255 means `uncovered glyph' */
89     FT_MEM_SET( globals->glyph_scripts,
90                 AF_SCRIPT_LIST_NONE,
91                 globals->glyph_count );
92
93     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
94     if ( error )
95     {
96      /*
97       *  Ignore this error; we simply use the default script.
98       *  XXX: Shouldn't we rather disable hinting?
99       */
100       error = AF_Err_Ok;
101       goto Exit;
102     }
103
104     /* scan each script in a Unicode charmap */
105     for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
106     {
107       AF_ScriptClass      clazz = AF_SCRIPT_CLASSES_GET[ss];
108       AF_Script_UniRange  range;
109
110
111       if ( clazz->script_uni_ranges == NULL )
112         continue;
113
114       /*
115        *  Scan all unicode points in the range and set the corresponding
116        *  glyph script index.
117        */
118       for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
119       {
120         FT_ULong  charcode = range->first;
121         FT_UInt   gindex;
122
123
124         gindex = FT_Get_Char_Index( face, charcode );
125
126         if ( gindex != 0                             &&
127              gindex < (FT_ULong)globals->glyph_count &&
128              gscripts[gindex] == AF_SCRIPT_LIST_NONE )
129         {
130           gscripts[gindex] = (FT_Byte)ss;
131         }
132
133         for (;;)
134         {
135           charcode = FT_Get_Next_Char( face, charcode, &gindex );
136
137           if ( gindex == 0 || charcode > range->last )
138             break;
139
140           if ( gindex < (FT_ULong)globals->glyph_count &&
141                gscripts[gindex] == AF_SCRIPT_LIST_NONE )
142           {
143             gscripts[gindex] = (FT_Byte)ss;
144           }
145         }
146       }
147     }
148
149     /* mark ASCII digits */
150     for ( i = 0x30; i <= 0x39; i++ )
151     {
152       FT_UInt  gindex = FT_Get_Char_Index( face, i );
153
154
155       if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
156         gscripts[gindex] |= AF_DIGIT;
157     }
158
159   Exit:
160     /*
161      *  By default, all uncovered glyphs are set to the latin script.
162      *  XXX: Shouldn't we disable hinting or do something similar?
163      */
164     {
165       FT_Long  nn;
166
167
168       for ( nn = 0; nn < globals->glyph_count; nn++ )
169       {
170         if ( gscripts[nn] == AF_SCRIPT_LIST_NONE )
171           gscripts[nn] = AF_SCRIPT_LIST_DEFAULT;
172       }
173     }
174
175     FT_Set_Charmap( face, old_charmap );
176     return error;
177   }
178
179
180   FT_LOCAL_DEF( FT_Error )
181   af_face_globals_new( FT_Face          face,
182                        AF_FaceGlobals  *aglobals )
183   {
184     FT_Error        error;
185     FT_Memory       memory;
186     AF_FaceGlobals  globals;
187
188
189     memory = face->memory;
190
191     if ( !FT_ALLOC( globals, sizeof ( *globals ) +
192                              face->num_glyphs * sizeof ( FT_Byte ) ) )
193     {
194       globals->face          = face;
195       globals->glyph_count   = face->num_glyphs;
196       globals->glyph_scripts = (FT_Byte*)( globals + 1 );
197
198       error = af_face_globals_compute_script_coverage( globals );
199       if ( error )
200       {
201         af_face_globals_free( globals );
202         globals = NULL;
203       }
204     }
205
206     *aglobals = globals;
207     return error;
208   }
209
210
211   FT_LOCAL_DEF( void )
212   af_face_globals_free( AF_FaceGlobals  globals )
213   {
214     if ( globals )
215     {
216       FT_Memory  memory = globals->face->memory;
217       FT_UInt    nn;
218
219
220       for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
221       {
222         if ( globals->metrics[nn] )
223         {
224           AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
225
226
227           FT_ASSERT( globals->metrics[nn]->clazz == clazz );
228
229           if ( clazz->script_metrics_done )
230             clazz->script_metrics_done( globals->metrics[nn] );
231
232           FT_FREE( globals->metrics[nn] );
233         }
234       }
235
236       globals->glyph_count   = 0;
237       globals->glyph_scripts = NULL;  /* no need to free this one! */
238       globals->face          = NULL;
239
240       FT_FREE( globals );
241     }
242   }
243
244
245   FT_LOCAL_DEF( FT_Error )
246   af_face_globals_get_metrics( AF_FaceGlobals     globals,
247                                FT_UInt            gindex,
248                                FT_UInt            options,
249                                AF_ScriptMetrics  *ametrics )
250   {
251     AF_ScriptMetrics  metrics = NULL;
252     FT_UInt           gidx;
253     AF_ScriptClass    clazz;
254     FT_UInt           script     = options & 15;
255     const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
256                                      sizeof ( AF_SCRIPT_CLASSES_GET[0] );
257     FT_Error          error      = AF_Err_Ok;
258
259
260     if ( gindex >= (FT_ULong)globals->glyph_count )
261     {
262       error = AF_Err_Invalid_Argument;
263       goto Exit;
264     }
265
266     gidx = script;
267     if ( gidx == 0 || gidx + 1 >= script_max )
268       gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
269
270     clazz = AF_SCRIPT_CLASSES_GET[gidx];
271     if ( script == 0 )
272       script = clazz->script;
273
274     metrics = globals->metrics[clazz->script];
275     if ( metrics == NULL )
276     {
277       /* create the global metrics object when needed */
278       FT_Memory  memory = globals->face->memory;
279
280
281       if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
282         goto Exit;
283
284       metrics->clazz = clazz;
285
286       if ( clazz->script_metrics_init )
287       {
288         error = clazz->script_metrics_init( metrics, globals->face );
289         if ( error )
290         {
291           if ( clazz->script_metrics_done )
292             clazz->script_metrics_done( metrics );
293
294           FT_FREE( metrics );
295           goto Exit;
296         }
297       }
298
299       globals->metrics[clazz->script] = metrics;
300     }
301
302   Exit:
303     *ametrics = metrics;
304
305     return error;
306   }
307
308
309   FT_LOCAL_DEF( FT_Bool )
310   af_face_globals_is_digit( AF_FaceGlobals  globals,
311                             FT_UInt         gindex )
312   {
313     if ( gindex < (FT_ULong)globals->glyph_count )
314       return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
315
316     return (FT_Bool)0;
317   }
318
319
320 /* END */