Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 1 | /***************************************************************************/ |
| 2 | /* */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 3 | /* t1parse.c */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 4 | /* */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 5 | /* Type 1 parser (body). */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 6 | /* */ |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 7 | /* Copyright 1996-2001, 2002, 2003, 2004 by */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 8 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| 9 | /* */ |
| 10 | /* This file is part of the FreeType project, and may only be used, */ |
| 11 | /* modified, and distributed under the terms of the FreeType project */ |
| 12 | /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
| 13 | /* this file you indicate that you have read the license and */ |
| 14 | /* understand and accept it fully. */ |
| 15 | /* */ |
| 16 | /***************************************************************************/ |
| 17 | |
| 18 | |
| 19 | /*************************************************************************/ |
| 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 Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 24 | /* a `T1_Table' (used to build various tables needed by the loader). */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 25 | /* */ |
| 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 Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 31 | /* See `t1load.c' to see how data is loaded from the font file. */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 32 | /* */ |
| 33 | /*************************************************************************/ |
| 34 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 35 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 36 | #include <ft2build.h> |
| 37 | #include FT_INTERNAL_DEBUG_H |
| 38 | #include FT_INTERNAL_CALC_H |
| 39 | #include FT_INTERNAL_STREAM_H |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 40 | #include FT_INTERNAL_POSTSCRIPT_AUX_H |
Werner Lemberg | 1f7f0e8 | 2001-06-06 17:30:41 +0000 | [diff] [blame] | 41 | |
David Turner | 8d3a401 | 2001-03-20 11:14:24 +0000 | [diff] [blame] | 42 | #include "t1parse.h" |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 43 | |
Werner Lemberg | 1f7f0e8 | 2001-06-06 17:30:41 +0000 | [diff] [blame] | 44 | #include "t1errors.h" |
| 45 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 46 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 47 | /*************************************************************************/ |
| 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 Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 54 | #define FT_COMPONENT trace_t1parse |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 55 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 56 | |
| 57 | /*************************************************************************/ |
| 58 | /*************************************************************************/ |
| 59 | /*************************************************************************/ |
| 60 | /***** *****/ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 61 | /***** INPUT STREAM PARSER *****/ |
| 62 | /***** *****/ |
| 63 | /*************************************************************************/ |
| 64 | /*************************************************************************/ |
| 65 | /*************************************************************************/ |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 66 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 67 | |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 68 | static FT_Error |
| 69 | read_pfb_tag( FT_Stream stream, |
| 70 | FT_UShort *atag, |
| 71 | FT_Long *asize ) |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 72 | { |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 73 | FT_Error error; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 74 | FT_UShort tag; |
| 75 | FT_Long size; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 76 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 77 | |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 78 | *atag = 0; |
| 79 | *asize = 0; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 80 | |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 81 | if ( !FT_READ_USHORT( tag ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 82 | { |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 83 | if ( tag == 0x8001U || tag == 0x8002U ) |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 84 | { |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 85 | if ( !FT_READ_LONG_LE( size ) ) |
| 86 | *asize = size; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 87 | } |
Werner Lemberg | a126d4c | 2003-09-20 14:25:10 +0000 | [diff] [blame] | 88 | |
Werner Lemberg | 3864f4e | 2003-09-30 06:43:54 +0000 | [diff] [blame] | 89 | *atag = tag; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 90 | } |
Werner Lemberg | a126d4c | 2003-09-20 14:25:10 +0000 | [diff] [blame] | 91 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 92 | return error; |
| 93 | } |
| 94 | |
| 95 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 96 | FT_LOCAL_DEF( FT_Error ) |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 97 | T1_New_Parser( T1_Parser parser, |
| 98 | FT_Stream stream, |
| 99 | FT_Memory memory, |
| 100 | PSAux_Service psaux ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 101 | { |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 102 | FT_Error error; |
| 103 | FT_UShort tag; |
| 104 | FT_Long size; |
| 105 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 106 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 107 | psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 108 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 109 | parser->stream = stream; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 110 | 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 Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 117 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 118 | /******************************************************************/ |
| 119 | /* */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 120 | /* Here a short summary of what is going on: */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 121 | /* */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 122 | /* 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 Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 125 | /* */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 126 | /* 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 Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 129 | /* */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 130 | /* 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 Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 132 | /* */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 133 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 134 | /* try to compute the size of the base dictionary; */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 135 | /* look for a Postscript binary file tag, i.e 0x8001 */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 136 | if ( FT_STREAM_SEEK( 0L ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 137 | goto Exit; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 138 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 139 | error = read_pfb_tag( stream, &tag, &size ); |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 140 | if ( error ) |
| 141 | goto Exit; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 142 | |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 143 | if ( tag != 0x8001U ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 144 | { |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 145 | /* assume that this is a PFA file for now; an error will */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 146 | /* be produced later when more things are checked */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 147 | if ( FT_STREAM_SEEK( 0L ) ) |
Werner Lemberg | e72c9fe | 2000-07-31 18:59:02 +0000 | [diff] [blame] | 148 | goto Exit; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 149 | size = stream->size; |
| 150 | } |
| 151 | else |
| 152 | parser->in_pfb = 1; |
| 153 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 154 | /* now, try to load `size' bytes of the `base' dictionary we */ |
| 155 | /* found previously */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 156 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 157 | /* if it is a memory-based resource, set up pointers */ |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 158 | if ( !stream->read ) |
| 159 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 160 | parser->base_dict = (FT_Byte*)stream->base + stream->pos; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 161 | parser->base_len = size; |
| 162 | parser->in_memory = 1; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 163 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 164 | /* check that the `size' field is valid */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 165 | if ( FT_STREAM_SKIP( size ) ) |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 166 | goto Exit; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 167 | } |
| 168 | else |
| 169 | { |
| 170 | /* read segment in memory */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 171 | if ( FT_ALLOC( parser->base_dict, size ) || |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 172 | FT_STREAM_READ( parser->base_dict, size ) ) |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 173 | goto Exit; |
| 174 | parser->base_len = size; |
| 175 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 176 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 177 | /* Now check font format; we must see `%!PS-AdobeFont-1' */ |
| 178 | /* or `%!FontType' */ |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 179 | { |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 180 | if ( size <= 16 || |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 181 | ( ft_strncmp( (const char*)parser->base_dict, |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 182 | "%!PS-AdobeFont-1", 16 ) && |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 183 | ft_strncmp( (const char*)parser->base_dict, |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 184 | "%!FontType", 10 ) ) ) |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 185 | { |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 186 | FT_TRACE2(( "[not a Type1 font]\n" )); |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 187 | error = T1_Err_Unknown_File_Format; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 188 | } |
| 189 | else |
| 190 | { |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 191 | parser->root.base = parser->base_dict; |
| 192 | parser->root.cursor = parser->base_dict; |
| 193 | parser->root.limit = parser->root.cursor + parser->base_len; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 194 | } |
| 195 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 196 | |
| 197 | Exit: |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 198 | if ( error && !parser->in_memory ) |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 199 | FT_FREE( parser->base_dict ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 200 | |
| 201 | return error; |
| 202 | } |
| 203 | |
| 204 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 205 | FT_LOCAL_DEF( void ) |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 206 | T1_Finalize_Parser( T1_Parser parser ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 207 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 208 | FT_Memory memory = parser->root.memory; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 209 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 210 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 211 | /* always free the private dictionary */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 212 | FT_FREE( parser->private_dict ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 213 | |
| 214 | /* free the base dictionary only when we have a disk stream */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 215 | if ( !parser->in_memory ) |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 216 | FT_FREE( parser->base_dict ); |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 217 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 218 | parser->root.funcs.done( &parser->root ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 219 | } |
| 220 | |
| 221 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 222 | FT_LOCAL_DEF( FT_Error ) |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 223 | T1_Get_Private_Dict( T1_Parser parser, |
| 224 | PSAux_Service psaux ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 225 | { |
| 226 | FT_Stream stream = parser->stream; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 227 | FT_Memory memory = parser->root.memory; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 228 | FT_Error error = T1_Err_Ok; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 229 | FT_Long size; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 230 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 231 | |
| 232 | if ( parser->in_pfb ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 233 | { |
| 234 | /* in the case of the PFB format, the private dictionary can be */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 235 | /* made of several segments. We thus first read the number of */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 236 | /* segments to compute the total size of the private dictionary */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 237 | /* then re-read them into memory. */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 238 | FT_Long start_pos = FT_STREAM_POS(); |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 239 | FT_UShort tag; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 240 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 241 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 242 | parser->private_len = 0; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 243 | for (;;) |
| 244 | { |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 245 | error = read_pfb_tag( stream, &tag, &size ); |
| 246 | if ( error ) |
| 247 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 248 | |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 249 | if ( tag != 0x8002U ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 250 | break; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 251 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 252 | parser->private_len += size; |
| 253 | |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 254 | if ( FT_STREAM_SKIP( size ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 255 | 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 Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 262 | FT_ERROR(( "T1_Get_Private_Dict:" )); |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 263 | FT_ERROR(( " invalid private dictionary section\n" )); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 264 | error = T1_Err_Invalid_File_Format; |
| 265 | goto Fail; |
| 266 | } |
| 267 | |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 268 | if ( FT_STREAM_SEEK( start_pos ) || |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 269 | FT_ALLOC( parser->private_dict, parser->private_len ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 270 | goto Fail; |
| 271 | |
| 272 | parser->private_len = 0; |
| 273 | for (;;) |
| 274 | { |
| 275 | error = read_pfb_tag( stream, &tag, &size ); |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 276 | if ( error || tag != 0x8002U ) |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 277 | { |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 278 | error = T1_Err_Ok; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 279 | break; |
| 280 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 281 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 282 | if ( FT_STREAM_READ( parser->private_dict + parser->private_len, |
| 283 | size ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 284 | goto Fail; |
| 285 | |
| 286 | parser->private_len += size; |
| 287 | } |
| 288 | } |
| 289 | else |
| 290 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 291 | /* We have already `loaded' the whole PFA font file into memory; */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 292 | /* if this is a memory resource, allocate a new block to hold */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 293 | /* the private dict. Otherwise, simply overwrite into the base */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 294 | /* dictionary block in the heap. */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 295 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 296 | /* first of all, look at the `eexec' keyword */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 297 | FT_Byte* cur = parser->base_dict; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 298 | FT_Byte* limit = cur + parser->base_len; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 299 | FT_Byte c; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 300 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 301 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 302 | Again: |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 303 | for (;;) |
| 304 | { |
| 305 | c = cur[0]; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 306 | if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ |
| 307 | /* newline + 4 chars */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 308 | { |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 309 | if ( cur[1] == 'e' && |
| 310 | cur[2] == 'x' && |
| 311 | cur[3] == 'e' && |
| 312 | cur[4] == 'c' ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 313 | break; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 314 | } |
| 315 | cur++; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 316 | if ( cur >= limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 317 | { |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 318 | FT_ERROR(( "T1_Get_Private_Dict:" )); |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 319 | FT_ERROR(( " could not find `eexec' keyword\n" )); |
Werner Lemberg | e35cac6 | 2000-06-11 03:46:57 +0000 | [diff] [blame] | 320 | error = T1_Err_Invalid_File_Format; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 321 | goto Exit; |
| 322 | } |
| 323 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 324 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 325 | /* 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 Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 351 | /* 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 Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 354 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 355 | Found: |
| 356 | parser->root.limit = parser->base_dict + parser->base_len; |
| 357 | |
| 358 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 359 | cur = parser->root.cursor; |
Werner Lemberg | 271b1e1 | 2004-01-19 23:31:56 +0000 | [diff] [blame] | 360 | 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 Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 375 | |
Werner Lemberg | 914b289 | 2001-03-10 17:07:42 +0000 | [diff] [blame] | 376 | size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 377 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 378 | if ( parser->in_memory ) |
| 379 | { |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 380 | /* note that we allocate one more byte to put a terminating `0' */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 381 | if ( FT_ALLOC( parser->private_dict, size + 1 ) ) |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 382 | goto Fail; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 383 | parser->private_len = size; |
| 384 | } |
| 385 | else |
| 386 | { |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 387 | parser->single_block = 1; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 388 | parser->private_dict = parser->base_dict; |
| 389 | parser->private_len = size; |
| 390 | parser->base_dict = 0; |
| 391 | parser->base_len = 0; |
| 392 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 393 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 394 | /* now determine whether the private dictionary is encoded in binary */ |
| 395 | /* or hexadecimal ASCII format -- decode it accordingly */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 396 | |
| 397 | /* we need to access the next 4 bytes (after the final \r following */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 398 | /* the `eexec' keyword); if they all are hexadecimal digits, then */ |
| 399 | /* we have a case of ASCII storage */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 400 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 401 | if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && |
| 402 | ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 403 | { |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 404 | /* ASCII hexadecimal encoding */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 405 | FT_Long len; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 406 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 407 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 408 | 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 Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 415 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 416 | /* put a safeguard */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 417 | parser->private_dict[len] = '\0'; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 418 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 419 | else |
| 420 | /* binary encoding -- copy the private dict */ |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 421 | FT_MEM_MOVE( parser->private_dict, cur, size ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 422 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 423 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 424 | /* we now decrypt the encoded binary private dictionary */ |
Werner Lemberg | a560a1e | 2001-07-03 12:45:24 +0000 | [diff] [blame] | 425 | psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 426 | |
| 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 Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 433 | parser->root.base = parser->private_dict; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 434 | parser->root.cursor = parser->private_dict; |
| 435 | parser->root.limit = parser->root.cursor + parser->private_len; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 436 | |
| 437 | Fail: |
| 438 | Exit: |
| 439 | return error; |
| 440 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 441 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 442 | |
| 443 | /* END */ |