sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
cidparse.c
1/****************************************************************************
2 *
3 * cidparse.c
4 *
5 * CID-keyed Type1 parser (body).
6 *
7 * Copyright (C) 1996-2025 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
22
23#include "cidparse.h"
24
25#include "ciderrs.h"
26
27
28 /**************************************************************************
29 *
30 * The macro FT_COMPONENT is used in trace mode. It is an implicit
31 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
32 * messages during execution.
33 */
34#undef FT_COMPONENT
35#define FT_COMPONENT cidparse
36
37
38 /*************************************************************************/
39 /*************************************************************************/
40 /*************************************************************************/
41 /***** *****/
42 /***** INPUT STREAM PARSER *****/
43 /***** *****/
44 /*************************************************************************/
45 /*************************************************************************/
46 /*************************************************************************/
47
48
49#define STARTDATA "StartData"
50#define STARTDATA_LEN ( sizeof ( STARTDATA ) - 1 )
51#define SFNTS "/sfnts"
52#define SFNTS_LEN ( sizeof ( SFNTS ) - 1 )
53
54
55 FT_LOCAL_DEF( FT_Error )
56 cid_parser_new( CID_Parser* parser,
57 FT_Stream stream,
58 FT_Memory memory,
59 PSAux_Service psaux )
60 {
61 FT_Error error;
62 FT_ULong base_offset, offset, ps_len;
63 FT_Byte *cur, *limit;
64 FT_Byte *arg1, *arg2;
65
66
67 FT_ZERO( parser );
68 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
69
70 parser->stream = stream;
71
72 base_offset = FT_STREAM_POS();
73
74 /* first of all, check the font format in the header */
75 if ( FT_FRAME_ENTER( 31 ) )
76 {
77 FT_TRACE2(( " not a CID-keyed font\n" ));
78 error = FT_THROW( Unknown_File_Format );
79 goto Exit;
80 }
81
82 if ( ft_strncmp( (char *)stream->cursor,
83 "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
84 {
85 FT_TRACE2(( " not a CID-keyed font\n" ));
86 error = FT_THROW( Unknown_File_Format );
87 }
88
89 FT_FRAME_EXIT();
90 if ( error )
91 goto Exit;
92
93 if ( !stream->read ) {
94 /* just parse memory-based streams */
95 offset = stream->size;
96 }
97 else
98 {
99 /* Find the last `StartData` or `/sfnts`. The parser requires */
100 /* contiguous memory; attempt to pin as little as necessary. */
101
102 /*
103 * The algorithm is as follows (omitting the case with less than 256
104 * bytes to fill for simplicity).
105 *
106 * 1. Fill the buffer with 256 + STARTDATA_LEN bytes.
107 *
108 * 2. Search for the STARTDATA and SFNTS strings at positions
109 * buffer[0], buffer[1], ...,
110 * buffer[255 + STARTDATA_LEN - SFNTS_LEN].
111 *
112 * 3. Move the last STARTDATA_LEN bytes to buffer[0].
113 *
114 * 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN.
115 *
116 * 5. Repeat with step 2.
117 *
118 */
119 FT_Byte buffer[256 + STARTDATA_LEN + 1];
120
121 /* values for the first loop */
122 FT_ULong read_len = 256 + STARTDATA_LEN;
123 FT_ULong read_offset = 0;
124 FT_Byte* p = buffer;
125
126
127 offset = 0;
128 while ( 1 )
129 {
130 FT_ULong stream_len;
131
132
133 stream_len = stream->size - FT_STREAM_POS();
134
135 read_len = FT_MIN( read_len, stream_len );
136 if ( read_len && FT_STREAM_READ( p, read_len ) )
137 goto Exit;
138
139 /* ensure that we do not compare with data beyond the buffer */
140 p[read_len] = '\0';
141
142 limit = p + read_len - SFNTS_LEN;
143
144 for ( p = buffer; p < limit; p++ )
145 {
146 if ( p[0] == 'S' &&
147 ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
148 {
149 /* save offset of binary data after `StartData' */
150 offset = FT_STREAM_POS() - read_len - read_offset
151 + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
152 }
153 else if ( p[1] == 's' &&
154 ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
155 {
156 offset = FT_STREAM_POS() - read_len - read_offset
157 + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
158 }
159 }
160
161 if ( read_offset + read_len <= STARTDATA_LEN )
162 {
163 if ( offset )
164 goto Found;
165
166 FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" ));
167 error = FT_THROW( Invalid_File_Format );
168 goto Exit;
169 }
170
171 FT_MEM_MOVE( buffer,
172 buffer + read_offset + read_len - STARTDATA_LEN,
173 STARTDATA_LEN );
174
175 /* values for the next loop */
176 read_len = 256;
177 read_offset = STARTDATA_LEN;
178 p = buffer + read_offset;
179 }
180 }
181
182 Found:
183 /* We have found an efficient range to look for the binary data or */
184 /* `/sfnts' token. Now rewind and extract the frame corresponding to */
185 /* this PostScript section. */
186
187 ps_len = offset - base_offset;
188 if ( FT_STREAM_SEEK( base_offset ) ||
189 FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
190 goto Exit;
191
192 parser->data_offset = offset;
193 parser->postscript_len = ps_len;
194 parser->root.base = parser->postscript;
195 parser->root.cursor = parser->postscript;
196 parser->root.limit = parser->root.cursor + ps_len;
197 parser->num_dict = FT_UINT_MAX;
198
199 /* Find the first real `StartData' or `/sfnts' -- the last one */
200 /* could be in a comment or string. We also get the arguments */
201 /* of `StartData' to find out whether the data is represented in */
202 /* binary or hex format. */
203
204 arg1 = parser->root.cursor;
205 cid_parser_skip_PS_token( parser );
206 cid_parser_skip_spaces ( parser );
207 arg2 = parser->root.cursor;
208 cid_parser_skip_PS_token( parser );
209 cid_parser_skip_spaces ( parser );
210
211 limit = parser->root.limit;
212 cur = parser->root.cursor;
213
214 while ( cur <= limit - SFNTS_LEN )
215 {
216 if ( parser->root.error )
217 {
218 error = parser->root.error;
219 goto Exit;
220 }
221
222 if ( cur[0] == 'S' &&
223 cur <= limit - STARTDATA_LEN &&
224 ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 )
225 {
226 T1_TokenRec type_token;
227 FT_Long binary_length;
228 FT_ULong found_offset;
229
230
231 parser->root.cursor = arg1;
232 cid_parser_to_token( parser, &type_token );
233 if ( type_token.limit - type_token.start == 5 &&
234 ft_memcmp( (char*)type_token.start, "(Hex)", 5 ) == 0 )
235 {
236 parser->root.cursor = arg2;
237 binary_length = cid_parser_to_int( parser );
238 if ( binary_length < 0 )
239 {
240 FT_ERROR(( "cid_parser_new: invalid length of hex data\n" ));
241 error = FT_THROW( Invalid_File_Format );
242 }
243 else
244 parser->binary_length = (FT_ULong)binary_length;
245 }
246
247 /* set the real values for the parser, if different */
248 found_offset = (FT_ULong)( cur - parser->postscript )
249 + STARTDATA_LEN + 1;
250 if ( found_offset != offset )
251 {
252 FT_FRAME_RELEASE( parser->postscript );
253
254 ps_len = found_offset - base_offset;
255 if ( FT_STREAM_SEEK( base_offset ) ||
256 FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
257 goto Exit;
258
259 parser->data_offset = found_offset;
260 parser->postscript_len = ps_len;
261 parser->root.base = parser->postscript;
262 parser->root.cursor = parser->postscript;
263 parser->root.limit = parser->root.cursor + ps_len;
264 }
265 goto Exit;
266 }
267 else if ( cur[1] == 's' &&
268 ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 )
269 {
270 FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
271 error = FT_THROW( Unknown_File_Format );
272 goto Exit;
273 }
274
275 cid_parser_skip_PS_token( parser );
276 cid_parser_skip_spaces ( parser );
277 arg1 = arg2;
278 arg2 = cur;
279 cur = parser->root.cursor;
280 }
281
282 FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" ));
283 error = FT_THROW( Invalid_File_Format );
284
285 Exit:
286 return error;
287 }
288
289
290#undef STARTDATA
291#undef STARTDATA_LEN
292#undef SFNTS
293#undef SFNTS_LEN
294
295
296 FT_LOCAL_DEF( void )
297 cid_parser_done( CID_Parser* parser )
298 {
299 /* always free the private dictionary */
300 if ( parser->postscript )
301 {
302 FT_Stream stream = parser->stream;
303
304
305 FT_FRAME_RELEASE( parser->postscript );
306 }
307 parser->root.funcs.done( &parser->root );
308 }
309
310
311/* END */