]>
Commit | Line | Data |
---|---|---|
824c7bf0 PL |
1 | /* ftglue.c: Glue code for compiling the OpenType code from |
2 | * FreeType 1 using only the public API of FreeType 2 | |
3 | * | |
4 | * By David Turner, The FreeType Project (www.freetype.org) | |
5 | * | |
6 | * This code is explicitely put in the public domain | |
7 | * | |
8 | * See ftglue.h for more information. | |
9 | */ | |
10 | ||
11 | #include "ftglue.h" | |
12 | ||
13 | #if 0 | |
14 | #include <stdio.h> | |
15 | #define LOG(x) ftglue_log x | |
16 | ||
17 | static void | |
18 | ftglue_log( const char* format, ... ) | |
19 | { | |
20 | va_list ap; | |
21 | ||
22 | va_start( ap, format ); | |
23 | vfprintf( stderr, format, ap ); | |
24 | va_end( ap ); | |
25 | } | |
26 | ||
27 | #else | |
28 | #define LOG(x) do {} while (0) | |
29 | #endif | |
30 | ||
31 | /* only used internally */ | |
32 | static FT_Pointer | |
33 | ftglue_qalloc( FT_Memory memory, | |
34 | FT_ULong size, | |
35 | FT_Error *perror ) | |
36 | { | |
37 | FT_Error error = 0; | |
38 | FT_Pointer block = NULL; | |
39 | ||
40 | if ( size > 0 ) | |
41 | { | |
42 | block = memory->alloc( memory, size ); | |
43 | if ( !block ) | |
44 | error = FT_Err_Out_Of_Memory; | |
45 | } | |
46 | ||
47 | *perror = error; | |
48 | return block; | |
49 | } | |
50 | ||
51 | #undef QALLOC /* just in case */ | |
52 | #define QALLOC(ptr,size) ( (ptr) = ftglue_qalloc( memory, (size), &error ), error != 0 ) | |
53 | ||
54 | ||
55 | FTGLUE_APIDEF( FT_Pointer ) | |
56 | ftglue_alloc( FT_Memory memory, | |
57 | FT_ULong size, | |
58 | FT_Error *perror ) | |
59 | { | |
60 | FT_Error error = 0; | |
61 | FT_Pointer block = NULL; | |
62 | ||
63 | if ( size > 0 ) | |
64 | { | |
65 | block = memory->alloc( memory, size ); | |
66 | if ( !block ) | |
67 | error = FT_Err_Out_Of_Memory; | |
68 | else | |
69 | memset( (char*)block, 0, (size_t)size ); | |
70 | } | |
71 | ||
72 | *perror = error; | |
73 | return block; | |
74 | } | |
75 | ||
76 | ||
77 | FTGLUE_APIDEF( FT_Pointer ) | |
78 | ftglue_realloc( FT_Memory memory, | |
79 | FT_Pointer block, | |
80 | FT_ULong old_size, | |
81 | FT_ULong new_size, | |
82 | FT_Error *perror ) | |
83 | { | |
84 | FT_Pointer block2 = NULL; | |
85 | FT_Error error = 0; | |
86 | ||
87 | if ( old_size == 0 || block == NULL ) | |
88 | { | |
89 | block2 = ftglue_alloc( memory, new_size, &error ); | |
90 | } | |
91 | else if ( new_size == 0 ) | |
92 | { | |
93 | ftglue_free( memory, block ); | |
94 | } | |
95 | else | |
96 | { | |
97 | block2 = memory->realloc( memory, old_size, new_size, block ); | |
98 | if ( block2 == NULL ) | |
99 | error = FT_Err_Out_Of_Memory; | |
100 | else if ( new_size > old_size ) | |
101 | memset( (char*)block2 + old_size, 0, (size_t)(new_size - old_size) ); | |
102 | } | |
103 | ||
104 | if ( !error ) | |
105 | block = block2; | |
106 | ||
107 | *perror = error; | |
108 | return block; | |
109 | } | |
110 | ||
111 | ||
112 | FTGLUE_APIDEF( void ) | |
113 | ftglue_free( FT_Memory memory, | |
114 | FT_Pointer block ) | |
115 | { | |
116 | if ( block ) | |
117 | memory->free( memory, block ); | |
118 | } | |
119 | ||
120 | ||
121 | FTGLUE_APIDEF( FT_Long ) | |
122 | ftglue_stream_pos( FT_Stream stream ) | |
123 | { | |
124 | LOG(( "ftglue:stream:pos() -> %ld\n", stream->pos )); | |
125 | return stream->pos; | |
126 | } | |
127 | ||
128 | ||
129 | FTGLUE_APIDEF( FT_Error ) | |
130 | ftglue_stream_seek( FT_Stream stream, | |
131 | FT_Long pos ) | |
132 | { | |
133 | FT_Error error = 0; | |
134 | ||
135 | stream->pos = pos; | |
136 | if ( stream->read ) | |
137 | { | |
138 | if ( stream->read( stream, pos, 0, 0 ) ) | |
139 | error = FT_Err_Invalid_Stream_Operation; | |
140 | } | |
141 | else if ( pos > stream->size ) | |
142 | error = FT_Err_Invalid_Stream_Operation; | |
143 | ||
144 | LOG(( "ftglue:stream:seek(%ld) -> %d\n", pos, error )); | |
145 | return error; | |
146 | } | |
147 | ||
148 | ||
149 | FTGLUE_APIDEF( FT_Error ) | |
150 | ftglue_stream_frame_enter( FT_Stream stream, | |
151 | FT_ULong count ) | |
152 | { | |
153 | FT_Error error = FT_Err_Ok; | |
154 | FT_ULong read_bytes; | |
155 | ||
156 | if ( stream->read ) | |
157 | { | |
158 | /* allocate the frame in memory */ | |
159 | FT_Memory memory = stream->memory; | |
160 | ||
161 | ||
162 | if ( QALLOC( stream->base, count ) ) | |
163 | goto Exit; | |
164 | ||
165 | /* read it */ | |
166 | read_bytes = stream->read( stream, stream->pos, | |
167 | stream->base, count ); | |
168 | if ( read_bytes < count ) | |
169 | { | |
170 | FREE( stream->base ); | |
171 | error = FT_Err_Invalid_Stream_Operation; | |
172 | } | |
173 | stream->cursor = stream->base; | |
174 | stream->limit = stream->cursor + count; | |
175 | stream->pos += read_bytes; | |
176 | } | |
177 | else | |
178 | { | |
179 | /* check current and new position */ | |
180 | if ( stream->pos >= stream->size || | |
181 | stream->pos + count > stream->size ) | |
182 | { | |
183 | error = FT_Err_Invalid_Stream_Operation; | |
184 | goto Exit; | |
185 | } | |
186 | ||
187 | /* set cursor */ | |
188 | stream->cursor = stream->base + stream->pos; | |
189 | stream->limit = stream->cursor + count; | |
190 | stream->pos += count; | |
191 | } | |
192 | ||
193 | Exit: | |
194 | LOG(( "ftglue:stream:frame_enter(%ld) -> %d\n", count, error )); | |
195 | return error; | |
196 | } | |
197 | ||
198 | ||
199 | FTGLUE_APIDEF( void ) | |
200 | ftglue_stream_frame_exit( FT_Stream stream ) | |
201 | { | |
202 | if ( stream->read ) | |
203 | { | |
204 | FT_Memory memory = stream->memory; | |
205 | ||
206 | FREE( stream->base ); | |
207 | } | |
208 | stream->cursor = 0; | |
209 | stream->limit = 0; | |
210 | ||
211 | LOG(( "ftglue:stream:frame_exit()\n" )); | |
212 | } | |
213 | ||
214 | ||
215 | FTGLUE_APIDEF( FT_Byte ) | |
216 | ftglue_stream_get_byte( FT_Stream stream ) | |
217 | { | |
218 | FT_Byte result = 0; | |
219 | ||
220 | if ( stream->cursor < stream->limit ) | |
221 | result = *stream->cursor++; | |
222 | ||
223 | return result; | |
224 | } | |
225 | ||
226 | ||
227 | FTGLUE_APIDEF( FT_Short ) | |
228 | ftglue_stream_get_short( FT_Stream stream ) | |
229 | { | |
230 | FT_Byte* p; | |
231 | FT_Short result = 0; | |
232 | ||
233 | p = stream->cursor; | |
234 | if ( p + 2 <= stream->limit ) | |
235 | { | |
236 | result = (FT_Short)((p[0] << 8) | p[1]); | |
237 | stream->cursor = p+2; | |
238 | } | |
239 | return result; | |
240 | } | |
241 | ||
242 | ||
243 | FTGLUE_APIDEF( FT_Long ) | |
244 | ftglue_stream_get_long( FT_Stream stream ) | |
245 | { | |
246 | FT_Byte* p; | |
247 | FT_Long result = 0; | |
248 | ||
249 | p = stream->cursor; | |
250 | if ( p + 4 <= stream->limit ) | |
251 | { | |
252 | result = (FT_Long)(((FT_Long)p[0] << 24) | | |
253 | ((FT_Long)p[1] << 16) | | |
254 | ((FT_Long)p[2] << 8) | | |
255 | p[3] ); | |
256 | stream->cursor = p+4; | |
257 | } | |
258 | return result; | |
259 | } | |
260 | ||
261 | ||
262 | FTGLUE_APIDEF( FT_Error ) | |
263 | ftglue_face_goto_table( FT_Face face, | |
264 | FT_ULong the_tag, | |
265 | FT_Stream stream ) | |
266 | { | |
267 | FT_Error error; | |
268 | ||
269 | LOG(( "ftglue_face_goto_table( %p, %c%c%c%c, %p )\n", | |
270 | face, | |
271 | (int)((the_tag >> 24) & 0xFF), | |
272 | (int)((the_tag >> 16) & 0xFF), | |
273 | (int)((the_tag >> 8) & 0xFF), | |
274 | (int)(the_tag & 0xFF), | |
275 | stream )); | |
276 | ||
277 | if ( !FT_IS_SFNT(face) ) | |
278 | { | |
279 | LOG(( "not a SFNT face !!\n" )); | |
280 | error = FT_Err_Invalid_Face_Handle; | |
281 | } | |
282 | else | |
283 | { | |
284 | /* parse the directory table directly, without using | |
285 | * FreeType's built-in data structures | |
286 | */ | |
287 | FT_ULong offset = 0; | |
288 | FT_UInt count, nn; | |
289 | ||
290 | if ( face->num_faces > 1 ) | |
291 | { | |
292 | /* deal with TrueType collections */ | |
293 | FT_ULong offset; | |
294 | ||
295 | LOG(( ">> This is a TrueType Collection\n" )); | |
296 | ||
297 | if ( FILE_Seek( 12 + face->face_index*4 ) || | |
298 | ACCESS_Frame( 4 ) ) | |
299 | goto Exit; | |
300 | ||
301 | offset = GET_ULong(); | |
302 | ||
303 | FORGET_Frame(); | |
304 | } | |
305 | ||
306 | LOG(( "TrueType offset = %ld\n", offset )); | |
307 | ||
308 | if ( FILE_Seek( offset+4 ) || | |
309 | ACCESS_Frame( 2 ) ) | |
310 | goto Exit; | |
311 | ||
312 | count = GET_UShort(); | |
313 | ||
314 | FORGET_Frame(); | |
315 | ||
316 | if ( FILE_Seek( offset+12 ) || | |
317 | ACCESS_Frame( count*16 ) ) | |
318 | goto Exit; | |
319 | ||
320 | for ( nn = 0; nn < count; nn++ ) | |
321 | { | |
322 | FT_ULong tag = GET_ULong(); | |
323 | FT_ULong checksum = GET_ULong(); | |
324 | FT_ULong start = GET_ULong(); | |
325 | FT_ULong size = GET_ULong(); | |
326 | ||
327 | FT_UNUSED(checksum); | |
328 | FT_UNUSED(size); | |
329 | ||
330 | if ( tag == the_tag ) | |
331 | { | |
332 | LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size )); | |
333 | error = ftglue_stream_seek( stream, offset+start ); | |
334 | goto FoundIt; | |
335 | } | |
336 | } | |
337 | error = TT_Err_Table_Missing; | |
338 | ||
339 | FoundIt: | |
340 | FORGET_Frame(); | |
341 | } | |
342 | ||
343 | Exit: | |
344 | LOG(( "TrueType error=%d\n", error )); | |
345 | ||
346 | return error; | |
347 | } | |
348 | ||
349 | #undef QALLOC |