Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / psaux / psconv.c
1 /***************************************************************************/
2 /* */
3 /* psconv.c */
4 /* */
5 /* Some convenience conversions (body). */
6 /* */
7 /* Copyright 2006, 2008, 2009 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
21
22 #include "psconv.h"
23 #include "psauxerr.h"
24
25
26 /* The following array is used by various functions to quickly convert */
27 /* digits (both decimal and non-decimal) into numbers. */
28
29 #if 'A' == 65
30 /* ASCII */
31
32 static const FT_Char ft_char_table[128] =
33 {
34 /* 0x00 */
35 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
39 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
40 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
41 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
42 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
43 };
44
45 /* no character >= 0x80 can represent a valid number */
46 #define OP >=
47
48 #endif /* 'A' == 65 */
49
50 #if 'A' == 193
51 /* EBCDIC */
52
53 static const FT_Char ft_char_table[128] =
54 {
55 /* 0x80 */
56 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
57 -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
58 -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
61 -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
62 -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
63 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
64 };
65
66 /* no character < 0x80 can represent a valid number */
67 #define OP <
68
69 #endif /* 'A' == 193 */
70
71
72 FT_LOCAL_DEF( FT_Int )
73 PS_Conv_Strtol( FT_Byte** cursor,
74 FT_Byte* limit,
75 FT_Int base )
76 {
77 FT_Byte* p = *cursor;
78 FT_Int num = 0;
79 FT_Bool sign = 0;
80
81
82 if ( p == limit || base < 2 || base > 36 )
83 return 0;
84
85 if ( *p == '-' || *p == '+' )
86 {
87 sign = FT_BOOL( *p == '-' );
88
89 p++;
90 if ( p == limit )
91 return 0;
92 }
93
94 for ( ; p < limit; p++ )
95 {
96 FT_Char c;
97
98
99 if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
100 break;
101
102 c = ft_char_table[*p & 0x7f];
103
104 if ( c < 0 || c >= base )
105 break;
106
107 num = num * base + c;
108 }
109
110 if ( sign )
111 num = -num;
112
113 *cursor = p;
114
115 return num;
116 }
117
118
119 FT_LOCAL_DEF( FT_Int )
120 PS_Conv_ToInt( FT_Byte** cursor,
121 FT_Byte* limit )
122
123 {
124 FT_Byte* p;
125 FT_Int num;
126
127
128 num = PS_Conv_Strtol( cursor, limit, 10 );
129 p = *cursor;
130
131 if ( p < limit && *p == '#' )
132 {
133 *cursor = p + 1;
134
135 return PS_Conv_Strtol( cursor, limit, num );
136 }
137 else
138 return num;
139 }
140
141
142 FT_LOCAL_DEF( FT_Fixed )
143 PS_Conv_ToFixed( FT_Byte** cursor,
144 FT_Byte* limit,
145 FT_Int power_ten )
146 {
147 FT_Byte* p = *cursor;
148 FT_Fixed integral;
149 FT_Long decimal = 0, divider = 1;
150 FT_Bool sign = 0;
151
152
153 if ( p == limit )
154 return 0;
155
156 if ( *p == '-' || *p == '+' )
157 {
158 sign = FT_BOOL( *p == '-' );
159
160 p++;
161 if ( p == limit )
162 return 0;
163 }
164
165 if ( *p != '.' )
166 integral = PS_Conv_ToInt( &p, limit ) << 16;
167 else
168 integral = 0;
169
170 /* read the decimal part */
171 if ( p < limit && *p == '.' )
172 {
173 p++;
174
175 for ( ; p < limit; p++ )
176 {
177 FT_Char c;
178
179
180 if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
181 break;
182
183 c = ft_char_table[*p & 0x7f];
184
185 if ( c < 0 || c >= 10 )
186 break;
187
188 if ( !integral && power_ten > 0 )
189 {
190 power_ten--;
191 decimal = decimal * 10 + c;
192 }
193 else
194 {
195 if ( divider < 10000000L )
196 {
197 decimal = decimal * 10 + c;
198 divider *= 10;
199 }
200 }
201 }
202 }
203
204 /* read exponent, if any */
205 if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
206 {
207 p++;
208 power_ten += PS_Conv_ToInt( &p, limit );
209 }
210
211 while ( power_ten > 0 )
212 {
213 integral *= 10;
214 decimal *= 10;
215 power_ten--;
216 }
217
218 while ( power_ten < 0 )
219 {
220 integral /= 10;
221 divider *= 10;
222 power_ten++;
223 }
224
225 if ( decimal )
226 integral += FT_DivFix( decimal, divider );
227
228 if ( sign )
229 integral = -integral;
230
231 *cursor = p;
232
233 return integral;
234 }
235
236
237 #if 0
238 FT_LOCAL_DEF( FT_UInt )
239 PS_Conv_StringDecode( FT_Byte** cursor,
240 FT_Byte* limit,
241 FT_Byte* buffer,
242 FT_Offset n )
243 {
244 FT_Byte* p;
245 FT_UInt r = 0;
246
247
248 for ( p = *cursor; r < n && p < limit; p++ )
249 {
250 FT_Byte b;
251
252
253 if ( *p != '\\' )
254 {
255 buffer[r++] = *p;
256
257 continue;
258 }
259
260 p++;
261
262 switch ( *p )
263 {
264 case 'n':
265 b = '\n';
266 break;
267 case 'r':
268 b = '\r';
269 break;
270 case 't':
271 b = '\t';
272 break;
273 case 'b':
274 b = '\b';
275 break;
276 case 'f':
277 b = '\f';
278 break;
279 case '\r':
280 p++;
281 if ( *p != '\n' )
282 {
283 b = *p;
284
285 break;
286 }
287 /* no break */
288 case '\n':
289 continue;
290 break;
291 default:
292 if ( IS_PS_DIGIT( *p ) )
293 {
294 b = *p - '0';
295
296 p++;
297
298 if ( IS_PS_DIGIT( *p ) )
299 {
300 b = b * 8 + *p - '0';
301
302 p++;
303
304 if ( IS_PS_DIGIT( *p ) )
305 b = b * 8 + *p - '0';
306 else
307 {
308 buffer[r++] = b;
309 b = *p;
310 }
311 }
312 else
313 {
314 buffer[r++] = b;
315 b = *p;
316 }
317 }
318 else
319 b = *p;
320 break;
321 }
322
323 buffer[r++] = b;
324 }
325
326 *cursor = p;
327
328 return r;
329 }
330 #endif /* 0 */
331
332
333 FT_LOCAL_DEF( FT_UInt )
334 PS_Conv_ASCIIHexDecode( FT_Byte** cursor,
335 FT_Byte* limit,
336 FT_Byte* buffer,
337 FT_Offset n )
338 {
339 FT_Byte* p;
340 FT_UInt r = 0;
341 FT_UInt w = 0;
342 FT_UInt pad = 0x01;
343
344
345 n *= 2;
346
347 #if 1
348
349 p = *cursor;
350 if ( n > (FT_UInt)( limit - p ) )
351 n = (FT_UInt)( limit - p );
352
353 /* we try to process two nibbles at a time to be as fast as possible */
354 for ( ; r < n; r++ )
355 {
356 FT_UInt c = p[r];
357
358
359 if ( IS_PS_SPACE( c ) )
360 continue;
361
362 if ( c OP 0x80 )
363 break;
364
365 c = ft_char_table[c & 0x7F];
366 if ( (unsigned)c >= 16 )
367 break;
368
369 pad = ( pad << 4 ) | c;
370 if ( pad & 0x100 )
371 {
372 buffer[w++] = (FT_Byte)pad;
373 pad = 0x01;
374 }
375 }
376
377 if ( pad != 0x01 )
378 buffer[w++] = (FT_Byte)( pad << 4 );
379
380 *cursor = p + r;
381
382 return w;
383
384 #else /* 0 */
385
386 for ( r = 0; r < n; r++ )
387 {
388 FT_Char c;
389
390
391 if ( IS_PS_SPACE( *p ) )
392 continue;
393
394 if ( *p OP 0x80 )
395 break;
396
397 c = ft_char_table[*p & 0x7f];
398
399 if ( (unsigned)c >= 16 )
400 break;
401
402 if ( r & 1 )
403 {
404 *buffer = (FT_Byte)(*buffer + c);
405 buffer++;
406 }
407 else
408 *buffer = (FT_Byte)(c << 4);
409
410 r++;
411 }
412
413 *cursor = p;
414
415 return ( r + 1 ) / 2;
416
417 #endif /* 0 */
418
419 }
420
421
422 FT_LOCAL_DEF( FT_UInt )
423 PS_Conv_EexecDecode( FT_Byte** cursor,
424 FT_Byte* limit,
425 FT_Byte* buffer,
426 FT_Offset n,
427 FT_UShort* seed )
428 {
429 FT_Byte* p;
430 FT_UInt r;
431 FT_UInt s = *seed;
432
433
434 #if 1
435
436 p = *cursor;
437 if ( n > (FT_UInt)(limit - p) )
438 n = (FT_UInt)(limit - p);
439
440 for ( r = 0; r < n; r++ )
441 {
442 FT_UInt val = p[r];
443 FT_UInt b = ( val ^ ( s >> 8 ) );
444
445
446 s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
447 buffer[r] = (FT_Byte) b;
448 }
449
450 *cursor = p + n;
451 *seed = (FT_UShort)s;
452
453 #else /* 0 */
454
455 for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
456 {
457 FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
458
459
460 s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
461 *buffer++ = b;
462 }
463 *cursor = p;
464 *seed = s;
465
466 #endif /* 0 */
467
468 return r;
469 }
470
471
472 /* END */