blob: 6bbb1ca5c814bc3b0385cd3a6e0b575b16d713cd [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
862 parser->cursor = token.start;
863 parser->limit = token.limit;
864
865 PS_Parser_ToToken( parser, &token2 );
866 parser->cursor = old_cur;
867 parser->limit = old_limit;
868
869 if ( token2.type == T1_TOKEN_TYPE_ARRAY )
870 goto FieldArray;
871 }
872 else if ( token.type == T1_TOKEN_TYPE_ARRAY )
873 {
874 FieldArray:
David Turner24d70242000-08-17 01:09:06 +0000875 /* if this is an array, and we have no blend, an error occurs */
876 if ( max_objects == 0 )
877 goto Fail;
878
879 count = max_objects;
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000880 idx = 1;
David Turner24d70242000-08-17 01:09:06 +0000881 }
882
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000883 for ( ; count > 0; count--, idx++ )
David Turner24d70242000-08-17 01:09:06 +0000884 {
Werner Lemberg0d9165e2002-03-07 21:59:59 +0000885 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
David Turner24d70242000-08-17 01:09:06 +0000886 FT_Long val;
887 FT_String* string;
888
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000889
David Turner24d70242000-08-17 01:09:06 +0000890 switch ( field->type )
891 {
David Turner4e7eeee2002-02-28 16:10:29 +0000892 case T1_FIELD_TYPE_BOOL:
David Turner24d70242000-08-17 01:09:06 +0000893 val = t1_tobool( &cur, limit );
894 goto Store_Integer;
895
David Turner4e7eeee2002-02-28 16:10:29 +0000896 case T1_FIELD_TYPE_FIXED:
David Turner24d70242000-08-17 01:09:06 +0000897 val = t1_tofixed( &cur, limit, 3 );
898 goto Store_Integer;
899
David Turner4e7eeee2002-02-28 16:10:29 +0000900 case T1_FIELD_TYPE_INTEGER:
David Turner24d70242000-08-17 01:09:06 +0000901 val = t1_toint( &cur, limit );
902
903 Store_Integer:
904 switch ( field->size )
905 {
906 case 1:
907 *(FT_Byte*)q = (FT_Byte)val;
908 break;
909
910 case 2:
911 *(FT_UShort*)q = (FT_UShort)val;
912 break;
913
914 case 4:
915 *(FT_UInt32*)q = (FT_UInt32)val;
916 break;
917
Werner Lemberg545a75f2002-03-31 11:18:15 +0000918 default: /* for 64-bit systems */
David Turner24d70242000-08-17 01:09:06 +0000919 *(FT_Long*)q = val;
920 }
921 break;
922
David Turner4e7eeee2002-02-28 16:10:29 +0000923 case T1_FIELD_TYPE_STRING:
David Turner24d70242000-08-17 01:09:06 +0000924 {
925 FT_Memory memory = parser->memory;
Werner Lemberg914b2892001-03-10 17:07:42 +0000926 FT_UInt len = (FT_UInt)( limit - cur );
David Turner24d70242000-08-17 01:09:06 +0000927
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000928
David Turner24d70242000-08-17 01:09:06 +0000929 if ( *(FT_String**)q )
Werner Lembergb1c8bf02000-08-17 07:18:04 +0000930 /* with synthetic fonts, it's possible to find a field twice */
David Turner24d70242000-08-17 01:09:06 +0000931 break;
932
David Turnere459d742002-03-22 13:52:37 +0000933 if ( FT_ALLOC( string, len + 1 ) )
David Turner24d70242000-08-17 01:09:06 +0000934 goto Exit;
935
David Turnere459d742002-03-22 13:52:37 +0000936 FT_MEM_COPY( string, cur, len );
David Turner24d70242000-08-17 01:09:06 +0000937 string[len] = 0;
938
939 *(FT_String**)q = string;
940 }
941 break;
942
David Turner8db6a072002-07-11 11:26:21 +0000943 case T1_FIELD_TYPE_BBOX:
944 {
945 FT_Fixed temp[4];
946 FT_BBox* bbox = (FT_BBox*)q;
947
948 /* we need the '[' and ']' delimiters */
949 token.start--;
950 token.limit++;
951 (void) t1_tofixedarray( &token.start, token.limit, 4, temp, 0 );
952
953 bbox->xMin = FT_RoundFix( temp[0] );
954 bbox->yMin = FT_RoundFix( temp[1] );
955 bbox->xMax = FT_RoundFix( temp[2] );
956 bbox->yMax = FT_RoundFix( temp[3] );
957 }
958 break;
959
David Turner24d70242000-08-17 01:09:06 +0000960 default:
961 /* an error occured */
962 goto Fail;
963 }
964 }
965
David Turner34f1c2f2000-08-23 22:47:44 +0000966#if 0 /* obsolete - keep for reference */
David Turner24d70242000-08-17 01:09:06 +0000967 if ( pflags )
968 *pflags |= 1L << field->flag_bit;
David Turner34f1c2f2000-08-23 22:47:44 +0000969#else
Werner Lemberge4b32a52000-10-31 20:42:18 +0000970 FT_UNUSED( pflags );
David Turner34f1c2f2000-08-23 22:47:44 +0000971#endif
David Turner24d70242000-08-17 01:09:06 +0000972
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000973 error = PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +0000974
975 Exit:
976 return error;
977
978 Fail:
Werner Lemberg1f7f0e82001-06-06 17:30:41 +0000979 error = PSaux_Err_Invalid_File_Format;
David Turner24d70242000-08-17 01:09:06 +0000980 goto Exit;
981 }
982
983
984#define T1_MAX_TABLE_ELEMENTS 32
985
986
David Turnerbc82f1b2002-03-01 02:26:22 +0000987 FT_LOCAL_DEF( FT_Error )
David Turner4e7eeee2002-02-28 16:10:29 +0000988 PS_Parser_LoadFieldTable( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +0000989 const T1_Field field,
990 void** objects,
991 FT_UInt max_objects,
992 FT_ULong* pflags )
David Turner24d70242000-08-17 01:09:06 +0000993 {
Werner Lemberg545a75f2002-03-31 11:18:15 +0000994 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
995 T1_Token token;
996 FT_Int num_elements;
997 FT_Error error = 0;
998 FT_Byte* old_cursor;
999 FT_Byte* old_limit;
1000 T1_FieldRec fieldrec = *(T1_Field)field;
1001
David Turner24d70242000-08-17 01:09:06 +00001002
David Turner34f1c2f2000-08-23 22:47:44 +00001003#if 1
David Turner4e7eeee2002-02-28 16:10:29 +00001004 fieldrec.type = T1_FIELD_TYPE_INTEGER;
1005 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1006 fieldrec.type = T1_FIELD_TYPE_FIXED;
David Turner34f1c2f2000-08-23 22:47:44 +00001007#endif
David Turner24d70242000-08-17 01:09:06 +00001008
David Turner4e7eeee2002-02-28 16:10:29 +00001009 PS_Parser_ToTokenArray( parser, elements, 32, &num_elements );
David Turner24d70242000-08-17 01:09:06 +00001010 if ( num_elements < 0 )
1011 goto Fail;
1012
1013 if ( num_elements > T1_MAX_TABLE_ELEMENTS )
1014 num_elements = T1_MAX_TABLE_ELEMENTS;
1015
1016 old_cursor = parser->cursor;
1017 old_limit = parser->limit;
1018
1019 /* we store the elements count */
Werner Lemberg8eb03532001-06-19 23:03:41 +00001020 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1021 (FT_Byte)num_elements;
David Turner24d70242000-08-17 01:09:06 +00001022
1023 /* we now load each element, adjusting the field.offset on each one */
1024 token = elements;
1025 for ( ; num_elements > 0; num_elements--, token++ )
1026 {
1027 parser->cursor = token->start;
1028 parser->limit = token->limit;
David Turner4e7eeee2002-02-28 16:10:29 +00001029 PS_Parser_LoadField( parser, &fieldrec, objects, max_objects, 0 );
David Turner24d70242000-08-17 01:09:06 +00001030 fieldrec.offset += fieldrec.size;
1031 }
1032
David Turner34f1c2f2000-08-23 22:47:44 +00001033#if 0 /* obsolete -- keep for reference */
David Turner24d70242000-08-17 01:09:06 +00001034 if ( pflags )
1035 *pflags |= 1L << field->flag_bit;
David Turner34f1c2f2000-08-23 22:47:44 +00001036#else
Werner Lemberge4b32a52000-10-31 20:42:18 +00001037 FT_UNUSED( pflags );
David Turner34f1c2f2000-08-23 22:47:44 +00001038#endif
David Turner24d70242000-08-17 01:09:06 +00001039
1040 parser->cursor = old_cursor;
1041 parser->limit = old_limit;
1042
1043 Exit:
1044 return error;
1045
1046 Fail:
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001047 error = PSaux_Err_Invalid_File_Format;
David Turner24d70242000-08-17 01:09:06 +00001048 goto Exit;
1049 }
1050
1051
David Turnerbc82f1b2002-03-01 02:26:22 +00001052 FT_LOCAL_DEF( FT_Long )
David Turner4e7eeee2002-02-28 16:10:29 +00001053 PS_Parser_ToInt( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001054 {
1055 return t1_toint( &parser->cursor, parser->limit );
1056 }
1057
1058
David Turnerbc82f1b2002-03-01 02:26:22 +00001059 FT_LOCAL_DEF( FT_Fixed )
David Turner4e7eeee2002-02-28 16:10:29 +00001060 PS_Parser_ToFixed( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001061 FT_Int power_ten )
David Turner24d70242000-08-17 01:09:06 +00001062 {
1063 return t1_tofixed( &parser->cursor, parser->limit, power_ten );
1064 }
1065
1066
David Turnerbc82f1b2002-03-01 02:26:22 +00001067 FT_LOCAL_DEF( FT_Int )
David Turner4e7eeee2002-02-28 16:10:29 +00001068 PS_Parser_ToCoordArray( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001069 FT_Int max_coords,
1070 FT_Short* coords )
David Turner24d70242000-08-17 01:09:06 +00001071 {
1072 return t1_tocoordarray( &parser->cursor, parser->limit,
1073 max_coords, coords );
1074 }
1075
1076
David Turnerbc82f1b2002-03-01 02:26:22 +00001077 FT_LOCAL_DEF( FT_Int )
David Turner4e7eeee2002-02-28 16:10:29 +00001078 PS_Parser_ToFixedArray( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001079 FT_Int max_values,
1080 FT_Fixed* values,
1081 FT_Int power_ten )
David Turner24d70242000-08-17 01:09:06 +00001082 {
1083 return t1_tofixedarray( &parser->cursor, parser->limit,
1084 max_values, values, power_ten );
1085 }
1086
1087
1088#if 0
1089
David Turnerbc82f1b2002-03-01 02:26:22 +00001090 FT_LOCAL_DEF( FT_String* )
David Turner4e7eeee2002-02-28 16:10:29 +00001091 T1_ToString( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001092 {
1093 return t1_tostring( &parser->cursor, parser->limit, parser->memory );
1094 }
1095
1096
David Turnerbc82f1b2002-03-01 02:26:22 +00001097 FT_LOCAL_DEF( FT_Bool )
David Turner4e7eeee2002-02-28 16:10:29 +00001098 T1_ToBool( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001099 {
1100 return t1_tobool( &parser->cursor, parser->limit );
1101 }
1102
1103#endif /* 0 */
1104
1105
David Turnerbc82f1b2002-03-01 02:26:22 +00001106 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +00001107 PS_Parser_Init( PS_Parser parser,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001108 FT_Byte* base,
1109 FT_Byte* limit,
1110 FT_Memory memory )
David Turner24d70242000-08-17 01:09:06 +00001111 {
1112 parser->error = 0;
1113 parser->base = base;
David Turnerf95a6032000-08-21 04:58:49 +00001114 parser->limit = limit;
David Turner24d70242000-08-17 01:09:06 +00001115 parser->cursor = base;
1116 parser->memory = memory;
David Turner4e7eeee2002-02-28 16:10:29 +00001117 parser->funcs = ps_parser_funcs;
Werner Lemberge4b32a52000-10-31 20:42:18 +00001118 }
David Turner24d70242000-08-17 01:09:06 +00001119
1120
David Turnerbc82f1b2002-03-01 02:26:22 +00001121 FT_LOCAL_DEF( void )
David Turner4e7eeee2002-02-28 16:10:29 +00001122 PS_Parser_Done( PS_Parser parser )
David Turner24d70242000-08-17 01:09:06 +00001123 {
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001124 FT_UNUSED( parser );
David Turner24d70242000-08-17 01:09:06 +00001125 }
1126
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001127
David Turner24d70242000-08-17 01:09:06 +00001128 /*************************************************************************/
1129 /*************************************************************************/
1130 /***** *****/
1131 /***** T1 BUILDER *****/
1132 /***** *****/
1133 /*************************************************************************/
1134 /*************************************************************************/
1135
1136 /*************************************************************************/
1137 /* */
1138 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +00001139 /* T1_Builder_Init */
David Turner24d70242000-08-17 01:09:06 +00001140 /* */
1141 /* <Description> */
1142 /* Initializes a given glyph builder. */
1143 /* */
1144 /* <InOut> */
1145 /* builder :: A pointer to the glyph builder to initialize. */
1146 /* */
1147 /* <Input> */
1148 /* face :: The current face object. */
1149 /* */
1150 /* size :: The current size object. */
1151 /* */
1152 /* glyph :: The current glyph object. */
1153 /* */
Werner Lemberg545a75f2002-03-31 11:18:15 +00001154 /* hinting :: Whether hinting should be applied. */
1155 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001156 FT_LOCAL_DEF( void )
Werner Lemberg545a75f2002-03-31 11:18:15 +00001157 T1_Builder_Init( T1_Builder builder,
Werner Lemberg93616ec2001-06-27 19:46:12 +00001158 FT_Face face,
1159 FT_Size size,
David Turner5893c1b2001-10-18 11:49:26 +00001160 FT_GlyphSlot glyph,
1161 FT_Bool hinting )
David Turner24d70242000-08-17 01:09:06 +00001162 {
1163 builder->path_begun = 0;
1164 builder->load_points = 1;
1165
1166 builder->face = face;
1167 builder->glyph = glyph;
David Turnerf95a6032000-08-21 04:58:49 +00001168 builder->memory = face->memory;
David Turner24d70242000-08-17 01:09:06 +00001169
1170 if ( glyph )
1171 {
David Turner4d570242002-02-24 02:59:24 +00001172 FT_GlyphLoader loader = glyph->internal->loader;
David Turner24d70242000-08-17 01:09:06 +00001173
1174
Werner Lembergc3b21602001-12-05 01:22:05 +00001175 builder->loader = loader;
1176 builder->base = &loader->base.outline;
1177 builder->current = &loader->current.outline;
David Turner24d70242000-08-17 01:09:06 +00001178 FT_GlyphLoader_Rewind( loader );
David Turner5893c1b2001-10-18 11:49:26 +00001179
1180 builder->hints_globals = size->internal;
1181 builder->hints_funcs = 0;
David Turner4d570242002-02-24 02:59:24 +00001182
Werner Lembergc3b21602001-12-05 01:22:05 +00001183 if ( hinting )
David Turner5893c1b2001-10-18 11:49:26 +00001184 builder->hints_funcs = glyph->internal->glyph_hints;
David Turner24d70242000-08-17 01:09:06 +00001185 }
1186
1187 if ( size )
1188 {
1189 builder->scale_x = size->metrics.x_scale;
1190 builder->scale_y = size->metrics.y_scale;
1191 }
1192
1193 builder->pos_x = 0;
1194 builder->pos_y = 0;
1195
1196 builder->left_bearing.x = 0;
1197 builder->left_bearing.y = 0;
1198 builder->advance.x = 0;
1199 builder->advance.y = 0;
Werner Lemberge4b32a52000-10-31 20:42:18 +00001200
David Turnera39acf52000-08-23 02:47:57 +00001201 builder->funcs = t1_builder_funcs;
David Turner24d70242000-08-17 01:09:06 +00001202 }
1203
1204
1205 /*************************************************************************/
1206 /* */
1207 /* <Function> */
David Turnerf95a6032000-08-21 04:58:49 +00001208 /* T1_Builder_Done */
David Turner24d70242000-08-17 01:09:06 +00001209 /* */
1210 /* <Description> */
1211 /* Finalizes a given glyph builder. Its contents can still be used */
1212 /* after the call, but the function saves important information */
1213 /* within the corresponding glyph slot. */
1214 /* */
1215 /* <Input> */
1216 /* builder :: A pointer to the glyph builder to finalize. */
1217 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +00001218 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001219 T1_Builder_Done( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001220 {
David Turnerf95a6032000-08-21 04:58:49 +00001221 FT_GlyphSlot glyph = builder->glyph;
David Turner24d70242000-08-17 01:09:06 +00001222
1223
1224 if ( glyph )
David Turnerf95a6032000-08-21 04:58:49 +00001225 glyph->outline = *builder->base;
David Turner24d70242000-08-17 01:09:06 +00001226 }
1227
1228
Werner Lemberg545a75f2002-03-31 11:18:15 +00001229 /* check that there is enough space for `count' more points */
David Turnerbc82f1b2002-03-01 02:26:22 +00001230 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001231 T1_Builder_Check_Points( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001232 FT_Int count )
David Turner24d70242000-08-17 01:09:06 +00001233 {
David Turnereba5ad42002-03-14 12:56:35 +00001234 return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
David Turner24d70242000-08-17 01:09:06 +00001235 }
1236
1237
1238 /* add a new point, do not check space */
David Turnerbc82f1b2002-03-01 02:26:22 +00001239 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001240 T1_Builder_Add_Point( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001241 FT_Pos x,
1242 FT_Pos y,
1243 FT_Byte flag )
David Turner24d70242000-08-17 01:09:06 +00001244 {
1245 FT_Outline* outline = builder->current;
1246
1247
1248 if ( builder->load_points )
1249 {
1250 FT_Vector* point = outline->points + outline->n_points;
1251 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1252
Werner Lemberg8728f292000-08-23 17:32:42 +00001253
1254 if ( builder->shift )
David Turner97488072000-08-22 22:36:33 +00001255 {
1256 x >>= 16;
1257 y >>= 16;
1258 }
1259 point->x = x;
1260 point->y = y;
Werner Lemberg8eb03532001-06-19 23:03:41 +00001261 *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
David Turner24d70242000-08-17 01:09:06 +00001262
1263 builder->last = *point;
1264 }
1265 outline->n_points++;
1266 }
1267
1268
1269 /* check space for a new on-curve point, then add it */
David Turnerbc82f1b2002-03-01 02:26:22 +00001270 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001271 T1_Builder_Add_Point1( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001272 FT_Pos x,
1273 FT_Pos y )
David Turner24d70242000-08-17 01:09:06 +00001274 {
1275 FT_Error error;
1276
1277
David Turnerf95a6032000-08-21 04:58:49 +00001278 error = T1_Builder_Check_Points( builder, 1 );
David Turner24d70242000-08-17 01:09:06 +00001279 if ( !error )
David Turnerf95a6032000-08-21 04:58:49 +00001280 T1_Builder_Add_Point( builder, x, y, 1 );
David Turner24d70242000-08-17 01:09:06 +00001281
1282 return error;
1283 }
1284
1285
1286 /* check room for a new contour, then add it */
David Turnerbc82f1b2002-03-01 02:26:22 +00001287 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001288 T1_Builder_Add_Contour( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001289 {
1290 FT_Outline* outline = builder->current;
1291 FT_Error error;
1292
1293
1294 if ( !builder->load_points )
1295 {
1296 outline->n_contours++;
Werner Lemberg1f7f0e82001-06-06 17:30:41 +00001297 return PSaux_Err_Ok;
David Turner24d70242000-08-17 01:09:06 +00001298 }
1299
David Turnereba5ad42002-03-14 12:56:35 +00001300 error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
David Turner24d70242000-08-17 01:09:06 +00001301 if ( !error )
1302 {
1303 if ( outline->n_contours > 0 )
Werner Lemberg8eb03532001-06-19 23:03:41 +00001304 outline->contours[outline->n_contours - 1] =
1305 (short)( outline->n_points - 1 );
David Turner24d70242000-08-17 01:09:06 +00001306
1307 outline->n_contours++;
1308 }
1309
1310 return error;
1311 }
1312
1313
1314 /* if a path was begun, add its first on-curve point */
David Turnerbc82f1b2002-03-01 02:26:22 +00001315 FT_LOCAL_DEF( FT_Error )
David Turner429978b2002-03-14 10:09:35 +00001316 T1_Builder_Start_Point( T1_Builder builder,
Werner Lemberg545a75f2002-03-31 11:18:15 +00001317 FT_Pos x,
1318 FT_Pos y )
David Turner24d70242000-08-17 01:09:06 +00001319 {
1320 FT_Error error = 0;
1321
1322
1323 /* test whether we are building a new contour */
1324 if ( !builder->path_begun )
1325 {
1326 builder->path_begun = 1;
David Turnerf95a6032000-08-21 04:58:49 +00001327 error = T1_Builder_Add_Contour( builder );
David Turner24d70242000-08-17 01:09:06 +00001328 if ( !error )
David Turnerf95a6032000-08-21 04:58:49 +00001329 error = T1_Builder_Add_Point1( builder, x, y );
David Turner24d70242000-08-17 01:09:06 +00001330 }
1331 return error;
1332 }
1333
1334
1335 /* close the current contour */
David Turnerbc82f1b2002-03-01 02:26:22 +00001336 FT_LOCAL_DEF( void )
David Turner429978b2002-03-14 10:09:35 +00001337 T1_Builder_Close_Contour( T1_Builder builder )
David Turner24d70242000-08-17 01:09:06 +00001338 {
1339 FT_Outline* outline = builder->current;
1340
Werner Lembergeadc8df2000-10-11 05:52:42 +00001341
David Turner24d70242000-08-17 01:09:06 +00001342 /* XXXX: We must not include the last point in the path if it */
1343 /* is located on the first point. */
1344 if ( outline->n_points > 1 )
1345 {
Werner Lembergeadc8df2000-10-11 05:52:42 +00001346 FT_Int first = 0;
1347 FT_Vector* p1 = outline->points + first;
1348 FT_Vector* p2 = outline->points + outline->n_points - 1;
1349 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
David Turner24d70242000-08-17 01:09:06 +00001350
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001351
David Turner24d70242000-08-17 01:09:06 +00001352 if ( outline->n_contours > 1 )
1353 {
1354 first = outline->contours[outline->n_contours - 2] + 1;
1355 p1 = outline->points + first;
1356 }
1357
Werner Lembergeadc8df2000-10-11 05:52:42 +00001358 /* `delete' last point only if it coincides with the first */
1359 /* point and it is not a control point (which can happen). */
David Turner24d70242000-08-17 01:09:06 +00001360 if ( p1->x == p2->x && p1->y == p2->y )
Werner Lembergeadc8df2000-10-11 05:52:42 +00001361 if ( *control == FT_Curve_Tag_On )
1362 outline->n_points--;
David Turner24d70242000-08-17 01:09:06 +00001363 }
1364
1365 if ( outline->n_contours > 0 )
Werner Lemberg8eb03532001-06-19 23:03:41 +00001366 outline->contours[outline->n_contours - 1] =
1367 (short)( outline->n_points - 1 );
David Turner24d70242000-08-17 01:09:06 +00001368 }
1369
1370
David Turner24d70242000-08-17 01:09:06 +00001371 /*************************************************************************/
1372 /*************************************************************************/
1373 /***** *****/
1374 /***** OTHER *****/
1375 /***** *****/
1376 /*************************************************************************/
1377 /*************************************************************************/
1378
David Turnerbc82f1b2002-03-01 02:26:22 +00001379 FT_LOCAL_DEF( void )
Werner Lemberg93616ec2001-06-27 19:46:12 +00001380 T1_Decrypt( FT_Byte* buffer,
1381 FT_Offset length,
1382 FT_UShort seed )
David Turner24d70242000-08-17 01:09:06 +00001383 {
1384 while ( length > 0 )
1385 {
1386 FT_Byte plain;
1387
1388
Werner Lemberg8eb03532001-06-19 23:03:41 +00001389 plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
Werner Lemberga560a1e2001-07-03 12:45:24 +00001390 seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
David Turner24d70242000-08-17 01:09:06 +00001391 *buffer++ = plain;
1392 length--;
1393 }
1394 }
1395
1396
Werner Lembergb1c8bf02000-08-17 07:18:04 +00001397/* END */