1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  cidload.c                                                              */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    CID-keyed Type1 font loader (body).                                  */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 1996-2006, 2009, 2011-2013 by                                */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h"
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h"
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/config/ftconfig.h"
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftmm.h"
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/t1types.h"
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidload.h"
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ciderrs.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* messages during execution.                                            */
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_cidload
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a single offset */
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Long )
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_get_offset( FT_Byte*  *start,
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte    offsize )
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  result;
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p = *start;
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( result = 0; offsize > 0; offsize-- )
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      result <<= 8;
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      result  |= *p++;
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *start = p;
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FT_Long)result;
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                    TYPE 1 SYMBOL PARSING                      *****/
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_load_keyword( CID_Face        face,
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    CID_Loader*     loader,
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const T1_Field  keyword )
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error      error;
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*   parser = &loader->parser;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*      object;
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void*         dummy_object;
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceInfo  cid = &face->cid;
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* if the keyword has a dedicated callback, call it */
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      keyword->reader( (FT_Face)face, parser );
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = parser->root.error;
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* we must now compute the address of our target object */
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch ( keyword->location )
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case T1_FIELD_LOCATION_CID_INFO:
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      object = (FT_Byte*)cid;
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case T1_FIELD_LOCATION_FONT_INFO:
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      object = (FT_Byte*)&cid->font_info;
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case T1_FIELD_LOCATION_FONT_EXTRA:
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      object = (FT_Byte*)&face->font_extra;
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case T1_FIELD_LOCATION_BBOX:
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      object = (FT_Byte*)&cid->font_bbox;
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      break;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    default:
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CID_FaceDict  dict;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts )
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     keyword->ident ));
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Syntax_Error );
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dict = cid->font_dicts + parser->num_dict;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        switch ( keyword->location )
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case T1_FIELD_LOCATION_PRIVATE:
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          object = (FT_Byte*)&dict->private_dict;
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        default:
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          object = (FT_Byte*)dict;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dummy_object = object;
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* now, load the keyword data in the object's field(s) */
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         keyword->type == T1_FIELD_TYPE_FIXED_ARRAY   )
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = cid_parser_load_field_table( &loader->parser, keyword,
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           &dummy_object );
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = cid_parser_load_field( &loader->parser,
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     keyword, &dummy_object );
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( FT_Error )
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_parse_font_matrix( CID_Face     face,
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         CID_Parser*  parser )
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Matrix*    matrix;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector*    offset;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceDict  dict;
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Face       root = (FT_Face)&face->root;
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed      temp[6];
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed      temp_scale;
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict   = face->cid.font_dicts + parser->num_dict;
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix = &dict->font_matrix;
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset = &dict->font_offset;
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp_scale = FT_ABS( temp[3] );
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Set Units per EM based on FontMatrix values.  We set the value to */
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* 1000 / temp_scale, because temp_scale was already multiplied by   */
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* 1000 (in t1_tofixed, from psobjs.c).                              */
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* we need to scale the values by 1.0/temp[3] */
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( temp_scale != 0x10000L )
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[0] = FT_DivFix( temp[0], temp_scale );
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[1] = FT_DivFix( temp[1], temp_scale );
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[2] = FT_DivFix( temp[2], temp_scale );
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[4] = FT_DivFix( temp[4], temp_scale );
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[5] = FT_DivFix( temp[5], temp_scale );
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[3] = 0x10000L;
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xx = temp[0];
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yx = temp[1];
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xy = temp[2];
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yy = temp[3];
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* note that the font offsets are expressed in integer font units */
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->x  = temp[4] >> 16;
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->y  = temp[5] >> 16;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;      /* this is a callback function; */
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            /* we must return an error code */
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( FT_Error )
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  parse_fd_array( CID_Face     face,
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  CID_Parser*  parser )
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceInfo  cid    = &face->cid;
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory     memory = face->root.memory;
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error      error  = FT_Err_Ok;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long       num_dicts;
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    num_dicts = cid_parser_to_int( parser );
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !cid->font_dicts )
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int  n;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cid->num_dicts = (FT_UInt)num_dicts;
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* don't forget to set a few defaults */
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < cid->num_dicts; n++ )
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CID_FaceDict  dict = cid->font_dicts + n;
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* default value for lenIV */
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dict->private_dict.lenIV = 4;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* by mistake, `expansion_factor' appears both in PS_PrivateRec */
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* and CID_FaceDictRec (both are public header files and can't  */
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* changed); we simply copy the value                           */
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( FT_Error )
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  parse_expansion_factor( CID_Face     face,
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          CID_Parser*  parser )
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceDict  dict;
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict = face->cid.font_dicts + parser->num_dict;
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->expansion_factor              = cid_parser_to_fixed( parser, 0 );
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->private_dict.expansion_factor = dict->expansion_factor;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  const T1_FieldRec  cid_field_records[] =
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidtoken.h"
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "FDArray",         parse_fd_array, 0 )
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "FontMatrix",      cid_parse_font_matrix, 0 )
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_parse_dict( CID_Face     face,
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  CID_Loader*  loader,
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte*     base,
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long      size )
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser = &loader->parser;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.cursor = base;
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.limit  = base + size;
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.error  = FT_Err_Ok;
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  cur   = base;
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  limit = cur + size;
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (;;)
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Byte*  newlimit;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        parser->root.cursor = cur;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cid_parser_skip_spaces( parser );
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->root.cursor >= limit )
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          newlimit = limit - 1 - 17;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          newlimit = parser->root.cursor - 17;
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* look for `%ADOBeginFontDict' */
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( ; cur < newlimit; cur++ )
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( *cur == '%'                                            &&
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* if /FDArray was found, then cid->num_dicts is > 0, and */
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* we can start increasing parser->num_dict               */
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( face->cid.num_dicts > 0 )
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              parser->num_dict++;
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cur = parser->root.cursor;
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* no error can occur in cid_parser_skip_spaces */
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( cur >= limit )
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cid_parser_skip_PS_token( parser );
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->root.cursor >= limit || parser->root.error )
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* look for immediates */
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *cur == '/' && cur + 2 < limit )
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_PtrDist  len;
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          cur++;
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          len = parser->root.cursor - cur;
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( len > 0 && len < 22 )
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* now compare the immediate name to the keyword table */
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            T1_Field  keyword = (T1_Field)cid_field_records;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (;;)
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            {
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Byte*  name;
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              name = (FT_Byte*)keyword->ident;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if ( !name )
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if ( cur[0] == name[0]                                 &&
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   len == (FT_PtrDist)ft_strlen( (const char*)name ) )
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_PtrDist  n;
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for ( n = 1; n < len; n++ )
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  if ( cur[n] != name[n] )
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if ( n >= len )
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  /* we found it - run the parsing callback */
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  parser->root.error = cid_load_keyword( face,
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                         loader,
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                         keyword );
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  if ( parser->root.error )
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    return parser->root.error;
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  break;
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              keyword++;
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cur = parser->root.cursor;
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return parser->root.error;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read the subrmap and the subrs of each font dict */
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_read_subrs( CID_Face  face )
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceInfo   cid    = &face->cid;
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory      memory = face->root.memory;
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream      stream = face->cid_stream;
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error       error;
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int         n;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Subrs      subr;
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt        max_offsets = 0;
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong*      offsets = 0;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PSAux_Service  psaux = (PSAux_Service)face->psaux;
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    subr = face->subrs;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( n = 0; n < cid->num_dicts; n++, subr++ )
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      CID_FaceDict  dict  = cid->font_dicts + n;
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int        lenIV = dict->private_dict.lenIV;
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt       count, num_subrs = dict->num_subrs;
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ULong      data_len;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*      p;
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Check for possible overflow. */
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( num_subrs == FT_UINT_MAX )
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Syntax_Error );
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* reallocate offsets array if needed */
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( num_subrs + 1 > max_offsets )
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_UInt  new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( new_max <= max_offsets )
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Syntax_Error );
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        max_offsets = new_max;
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* read the subrmap's offsets */
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes )      )
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p = (FT_Byte*)stream->cursor;
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 0; count <= num_subrs; count++ )
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FRAME_EXIT();
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* offsets must be ordered */
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 1; count <= num_subrs; count++ )
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( offsets[count - 1] > offsets[count] )
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* now, compute the size of subrs charstrings, */
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* allocate, and read them                     */
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      data_len = offsets[num_subrs] - offsets[0];
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               FT_ALLOC( subr->code[0], data_len )   )
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           FT_STREAM_READ( subr->code[0], data_len )  )
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* set up pointers */
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 1; count <= num_subrs; count++ )
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  len;
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        len               = offsets[count] - offsets[count - 1];
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        subr->code[count] = subr->code[count - 1] + len;
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* decrypt subroutines, but only if lenIV >= 0 */
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( lenIV >= 0 )
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( count = 0; count < num_subrs; count++ )
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_ULong  len;
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          len = offsets[count + 1] - offsets[count];
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          psaux->t1_decrypt( subr->code[count], len, 4330 );
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      subr->num_subrs = num_subrs;
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_FREE( offsets );
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( face->subrs )
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < cid->num_dicts; n++ )
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( face->subrs[n].code )
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_FREE( face->subrs[n].code[0] );
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_FREE( face->subrs[n].code );
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FREE( face->subrs );
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_init_loader( CID_Loader*  loader,
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   CID_Face     face )
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( face );
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_MEM_ZERO( loader, sizeof ( *loader ) );
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static  void
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_done_loader( CID_Loader*  loader )
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser = &loader->parser;
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* finalize parser */
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_parser_done( parser );
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_hex_to_binary( FT_Byte*  data,
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Long   data_len,
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_ULong  offset,
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     CID_Face  face )
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream  stream = face->root.stream;
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error   error;
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte    buffer[256];
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte   *p, *plimit;
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte   *d, *dlimit;
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte    val;
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bool    upper_nibble, done;
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_STREAM_SEEK( offset ) )
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d      = data;
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dlimit = d + data_len;
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p      = buffer;
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    plimit = p;
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    upper_nibble = 1;
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    done         = 0;
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( d < dlimit )
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p >= plimit )
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  oldpos = FT_STREAM_POS();
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  size   = stream->size - oldpos;
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( size == 0 )
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Syntax_Error );
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p      = buffer;
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        plimit = p + FT_STREAM_POS() - oldpos;
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( ft_isdigit( *p ) )
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - '0' );
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p >= 'a' && *p <= 'f' )
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - 'a' );
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p >= 'A' && *p <= 'F' )
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - 'A' + 10 );
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p == ' '  ||
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\t' ||
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\r' ||
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\n' ||
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\f' ||
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\0' )
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p++;
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        continue;
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p == '>' )
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val  = 0;
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        done = 1;
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Syntax_Error );
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( upper_nibble )
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *d = (FT_Byte)( val << 4 );
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *d = (FT_Byte)( *d + val );
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d++;
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      upper_nibble = (FT_Byte)( 1 - upper_nibble );
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( done )
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p++;
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_Err_Ok;
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_face_open( CID_Face  face,
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Int    face_index )
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Loader   loader;
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser;
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory    memory = face->root.memory;
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error     error;
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_init_loader( &loader, face );
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser = &loader.parser;
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_parser_new( parser, face->root.stream, face->root.memory,
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            (PSAux_Service)face->psaux );
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_parse_dict( face, &loader,
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            parser->postscript,
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            parser->postscript_len );
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( face_index < 0 )
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_NEW( face->cid_stream ) )
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->binary_length )
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* we must convert the data section from hexadecimal to binary */
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_ALLOC( face->binary_data, parser->binary_length )         ||
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           cid_hex_to_binary( face->binary_data, parser->binary_length,
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              parser->data_offset, face )               )
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Stream_OpenMemory( face->cid_stream,
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            face->binary_data, parser->binary_length );
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      face->cid.data_offset = 0;
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *face->cid_stream     = *face->root.stream;
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      face->cid.data_offset = loader.parser.data_offset;
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_read_subrs( face );
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_done_loader( &loader );
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
691