blob: 7f7373de47d489cc831a9702af8fc318b5fe05d3 [file] [log] [blame]
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001/***************************************************************************/
2/* */
3/* psobjs.c */
4/* */
5/* Auxiliary functions for PostScript fonts (body). */
6/* */
Werner Lemberg545a75f2002-03-31 11:18:15 +00007/* Copyright 1996-2001, 2002 by */
Werner Lembergb1c8bf02000-08-17 07:18:04 +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
Werner Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
20#include FT_INTERNAL_POSTSCRIPT_AUX_H
21#include FT_INTERNAL_DEBUG_H
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000022
David Turner8d3a4012001-03-20 11:14:24 +000023#include "psobjs.h"
Werner Lembergb1c8bf02000-08-17 07:18:04 +000024
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000025#include "psauxerr.h"
26
Werner Lembergb1c8bf02000-08-17 07:18:04 +000027
David Turner24d70242000-08-17 01:09:06 +000028 /*************************************************************************/
29 /*************************************************************************/
30 /***** *****/
David Turnerf95a6032000-08-21 04:58:49 +000031 /***** PS_TABLE *****/
David Turner24d70242000-08-17 01:09:06 +000032 /***** *****/
33 /*************************************************************************/
34 /*************************************************************************/
35
36 /*************************************************************************/
37 /* */
38 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +000039 /* PS_Table_New */
David Turner24d70242000-08-17 01:09:06 +000040 /* */
41 /* <Description> */
Werner Lemberg8728f292000-08-23 17:32:42 +000042 /* Initializes a PS_Table. */
David Turner24d70242000-08-17 01:09:06 +000043 /* */
44 /* <InOut> */
45 /* table :: The address of the target table. */
46 /* */
47 /* <Input> */
48 /* count :: The table size = the maximum number of elements. */
49 /* */
50 /* memory :: The memory object to use for all subsequent */
51 /* reallocations. */
52 /* */
53 /* <Return> */
54 /* FreeType error code. 0 means success. */
55 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +000056 FT_LOCAL_DEF( FT_Error )
Werner Lemberg545a75f2002-03-31 11:18:15 +000057 PS_Table_New( PS_Table table,
Werner Lemberg93616ec2001-06-27 19:46:12 +000058 FT_Int count,
59 FT_Memory memory )
David Turner24d70242000-08-17 01:09:06 +000060 {
61 FT_Error error;
62
63
64 table->memory = memory;
David Turnere459d742002-03-22 13:52:37 +000065 if ( FT_NEW_ARRAY( table->elements, count ) ||
66 FT_NEW_ARRAY( table->lengths, count ) )
David Turner24d70242000-08-17 01:09:06 +000067 goto Exit;
68
69 table->max_elems = count;
Werner Lemberg8c883fb2000-11-05 23:41:08 +000070 table->init = 0xDEADBEEFUL;
David Turner24d70242000-08-17 01:09:06 +000071 table->num_elems = 0;
72 table->block = 0;
73 table->capacity = 0;
74 table->cursor = 0;
David Turner4e7eeee2002-02-28 16:10:29 +000075
76 *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
David Turner24d70242000-08-17 01:09:06 +000077
78 Exit:
79 if ( error )
David Turnere459d742002-03-22 13:52:37 +000080 FT_FREE( table->elements );
David Turner24d70242000-08-17 01:09:06 +000081
82 return error;
83 }
84
85
Werner Lemberg93616ec2001-06-27 19:46:12 +000086 static void
David Turner4e7eeee2002-02-28 16:10:29 +000087 shift_elements( PS_Table table,
Werner Lemberg545a75f2002-03-31 11:18:15 +000088 FT_Byte* old_base )
David Turner24d70242000-08-17 01:09:06 +000089 {
Werner Lemberg914b2892001-03-10 17:07:42 +000090 FT_Long delta = (FT_Long)( table->block - old_base );
David Turner24d70242000-08-17 01:09:06 +000091 FT_Byte** offset = table->elements;
92 FT_Byte** limit = offset + table->max_elems;
93
94
Werner Lemberge56b4112001-02-03 04:34:53 +000095 for ( ; offset < limit; offset++ )
96 {
97 if ( offset[0] )
98 offset[0] += delta;
99 }
David Turner24d70242000-08-17 01:09:06 +0000100 }
101
102
Werner Lemberg93616ec2001-06-27 19:46:12 +0000103 static FT_Error
David Turner4e7eeee2002-02-28 16:10:29 +0000104 reallocate_t1_table( PS_Table table,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000105 FT_Int new_size )
David Turner24d70242000-08-17 01:09:06 +0000106 {
107 FT_Memory memory = table->memory;
108 FT_Byte* old_base = table->block;
109 FT_Error error;
110
111
Werner Lemberge56b4112001-02-03 04:34:53 +0000112 /* allocate new base block */
David Turnere459d742002-03-22 13:52:37 +0000113 if ( FT_ALLOC( table->block, new_size ) )
David Turner24d70242000-08-17 01:09:06 +0000114 return error;
115
Werner Lemberge56b4112001-02-03 04:34:53 +0000116 /* copy elements and shift offsets */
117 if (old_base )
118 {
David Turnere459d742002-03-22 13:52:37 +0000119 FT_MEM_COPY( table->block, old_base, table->capacity );
David Turner24d70242000-08-17 01:09:06 +0000120 shift_elements( table, old_base );
David Turnere459d742002-03-22 13:52:37 +0000121 FT_FREE( old_base );
Werner Lemberge56b4112001-02-03 04:34:53 +0000122 }
123
124 table->capacity = new_size;
David Turner24d70242000-08-17 01:09:06 +0000125
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000126 return PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +0000127 }
128
129
130 /*************************************************************************/
131 /* */
132 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +0000133 /* PS_Table_Add */
David Turner24d70242000-08-17 01:09:06 +0000134 /* */
135 /* <Description> */
David Turner429978b2002-03-14 10:09:35 +0000136 /* Adds an object to a PS_Table, possibly growing its memory block. */
David Turner24d70242000-08-17 01:09:06 +0000137 /* */
138 /* <InOut> */
139 /* table :: The target table. */
140 /* */
141 /* <Input> */
Werner Lemberg91db04c2002-04-01 14:25:28 +0000142 /* idx :: The index of the object in the table. */
David Turner24d70242000-08-17 01:09:06 +0000143 /* */
144 /* object :: The address of the object to copy in memory. */
145 /* */
146 /* length :: The length in bytes of the source object. */
147 /* */
148 /* <Return> */
149 /* FreeType error code. 0 means success. An error is returned if a */
150 /* reallocation fails. */
151 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000152 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +0000153 PS_Table_Add( PS_Table table,
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000154 FT_Int idx,
155 void* object,
156 FT_Int length )
David Turner24d70242000-08-17 01:09:06 +0000157 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000158 if ( idx < 0 || idx > table->max_elems )
David Turner24d70242000-08-17 01:09:06 +0000159 {
David Turnerf95a6032000-08-21 04:58:49 +0000160 FT_ERROR(( "PS_Table_Add: invalid index\n" ));
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000161 return PSaux_Err_Invalid_Argument;
David Turner24d70242000-08-17 01:09:06 +0000162 }
163
164 /* grow the base block if needed */
165 if ( table->cursor + length > table->capacity )
166 {
Werner Lemberg36af3ea2001-07-17 12:37:54 +0000167 FT_Error error;
David Turner8ab0add2001-08-30 07:59:28 +0000168 FT_Offset new_size = table->capacity;
169 FT_Long in_offset;
David Turner4d570242002-02-24 02:59:24 +0000170
Werner Lembergec342902001-09-10 06:55:43 +0000171
David Turner8ab0add2001-08-30 07:59:28 +0000172 in_offset = (FT_Long)((FT_Byte*)object - table->block);
173 if ( (FT_ULong)in_offset >= table->capacity )
174 in_offset = -1;
David Turner24d70242000-08-17 01:09:06 +0000175
176 while ( new_size < table->cursor + length )
177 new_size += 1024;
178
179 error = reallocate_t1_table( table, new_size );
180 if ( error )
181 return error;
David Turner4d570242002-02-24 02:59:24 +0000182
David Turner8ab0add2001-08-30 07:59:28 +0000183 if ( in_offset >= 0 )
184 object = table->block + in_offset;
David Turner24d70242000-08-17 01:09:06 +0000185 }
186
187 /* add the object to the base block and adjust offset */
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000188 table->elements[idx] = table->block + table->cursor;
189 table->lengths [idx] = length;
David Turnere459d742002-03-22 13:52:37 +0000190 FT_MEM_COPY( table->block + table->cursor, object, length );
David Turner24d70242000-08-17 01:09:06 +0000191
192 table->cursor += length;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000193 return PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +0000194 }
195
196
David Turner24d70242000-08-17 01:09:06 +0000197 /*************************************************************************/
198 /* */
199 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +0000200 /* PS_Table_Done */
David Turner24d70242000-08-17 01:09:06 +0000201 /* */
202 /* <Description> */
Werner Lemberg545a75f2002-03-31 11:18:15 +0000203 /* Finalizes a PS_TableRec (i.e., reallocate it to its current */
204 /* cursor). */
David Turner24d70242000-08-17 01:09:06 +0000205 /* */
206 /* <InOut> */
207 /* table :: The target table. */
208 /* */
209 /* <Note> */
210 /* This function does NOT release the heap's memory block. It is up */
211 /* to the caller to clean it, or reference it in its own structures. */
212 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000213 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000214 PS_Table_Done( PS_Table table )
David Turner24d70242000-08-17 01:09:06 +0000215 {
216 FT_Memory memory = table->memory;
217 FT_Error error;
Werner Lemberge56b4112001-02-03 04:34:53 +0000218 FT_Byte* old_base = table->block;
David Turner24d70242000-08-17 01:09:06 +0000219
220
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000221 /* should never fail, because rec.cursor <= rec.size */
David Turner24d70242000-08-17 01:09:06 +0000222 if ( !old_base )
223 return;
224
David Turnere459d742002-03-22 13:52:37 +0000225 if ( FT_ALLOC( table->block, table->cursor ) )
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000226 return;
David Turnere459d742002-03-22 13:52:37 +0000227 FT_MEM_COPY( table->block, old_base, table->cursor );
Werner Lemberge56b4112001-02-03 04:34:53 +0000228 shift_elements( table, old_base );
David Turner24d70242000-08-17 01:09:06 +0000229
Werner Lemberge56b4112001-02-03 04:34:53 +0000230 table->capacity = table->cursor;
David Turnere459d742002-03-22 13:52:37 +0000231 FT_FREE( old_base );
Werner Lembergb5349a92002-02-19 16:30:15 +0000232
233 FT_UNUSED( error );
David Turner24d70242000-08-17 01:09:06 +0000234 }
235
236
David Turnerbc82f1b2002-03-01 02:26:22 +0000237 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000238 PS_Table_Release( PS_Table table )
David Turner24d70242000-08-17 01:09:06 +0000239 {
240 FT_Memory memory = table->memory;
241
242
David Turner97488072000-08-22 22:36:33 +0000243 if ( (FT_ULong)table->init == 0xDEADBEEFUL )
David Turner24d70242000-08-17 01:09:06 +0000244 {
David Turnere459d742002-03-22 13:52:37 +0000245 FT_FREE( table->block );
246 FT_FREE( table->elements );
247 FT_FREE( table->lengths );
David Turner24d70242000-08-17 01:09:06 +0000248 table->init = 0;
249 }
250 }
251
252
David Turner24d70242000-08-17 01:09:06 +0000253 /*************************************************************************/
254 /*************************************************************************/
255 /***** *****/
256 /***** T1 PARSER *****/
257 /***** *****/
258 /*************************************************************************/
259 /*************************************************************************/
260
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000261
David Turner24d70242000-08-17 01:09:06 +0000262#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
263#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
264
265#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
266
267
David Turnerbc82f1b2002-03-01 02:26:22 +0000268 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000269 PS_Parser_SkipSpaces( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +0000270 {
271 FT_Byte* cur = parser->cursor;
272 FT_Byte* limit = parser->limit;
273
274
275 while ( cur < limit )
276 {
277 FT_Byte c = *cur;
278
279
280 if ( !IS_T1_SPACE( c ) )
281 break;
282 cur++;
283 }
284 parser->cursor = cur;
285 }
286
287
David Turnerbc82f1b2002-03-01 02:26:22 +0000288 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000289 PS_Parser_SkipAlpha( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +0000290 {
291 FT_Byte* cur = parser->cursor;
292 FT_Byte* limit = parser->limit;
293
294
295 while ( cur < limit )
296 {
297 FT_Byte c = *cur;
298
299
300 if ( IS_T1_SPACE( c ) )
301 break;
302 cur++;
303 }
304 parser->cursor = cur;
305 }
306
307
David Turnerbc82f1b2002-03-01 02:26:22 +0000308 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000309 PS_Parser_ToToken( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000310 T1_Token token )
David Turner24d70242000-08-17 01:09:06 +0000311 {
312 FT_Byte* cur;
313 FT_Byte* limit;
314 FT_Byte starter, ender;
315 FT_Int embed;
316
317
David Turner4e7eeee2002-02-28 16:10:29 +0000318 token->type = T1_TOKEN_TYPE_NONE;
David Turner24d70242000-08-17 01:09:06 +0000319 token->start = 0;
320 token->limit = 0;
321
322 /* first of all, skip space */
David Turner4e7eeee2002-02-28 16:10:29 +0000323 PS_Parser_SkipSpaces( parser );
David Turner24d70242000-08-17 01:09:06 +0000324
325 cur = parser->cursor;
326 limit = parser->limit;
327
328 if ( cur < limit )
329 {
330 switch ( *cur )
331 {
332 /************* check for strings ***********************/
333 case '(':
David Turner4e7eeee2002-02-28 16:10:29 +0000334 token->type = T1_TOKEN_TYPE_STRING;
David Turner24d70242000-08-17 01:09:06 +0000335 ender = ')';
336 goto Lookup_Ender;
337
338 /************* check for programs/array ****************/
339 case '{':
David Turner4e7eeee2002-02-28 16:10:29 +0000340 token->type = T1_TOKEN_TYPE_ARRAY;
David Turner24d70242000-08-17 01:09:06 +0000341 ender = '}';
342 goto Lookup_Ender;
343
344 /************* check for table/array ******************/
345 case '[':
David Turner4e7eeee2002-02-28 16:10:29 +0000346 token->type = T1_TOKEN_TYPE_ARRAY;
David Turner24d70242000-08-17 01:09:06 +0000347 ender = ']';
348
349 Lookup_Ender:
350 embed = 1;
351 starter = *cur++;
352 token->start = cur;
353 while ( cur < limit )
354 {
355 if ( *cur == starter )
356 embed++;
357 else if ( *cur == ender )
358 {
359 embed--;
360 if ( embed <= 0 )
361 {
362 token->limit = cur++;
363 break;
364 }
365 }
366 cur++;
367 }
368 break;
369
370 /* **************** otherwise, it's any token **********/
371 default:
372 token->start = cur++;
David Turner4e7eeee2002-02-28 16:10:29 +0000373 token->type = T1_TOKEN_TYPE_ANY;
David Turner24d70242000-08-17 01:09:06 +0000374 while ( cur < limit && !IS_T1_SPACE( *cur ) )
375 cur++;
376
377 token->limit = cur;
378 }
379
380 if ( !token->limit )
381 {
382 token->start = 0;
David Turner4e7eeee2002-02-28 16:10:29 +0000383 token->type = T1_TOKEN_TYPE_NONE;
David Turner24d70242000-08-17 01:09:06 +0000384 }
385
386 parser->cursor = cur;
387 }
388 }
389
390
David Turnerbc82f1b2002-03-01 02:26:22 +0000391 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +0000392 PS_Parser_ToTokenArray( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000393 T1_Token tokens,
394 FT_UInt max_tokens,
395 FT_Int* pnum_tokens )
David Turner24d70242000-08-17 01:09:06 +0000396 {
David Turner4e7eeee2002-02-28 16:10:29 +0000397 T1_TokenRec master;
David Turner24d70242000-08-17 01:09:06 +0000398
399
400 *pnum_tokens = -1;
401
David Turner4e7eeee2002-02-28 16:10:29 +0000402 PS_Parser_ToToken( parser, &master );
403 if ( master.type == T1_TOKEN_TYPE_ARRAY )
David Turner24d70242000-08-17 01:09:06 +0000404 {
Werner Lemberg545a75f2002-03-31 11:18:15 +0000405 FT_Byte* old_cursor = parser->cursor;
406 FT_Byte* old_limit = parser->limit;
David Turner4e7eeee2002-02-28 16:10:29 +0000407 T1_Token cur = tokens;
408 T1_Token limit = cur + max_tokens;
David Turner24d70242000-08-17 01:09:06 +0000409
410
411 parser->cursor = master.start;
412 parser->limit = master.limit;
413
414 while ( parser->cursor < parser->limit )
415 {
David Turner4e7eeee2002-02-28 16:10:29 +0000416 T1_TokenRec token;
David Turner24d70242000-08-17 01:09:06 +0000417
418
David Turner4e7eeee2002-02-28 16:10:29 +0000419 PS_Parser_ToToken( parser, &token );
David Turner24d70242000-08-17 01:09:06 +0000420 if ( !token.type )
421 break;
422
423 if ( cur < limit )
424 *cur = token;
425
426 cur++;
427 }
428
Werner Lemberg914b2892001-03-10 17:07:42 +0000429 *pnum_tokens = (FT_Int)( cur - tokens );
David Turner24d70242000-08-17 01:09:06 +0000430
431 parser->cursor = old_cursor;
432 parser->limit = old_limit;
433 }
434 }
435
436
Werner Lemberg93616ec2001-06-27 19:46:12 +0000437 static FT_Long
Werner Lembergb1859042002-05-22 04:53:25 +0000438 T1Radix( FT_Long radixBase,
439 FT_Byte** cur,
440 FT_Byte* limit )
441 {
442 FT_Long result = 0;
443 FT_Byte radixEndChar0 =
444 (FT_Byte)( radixBase > 10 ? '9' + 1 : '0' + radixBase );
445 FT_Byte radixEndChar1 =
446 (FT_Byte)( 'A' + radixBase - 10 );
447 FT_Byte radixEndChar2 =
448 (FT_Byte)( 'a' + radixBase - 10 );
449
450
451 while( *cur < limit )
452 {
453 if ( (*cur)[0] >= '0' && (*cur)[0] < radixEndChar0 )
454 result = result * radixBase + (*cur)[0] - '0';
455
456 else if ( radixBase > 10 &&
457 (*cur)[0] >= 'A' && (*cur)[0] < radixEndChar1 )
458 result = result * radixBase + ( (*cur)[0] - 'A' + 10 );
459
460 else if ( radixBase > 10 &&
461 (*cur)[0] >= 'a' && (*cur)[0] < radixEndChar2 )
462 result = result * radixBase + ( (*cur)[0] - 'a' + 10 );
463
464 else
465 return result;
466
467 (*cur)++;
468 }
469
470 return result;
471 }
472
473
474 static FT_Long
Werner Lemberg93616ec2001-06-27 19:46:12 +0000475 t1_toint( FT_Byte** cursor,
476 FT_Byte* limit )
David Turner24d70242000-08-17 01:09:06 +0000477 {
478 FT_Long result = 0;
479 FT_Byte* cur = *cursor;
Werner Lembergb1859042002-05-22 04:53:25 +0000480 FT_Byte c = '\0', d;
David Turner24d70242000-08-17 01:09:06 +0000481
482
483 for ( ; cur < limit; cur++ )
484 {
485 c = *cur;
486 d = (FT_Byte)( c - '0' );
487 if ( d < 10 )
488 break;
489
490 if ( c == '-' )
491 {
492 cur++;
493 break;
494 }
495 }
496
497 if ( cur < limit )
498 {
499 do
500 {
501 d = (FT_Byte)( cur[0] - '0' );
502 if ( d >= 10 )
Werner Lembergb1859042002-05-22 04:53:25 +0000503 {
504 if ( cur[0] == '#' )
505 {
506 cur++;
507 result = T1Radix( result, &cur, limit );
508 }
David Turner24d70242000-08-17 01:09:06 +0000509 break;
Werner Lembergb1859042002-05-22 04:53:25 +0000510 }
David Turner24d70242000-08-17 01:09:06 +0000511
512 result = result * 10 + d;
513 cur++;
514
515 } while ( cur < limit );
516
517 if ( c == '-' )
518 result = -result;
519 }
520
521 *cursor = cur;
522 return result;
523 }
524
525
Werner Lemberg93616ec2001-06-27 19:46:12 +0000526 static FT_Long
527 t1_tofixed( FT_Byte** cursor,
528 FT_Byte* limit,
529 FT_Long power_ten )
David Turner24d70242000-08-17 01:09:06 +0000530 {
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000531 FT_Byte* cur = *cursor;
532 FT_Long num, divider, result;
533 FT_Int sign = 0;
534 FT_Byte d;
David Turner24d70242000-08-17 01:09:06 +0000535
536
537 if ( cur >= limit )
538 return 0;
539
540 /* first of all, check the sign */
541 if ( *cur == '-' )
542 {
543 sign = 1;
544 cur++;
545 }
546
547 /* then, read the integer part, if any */
548 if ( *cur != '.' )
549 result = t1_toint( &cur, limit ) << 16;
550 else
551 result = 0;
552
553 num = 0;
554 divider = 1;
555
556 if ( cur >= limit )
557 goto Exit;
558
559 /* read decimal part, if any */
560 if ( *cur == '.' && cur + 1 < limit )
561 {
562 cur++;
563
564 for (;;)
565 {
566 d = (FT_Byte)( *cur - '0' );
567 if ( d >= 10 )
568 break;
569
570 if ( divider < 10000000L )
571 {
572 num = num * 10 + d;
573 divider *= 10;
574 }
575
576 cur++;
577 if ( cur >= limit )
578 break;
579 }
580 }
581
582 /* read exponent, if any */
583 if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
584 {
585 cur++;
586 power_ten += t1_toint( &cur, limit );
587 }
588
589 Exit:
590 /* raise to power of ten if needed */
591 while ( power_ten > 0 )
592 {
593 result = result * 10;
594 num = num * 10;
595 power_ten--;
596 }
597
598 while ( power_ten < 0 )
599 {
600 result = result / 10;
601 divider = divider * 10;
602 power_ten++;
603 }
604
605 if ( num )
606 result += FT_DivFix( num, divider );
607
608 if ( sign )
609 result = -result;
610
611 *cursor = cur;
612 return result;
613 }
614
615
Werner Lemberg93616ec2001-06-27 19:46:12 +0000616 static FT_Int
617 t1_tocoordarray( FT_Byte** cursor,
618 FT_Byte* limit,
619 FT_Int max_coords,
620 FT_Short* coords )
David Turner24d70242000-08-17 01:09:06 +0000621 {
622 FT_Byte* cur = *cursor;
623 FT_Int count = 0;
624 FT_Byte c, ender;
625
626
627 if ( cur >= limit )
628 goto Exit;
629
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000630 /* check for the beginning of an array; if not, only one number will */
David Turner24d70242000-08-17 01:09:06 +0000631 /* be read */
632 c = *cur;
633 ender = 0;
634
635 if ( c == '[' )
636 ender = ']';
637
638 if ( c == '{' )
639 ender = '}';
640
641 if ( ender )
642 cur++;
643
644 /* now, read the coordinates */
645 for ( ; cur < limit; )
646 {
647 /* skip whitespace in front of data */
648 for (;;)
649 {
650 c = *cur;
651 if ( c != ' ' && c != '\t' )
652 break;
653
654 cur++;
655 if ( cur >= limit )
656 goto Exit;
657 }
658
659 if ( count >= max_coords || c == ender )
660 break;
661
662 coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
663 count++;
664
665 if ( !ender )
666 break;
667 }
668
669 Exit:
670 *cursor = cur;
671 return count;
672 }
673
674
Werner Lemberg93616ec2001-06-27 19:46:12 +0000675 static FT_Int
676 t1_tofixedarray( FT_Byte** cursor,
677 FT_Byte* limit,
678 FT_Int max_values,
679 FT_Fixed* values,
680 FT_Int power_ten )
David Turner24d70242000-08-17 01:09:06 +0000681 {
682 FT_Byte* cur = *cursor;
683 FT_Int count = 0;
684 FT_Byte c, ender;
685
686
687 if ( cur >= limit ) goto Exit;
688
689 /* check for the beginning of an array. If not, only one number will */
690 /* be read */
691 c = *cur;
692 ender = 0;
693
694 if ( c == '[' )
695 ender = ']';
696
697 if ( c == '{' )
698 ender = '}';
699
700 if ( ender )
701 cur++;
702
703 /* now, read the values */
704 for ( ; cur < limit; )
705 {
706 /* skip whitespace in front of data */
707 for (;;)
708 {
709 c = *cur;
710 if ( c != ' ' && c != '\t' )
711 break;
712
713 cur++;
714 if ( cur >= limit )
715 goto Exit;
716 }
717
718 if ( count >= max_values || c == ender )
719 break;
720
721 values[count] = t1_tofixed( &cur, limit, power_ten );
722 count++;
723
724 if ( !ender )
725 break;
726 }
727
728 Exit:
729 *cursor = cur;
730 return count;
731 }
732
733
734#if 0
735
Werner Lemberg93616ec2001-06-27 19:46:12 +0000736 static FT_String*
737 t1_tostring( FT_Byte** cursor,
738 FT_Byte* limit,
739 FT_Memory memory )
David Turner24d70242000-08-17 01:09:06 +0000740 {
741 FT_Byte* cur = *cursor;
742 FT_Int len = 0;
743 FT_Int count;
744 FT_String* result;
745 FT_Error error;
746
747
748 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
749 /* that simply doesn't begin with an opening parenthesis, even */
750 /* though they have a closing one! E.g. "amuncial.pfb" */
751 /* */
752 /* We must deal with these ill-fated cases there. Note that */
753 /* these fonts didn't work with the old Type 1 driver as the */
754 /* notice/copyright was not recognized as a valid string token */
755 /* and made the old token parser commit errors. */
756
757 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
758 cur++;
759 if ( cur + 1 >= limit )
760 return 0;
761
762 if ( *cur == '(' )
763 cur++; /* skip the opening parenthesis, if there is one */
764
765 *cursor = cur;
766 count = 0;
767
768 /* then, count its length */
769 for ( ; cur < limit; cur++ )
770 {
771 if ( *cur == '(' )
772 count++;
773
774 else if ( *cur == ')' )
775 {
776 count--;
777 if ( count < 0 )
778 break;
779 }
780 }
781
782 len = cur - *cursor;
David Turnere459d742002-03-22 13:52:37 +0000783 if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
David Turner24d70242000-08-17 01:09:06 +0000784 return 0;
785
786 /* now copy the string */
David Turnere459d742002-03-22 13:52:37 +0000787 FT_MEM_COPY( result, *cursor, len );
David Turner24d70242000-08-17 01:09:06 +0000788 result[len] = '\0';
789 *cursor = cur;
790 return result;
791 }
792
793#endif /* 0 */
794
795
Werner Lemberg93616ec2001-06-27 19:46:12 +0000796 static int
797 t1_tobool( FT_Byte** cursor,
798 FT_Byte* limit )
David Turner24d70242000-08-17 01:09:06 +0000799 {
800 FT_Byte* cur = *cursor;
801 FT_Bool result = 0;
802
803
804 /* return 1 if we find `true', 0 otherwise */
805 if ( cur + 3 < limit &&
806 cur[0] == 't' &&
807 cur[1] == 'r' &&
808 cur[2] == 'u' &&
809 cur[3] == 'e' )
810 {
811 result = 1;
812 cur += 5;
813 }
814 else if ( cur + 4 < limit &&
815 cur[0] == 'f' &&
816 cur[1] == 'a' &&
817 cur[2] == 'l' &&
818 cur[3] == 's' &&
819 cur[4] == 'e' )
820 {
821 result = 0;
822 cur += 6;
823 }
824
825 *cursor = cur;
826 return result;
827 }
828
829
830 /* Load a simple field (i.e. non-table) into the current list of objects */
David Turnerbc82f1b2002-03-01 02:26:22 +0000831 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +0000832 PS_Parser_LoadField( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000833 const T1_Field field,
834 void** objects,
835 FT_UInt max_objects,
836 FT_ULong* pflags )
David Turner24d70242000-08-17 01:09:06 +0000837 {
David Turner4e7eeee2002-02-28 16:10:29 +0000838 T1_TokenRec token;
Werner Lemberg545a75f2002-03-31 11:18:15 +0000839 FT_Byte* cur;
840 FT_Byte* limit;
841 FT_UInt count;
842 FT_UInt idx;
843 FT_Error error;
David Turner24d70242000-08-17 01:09:06 +0000844
845
David Turner4e7eeee2002-02-28 16:10:29 +0000846 PS_Parser_ToToken( parser, &token );
David Turner24d70242000-08-17 01:09:06 +0000847 if ( !token.type )
848 goto Fail;
849
850 count = 1;
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000851 idx = 0;
David Turner24d70242000-08-17 01:09:06 +0000852 cur = token.start;
853 limit = token.limit;
854
David Turner8db6a072002-07-11 11:26:21 +0000855 /* we must detect arrays */
856 if ( field->type == T1_FIELD_TYPE_BBOX )
David Turner24d70242000-08-17 01:09:06 +0000857 {
David Turner8db6a072002-07-11 11:26:21 +0000858 T1_TokenRec token2;
859 FT_Byte* old_cur = parser->cursor;
860 FT_Byte* old_limit = parser->limit;
861
Werner Lemberg7f74a522002-07-26 09:09:10 +0000862
David Turner8db6a072002-07-11 11:26:21 +0000863 parser->cursor = token.start;
864 parser->limit = token.limit;
865
866 PS_Parser_ToToken( parser, &token2 );
867 parser->cursor = old_cur;
868 parser->limit = old_limit;
869
870 if ( token2.type == T1_TOKEN_TYPE_ARRAY )
871 goto FieldArray;
872 }
873 else if ( token.type == T1_TOKEN_TYPE_ARRAY )
874 {
875 FieldArray:
David Turner24d70242000-08-17 01:09:06 +0000876 /* if this is an array, and we have no blend, an error occurs */
877 if ( max_objects == 0 )
878 goto Fail;
879
880 count = max_objects;
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000881 idx = 1;
David Turner24d70242000-08-17 01:09:06 +0000882 }
883
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000884 for ( ; count > 0; count--, idx++ )
David Turner24d70242000-08-17 01:09:06 +0000885 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000886 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
David Turner24d70242000-08-17 01:09:06 +0000887 FT_Long val;
888 FT_String* string;
889
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000890
David Turner24d70242000-08-17 01:09:06 +0000891 switch ( field->type )
892 {
David Turner4e7eeee2002-02-28 16:10:29 +0000893 case T1_FIELD_TYPE_BOOL:
David Turner24d70242000-08-17 01:09:06 +0000894 val = t1_tobool( &cur, limit );
895 goto Store_Integer;
896
David Turner4e7eeee2002-02-28 16:10:29 +0000897 case T1_FIELD_TYPE_FIXED:
David Turner24d70242000-08-17 01:09:06 +0000898 val = t1_tofixed( &cur, limit, 3 );
899 goto Store_Integer;
900
David Turner4e7eeee2002-02-28 16:10:29 +0000901 case T1_FIELD_TYPE_INTEGER:
David Turner24d70242000-08-17 01:09:06 +0000902 val = t1_toint( &cur, limit );
903
904 Store_Integer:
905 switch ( field->size )
906 {
907 case 1:
908 *(FT_Byte*)q = (FT_Byte)val;
909 break;
910
911 case 2:
912 *(FT_UShort*)q = (FT_UShort)val;
913 break;
914
915 case 4:
916 *(FT_UInt32*)q = (FT_UInt32)val;
917 break;
918
Werner Lemberg545a75f2002-03-31 11:18:15 +0000919 default: /* for 64-bit systems */
David Turner24d70242000-08-17 01:09:06 +0000920 *(FT_Long*)q = val;
921 }
922 break;
923
David Turner4e7eeee2002-02-28 16:10:29 +0000924 case T1_FIELD_TYPE_STRING:
David Turner24d70242000-08-17 01:09:06 +0000925 {
926 FT_Memory memory = parser->memory;
Werner Lemberg914b2892001-03-10 17:07:42 +0000927 FT_UInt len = (FT_UInt)( limit - cur );
David Turner24d70242000-08-17 01:09:06 +0000928
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000929
David Turner24d70242000-08-17 01:09:06 +0000930 if ( *(FT_String**)q )
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000931 /* with synthetic fonts, it's possible to find a field twice */
David Turner24d70242000-08-17 01:09:06 +0000932 break;
933
David Turnere459d742002-03-22 13:52:37 +0000934 if ( FT_ALLOC( string, len + 1 ) )
David Turner24d70242000-08-17 01:09:06 +0000935 goto Exit;
936
David Turnere459d742002-03-22 13:52:37 +0000937 FT_MEM_COPY( string, cur, len );
David Turner24d70242000-08-17 01:09:06 +0000938 string[len] = 0;
939
940 *(FT_String**)q = string;
941 }
942 break;
943
David Turner8db6a072002-07-11 11:26:21 +0000944 case T1_FIELD_TYPE_BBOX:
945 {
946 FT_Fixed temp[4];
947 FT_BBox* bbox = (FT_BBox*)q;
948
Werner Lemberg7f74a522002-07-26 09:09:10 +0000949
David Turner8db6a072002-07-11 11:26:21 +0000950 /* we need the '[' and ']' delimiters */
951 token.start--;
952 token.limit++;
Werner Lemberg7f74a522002-07-26 09:09:10 +0000953 (void)t1_tofixedarray( &token.start, token.limit, 4, temp, 0 );
David Turner8db6a072002-07-11 11:26:21 +0000954
955 bbox->xMin = FT_RoundFix( temp[0] );
956 bbox->yMin = FT_RoundFix( temp[1] );
957 bbox->xMax = FT_RoundFix( temp[2] );
958 bbox->yMax = FT_RoundFix( temp[3] );
959 }
960 break;
961
David Turner24d70242000-08-17 01:09:06 +0000962 default:
963 /* an error occured */
964 goto Fail;
965 }
966 }
967
David Turner34f1c2f2000-08-23 22:47:44 +0000968#if 0 /* obsolete - keep for reference */
David Turner24d70242000-08-17 01:09:06 +0000969 if ( pflags )
970 *pflags |= 1L << field->flag_bit;
David Turner34f1c2f2000-08-23 22:47:44 +0000971#else
Werner Lemberge4b32a52000-10-31 20:42:18 +0000972 FT_UNUSED( pflags );
David Turner34f1c2f2000-08-23 22:47:44 +0000973#endif
David Turner24d70242000-08-17 01:09:06 +0000974
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000975 error = PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +0000976
977 Exit:
978 return error;
979
980 Fail:
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000981 error = PSaux_Err_Invalid_File_Format;
David Turner24d70242000-08-17 01:09:06 +0000982 goto Exit;
983 }
984
985
986#define T1_MAX_TABLE_ELEMENTS 32
987
988
David Turnerbc82f1b2002-03-01 02:26:22 +0000989 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +0000990 PS_Parser_LoadFieldTable( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000991 const T1_Field field,
992 void** objects,
993 FT_UInt max_objects,
994 FT_ULong* pflags )
David Turner24d70242000-08-17 01:09:06 +0000995 {
Werner Lemberg545a75f2002-03-31 11:18:15 +0000996 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
997 T1_Token token;
998 FT_Int num_elements;
999 FT_Error error = 0;
1000 FT_Byte* old_cursor;
1001 FT_Byte* old_limit;
1002 T1_FieldRec fieldrec = *(T1_Field)field;
1003
David Turner24d70242000-08-17 01:09:06 +00001004
David Turner34f1c2f2000-08-23 22:47:44 +00001005#if 1
David Turner4e7eeee2002-02-28 16:10:29 +00001006 fieldrec.type = T1_FIELD_TYPE_INTEGER;
1007 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1008 fieldrec.type = T1_FIELD_TYPE_FIXED;
David Turner34f1c2f2000-08-23 22:47:44 +00001009#endif
David Turner24d70242000-08-17 01:09:06 +00001010
David Turner4e7eeee2002-02-28 16:10:29 +00001011 PS_Parser_ToTokenArray( parser, elements, 32, &num_elements );
David Turner24d70242000-08-17 01:09:06 +00001012 if ( num_elements < 0 )
1013 goto Fail;
1014
1015 if ( num_elements > T1_MAX_TABLE_ELEMENTS )
1016 num_elements = T1_MAX_TABLE_ELEMENTS;
1017
1018 old_cursor = parser->cursor;
1019 old_limit = parser->limit;
1020
1021 /* we store the elements count */
Werner Lemberg8eb03532001-06-19 23:03:41 +00001022 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1023 (FT_Byte)num_elements;
David Turner24d70242000-08-17 01:09:06 +00001024
1025 /* we now load each element, adjusting the field.offset on each one */
1026 token = elements;
1027 for ( ; num_elements > 0; num_elements--, token++ )
1028 {
1029 parser->cursor = token->start;
1030 parser->limit = token->limit;
David Turner4e7eeee2002-02-28 16:10:29 +00001031 PS_Parser_LoadField( parser, &fieldrec, objects, max_objects, 0 );
David Turner24d70242000-08-17 01:09:06 +00001032 fieldrec.offset += fieldrec.size;
1033 }
1034
David Turner34f1c2f2000-08-23 22:47:44 +00001035#if 0 /* obsolete -- keep for reference */
David Turner24d70242000-08-17 01:09:06 +00001036 if ( pflags )
1037 *pflags |= 1L << field->flag_bit;
David Turner34f1c2f2000-08-23 22:47:44 +00001038#else
Werner Lemberge4b32a52000-10-31 20:42:18 +00001039 FT_UNUSED( pflags );
David Turner34f1c2f2000-08-23 22:47:44 +00001040#endif
David Turner24d70242000-08-17 01:09:06 +00001041
1042 parser->cursor = old_cursor;
1043 parser->limit = old_limit;
1044
1045 Exit:
1046 return error;
1047
1048 Fail:
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001049 error = PSaux_Err_Invalid_File_Format;
David Turner24d70242000-08-17 01:09:06 +00001050 goto Exit;
1051 }
1052
1053
David Turnerbc82f1b2002-03-01 02:26:22 +00001054 FT_LOCAL_DEF( FT_Long )
David Turner4e7eeee2002-02-28 16:10:29 +00001055 PS_Parser_ToInt( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001056 {
1057 return t1_toint( &parser->cursor, parser->limit );
1058 }
1059
1060
David Turnerbc82f1b2002-03-01 02:26:22 +00001061 FT_LOCAL_DEF( FT_Fixed )
David Turner4e7eeee2002-02-28 16:10:29 +00001062 PS_Parser_ToFixed( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001063 FT_Int power_ten )
David Turner24d70242000-08-17 01:09:06 +00001064 {
1065 return t1_tofixed( &parser->cursor, parser->limit, power_ten );
1066 }
1067
1068
David Turnerbc82f1b2002-03-01 02:26:22 +00001069 FT_LOCAL_DEF( FT_Int )
David Turner4e7eeee2002-02-28 16:10:29 +00001070 PS_Parser_ToCoordArray( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001071 FT_Int max_coords,
1072 FT_Short* coords )
David Turner24d70242000-08-17 01:09:06 +00001073 {
1074 return t1_tocoordarray( &parser->cursor, parser->limit,
1075 max_coords, coords );
1076 }
1077
1078
David Turnerbc82f1b2002-03-01 02:26:22 +00001079 FT_LOCAL_DEF( FT_Int )
David Turner4e7eeee2002-02-28 16:10:29 +00001080 PS_Parser_ToFixedArray( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001081 FT_Int max_values,
1082 FT_Fixed* values,
1083 FT_Int power_ten )
David Turner24d70242000-08-17 01:09:06 +00001084 {
1085 return t1_tofixedarray( &parser->cursor, parser->limit,
1086 max_values, values, power_ten );
1087 }
1088
1089
1090#if 0
1091
David Turnerbc82f1b2002-03-01 02:26:22 +00001092 FT_LOCAL_DEF( FT_String* )
David Turner4e7eeee2002-02-28 16:10:29 +00001093 T1_ToString( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001094 {
1095 return t1_tostring( &parser->cursor, parser->limit, parser->memory );
1096 }
1097
1098
David Turnerbc82f1b2002-03-01 02:26:22 +00001099 FT_LOCAL_DEF( FT_Bool )
David Turner4e7eeee2002-02-28 16:10:29 +00001100 T1_ToBool( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001101 {
1102 return t1_tobool( &parser->cursor, parser->limit );
1103 }
1104
1105#endif /* 0 */
1106
1107
David Turnerbc82f1b2002-03-01 02:26:22 +00001108 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +00001109 PS_Parser_Init( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001110 FT_Byte* base,
1111 FT_Byte* limit,
1112 FT_Memory memory )
David Turner24d70242000-08-17 01:09:06 +00001113 {
1114 parser->error = 0;
1115 parser->base = base;
David Turnerf95a6032000-08-21 04:58:49 +00001116 parser->limit = limit;
David Turner24d70242000-08-17 01:09:06 +00001117 parser->cursor = base;
1118 parser->memory = memory;
David Turner4e7eeee2002-02-28 16:10:29 +00001119 parser->funcs = ps_parser_funcs;
Werner Lemberge4b32a52000-10-31 20:42:18 +00001120 }
David Turner24d70242000-08-17 01:09:06 +00001121
1122
David Turnerbc82f1b2002-03-01 02:26:22 +00001123 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +00001124 PS_Parser_Done( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001125 {
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001126 FT_UNUSED( parser );
David Turner24d70242000-08-17 01:09:06 +00001127 }
1128
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001129
David Turner24d70242000-08-17 01:09:06 +00001130 /*************************************************************************/
1131 /*************************************************************************/
1132 /***** *****/
1133 /***** T1 BUILDER *****/
1134 /***** *****/
1135 /*************************************************************************/
1136 /*************************************************************************/
1137
1138 /*************************************************************************/
1139 /* */
1140 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +00001141 /* T1_Builder_Init */
David Turner24d70242000-08-17 01:09:06 +00001142 /* */
1143 /* <Description> */
1144 /* Initializes a given glyph builder. */
1145 /* */
1146 /* <InOut> */
1147 /* builder :: A pointer to the glyph builder to initialize. */
1148 /* */
1149 /* <Input> */
1150 /* face :: The current face object. */
1151 /* */
1152 /* size :: The current size object. */
1153 /* */
1154 /* glyph :: The current glyph object. */
1155 /* */
Werner Lemberg545a75f2002-03-31 11:18:15 +00001156 /* hinting :: Whether hinting should be applied. */
1157 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001158 FT_LOCAL_DEF( void )
Werner Lemberg545a75f2002-03-31 11:18:15 +00001159 T1_Builder_Init( T1_Builder builder,
Werner Lemberg93616ec2001-06-27 19:46:12 +00001160 FT_Face face,
1161 FT_Size size,
David Turner5893c1b2001-10-18 11:49:26 +00001162 FT_GlyphSlot glyph,
1163 FT_Bool hinting )
David Turner24d70242000-08-17 01:09:06 +00001164 {
1165 builder->path_begun = 0;
1166 builder->load_points = 1;
1167
1168 builder->face = face;
1169 builder->glyph = glyph;
David Turnerf95a6032000-08-21 04:58:49 +00001170 builder->memory = face->memory;
David Turner24d70242000-08-17 01:09:06 +00001171
1172 if ( glyph )
1173 {
David Turner4d570242002-02-24 02:59:24 +00001174 FT_GlyphLoader loader = glyph->internal->loader;
David Turner24d70242000-08-17 01:09:06 +00001175
1176
Werner Lembergc3b21602001-12-05 01:22:05 +00001177 builder->loader = loader;
1178 builder->base = &loader->base.outline;
1179 builder->current = &loader->current.outline;
David Turner24d70242000-08-17 01:09:06 +00001180 FT_GlyphLoader_Rewind( loader );
David Turner5893c1b2001-10-18 11:49:26 +00001181
1182 builder->hints_globals = size->internal;
1183 builder->hints_funcs = 0;
David Turner4d570242002-02-24 02:59:24 +00001184
Werner Lembergc3b21602001-12-05 01:22:05 +00001185 if ( hinting )
David Turner5893c1b2001-10-18 11:49:26 +00001186 builder->hints_funcs = glyph->internal->glyph_hints;
David Turner24d70242000-08-17 01:09:06 +00001187 }
1188
1189 if ( size )
1190 {
1191 builder->scale_x = size->metrics.x_scale;
1192 builder->scale_y = size->metrics.y_scale;
1193 }
1194
1195 builder->pos_x = 0;
1196 builder->pos_y = 0;
1197
1198 builder->left_bearing.x = 0;
1199 builder->left_bearing.y = 0;
1200 builder->advance.x = 0;
1201 builder->advance.y = 0;
Werner Lemberge4b32a52000-10-31 20:42:18 +00001202
David Turnera39acf52000-08-23 02:47:57 +00001203 builder->funcs = t1_builder_funcs;
David Turner24d70242000-08-17 01:09:06 +00001204 }
1205
1206
1207 /*************************************************************************/
1208 /* */
1209 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +00001210 /* T1_Builder_Done */
David Turner24d70242000-08-17 01:09:06 +00001211 /* */
1212 /* <Description> */
1213 /* Finalizes a given glyph builder. Its contents can still be used */
1214 /* after the call, but the function saves important information */
1215 /* within the corresponding glyph slot. */
1216 /* */
1217 /* <Input> */
1218 /* builder :: A pointer to the glyph builder to finalize. */
1219 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001220 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001221 T1_Builder_Done( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001222 {
David Turnerf95a6032000-08-21 04:58:49 +00001223 FT_GlyphSlot glyph = builder->glyph;
David Turner24d70242000-08-17 01:09:06 +00001224
1225
1226 if ( glyph )
David Turnerf95a6032000-08-21 04:58:49 +00001227 glyph->outline = *builder->base;
David Turner24d70242000-08-17 01:09:06 +00001228 }
1229
1230
Werner Lemberg545a75f2002-03-31 11:18:15 +00001231 /* check that there is enough space for `count' more points */
David Turnerbc82f1b2002-03-01 02:26:22 +00001232 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001233 T1_Builder_Check_Points( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001234 FT_Int count )
David Turner24d70242000-08-17 01:09:06 +00001235 {
David Turnereba5ad42002-03-14 12:56:35 +00001236 return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
David Turner24d70242000-08-17 01:09:06 +00001237 }
1238
1239
1240 /* add a new point, do not check space */
David Turnerbc82f1b2002-03-01 02:26:22 +00001241 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001242 T1_Builder_Add_Point( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001243 FT_Pos x,
1244 FT_Pos y,
1245 FT_Byte flag )
David Turner24d70242000-08-17 01:09:06 +00001246 {
1247 FT_Outline* outline = builder->current;
1248
1249
1250 if ( builder->load_points )
1251 {
1252 FT_Vector* point = outline->points + outline->n_points;
1253 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1254
Werner Lemberg8728f292000-08-23 17:32:42 +00001255
1256 if ( builder->shift )
David Turner97488072000-08-22 22:36:33 +00001257 {
1258 x >>= 16;
1259 y >>= 16;
1260 }
1261 point->x = x;
1262 point->y = y;
Werner Lemberg8eb03532001-06-19 23:03:41 +00001263 *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
David Turner24d70242000-08-17 01:09:06 +00001264
1265 builder->last = *point;
1266 }
1267 outline->n_points++;
1268 }
1269
1270
1271 /* check space for a new on-curve point, then add it */
David Turnerbc82f1b2002-03-01 02:26:22 +00001272 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001273 T1_Builder_Add_Point1( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001274 FT_Pos x,
1275 FT_Pos y )
David Turner24d70242000-08-17 01:09:06 +00001276 {
1277 FT_Error error;
1278
1279
David Turnerf95a6032000-08-21 04:58:49 +00001280 error = T1_Builder_Check_Points( builder, 1 );
David Turner24d70242000-08-17 01:09:06 +00001281 if ( !error )
David Turnerf95a6032000-08-21 04:58:49 +00001282 T1_Builder_Add_Point( builder, x, y, 1 );
David Turner24d70242000-08-17 01:09:06 +00001283
1284 return error;
1285 }
1286
1287
1288 /* check room for a new contour, then add it */
David Turnerbc82f1b2002-03-01 02:26:22 +00001289 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001290 T1_Builder_Add_Contour( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001291 {
1292 FT_Outline* outline = builder->current;
1293 FT_Error error;
1294
1295
1296 if ( !builder->load_points )
1297 {
1298 outline->n_contours++;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001299 return PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +00001300 }
1301
David Turnereba5ad42002-03-14 12:56:35 +00001302 error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
David Turner24d70242000-08-17 01:09:06 +00001303 if ( !error )
1304 {
1305 if ( outline->n_contours > 0 )
Werner Lemberg8eb03532001-06-19 23:03:41 +00001306 outline->contours[outline->n_contours - 1] =
1307 (short)( outline->n_points - 1 );
David Turner24d70242000-08-17 01:09:06 +00001308
1309 outline->n_contours++;
1310 }
1311
1312 return error;
1313 }
1314
1315
1316 /* if a path was begun, add its first on-curve point */
David Turnerbc82f1b2002-03-01 02:26:22 +00001317 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001318 T1_Builder_Start_Point( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001319 FT_Pos x,
1320 FT_Pos y )
David Turner24d70242000-08-17 01:09:06 +00001321 {
1322 FT_Error error = 0;
1323
1324
1325 /* test whether we are building a new contour */
1326 if ( !builder->path_begun )
1327 {
1328 builder->path_begun = 1;
David Turnerf95a6032000-08-21 04:58:49 +00001329 error = T1_Builder_Add_Contour( builder );
David Turner24d70242000-08-17 01:09:06 +00001330 if ( !error )
David Turnerf95a6032000-08-21 04:58:49 +00001331 error = T1_Builder_Add_Point1( builder, x, y );
David Turner24d70242000-08-17 01:09:06 +00001332 }
1333 return error;
1334 }
1335
1336
1337 /* close the current contour */
David Turnerbc82f1b2002-03-01 02:26:22 +00001338 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001339 T1_Builder_Close_Contour( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001340 {
1341 FT_Outline* outline = builder->current;
1342
Werner Lembergeadc8df2000-10-11 05:52:42 +00001343
David Turner24d70242000-08-17 01:09:06 +00001344 /* XXXX: We must not include the last point in the path if it */
1345 /* is located on the first point. */
1346 if ( outline->n_points > 1 )
1347 {
Werner Lembergeadc8df2000-10-11 05:52:42 +00001348 FT_Int first = 0;
1349 FT_Vector* p1 = outline->points + first;
1350 FT_Vector* p2 = outline->points + outline->n_points - 1;
1351 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
David Turner24d70242000-08-17 01:09:06 +00001352
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001353
David Turner24d70242000-08-17 01:09:06 +00001354 if ( outline->n_contours > 1 )
1355 {
1356 first = outline->contours[outline->n_contours - 2] + 1;
1357 p1 = outline->points + first;
1358 }
1359
Werner Lembergeadc8df2000-10-11 05:52:42 +00001360 /* `delete' last point only if it coincides with the first */
1361 /* point and it is not a control point (which can happen). */
David Turner24d70242000-08-17 01:09:06 +00001362 if ( p1->x == p2->x && p1->y == p2->y )
Werner Lembergeadc8df2000-10-11 05:52:42 +00001363 if ( *control == FT_Curve_Tag_On )
1364 outline->n_points--;
David Turner24d70242000-08-17 01:09:06 +00001365 }
1366
1367 if ( outline->n_contours > 0 )
Werner Lemberg8eb03532001-06-19 23:03:41 +00001368 outline->contours[outline->n_contours - 1] =
1369 (short)( outline->n_points - 1 );
David Turner24d70242000-08-17 01:09:06 +00001370 }
1371
1372
David Turner24d70242000-08-17 01:09:06 +00001373 /*************************************************************************/
1374 /*************************************************************************/
1375 /***** *****/
1376 /***** OTHER *****/
1377 /***** *****/
1378 /*************************************************************************/
1379 /*************************************************************************/
1380
David Turnerbc82f1b2002-03-01 02:26:22 +00001381 FT_LOCAL_DEF( void )
Werner Lemberg93616ec2001-06-27 19:46:12 +00001382 T1_Decrypt( FT_Byte* buffer,
1383 FT_Offset length,
1384 FT_UShort seed )
David Turner24d70242000-08-17 01:09:06 +00001385 {
1386 while ( length > 0 )
1387 {
1388 FT_Byte plain;
1389
1390
Werner Lemberg8eb03532001-06-19 23:03:41 +00001391 plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
Werner Lemberga560a1e2001-07-03 12:45:24 +00001392 seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
David Turner24d70242000-08-17 01:09:06 +00001393 *buffer++ = plain;
1394 length--;
1395 }
1396 }
1397
1398
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001399/* END */