blob: 544aa093f8df230001b2f1d03edb8b5b2f89f728 [file] [log] [blame]
Werner Lemberg7fa51b52000-07-08 19:51:42 +00001/***************************************************************************/
2/* */
Werner Lembergb5084e12000-10-28 17:10:06 +00003/* t1parse.c */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00004/* */
Werner Lembergb5084e12000-10-28 17:10:06 +00005/* Type 1 parser (body). */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00006/* */
Werner Lemberg5972e9a2004-02-01 00:49:56 +00007/* Copyright 1996-2001, 2002, 2003, 2004 by */
Werner Lemberg7fa51b52000-07-08 19:51:42 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18
19 /*************************************************************************/
20 /* */
21 /* The Type 1 parser is in charge of the following: */
22 /* */
23 /* - provide an implementation of a growing sequence of objects called */
Werner Lembergb5084e12000-10-28 17:10:06 +000024 /* a `T1_Table' (used to build various tables needed by the loader). */
Werner Lemberg7fa51b52000-07-08 19:51:42 +000025 /* */
26 /* - opening .pfb and .pfa files to extract their top-level and private */
27 /* dictionaries. */
28 /* */
29 /* - read numbers, arrays & strings from any dictionary. */
30 /* */
Werner Lembergb5084e12000-10-28 17:10:06 +000031 /* See `t1load.c' to see how data is loaded from the font file. */
Werner Lemberg7fa51b52000-07-08 19:51:42 +000032 /* */
33 /*************************************************************************/
34
Werner Lembergcc069be2000-12-08 16:17:16 +000035
David Turner19ed8af2000-12-08 02:42:29 +000036#include <ft2build.h>
37#include FT_INTERNAL_DEBUG_H
38#include FT_INTERNAL_CALC_H
39#include FT_INTERNAL_STREAM_H
David Turner19ed8af2000-12-08 02:42:29 +000040#include FT_INTERNAL_POSTSCRIPT_AUX_H
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000041
David Turner8d3a4012001-03-20 11:14:24 +000042#include "t1parse.h"
Werner Lembergcc069be2000-12-08 16:17:16 +000043
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000044#include "t1errors.h"
45
David Turner1c9a1ca2000-05-24 21:12:02 +000046
Werner Lemberg7fa51b52000-07-08 19:51:42 +000047 /*************************************************************************/
48 /* */
49 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
50 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
51 /* messages during execution. */
52 /* */
53#undef FT_COMPONENT
Werner Lembergb5084e12000-10-28 17:10:06 +000054#define FT_COMPONENT trace_t1parse
David Turner2dfb5ac2000-01-27 14:02:04 +000055
Werner Lemberg7fa51b52000-07-08 19:51:42 +000056
57 /*************************************************************************/
58 /*************************************************************************/
59 /*************************************************************************/
60 /***** *****/
Werner Lemberg7fa51b52000-07-08 19:51:42 +000061 /***** INPUT STREAM PARSER *****/
62 /***** *****/
63 /*************************************************************************/
64 /*************************************************************************/
65 /*************************************************************************/
David Turner1c9a1ca2000-05-24 21:12:02 +000066
Werner Lemberg7fa51b52000-07-08 19:51:42 +000067
Werner Lemberg3864f4e2003-09-30 06:43:54 +000068 static FT_Error
69 read_pfb_tag( FT_Stream stream,
70 FT_UShort *atag,
71 FT_Long *asize )
David Turner1c9a1ca2000-05-24 21:12:02 +000072 {
Werner Lemberg3864f4e2003-09-30 06:43:54 +000073 FT_Error error;
David Turnera39acf52000-08-23 02:47:57 +000074 FT_UShort tag;
75 FT_Long size;
Werner Lemberge4b32a52000-10-31 20:42:18 +000076
David Turner1c9a1ca2000-05-24 21:12:02 +000077
Werner Lemberg3864f4e2003-09-30 06:43:54 +000078 *atag = 0;
79 *asize = 0;
Werner Lemberg7fa51b52000-07-08 19:51:42 +000080
Werner Lemberg3864f4e2003-09-30 06:43:54 +000081 if ( !FT_READ_USHORT( tag ) )
David Turner2dfb5ac2000-01-27 14:02:04 +000082 {
Werner Lemberg3864f4e2003-09-30 06:43:54 +000083 if ( tag == 0x8001U || tag == 0x8002U )
David Turnera39acf52000-08-23 02:47:57 +000084 {
Werner Lemberg3864f4e2003-09-30 06:43:54 +000085 if ( !FT_READ_LONG_LE( size ) )
86 *asize = size;
David Turnera39acf52000-08-23 02:47:57 +000087 }
Werner Lemberga126d4c2003-09-20 14:25:10 +000088
Werner Lemberg3864f4e2003-09-30 06:43:54 +000089 *atag = tag;
David Turner2dfb5ac2000-01-27 14:02:04 +000090 }
Werner Lemberga126d4c2003-09-20 14:25:10 +000091
David Turner2dfb5ac2000-01-27 14:02:04 +000092 return error;
93 }
94
95
David Turnerbc82f1b2002-03-01 02:26:22 +000096 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +000097 T1_New_Parser( T1_Parser parser,
98 FT_Stream stream,
99 FT_Memory memory,
100 PSAux_Service psaux )
David Turner2dfb5ac2000-01-27 14:02:04 +0000101 {
Werner Lemberg8728f292000-08-23 17:32:42 +0000102 FT_Error error;
103 FT_UShort tag;
104 FT_Long size;
105
David Turnere49ab252000-05-16 23:44:38 +0000106
Werner Lemberg52f911a2003-10-07 05:49:41 +0000107 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000108
David Turner2dfb5ac2000-01-27 14:02:04 +0000109 parser->stream = stream;
David Turner2dfb5ac2000-01-27 14:02:04 +0000110 parser->base_len = 0;
111 parser->base_dict = 0;
112 parser->private_len = 0;
113 parser->private_dict = 0;
114 parser->in_pfb = 0;
115 parser->in_memory = 0;
116 parser->single_block = 0;
David Turnere49ab252000-05-16 23:44:38 +0000117
David Turner2dfb5ac2000-01-27 14:02:04 +0000118 /******************************************************************/
119 /* */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000120 /* Here a short summary of what is going on: */
David Turner2dfb5ac2000-01-27 14:02:04 +0000121 /* */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000122 /* When creating a new Type 1 parser, we try to locate and load */
123 /* the base dictionary if this is possible (i.e. for PFB */
124 /* files). Otherwise, we load the whole font into memory. */
David Turner2dfb5ac2000-01-27 14:02:04 +0000125 /* */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000126 /* When `loading' the base dictionary, we only setup pointers */
127 /* in the case of a memory-based stream. Otherwise, we */
128 /* allocate and load the base dictionary in it. */
David Turner2dfb5ac2000-01-27 14:02:04 +0000129 /* */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000130 /* parser->in_pfb is set if we are in a binary (".pfb") font. */
131 /* parser->in_memory is set if we have a memory stream. */
David Turner2dfb5ac2000-01-27 14:02:04 +0000132 /* */
David Turnere49ab252000-05-16 23:44:38 +0000133
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000134 /* try to compute the size of the base dictionary; */
David Turner2dfb5ac2000-01-27 14:02:04 +0000135 /* look for a Postscript binary file tag, i.e 0x8001 */
David Turner7d3a2642002-03-20 10:49:31 +0000136 if ( FT_STREAM_SEEK( 0L ) )
David Turner2dfb5ac2000-01-27 14:02:04 +0000137 goto Exit;
David Turnere49ab252000-05-16 23:44:38 +0000138
David Turner2dfb5ac2000-01-27 14:02:04 +0000139 error = read_pfb_tag( stream, &tag, &size );
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000140 if ( error )
141 goto Exit;
David Turner2dfb5ac2000-01-27 14:02:04 +0000142
Werner Lembergefa99612002-04-01 22:01:46 +0000143 if ( tag != 0x8001U )
David Turner2dfb5ac2000-01-27 14:02:04 +0000144 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000145 /* assume that this is a PFA file for now; an error will */
David Turner2dfb5ac2000-01-27 14:02:04 +0000146 /* be produced later when more things are checked */
David Turner7d3a2642002-03-20 10:49:31 +0000147 if ( FT_STREAM_SEEK( 0L ) )
Werner Lemberge72c9fe2000-07-31 18:59:02 +0000148 goto Exit;
David Turner2dfb5ac2000-01-27 14:02:04 +0000149 size = stream->size;
150 }
151 else
152 parser->in_pfb = 1;
153
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000154 /* now, try to load `size' bytes of the `base' dictionary we */
155 /* found previously */
David Turnere49ab252000-05-16 23:44:38 +0000156
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000157 /* if it is a memory-based resource, set up pointers */
David Turner95bec282000-02-15 12:55:57 +0000158 if ( !stream->read )
159 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000160 parser->base_dict = (FT_Byte*)stream->base + stream->pos;
David Turner95bec282000-02-15 12:55:57 +0000161 parser->base_len = size;
162 parser->in_memory = 1;
David Turnere49ab252000-05-16 23:44:38 +0000163
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000164 /* check that the `size' field is valid */
David Turner7d3a2642002-03-20 10:49:31 +0000165 if ( FT_STREAM_SKIP( size ) )
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000166 goto Exit;
David Turner95bec282000-02-15 12:55:57 +0000167 }
168 else
169 {
170 /* read segment in memory */
David Turnere459d742002-03-22 13:52:37 +0000171 if ( FT_ALLOC( parser->base_dict, size ) ||
David Turner7d3a2642002-03-20 10:49:31 +0000172 FT_STREAM_READ( parser->base_dict, size ) )
David Turner95bec282000-02-15 12:55:57 +0000173 goto Exit;
174 parser->base_len = size;
175 }
David Turnere49ab252000-05-16 23:44:38 +0000176
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000177 /* Now check font format; we must see `%!PS-AdobeFont-1' */
178 /* or `%!FontType' */
David Turner95bec282000-02-15 12:55:57 +0000179 {
Werner Lemberg94ffae52002-04-14 00:54:32 +0000180 if ( size <= 16 ||
David Turnerd15bc0d2002-04-12 09:31:48 +0000181 ( ft_strncmp( (const char*)parser->base_dict,
Werner Lemberg94ffae52002-04-14 00:54:32 +0000182 "%!PS-AdobeFont-1", 16 ) &&
David Turnerd15bc0d2002-04-12 09:31:48 +0000183 ft_strncmp( (const char*)parser->base_dict,
Werner Lemberg94ffae52002-04-14 00:54:32 +0000184 "%!FontType", 10 ) ) )
David Turner95bec282000-02-15 12:55:57 +0000185 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000186 FT_TRACE2(( "[not a Type1 font]\n" ));
Werner Lemberg1429db62001-04-02 23:54:01 +0000187 error = T1_Err_Unknown_File_Format;
David Turner95bec282000-02-15 12:55:57 +0000188 }
189 else
190 {
David Turnera39acf52000-08-23 02:47:57 +0000191 parser->root.base = parser->base_dict;
192 parser->root.cursor = parser->base_dict;
193 parser->root.limit = parser->root.cursor + parser->base_len;
David Turner95bec282000-02-15 12:55:57 +0000194 }
195 }
David Turner2dfb5ac2000-01-27 14:02:04 +0000196
197 Exit:
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000198 if ( error && !parser->in_memory )
David Turnere459d742002-03-22 13:52:37 +0000199 FT_FREE( parser->base_dict );
David Turner2dfb5ac2000-01-27 14:02:04 +0000200
201 return error;
202 }
203
204
David Turnerbc82f1b2002-03-01 02:26:22 +0000205 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000206 T1_Finalize_Parser( T1_Parser parser )
David Turner2dfb5ac2000-01-27 14:02:04 +0000207 {
Werner Lembergefa99612002-04-01 22:01:46 +0000208 FT_Memory memory = parser->root.memory;
David Turner2dfb5ac2000-01-27 14:02:04 +0000209
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000210
David Turner2dfb5ac2000-01-27 14:02:04 +0000211 /* always free the private dictionary */
David Turnere459d742002-03-22 13:52:37 +0000212 FT_FREE( parser->private_dict );
David Turner2dfb5ac2000-01-27 14:02:04 +0000213
214 /* free the base dictionary only when we have a disk stream */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000215 if ( !parser->in_memory )
David Turnere459d742002-03-22 13:52:37 +0000216 FT_FREE( parser->base_dict );
Werner Lemberge4b32a52000-10-31 20:42:18 +0000217
David Turnera39acf52000-08-23 02:47:57 +0000218 parser->root.funcs.done( &parser->root );
David Turner2dfb5ac2000-01-27 14:02:04 +0000219 }
220
221
David Turnerbc82f1b2002-03-01 02:26:22 +0000222 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +0000223 T1_Get_Private_Dict( T1_Parser parser,
224 PSAux_Service psaux )
David Turner2dfb5ac2000-01-27 14:02:04 +0000225 {
226 FT_Stream stream = parser->stream;
David Turnera39acf52000-08-23 02:47:57 +0000227 FT_Memory memory = parser->root.memory;
Werner Lemberg52f911a2003-10-07 05:49:41 +0000228 FT_Error error = T1_Err_Ok;
David Turnerf9b8dec2000-06-16 19:34:52 +0000229 FT_Long size;
David Turnere49ab252000-05-16 23:44:38 +0000230
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000231
232 if ( parser->in_pfb )
David Turner2dfb5ac2000-01-27 14:02:04 +0000233 {
234 /* in the case of the PFB format, the private dictionary can be */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000235 /* made of several segments. We thus first read the number of */
David Turner2dfb5ac2000-01-27 14:02:04 +0000236 /* segments to compute the total size of the private dictionary */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000237 /* then re-read them into memory. */
David Turner7d3a2642002-03-20 10:49:31 +0000238 FT_Long start_pos = FT_STREAM_POS();
David Turnerf9b8dec2000-06-16 19:34:52 +0000239 FT_UShort tag;
David Turner2dfb5ac2000-01-27 14:02:04 +0000240
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000241
David Turnere49ab252000-05-16 23:44:38 +0000242 parser->private_len = 0;
David Turner2dfb5ac2000-01-27 14:02:04 +0000243 for (;;)
244 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000245 error = read_pfb_tag( stream, &tag, &size );
246 if ( error )
247 goto Fail;
David Turnere49ab252000-05-16 23:44:38 +0000248
Werner Lembergefa99612002-04-01 22:01:46 +0000249 if ( tag != 0x8002U )
David Turner2dfb5ac2000-01-27 14:02:04 +0000250 break;
David Turnere49ab252000-05-16 23:44:38 +0000251
David Turner2dfb5ac2000-01-27 14:02:04 +0000252 parser->private_len += size;
253
David Turner7d3a2642002-03-20 10:49:31 +0000254 if ( FT_STREAM_SKIP( size ) )
David Turner2dfb5ac2000-01-27 14:02:04 +0000255 goto Fail;
256 }
257
258 /* Check that we have a private dictionary there */
259 /* and allocate private dictionary buffer */
260 if ( parser->private_len == 0 )
261 {
Werner Lembergb5084e12000-10-28 17:10:06 +0000262 FT_ERROR(( "T1_Get_Private_Dict:" ));
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000263 FT_ERROR(( " invalid private dictionary section\n" ));
David Turner2dfb5ac2000-01-27 14:02:04 +0000264 error = T1_Err_Invalid_File_Format;
265 goto Fail;
266 }
267
David Turner7d3a2642002-03-20 10:49:31 +0000268 if ( FT_STREAM_SEEK( start_pos ) ||
David Turnere459d742002-03-22 13:52:37 +0000269 FT_ALLOC( parser->private_dict, parser->private_len ) )
David Turner2dfb5ac2000-01-27 14:02:04 +0000270 goto Fail;
271
272 parser->private_len = 0;
273 for (;;)
274 {
275 error = read_pfb_tag( stream, &tag, &size );
Werner Lembergefa99612002-04-01 22:01:46 +0000276 if ( error || tag != 0x8002U )
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000277 {
Werner Lemberg1429db62001-04-02 23:54:01 +0000278 error = T1_Err_Ok;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000279 break;
280 }
David Turner2dfb5ac2000-01-27 14:02:04 +0000281
Werner Lemberg52f911a2003-10-07 05:49:41 +0000282 if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
283 size ) )
David Turner2dfb5ac2000-01-27 14:02:04 +0000284 goto Fail;
285
286 parser->private_len += size;
287 }
288 }
289 else
290 {
Werner Lemberg52f911a2003-10-07 05:49:41 +0000291 /* We have already `loaded' the whole PFA font file into memory; */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000292 /* if this is a memory resource, allocate a new block to hold */
Werner Lemberg52f911a2003-10-07 05:49:41 +0000293 /* the private dict. Otherwise, simply overwrite into the base */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000294 /* dictionary block in the heap. */
David Turner2dfb5ac2000-01-27 14:02:04 +0000295
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000296 /* first of all, look at the `eexec' keyword */
David Turner2dfb5ac2000-01-27 14:02:04 +0000297 FT_Byte* cur = parser->base_dict;
David Turnere49ab252000-05-16 23:44:38 +0000298 FT_Byte* limit = cur + parser->base_len;
David Turner2dfb5ac2000-01-27 14:02:04 +0000299 FT_Byte c;
David Turnere49ab252000-05-16 23:44:38 +0000300
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000301
Werner Lemberg4795b362003-10-23 16:24:10 +0000302 Again:
David Turner2dfb5ac2000-01-27 14:02:04 +0000303 for (;;)
304 {
305 c = cur[0];
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000306 if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
307 /* newline + 4 chars */
David Turner2dfb5ac2000-01-27 14:02:04 +0000308 {
Werner Lemberg4795b362003-10-23 16:24:10 +0000309 if ( cur[1] == 'e' &&
310 cur[2] == 'x' &&
311 cur[3] == 'e' &&
312 cur[4] == 'c' )
David Turner2dfb5ac2000-01-27 14:02:04 +0000313 break;
David Turner2dfb5ac2000-01-27 14:02:04 +0000314 }
315 cur++;
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000316 if ( cur >= limit )
David Turner2dfb5ac2000-01-27 14:02:04 +0000317 {
Werner Lembergb5084e12000-10-28 17:10:06 +0000318 FT_ERROR(( "T1_Get_Private_Dict:" ));
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000319 FT_ERROR(( " could not find `eexec' keyword\n" ));
Werner Lemberge35cac62000-06-11 03:46:57 +0000320 error = T1_Err_Invalid_File_Format;
David Turner2dfb5ac2000-01-27 14:02:04 +0000321 goto Exit;
322 }
323 }
David Turnere49ab252000-05-16 23:44:38 +0000324
Werner Lemberg4795b362003-10-23 16:24:10 +0000325 /* check whether `eexec' was real -- it could be in a comment */
326 /* or string (as e.g. in u003043t.gsf from ghostscript) */
327
328 parser->root.cursor = parser->base_dict;
329 parser->root.limit = cur + 9;
330
331 cur = parser->root.cursor;
332 limit = parser->root.limit;
333
334 while ( cur < limit )
335 {
336 if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
337 goto Found;
338
339 T1_Skip_PS_Token( parser );
340 T1_Skip_Spaces ( parser );
341 cur = parser->root.cursor;
342 }
343
344 /* we haven't found the correct `eexec'; go back and continue */
345 /* searching */
346
347 cur = limit;
348 limit = parser->base_dict + parser->base_len;
349 goto Again;
350
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000351 /* now determine where to write the _encrypted_ binary private */
352 /* dictionary. We overwrite the base dictionary for disk-based */
353 /* resources and allocate a new block otherwise */
David Turnere49ab252000-05-16 23:44:38 +0000354
Werner Lemberg4795b362003-10-23 16:24:10 +0000355 Found:
356 parser->root.limit = parser->base_dict + parser->base_len;
357
358 T1_Skip_PS_Token( parser );
Werner Lemberg4795b362003-10-23 16:24:10 +0000359 cur = parser->root.cursor;
Werner Lemberg271b1e12004-01-19 23:31:56 +0000360 if ( *cur == '\r' )
361 {
362 cur++;
363 if ( *cur == '\n' )
364 cur++;
365 }
366 else if ( *cur == '\n' )
367 cur++;
368 else
369 {
370 FT_ERROR(( "T1_Get_Private_Dict:" ));
371 FT_ERROR(( " `eexec' not properly terminated\n" ));
372 error = T1_Err_Invalid_File_Format;
373 goto Exit;
374 }
Werner Lemberg4795b362003-10-23 16:24:10 +0000375
Werner Lemberg914b2892001-03-10 17:07:42 +0000376 size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
David Turnere49ab252000-05-16 23:44:38 +0000377
David Turner2dfb5ac2000-01-27 14:02:04 +0000378 if ( parser->in_memory )
379 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000380 /* note that we allocate one more byte to put a terminating `0' */
David Turnere459d742002-03-22 13:52:37 +0000381 if ( FT_ALLOC( parser->private_dict, size + 1 ) )
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000382 goto Fail;
David Turner2dfb5ac2000-01-27 14:02:04 +0000383 parser->private_len = size;
384 }
385 else
386 {
David Turnere49ab252000-05-16 23:44:38 +0000387 parser->single_block = 1;
David Turner2dfb5ac2000-01-27 14:02:04 +0000388 parser->private_dict = parser->base_dict;
389 parser->private_len = size;
390 parser->base_dict = 0;
391 parser->base_len = 0;
392 }
David Turnere49ab252000-05-16 23:44:38 +0000393
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000394 /* now determine whether the private dictionary is encoded in binary */
395 /* or hexadecimal ASCII format -- decode it accordingly */
David Turner2dfb5ac2000-01-27 14:02:04 +0000396
397 /* we need to access the next 4 bytes (after the final \r following */
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000398 /* the `eexec' keyword); if they all are hexadecimal digits, then */
399 /* we have a case of ASCII storage */
David Turner2dfb5ac2000-01-27 14:02:04 +0000400
Werner Lemberg52f911a2003-10-07 05:49:41 +0000401 if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
402 ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
David Turnere49ab252000-05-16 23:44:38 +0000403 {
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000404 /* ASCII hexadecimal encoding */
Werner Lemberg52f911a2003-10-07 05:49:41 +0000405 FT_Long len;
David Turner2dfb5ac2000-01-27 14:02:04 +0000406
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000407
Werner Lemberg52f911a2003-10-07 05:49:41 +0000408 parser->root.cursor = cur;
409 (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
410 parser->private_dict,
411 parser->private_len,
412 &len,
413 0 );
414 parser->private_len = len;
David Turnere49ab252000-05-16 23:44:38 +0000415
David Turner2dfb5ac2000-01-27 14:02:04 +0000416 /* put a safeguard */
Werner Lemberg52f911a2003-10-07 05:49:41 +0000417 parser->private_dict[len] = '\0';
David Turner2dfb5ac2000-01-27 14:02:04 +0000418 }
Werner Lemberg52f911a2003-10-07 05:49:41 +0000419 else
420 /* binary encoding -- copy the private dict */
Werner Lemberg5972e9a2004-02-01 00:49:56 +0000421 FT_MEM_MOVE( parser->private_dict, cur, size );
David Turner2dfb5ac2000-01-27 14:02:04 +0000422 }
David Turnere49ab252000-05-16 23:44:38 +0000423
David Turner2dfb5ac2000-01-27 14:02:04 +0000424 /* we now decrypt the encoded binary private dictionary */
Werner Lemberga560a1e2001-07-03 12:45:24 +0000425 psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
Werner Lemberg52f911a2003-10-07 05:49:41 +0000426
427 /* replace the four random bytes at the beginning with whitespace */
428 parser->private_dict[0] = ' ';
429 parser->private_dict[1] = ' ';
430 parser->private_dict[2] = ' ';
431 parser->private_dict[3] = ' ';
432
David Turner4e7eeee2002-02-28 16:10:29 +0000433 parser->root.base = parser->private_dict;
David Turnera39acf52000-08-23 02:47:57 +0000434 parser->root.cursor = parser->private_dict;
435 parser->root.limit = parser->root.cursor + parser->private_len;
David Turner2dfb5ac2000-01-27 14:02:04 +0000436
437 Fail:
438 Exit:
439 return error;
440 }
David Turnere49ab252000-05-16 23:44:38 +0000441
Werner Lemberg7fa51b52000-07-08 19:51:42 +0000442
443/* END */