1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* cidparse.c */ |
|
4 /* */ |
|
5 /* CID-keyed Type1 parser (body). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 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 |
|
19 #include <ft2build.h> |
|
20 #include FT_INTERNAL_DEBUG_H |
|
21 #include FT_INTERNAL_OBJECTS_H |
|
22 #include FT_INTERNAL_STREAM_H |
|
23 |
|
24 #include "cidparse.h" |
|
25 |
|
26 #include "ciderrs.h" |
|
27 |
|
28 |
|
29 /*************************************************************************/ |
|
30 /* */ |
|
31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
33 /* messages during execution. */ |
|
34 /* */ |
|
35 #undef FT_COMPONENT |
|
36 #define FT_COMPONENT trace_cidparse |
|
37 |
|
38 |
|
39 /*************************************************************************/ |
|
40 /*************************************************************************/ |
|
41 /*************************************************************************/ |
|
42 /***** *****/ |
|
43 /***** INPUT STREAM PARSER *****/ |
|
44 /***** *****/ |
|
45 /*************************************************************************/ |
|
46 /*************************************************************************/ |
|
47 /*************************************************************************/ |
|
48 |
|
49 |
|
50 FT_LOCAL_DEF( FT_Error ) |
|
51 cid_parser_new( CID_Parser* parser, |
|
52 FT_Stream stream, |
|
53 FT_Memory memory, |
|
54 PSAux_Service psaux ) |
|
55 { |
|
56 FT_Error error; |
|
57 FT_ULong base_offset, offset, ps_len; |
|
58 FT_Byte *cur, *limit; |
|
59 FT_Byte *arg1, *arg2; |
|
60 |
|
61 |
|
62 FT_MEM_ZERO( parser, sizeof ( *parser ) ); |
|
63 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); |
|
64 |
|
65 parser->stream = stream; |
|
66 |
|
67 base_offset = FT_STREAM_POS(); |
|
68 |
|
69 /* first of all, check the font format in the header */ |
|
70 if ( FT_FRAME_ENTER( 31 ) ) |
|
71 goto Exit; |
|
72 |
|
73 if ( ft_strncmp( (char *)stream->cursor, |
|
74 "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) |
|
75 { |
|
76 FT_TRACE2(( "[not a valid CID-keyed font]\n" )); |
|
77 error = CID_Err_Unknown_File_Format; |
|
78 } |
|
79 |
|
80 FT_FRAME_EXIT(); |
|
81 if ( error ) |
|
82 goto Exit; |
|
83 |
|
84 Again: |
|
85 /* now, read the rest of the file until we find */ |
|
86 /* `StartData' or `/sfnts' */ |
|
87 { |
|
88 FT_Byte buffer[256 + 10]; |
|
89 FT_Long read_len = 256 + 10; /* same as signed FT_Stream->size */ |
|
90 FT_Byte* p = buffer; |
|
91 |
|
92 |
|
93 for ( offset = FT_STREAM_POS(); ; offset += 256 ) |
|
94 { |
|
95 FT_Long stream_len; /* same as signed FT_Stream->size */ |
|
96 |
|
97 |
|
98 stream_len = stream->size - FT_STREAM_POS(); |
|
99 if ( stream_len == 0 ) |
|
100 { |
|
101 FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); |
|
102 error = CID_Err_Unknown_File_Format; |
|
103 goto Exit; |
|
104 } |
|
105 |
|
106 read_len = FT_MIN( read_len, stream_len ); |
|
107 if ( FT_STREAM_READ( p, read_len ) ) |
|
108 goto Exit; |
|
109 |
|
110 if ( read_len < 256 ) |
|
111 p[read_len] = '\0'; |
|
112 |
|
113 limit = p + read_len - 10; |
|
114 |
|
115 for ( p = buffer; p < limit; p++ ) |
|
116 { |
|
117 if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) |
|
118 { |
|
119 /* save offset of binary data after `StartData' */ |
|
120 offset += p - buffer + 10; |
|
121 goto Found; |
|
122 } |
|
123 else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 ) |
|
124 { |
|
125 offset += p - buffer + 7; |
|
126 goto Found; |
|
127 } |
|
128 } |
|
129 |
|
130 FT_MEM_MOVE( buffer, p, 10 ); |
|
131 read_len = 256; |
|
132 p = buffer + 10; |
|
133 } |
|
134 } |
|
135 |
|
136 Found: |
|
137 /* We have found the start of the binary data or the `/sfnts' token. */ |
|
138 /* Now rewind and extract the frame corresponding to this PostScript */ |
|
139 /* section. */ |
|
140 |
|
141 ps_len = offset - base_offset; |
|
142 if ( FT_STREAM_SEEK( base_offset ) || |
|
143 FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) |
|
144 goto Exit; |
|
145 |
|
146 parser->data_offset = offset; |
|
147 parser->postscript_len = ps_len; |
|
148 parser->root.base = parser->postscript; |
|
149 parser->root.cursor = parser->postscript; |
|
150 parser->root.limit = parser->root.cursor + ps_len; |
|
151 parser->num_dict = -1; |
|
152 |
|
153 /* Finally, we check whether `StartData' or `/sfnts' was real -- */ |
|
154 /* it could be in a comment or string. We also get the arguments */ |
|
155 /* of `StartData' to find out whether the data is represented in */ |
|
156 /* binary or hex format. */ |
|
157 |
|
158 arg1 = parser->root.cursor; |
|
159 cid_parser_skip_PS_token( parser ); |
|
160 cid_parser_skip_spaces ( parser ); |
|
161 arg2 = parser->root.cursor; |
|
162 cid_parser_skip_PS_token( parser ); |
|
163 cid_parser_skip_spaces ( parser ); |
|
164 |
|
165 limit = parser->root.limit; |
|
166 cur = parser->root.cursor; |
|
167 |
|
168 while ( cur < limit ) |
|
169 { |
|
170 if ( parser->root.error ) |
|
171 { |
|
172 error = parser->root.error; |
|
173 goto Exit; |
|
174 } |
|
175 |
|
176 if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) |
|
177 { |
|
178 if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) |
|
179 parser->binary_length = ft_atol( (const char *)arg2 ); |
|
180 |
|
181 limit = parser->root.limit; |
|
182 cur = parser->root.cursor; |
|
183 goto Exit; |
|
184 } |
|
185 else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 ) |
|
186 { |
|
187 FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); |
|
188 error = CID_Err_Unknown_File_Format; |
|
189 goto Exit; |
|
190 } |
|
191 |
|
192 cid_parser_skip_PS_token( parser ); |
|
193 cid_parser_skip_spaces ( parser ); |
|
194 arg1 = arg2; |
|
195 arg2 = cur; |
|
196 cur = parser->root.cursor; |
|
197 } |
|
198 |
|
199 /* we haven't found the correct `StartData'; go back and continue */ |
|
200 /* searching */ |
|
201 FT_FRAME_RELEASE( parser->postscript ); |
|
202 if ( !FT_STREAM_SEEK( offset ) ) |
|
203 goto Again; |
|
204 |
|
205 Exit: |
|
206 return error; |
|
207 } |
|
208 |
|
209 |
|
210 FT_LOCAL_DEF( void ) |
|
211 cid_parser_done( CID_Parser* parser ) |
|
212 { |
|
213 /* always free the private dictionary */ |
|
214 if ( parser->postscript ) |
|
215 { |
|
216 FT_Stream stream = parser->stream; |
|
217 |
|
218 |
|
219 FT_FRAME_RELEASE( parser->postscript ); |
|
220 } |
|
221 parser->root.funcs.done( &parser->root ); |
|
222 } |
|
223 |
|
224 |
|
225 /* END */ |
|