1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  cidload.c                                                              */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    CID-keyed Type1 font loader (body).                                  */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann/*  Copyright 1996-2015 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
19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h>
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_CONFIG_CONFIG_H
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_MULTIPLE_MASTERS_H
23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_TYPE1_TYPES_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 */
41ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FT_LOCAL_DEF( FT_ULong )
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;
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return 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    CID_FaceDict  dict;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Face       root = (FT_Face)&face->root;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed      temp[6];
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed      temp_scale;
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      FT_Matrix*  matrix;
162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      FT_Vector*  offset;
163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      FT_Int      result;
164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict   = face->cid.font_dicts + parser->num_dict;
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix = &dict->font_matrix;
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset = &dict->font_offset;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      /* input is scaled by 1000 to accommodate default FontMatrix */
171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      result = cid_parser_to_fixed_array( parser, 6, temp, 3 );
172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      if ( result < 6 )
174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return FT_THROW( Invalid_File_Format );
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp_scale = FT_ABS( temp[3] );
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      if ( temp_scale == 0 )
179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      {
180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FT_ERROR(( "cid_parse_font_matrix: invalid font matrix\n" ));
181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return FT_THROW( Invalid_File_Format );
182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      }
183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
184ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      /* atypical case */
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( temp_scale != 0x10000L )
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
187ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        /* set units per EM based on FontMatrix values */
188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[0] = FT_DivFix( temp[0], temp_scale );
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[1] = FT_DivFix( temp[1], temp_scale );
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[2] = FT_DivFix( temp[2], temp_scale );
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[4] = FT_DivFix( temp[4], temp_scale );
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        temp[5] = FT_DivFix( temp[5], temp_scale );
195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xx = temp[0];
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yx = temp[1];
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xy = temp[2];
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yy = temp[3];
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* note that the font offsets are expressed in integer font units */
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->x  = temp[4] >> 16;
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->y  = temp[5] >> 16;
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return FT_Err_Ok;
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( FT_Error )
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  parse_fd_array( CID_Face     face,
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  CID_Parser*  parser )
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceInfo  cid    = &face->cid;
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory     memory = face->root.memory;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error      error  = FT_Err_Ok;
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long       num_dicts;
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    num_dicts = cid_parser_to_int( parser );
223ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if ( num_dicts < 0 )
224ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    {
225ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FT_ERROR(( "parse_fd_array: invalid number of dictionaries\n" ));
226ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      error = FT_THROW( Invalid_File_Format );
227ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      goto Exit;
228ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !cid->font_dicts )
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int  n;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
238ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      cid->num_dicts = num_dicts;
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* don't forget to set a few defaults */
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < cid->num_dicts; n++ )
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CID_FaceDict  dict = cid->font_dicts + n;
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* default value for lenIV */
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dict->private_dict.lenIV = 4;
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* by mistake, `expansion_factor' appears both in PS_PrivateRec */
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* and CID_FaceDictRec (both are public header files and can't  */
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* changed); we simply copy the value                           */
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CALLBACK_DEF( FT_Error )
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  parse_expansion_factor( CID_Face     face,
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          CID_Parser*  parser )
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceDict  dict;
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict = face->cid.font_dicts + parser->num_dict;
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->expansion_factor              = cid_parser_to_fixed( parser, 0 );
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->private_dict.expansion_factor = dict->expansion_factor;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  const T1_FieldRec  cid_field_records[] =
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidtoken.h"
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "FDArray",         parse_fd_array, 0 )
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "FontMatrix",      cid_parse_font_matrix, 0 )
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_parse_dict( CID_Face     face,
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  CID_Loader*  loader,
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte*     base,
297ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  FT_ULong     size )
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser = &loader->parser;
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.cursor = base;
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.limit  = base + size;
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->root.error  = FT_Err_Ok;
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  cur   = base;
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*  limit = cur + size;
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (;;)
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Byte*  newlimit;
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        parser->root.cursor = cur;
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cid_parser_skip_spaces( parser );
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->root.cursor >= limit )
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          newlimit = limit - 1 - 17;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          newlimit = parser->root.cursor - 17;
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* look for `%ADOBeginFontDict' */
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( ; cur < newlimit; cur++ )
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( *cur == '%'                                            &&
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* if /FDArray was found, then cid->num_dicts is > 0, and */
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* we can start increasing parser->num_dict               */
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( face->cid.num_dicts > 0 )
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              parser->num_dict++;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cur = parser->root.cursor;
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* no error can occur in cid_parser_skip_spaces */
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( cur >= limit )
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cid_parser_skip_PS_token( parser );
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->root.cursor >= limit || parser->root.error )
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* look for immediates */
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( *cur == '/' && cur + 2 < limit )
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
349ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FT_UInt  len;
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          cur++;
353ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          len = (FT_UInt)( parser->root.cursor - cur );
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( len > 0 && len < 22 )
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* now compare the immediate name to the keyword table */
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            T1_Field  keyword = (T1_Field)cid_field_records;
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (;;)
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            {
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Byte*  name;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              name = (FT_Byte*)keyword->ident;
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if ( !name )
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
370ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              if ( cur[0] == name[0]                     &&
371ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   len == ft_strlen( (const char*)name ) )
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
373ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                FT_UInt  n;
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for ( n = 1; n < len; n++ )
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  if ( cur[n] != name[n] )
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if ( n >= len )
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  /* we found it - run the parsing callback */
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  parser->root.error = cid_load_keyword( face,
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                         loader,
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                         keyword );
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  if ( parser->root.error )
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    return parser->root.error;
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  break;
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              keyword++;
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cur = parser->root.cursor;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return parser->root.error;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read the subrmap and the subrs of each font dict */
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_read_subrs( CID_Face  face )
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_FaceInfo   cid    = &face->cid;
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory      memory = face->root.memory;
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream      stream = face->cid_stream;
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error       error;
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int         n;
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Subrs      subr;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt        max_offsets = 0;
414ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FT_ULong*      offsets = NULL;
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    PSAux_Service  psaux = (PSAux_Service)face->psaux;
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    subr = face->subrs;
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( n = 0; n < cid->num_dicts; n++, subr++ )
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      CID_FaceDict  dict  = cid->font_dicts + n;
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int        lenIV = dict->private_dict.lenIV;
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt       count, num_subrs = dict->num_subrs;
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ULong      data_len;
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Byte*      p;
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Check for possible overflow. */
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( num_subrs == FT_UINT_MAX )
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Syntax_Error );
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* reallocate offsets array if needed */
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( num_subrs + 1 > max_offsets )
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_UInt  new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( new_max <= max_offsets )
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Syntax_Error );
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        max_offsets = new_max;
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* read the subrmap's offsets */
457ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset )     ||
458ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann           FT_FRAME_ENTER( ( num_subrs + 1 ) * (FT_UInt)dict->sd_bytes ) )
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p = (FT_Byte*)stream->cursor;
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 0; count <= num_subrs; count++ )
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FRAME_EXIT();
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* offsets must be ordered */
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 1; count <= num_subrs; count++ )
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( offsets[count - 1] > offsets[count] )
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Fail;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* now, compute the size of subrs charstrings, */
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* allocate, and read them                     */
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      data_len = offsets[num_subrs] - offsets[0];
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               FT_ALLOC( subr->code[0], data_len )   )
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           FT_STREAM_READ( subr->code[0], data_len )  )
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Fail;
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* set up pointers */
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( count = 1; count <= num_subrs; count++ )
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  len;
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        len               = offsets[count] - offsets[count - 1];
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        subr->code[count] = subr->code[count - 1] + len;
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* decrypt subroutines, but only if lenIV >= 0 */
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( lenIV >= 0 )
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( count = 0; count < num_subrs; count++ )
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_ULong  len;
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          len = offsets[count + 1] - offsets[count];
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          psaux->t1_decrypt( subr->code[count], len, 4330 );
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
507ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      subr->num_subrs = (FT_Int)num_subrs;
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_FREE( offsets );
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Fail:
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( face->subrs )
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for ( n = 0; n < cid->num_dicts; n++ )
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( face->subrs[n].code )
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          FT_FREE( face->subrs[n].code[0] );
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_FREE( face->subrs[n].code );
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FREE( face->subrs );
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_init_loader( CID_Loader*  loader,
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   CID_Face     face )
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( face );
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_MEM_ZERO( loader, sizeof ( *loader ) );
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static  void
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_done_loader( CID_Loader*  loader )
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser = &loader->parser;
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* finalize parser */
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_parser_done( parser );
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_hex_to_binary( FT_Byte*  data,
553ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     FT_ULong  data_len,
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_ULong  offset,
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     CID_Face  face )
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Stream  stream = face->root.stream;
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error   error;
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte    buffer[256];
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte   *p, *plimit;
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte   *d, *dlimit;
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte    val;
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Bool    upper_nibble, done;
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_STREAM_SEEK( offset ) )
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d      = data;
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dlimit = d + data_len;
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p      = buffer;
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    plimit = p;
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    upper_nibble = 1;
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    done         = 0;
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( d < dlimit )
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p >= plimit )
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  oldpos = FT_STREAM_POS();
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_ULong  size   = stream->size - oldpos;
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( size == 0 )
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          error = FT_THROW( Syntax_Error );
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p      = buffer;
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        plimit = p + FT_STREAM_POS() - oldpos;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( ft_isdigit( *p ) )
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - '0' );
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p >= 'a' && *p <= 'f' )
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - 'a' );
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p >= 'A' && *p <= 'F' )
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = (FT_Byte)( *p - 'A' + 10 );
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p == ' '  ||
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\t' ||
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\r' ||
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\n' ||
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\f' ||
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *p == '\0' )
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p++;
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        continue;
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( *p == '>' )
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val  = 0;
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        done = 1;
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Syntax_Error );
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( upper_nibble )
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *d = (FT_Byte)( val << 4 );
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *d = (FT_Byte)( *d + val );
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        d++;
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      upper_nibble = (FT_Byte)( 1 - upper_nibble );
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( done )
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p++;
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_Err_Ok;
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cid_face_open( CID_Face  face,
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Int    face_index )
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Loader   loader;
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CID_Parser*  parser;
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory    memory = face->root.memory;
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error     error;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_init_loader( &loader, face );
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser = &loader.parser;
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_parser_new( parser, face->root.stream, face->root.memory,
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            (PSAux_Service)face->psaux );
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_parse_dict( face, &loader,
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            parser->postscript,
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            parser->postscript_len );
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( error )
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( face_index < 0 )
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_NEW( face->cid_stream ) )
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->binary_length )
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* we must convert the data section from hexadecimal to binary */
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( FT_ALLOC( face->binary_data, parser->binary_length )         ||
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           cid_hex_to_binary( face->binary_data, parser->binary_length,
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              parser->data_offset, face )               )
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Stream_OpenMemory( face->cid_stream,
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            face->binary_data, parser->binary_length );
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      face->cid.data_offset = 0;
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *face->cid_stream     = *face->root.stream;
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      face->cid.data_offset = loader.parser.data_offset;
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = cid_read_subrs( face );
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cid_done_loader( &loader );
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
706