source: trunk/poppler/freetype-2.1.10/src/cid/cidgload.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 16.4 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  cidgload.c                                                             */
4/*                                                                         */
5/*    CID-keyed Type1 Glyph Loader (body).                                 */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004 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 <ft2build.h>
20#include "cidload.h"
21#include "cidgload.h"
22#include FT_INTERNAL_DEBUG_H
23#include FT_INTERNAL_STREAM_H
24#include FT_OUTLINE_H
25
26#include "ciderrs.h"
27
28
29  /*************************************************************************/
30  /*                                                                       */
31  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
32  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
33  /* messages during execution.                                            */
34  /*                                                                       */
35#undef  FT_COMPONENT
36#define FT_COMPONENT  trace_cidgload
37
38
39  FT_CALLBACK_DEF( FT_Error )
40  cid_load_glyph( T1_Decoder  decoder,
41                  FT_UInt     glyph_index )
42  {
43    CID_Face       face = (CID_Face)decoder->builder.face;
44    CID_FaceInfo   cid  = &face->cid;
45    FT_Byte*       p;
46    FT_UInt        fd_select;
47    FT_Stream      stream = face->cid_stream;
48    FT_Error       error  = 0;
49    FT_Byte*       charstring = 0;
50    FT_Memory      memory = face->root.memory;
51    FT_ULong       glyph_length = 0;
52    PSAux_Service  psaux = (PSAux_Service)face->psaux;
53
54
55#ifdef FT_CONFIG_OPTION_INCREMENTAL
56
57    /* For incremental fonts get the character data using */
58    /* the callback function.                             */
59    if ( face->root.internal->incremental_interface )
60    {
61      FT_Data  glyph_data;
62
63
64      error = face->root.internal->incremental_interface->funcs->get_glyph_data(
65                face->root.internal->incremental_interface->object,
66                glyph_index,
67                &glyph_data );
68      if ( error )
69        goto Exit;
70
71      p         = (FT_Byte*)glyph_data.pointer;
72      fd_select = (FT_UInt)cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
73
74      if ( glyph_data.length != 0 )
75      {
76        glyph_length = glyph_data.length - cid->fd_bytes;
77        FT_ALLOC( charstring, glyph_length );
78        if ( !error )
79          ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes,
80                     glyph_length );
81      }
82
83      face->root.internal->incremental_interface->funcs->free_glyph_data(
84                face->root.internal->incremental_interface->object,
85                &glyph_data );
86
87      if ( error )
88        goto Exit;
89    }
90
91    else
92
93#endif /* FT_CONFIG_OPTION_INCREMENTAL */
94
95    /* For ordinary fonts read the CID font dictionary index */
96    /* and charstring offset from the CIDMap.                */
97    {
98      FT_UInt   entry_len = cid->fd_bytes + cid->gd_bytes;
99      FT_ULong  off1;
100
101
102      if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
103                           glyph_index * entry_len )               ||
104           FT_FRAME_ENTER( 2 * entry_len )                         )
105        goto Exit;
106
107      p            = (FT_Byte*)stream->cursor;
108      fd_select    = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
109      off1         = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
110      p           += cid->fd_bytes;
111      glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
112      FT_FRAME_EXIT();
113
114      if ( glyph_length == 0 )
115        goto Exit;
116      if ( FT_ALLOC( charstring, glyph_length ) )
117        goto Exit;
118      if ( FT_STREAM_READ_AT( cid->data_offset + off1,
119                              charstring, glyph_length ) )
120        goto Exit;
121    }
122
123    /* Now set up the subrs array and parse the charstrings. */
124    {
125      CID_FaceDict  dict;
126      CID_Subrs     cid_subrs = face->subrs + fd_select;
127      FT_Int        cs_offset;
128
129
130      /* Set up subrs */
131      decoder->num_subrs = cid_subrs->num_subrs;
132      decoder->subrs     = cid_subrs->code;
133      decoder->subrs_len = 0;
134
135      /* Set up font matrix */
136      dict                 = cid->font_dicts + fd_select;
137
138      decoder->font_matrix = dict->font_matrix;
139      decoder->font_offset = dict->font_offset;
140      decoder->lenIV       = dict->private_dict.lenIV;
141
142      /* Decode the charstring. */
143
144      /* Adjustment for seed bytes. */
145      cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
146
147      /* Decrypt only if lenIV >= 0. */
148      if ( decoder->lenIV >= 0 )
149        psaux->t1_decrypt( charstring, glyph_length, 4330 );
150
151      error = decoder->funcs.parse_charstrings(
152                decoder, charstring + cs_offset,
153                (FT_Int)glyph_length - cs_offset  );
154    }
155
156    FT_FREE( charstring );
157
158#ifdef FT_CONFIG_OPTION_INCREMENTAL
159
160    /* Incremental fonts can optionally override the metrics. */
161    if ( !error                                                              &&
162         face->root.internal->incremental_interface                          &&
163         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
164    {
165      FT_Incremental_MetricsRec  metrics;
166
167
168      metrics.bearing_x = decoder->builder.left_bearing.x;
169      metrics.bearing_y = decoder->builder.left_bearing.y;
170      metrics.advance   = decoder->builder.advance.x;
171      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
172                face->root.internal->incremental_interface->object,
173                glyph_index, FALSE, &metrics );
174      decoder->builder.left_bearing.x = metrics.bearing_x;
175      decoder->builder.left_bearing.y = metrics.bearing_y;
176      decoder->builder.advance.x      = metrics.advance;
177      decoder->builder.advance.y      = 0;
178    }
179
180#endif /* FT_CONFIG_OPTION_INCREMENTAL */
181
182  Exit:
183    return error;
184  }
185
186
187#if 0
188
189
190  /*************************************************************************/
191  /*************************************************************************/
192  /*************************************************************************/
193  /**********                                                      *********/
194  /**********                                                      *********/
195  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
196  /**********                                                      *********/
197  /**********    The following code is in charge of computing      *********/
198  /**********    the maximum advance width of the font.  It        *********/
199  /**********    quickly processes each glyph charstring to        *********/
200  /**********    extract the value from either a `sbw' or `seac'   *********/
201  /**********    operator.                                         *********/
202  /**********                                                      *********/
203  /*************************************************************************/
204  /*************************************************************************/
205  /*************************************************************************/
206
207
208  FT_LOCAL_DEF( FT_Error )
209  cid_face_compute_max_advance( CID_Face  face,
210                                FT_Int*   max_advance )
211  {
212    FT_Error       error;
213    T1_DecoderRec  decoder;
214    FT_Int         glyph_index;
215
216    PSAux_Service  psaux = (PSAux_Service)face->psaux;
217
218
219    *max_advance = 0;
220
221    /* Initialize load decoder */
222    error = psaux->t1_decoder_funcs->init( &decoder,
223                                           (FT_Face)face,
224                                           0, /* size       */
225                                           0, /* glyph slot */
226                                           0, /* glyph names! XXX */
227                                           0, /* blend == 0 */
228                                           0, /* hinting == 0 */
229                                           cid_load_glyph );
230    if ( error )
231      return error;
232
233    decoder.builder.metrics_only = 1;
234    decoder.builder.load_points  = 0;
235
236    /* for each glyph, parse the glyph charstring and extract */
237    /* the advance width                                      */
238    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
239          glyph_index++ )
240    {
241      /* now get load the unscaled outline */
242      error = cid_load_glyph( &decoder, glyph_index );
243      /* ignore the error if one occurred - skip to next glyph */
244    }
245
246    *max_advance = decoder.builder.advance.x;
247
248    return CID_Err_Ok;
249  }
250
251
252#endif /* 0 */
253
254
255  /*************************************************************************/
256  /*************************************************************************/
257  /*************************************************************************/
258  /**********                                                      *********/
259  /**********                                                      *********/
260  /**********               UNHINTED GLYPH LOADER                  *********/
261  /**********                                                      *********/
262  /**********    The following code is in charge of loading a      *********/
263  /**********    single outline.  It completely ignores hinting    *********/
264  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
265  /**********                                                      *********/
266  /*************************************************************************/
267  /*************************************************************************/
268  /*************************************************************************/
269
270
271  FT_LOCAL_DEF( FT_Error )
272  cid_slot_load_glyph( FT_GlyphSlot  cidglyph,      /* CID_GlyphSlot */
273                       FT_Size       cidsize,       /* CID_Size      */
274                       FT_UInt       glyph_index,
275                       FT_Int32      load_flags )
276  {
277    CID_GlyphSlot  glyph = (CID_GlyphSlot)cidglyph;
278    CID_Size       size  = (CID_Size)cidsize;
279    FT_Error       error;
280    T1_DecoderRec  decoder;
281    CID_Face       face = (CID_Face)cidglyph->face;
282    FT_Bool        hinting;
283
284    PSAux_Service  psaux = (PSAux_Service)face->psaux;
285    FT_Matrix      font_matrix;
286    FT_Vector      font_offset;
287
288
289    if ( load_flags & FT_LOAD_NO_RECURSE )
290      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
291
292    glyph->x_scale = cidsize->metrics.x_scale;
293    glyph->y_scale = cidsize->metrics.y_scale;
294
295    cidglyph->outline.n_points   = 0;
296    cidglyph->outline.n_contours = 0;
297
298    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
299                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
300
301    cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;
302
303    {
304      error = psaux->t1_decoder_funcs->init( &decoder,
305                                             cidglyph->face,
306                                             cidsize,
307                                             cidglyph,
308                                             0, /* glyph names -- XXX */
309                                             0, /* blend == 0 */
310                                             hinting,
311                                             FT_LOAD_TARGET_MODE( load_flags ),
312                                             cid_load_glyph );
313
314      /* set up the decoder */
315      decoder.builder.no_recurse = FT_BOOL(
316        ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
317
318      error = cid_load_glyph( &decoder, glyph_index );
319
320      font_matrix = decoder.font_matrix;
321      font_offset = decoder.font_offset;
322
323      /* save new glyph tables */
324      psaux->t1_decoder_funcs->done( &decoder );
325    }
326
327    /* now, set the metrics -- this is rather simple, as   */
328    /* the left side bearing is the xMin, and the top side */
329    /* bearing the yMax                                    */
330    if ( !error )
331    {
332      cidglyph->outline.flags &= FT_OUTLINE_OWNER;
333      cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;
334
335      /* for composite glyphs, return only left side bearing and */
336      /* advance width                                           */
337      if ( load_flags & FT_LOAD_NO_RECURSE )
338      {
339        FT_Slot_Internal  internal = cidglyph->internal;
340
341
342        cidglyph->metrics.horiBearingX = decoder.builder.left_bearing.x;
343        cidglyph->metrics.horiAdvance  = decoder.builder.advance.x;
344
345        internal->glyph_matrix         = font_matrix;
346        internal->glyph_delta          = font_offset;
347        internal->glyph_transformed    = 1;
348      }
349      else
350      {
351        FT_BBox            cbox;
352        FT_Glyph_Metrics*  metrics = &cidglyph->metrics;
353        FT_Vector          advance;
354
355
356        /* copy the _unscaled_ advance width */
357        metrics->horiAdvance                  = decoder.builder.advance.x;
358        cidglyph->linearHoriAdvance           = decoder.builder.advance.x;
359        cidglyph->internal->glyph_transformed = 0;
360
361        /* make up vertical metrics */
362        metrics->vertBearingX = 0;
363        metrics->vertBearingY = 0;
364        metrics->vertAdvance  = 0;
365
366        cidglyph->linearVertAdvance = 0;
367        cidglyph->format            = FT_GLYPH_FORMAT_OUTLINE;
368
369        if ( size && cidsize->metrics.y_ppem < 24 )
370          cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
371
372        /* apply the font matrix */
373        FT_Outline_Transform( &cidglyph->outline, &font_matrix );
374
375        FT_Outline_Translate( &cidglyph->outline,
376                              font_offset.x,
377                              font_offset.y );
378
379        advance.x = metrics->horiAdvance;
380        advance.y = 0;
381        FT_Vector_Transform( &advance, &font_matrix );
382        metrics->horiAdvance = advance.x + font_offset.x;
383        advance.x = 0;
384        advance.y = metrics->vertAdvance;
385        FT_Vector_Transform( &advance, &font_matrix );
386        metrics->vertAdvance = advance.y + font_offset.y;
387
388        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
389        {
390          /* scale the outline and the metrics */
391          FT_Int       n;
392          FT_Outline*  cur = decoder.builder.base;
393          FT_Vector*   vec = cur->points;
394          FT_Fixed     x_scale = glyph->x_scale;
395          FT_Fixed     y_scale = glyph->y_scale;
396
397
398          /* First of all, scale the points */
399          if ( !hinting )
400            for ( n = cur->n_points; n > 0; n--, vec++ )
401            {
402              vec->x = FT_MulFix( vec->x, x_scale );
403              vec->y = FT_MulFix( vec->y, y_scale );
404            }
405
406          FT_Outline_Get_CBox( &cidglyph->outline, &cbox );
407
408          /* Then scale the metrics */
409          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
410          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
411
412          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
413          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
414
415          if ( hinting )
416          {
417            metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
418            metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
419
420            metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX );
421            metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY );
422          }
423        }
424
425        /* compute the other metrics */
426        FT_Outline_Get_CBox( &cidglyph->outline, &cbox );
427
428        /* grid fit the bounding box if necessary */
429        if ( hinting )
430        {
431          cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
432          cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
433          cbox.xMax = FT_PIX_CEIL( cbox.xMax );
434          cbox.yMax = FT_PIX_CEIL( cbox.yMax );
435        }
436
437        metrics->width  = cbox.xMax - cbox.xMin;
438        metrics->height = cbox.yMax - cbox.yMin;
439
440        metrics->horiBearingX = cbox.xMin;
441        metrics->horiBearingY = cbox.yMax;
442      }
443    }
444
445    return error;
446  }
447
448
449/* END */
Note: See TracBrowser for help on using the repository browser.