source: trunk/poppler/freetype2/src/autofit/afglobal.c @ 251

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 8.0 KB
Line 
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 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
25#include "aferrors.h"
26
27#ifdef FT_OPTION_AUTOFIT2
28#include "aflatin2.h"
29#endif
30
31  /* populate this list when you add new scripts */
32  static AF_ScriptClass const  af_script_classes[] =
33  {
34    &af_dummy_script_class,
35#ifdef FT_OPTION_AUTOFIT2
36    &af_latin2_script_class,
37#endif
38    &af_latin_script_class,
39    &af_cjk_script_class,
40    &af_indic_script_class, 
41    NULL  /* do not remove */
42  };
43
44  /* index of default script in `af_script_classes' */
45#define AF_SCRIPT_LIST_DEFAULT  2
46  /* indicates an uncovered glyph                   */
47#define AF_SCRIPT_LIST_NONE   255
48
49
50  /*
51   *  Note that glyph_scripts[] is used to map each glyph into
52   *  an index into the `af_script_classes' array.
53   *
54   */
55  typedef struct  AF_FaceGlobalsRec_
56  {
57    FT_Face           face;
58    FT_UInt           glyph_count;    /* same as face->num_glyphs */
59    FT_Byte*          glyph_scripts;
60
61    AF_ScriptMetrics  metrics[AF_SCRIPT_MAX];
62
63  } AF_FaceGlobalsRec;
64
65
66  /* Compute the script index of each glyph within a given face. */
67
68  static FT_Error
69  af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
70  {
71    FT_Error    error       = AF_Err_Ok;
72    FT_Face     face        = globals->face;
73    FT_CharMap  old_charmap = face->charmap;
74    FT_Byte*    gscripts    = globals->glyph_scripts;
75    FT_UInt     ss;
76
77
78    /* the value 255 means `uncovered glyph' */
79    FT_MEM_SET( globals->glyph_scripts,
80                AF_SCRIPT_LIST_NONE,
81                globals->glyph_count );
82
83    error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
84    if ( error )
85    {
86     /*
87      *  Ignore this error; we simply use the default script.
88      *  XXX: Shouldn't we rather disable hinting?
89      */
90      error = AF_Err_Ok;
91      goto Exit;
92    }
93
94    /* scan each script in a Unicode charmap */
95    for ( ss = 0; af_script_classes[ss]; ss++ )
96    {
97      AF_ScriptClass      clazz = af_script_classes[ss];
98      AF_Script_UniRange  range;
99
100
101      if ( clazz->script_uni_ranges == NULL )
102        continue;
103
104      /*
105       *  Scan all unicode points in the range and set the corresponding
106       *  glyph script index.
107       */
108      for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
109      {
110        FT_ULong  charcode = range->first;
111        FT_UInt   gindex;
112
113
114        gindex = FT_Get_Char_Index( face, charcode );
115
116        if ( gindex != 0                             &&
117             gindex < globals->glyph_count           &&
118             gscripts[gindex] == AF_SCRIPT_LIST_NONE )
119        {
120          gscripts[gindex] = (FT_Byte)ss;
121        }
122
123        for (;;)
124        {
125          charcode = FT_Get_Next_Char( face, charcode, &gindex );
126
127          if ( gindex == 0 || charcode > range->last )
128            break;
129
130          if ( gindex < globals->glyph_count           &&
131               gscripts[gindex] == AF_SCRIPT_LIST_NONE )
132          {
133            gscripts[gindex] = (FT_Byte)ss;
134          }
135        }
136      }
137    }
138
139  Exit:
140    /*
141     *  By default, all uncovered glyphs are set to the latin script.
142     *  XXX: Shouldn't we disable hinting or do something similar?
143     */
144    {
145      FT_UInt  nn;
146
147
148      for ( nn = 0; nn < globals->glyph_count; nn++ )
149      {
150        if ( gscripts[nn] == AF_SCRIPT_LIST_NONE )
151          gscripts[nn] = AF_SCRIPT_LIST_DEFAULT;
152      }
153    }
154
155    FT_Set_Charmap( face, old_charmap );
156    return error;
157  }
158
159
160  FT_LOCAL_DEF( FT_Error )
161  af_face_globals_new( FT_Face          face,
162                       AF_FaceGlobals  *aglobals )
163  {
164    FT_Error        error;
165    FT_Memory       memory;
166    AF_FaceGlobals  globals;
167
168
169    memory = face->memory;
170
171    if ( !FT_ALLOC( globals, sizeof ( *globals ) +
172                             face->num_glyphs * sizeof ( FT_Byte ) ) )
173    {
174      globals->face          = face;
175      globals->glyph_count   = face->num_glyphs;
176      globals->glyph_scripts = (FT_Byte*)( globals + 1 );
177
178      error = af_face_globals_compute_script_coverage( globals );
179      if ( error )
180      {
181        af_face_globals_free( globals );
182        globals = NULL;
183      }
184    }
185
186    *aglobals = globals;
187    return error;
188  }
189
190
191  FT_LOCAL_DEF( void )
192  af_face_globals_free( AF_FaceGlobals  globals )
193  {
194    if ( globals )
195    {
196      FT_Memory  memory = globals->face->memory;
197      FT_UInt    nn;
198
199
200      for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
201      {
202        if ( globals->metrics[nn] )
203        {
204          AF_ScriptClass  clazz = af_script_classes[nn];
205
206
207          FT_ASSERT( globals->metrics[nn]->clazz == clazz );
208
209          if ( clazz->script_metrics_done )
210            clazz->script_metrics_done( globals->metrics[nn] );
211
212          FT_FREE( globals->metrics[nn] );
213        }
214      }
215
216      globals->glyph_count   = 0;
217      globals->glyph_scripts = NULL;  /* no need to free this one! */
218      globals->face          = NULL;
219
220      FT_FREE( globals );
221    }
222  }
223
224
225  FT_LOCAL_DEF( FT_Error )
226  af_face_globals_get_metrics( AF_FaceGlobals     globals,
227                               FT_UInt            gindex,
228                               FT_UInt            options,
229                               AF_ScriptMetrics  *ametrics )
230  {
231    AF_ScriptMetrics  metrics = NULL;
232    FT_UInt           gidx;
233    AF_ScriptClass    clazz;
234    FT_UInt           script     = options & 15;
235    const FT_UInt     script_max = sizeof ( af_script_classes ) /
236                                     sizeof ( af_script_classes[0] );
237    FT_Error          error      = AF_Err_Ok;
238
239
240    if ( gindex >= globals->glyph_count )
241    {
242      error = AF_Err_Invalid_Argument;
243      goto Exit;
244    }
245
246    gidx = script;
247    if ( gidx == 0 || gidx + 1 >= script_max )
248      gidx = globals->glyph_scripts[gindex];
249
250    clazz = af_script_classes[gidx];
251    if ( script == 0 )
252      script = clazz->script;
253
254    metrics = globals->metrics[clazz->script];
255    if ( metrics == NULL )
256    {
257      /* create the global metrics object when needed */
258      FT_Memory  memory = globals->face->memory;
259
260
261      if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
262        goto Exit;
263
264      metrics->clazz = clazz;
265
266      if ( clazz->script_metrics_init )
267      {
268        error = clazz->script_metrics_init( metrics, globals->face );
269        if ( error )
270        {
271          if ( clazz->script_metrics_done )
272            clazz->script_metrics_done( metrics );
273
274          FT_FREE( metrics );
275          goto Exit;
276        }
277      }
278
279      globals->metrics[clazz->script] = metrics;
280    }
281
282  Exit:
283    *ametrics = metrics;
284
285    return error;
286  }
287
288
289/* END */
Note: See TracBrowser for help on using the repository browser.