PageRenderTime 59ms CodeModel.GetById 15ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/freetype2/src/autofit/afglobal.c

http://github.com/zpao/v8monkey
C | 323 lines | 205 code | 73 blank | 45 comment | 42 complexity | a03cdd924b27ced3047fe017b7e5b9f5 MD5 | raw file
  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, 2010 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_DIGIT ) == AF_SCRIPT_LIST_NONE )
171        {
172          gscripts[nn] &= ~AF_SCRIPT_LIST_NONE;
173          gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT;
174        }
175      }
176    }
177
178    FT_Set_Charmap( face, old_charmap );
179    return error;
180  }
181
182
183  FT_LOCAL_DEF( FT_Error )
184  af_face_globals_new( FT_Face          face,
185                       AF_FaceGlobals  *aglobals )
186  {
187    FT_Error        error;
188    FT_Memory       memory;
189    AF_FaceGlobals  globals = NULL;
190
191
192    memory = face->memory;
193
194    if ( !FT_ALLOC( globals, sizeof ( *globals ) +
195                             face->num_glyphs * sizeof ( FT_Byte ) ) )
196    {
197      globals->face          = face;
198      globals->glyph_count   = face->num_glyphs;
199      globals->glyph_scripts = (FT_Byte*)( globals + 1 );
200
201      error = af_face_globals_compute_script_coverage( globals );
202      if ( error )
203      {
204        af_face_globals_free( globals );
205        globals = NULL;
206      }
207    }
208
209    *aglobals = globals;
210    return error;
211  }
212
213
214  FT_LOCAL_DEF( void )
215  af_face_globals_free( AF_FaceGlobals  globals )
216  {
217    if ( globals )
218    {
219      FT_Memory  memory = globals->face->memory;
220      FT_UInt    nn;
221
222
223      for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
224      {
225        if ( globals->metrics[nn] )
226        {
227          AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
228
229
230          FT_ASSERT( globals->metrics[nn]->clazz == clazz );
231
232          if ( clazz->script_metrics_done )
233            clazz->script_metrics_done( globals->metrics[nn] );
234
235          FT_FREE( globals->metrics[nn] );
236        }
237      }
238
239      globals->glyph_count   = 0;
240      globals->glyph_scripts = NULL;  /* no need to free this one! */
241      globals->face          = NULL;
242
243      FT_FREE( globals );
244    }
245  }
246
247
248  FT_LOCAL_DEF( FT_Error )
249  af_face_globals_get_metrics( AF_FaceGlobals     globals,
250                               FT_UInt            gindex,
251                               FT_UInt            options,
252                               AF_ScriptMetrics  *ametrics )
253  {
254    AF_ScriptMetrics  metrics = NULL;
255    FT_UInt           gidx;
256    AF_ScriptClass    clazz;
257    FT_UInt           script     = options & 15;
258    const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
259                                     sizeof ( AF_SCRIPT_CLASSES_GET[0] );
260    FT_Error          error      = AF_Err_Ok;
261
262
263    if ( gindex >= (FT_ULong)globals->glyph_count )
264    {
265      error = AF_Err_Invalid_Argument;
266      goto Exit;
267    }
268
269    gidx = script;
270    if ( gidx == 0 || gidx + 1 >= script_max )
271      gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
272
273    clazz = AF_SCRIPT_CLASSES_GET[gidx];
274    if ( script == 0 )
275      script = clazz->script;
276
277    metrics = globals->metrics[clazz->script];
278    if ( metrics == NULL )
279    {
280      /* create the global metrics object when needed */
281      FT_Memory  memory = globals->face->memory;
282
283
284      if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
285        goto Exit;
286
287      metrics->clazz = clazz;
288
289      if ( clazz->script_metrics_init )
290      {
291        error = clazz->script_metrics_init( metrics, globals->face );
292        if ( error )
293        {
294          if ( clazz->script_metrics_done )
295            clazz->script_metrics_done( metrics );
296
297          FT_FREE( metrics );
298          goto Exit;
299        }
300      }
301
302      globals->metrics[clazz->script] = metrics;
303    }
304
305  Exit:
306    *ametrics = metrics;
307
308    return error;
309  }
310
311
312  FT_LOCAL_DEF( FT_Bool )
313  af_face_globals_is_digit( AF_FaceGlobals  globals,
314                            FT_UInt         gindex )
315  {
316    if ( gindex < (FT_ULong)globals->glyph_count )
317      return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
318
319    return (FT_Bool)0;
320  }
321
322
323/* END */