Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / pfr / pfrgload.c
blob6fe6e4225ab516259629766846e86bc807c1379d
1 /***************************************************************************/
2 /* */
3 /* pfrgload.c */
4 /* */
5 /* FreeType PFR glyph loader (body). */
6 /* */
7 /* Copyright 2002, 2003, 2005, 2007 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 /***************************************************************************/
19 #include "pfrgload.h"
20 #include "pfrsbit.h"
21 #include "pfrload.h" /* for macro definitions */
22 #include FT_INTERNAL_DEBUG_H
24 #include "pfrerror.h"
26 #undef FT_COMPONENT
27 #define FT_COMPONENT trace_pfr
30 /*************************************************************************/
31 /*************************************************************************/
32 /***** *****/
33 /***** PFR GLYPH BUILDER *****/
34 /***** *****/
35 /*************************************************************************/
36 /*************************************************************************/
39 FT_LOCAL_DEF( void )
40 pfr_glyph_init( PFR_Glyph glyph,
41 FT_GlyphLoader loader )
43 FT_ZERO( glyph );
45 glyph->loader = loader;
46 glyph->path_begun = 0;
48 FT_GlyphLoader_Rewind( loader );
52 FT_LOCAL_DEF( void )
53 pfr_glyph_done( PFR_Glyph glyph )
55 FT_Memory memory = glyph->loader->memory;
58 FT_FREE( glyph->x_control );
59 glyph->y_control = NULL;
61 glyph->max_xy_control = 0;
62 #if 0
63 glyph->num_x_control = 0;
64 glyph->num_y_control = 0;
65 #endif
67 FT_FREE( glyph->subs );
69 glyph->max_subs = 0;
70 glyph->num_subs = 0;
72 glyph->loader = NULL;
73 glyph->path_begun = 0;
77 /* close current contour, if any */
78 static void
79 pfr_glyph_close_contour( PFR_Glyph glyph )
81 FT_GlyphLoader loader = glyph->loader;
82 FT_Outline* outline = &loader->current.outline;
83 FT_Int last, first;
86 if ( !glyph->path_begun )
87 return;
89 /* compute first and last point indices in current glyph outline */
90 last = outline->n_points - 1;
91 first = 0;
92 if ( outline->n_contours > 0 )
93 first = outline->contours[outline->n_contours - 1];
95 /* if the last point falls on the same location than the first one */
96 /* we need to delete it */
97 if ( last > first )
99 FT_Vector* p1 = outline->points + first;
100 FT_Vector* p2 = outline->points + last;
103 if ( p1->x == p2->x && p1->y == p2->y )
105 outline->n_points--;
106 last--;
110 /* don't add empty contours */
111 if ( last >= first )
112 outline->contours[outline->n_contours++] = (short)last;
114 glyph->path_begun = 0;
118 /* reset glyph to start the loading of a new glyph */
119 static void
120 pfr_glyph_start( PFR_Glyph glyph )
122 glyph->path_begun = 0;
126 static FT_Error
127 pfr_glyph_line_to( PFR_Glyph glyph,
128 FT_Vector* to )
130 FT_GlyphLoader loader = glyph->loader;
131 FT_Outline* outline = &loader->current.outline;
132 FT_Error error;
135 /* check that we have begun a new path */
136 if ( !glyph->path_begun )
138 error = PFR_Err_Invalid_Table;
139 FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
140 goto Exit;
143 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
144 if ( !error )
146 FT_UInt n = outline->n_points;
149 outline->points[n] = *to;
150 outline->tags [n] = FT_CURVE_TAG_ON;
152 outline->n_points++;
155 Exit:
156 return error;
160 static FT_Error
161 pfr_glyph_curve_to( PFR_Glyph glyph,
162 FT_Vector* control1,
163 FT_Vector* control2,
164 FT_Vector* to )
166 FT_GlyphLoader loader = glyph->loader;
167 FT_Outline* outline = &loader->current.outline;
168 FT_Error error;
171 /* check that we have begun a new path */
172 if ( !glyph->path_begun )
174 error = PFR_Err_Invalid_Table;
175 FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
176 goto Exit;
179 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
180 if ( !error )
182 FT_Vector* vec = outline->points + outline->n_points;
183 FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
186 vec[0] = *control1;
187 vec[1] = *control2;
188 vec[2] = *to;
189 tag[0] = FT_CURVE_TAG_CUBIC;
190 tag[1] = FT_CURVE_TAG_CUBIC;
191 tag[2] = FT_CURVE_TAG_ON;
193 outline->n_points = (FT_Short)( outline->n_points + 3 );
196 Exit:
197 return error;
201 static FT_Error
202 pfr_glyph_move_to( PFR_Glyph glyph,
203 FT_Vector* to )
205 FT_GlyphLoader loader = glyph->loader;
206 FT_Error error;
209 /* close current contour if any */
210 pfr_glyph_close_contour( glyph );
212 /* indicate that a new contour has started */
213 glyph->path_begun = 1;
215 /* check that there is space for a new contour and a new point */
216 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
217 if ( !error )
218 /* add new start point */
219 error = pfr_glyph_line_to( glyph, to );
221 return error;
225 static void
226 pfr_glyph_end( PFR_Glyph glyph )
228 /* close current contour if any */
229 pfr_glyph_close_contour( glyph );
231 /* merge the current glyph into the stack */
232 FT_GlyphLoader_Add( glyph->loader );
236 /*************************************************************************/
237 /*************************************************************************/
238 /***** *****/
239 /***** PFR GLYPH LOADER *****/
240 /***** *****/
241 /*************************************************************************/
242 /*************************************************************************/
245 /* load a simple glyph */
246 static FT_Error
247 pfr_glyph_load_simple( PFR_Glyph glyph,
248 FT_Byte* p,
249 FT_Byte* limit )
251 FT_Error error = 0;
252 FT_Memory memory = glyph->loader->memory;
253 FT_UInt flags, x_count, y_count, i, count, mask;
254 FT_Int x;
257 PFR_CHECK( 1 );
258 flags = PFR_NEXT_BYTE( p );
260 /* test for composite glyphs */
261 if ( flags & PFR_GLYPH_IS_COMPOUND )
262 goto Failure;
264 x_count = 0;
265 y_count = 0;
267 if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
269 PFR_CHECK( 1 );
270 count = PFR_NEXT_BYTE( p );
271 x_count = ( count & 15 );
272 y_count = ( count >> 4 );
274 else
276 if ( flags & PFR_GLYPH_XCOUNT )
278 PFR_CHECK( 1 );
279 x_count = PFR_NEXT_BYTE( p );
282 if ( flags & PFR_GLYPH_YCOUNT )
284 PFR_CHECK( 1 );
285 y_count = PFR_NEXT_BYTE( p );
289 count = x_count + y_count;
291 /* re-allocate array when necessary */
292 if ( count > glyph->max_xy_control )
294 FT_UInt new_max = FT_PAD_CEIL( count, 8 );
297 if ( FT_RENEW_ARRAY( glyph->x_control,
298 glyph->max_xy_control,
299 new_max ) )
300 goto Exit;
302 glyph->max_xy_control = new_max;
305 glyph->y_control = glyph->x_control + x_count;
307 mask = 0;
308 x = 0;
310 for ( i = 0; i < count; i++ )
312 if ( ( i & 7 ) == 0 )
314 PFR_CHECK( 1 );
315 mask = PFR_NEXT_BYTE( p );
318 if ( mask & 1 )
320 PFR_CHECK( 2 );
321 x = PFR_NEXT_SHORT( p );
323 else
325 PFR_CHECK( 1 );
326 x += PFR_NEXT_BYTE( p );
329 glyph->x_control[i] = x;
331 mask >>= 1;
334 /* XXX: for now we ignore the secondary stroke and edge definitions */
335 /* since we don't want to support native PFR hinting */
336 /* */
337 if ( flags & PFR_GLYPH_EXTRA_ITEMS )
339 error = pfr_extra_items_skip( &p, limit );
340 if ( error )
341 goto Exit;
344 pfr_glyph_start( glyph );
346 /* now load a simple glyph */
348 FT_Vector pos[4];
349 FT_Vector* cur;
352 pos[0].x = pos[0].y = 0;
353 pos[3] = pos[0];
355 for (;;)
357 FT_UInt format, format_low, args_format = 0, args_count, n;
360 /***************************************************************/
361 /* read instruction */
362 /* */
363 PFR_CHECK( 1 );
364 format = PFR_NEXT_BYTE( p );
365 format_low = format & 15;
367 switch ( format >> 4 )
369 case 0: /* end glyph */
370 FT_TRACE6(( "- end glyph" ));
371 args_count = 0;
372 break;
374 case 1: /* general line operation */
375 FT_TRACE6(( "- general line" ));
376 goto Line1;
378 case 4: /* move to inside contour */
379 FT_TRACE6(( "- move to inside" ));
380 goto Line1;
382 case 5: /* move to outside contour */
383 FT_TRACE6(( "- move to outside" ));
384 Line1:
385 args_format = format_low;
386 args_count = 1;
387 break;
389 case 2: /* horizontal line to */
390 FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
391 if ( format_low > x_count )
392 goto Failure;
393 pos[0].x = glyph->x_control[format_low];
394 pos[0].y = pos[3].y;
395 pos[3] = pos[0];
396 args_count = 0;
397 break;
399 case 3: /* vertical line to */
400 FT_TRACE6(( "- vertical line to cy.%d", format_low ));
401 if ( format_low > y_count )
402 goto Failure;
403 pos[0].x = pos[3].x;
404 pos[0].y = glyph->y_control[format_low];
405 pos[3] = pos[0];
406 args_count = 0;
407 break;
409 case 6: /* horizontal to vertical curve */
410 FT_TRACE6(( "- hv curve " ));
411 args_format = 0xB8E;
412 args_count = 3;
413 break;
415 case 7: /* vertical to horizontal curve */
416 FT_TRACE6(( "- vh curve" ));
417 args_format = 0xE2B;
418 args_count = 3;
419 break;
421 default: /* general curve to */
422 FT_TRACE6(( "- general curve" ));
423 args_count = 4;
424 args_format = format_low;
427 /***********************************************************/
428 /* now read arguments */
429 /* */
430 cur = pos;
431 for ( n = 0; n < args_count; n++ )
433 FT_UInt idx;
434 FT_Int delta;
437 /* read the X argument */
438 switch ( args_format & 3 )
440 case 0: /* 8-bit index */
441 PFR_CHECK( 1 );
442 idx = PFR_NEXT_BYTE( p );
443 if ( idx > x_count )
444 goto Failure;
445 cur->x = glyph->x_control[idx];
446 FT_TRACE7(( " cx#%d", idx ));
447 break;
449 case 1: /* 16-bit value */
450 PFR_CHECK( 2 );
451 cur->x = PFR_NEXT_SHORT( p );
452 FT_TRACE7(( " x.%d", cur->x ));
453 break;
455 case 2: /* 8-bit delta */
456 PFR_CHECK( 1 );
457 delta = PFR_NEXT_INT8( p );
458 cur->x = pos[3].x + delta;
459 FT_TRACE7(( " dx.%d", delta ));
460 break;
462 default:
463 FT_TRACE7(( " |" ));
464 cur->x = pos[3].x;
467 /* read the Y argument */
468 switch ( ( args_format >> 2 ) & 3 )
470 case 0: /* 8-bit index */
471 PFR_CHECK( 1 );
472 idx = PFR_NEXT_BYTE( p );
473 if ( idx > y_count )
474 goto Failure;
475 cur->y = glyph->y_control[idx];
476 FT_TRACE7(( " cy#%d", idx ));
477 break;
479 case 1: /* 16-bit absolute value */
480 PFR_CHECK( 2 );
481 cur->y = PFR_NEXT_SHORT( p );
482 FT_TRACE7(( " y.%d", cur->y ));
483 break;
485 case 2: /* 8-bit delta */
486 PFR_CHECK( 1 );
487 delta = PFR_NEXT_INT8( p );
488 cur->y = pos[3].y + delta;
489 FT_TRACE7(( " dy.%d", delta ));
490 break;
492 default:
493 FT_TRACE7(( " -" ));
494 cur->y = pos[3].y;
497 /* read the additional format flag for the general curve */
498 if ( n == 0 && args_count == 4 )
500 PFR_CHECK( 1 );
501 args_format = PFR_NEXT_BYTE( p );
502 args_count--;
504 else
505 args_format >>= 4;
507 /* save the previous point */
508 pos[3] = cur[0];
509 cur++;
512 FT_TRACE7(( "\n" ));
514 /***********************************************************/
515 /* finally, execute instruction */
516 /* */
517 switch ( format >> 4 )
519 case 0: /* end glyph => EXIT */
520 pfr_glyph_end( glyph );
521 goto Exit;
523 case 1: /* line operations */
524 case 2:
525 case 3:
526 error = pfr_glyph_line_to( glyph, pos );
527 goto Test_Error;
529 case 4: /* move to inside contour */
530 case 5: /* move to outside contour */
531 error = pfr_glyph_move_to( glyph, pos );
532 goto Test_Error;
534 default: /* curve operations */
535 error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
537 Test_Error: /* test error condition */
538 if ( error )
539 goto Exit;
541 } /* for (;;) */
544 Exit:
545 return error;
547 Failure:
548 Too_Short:
549 error = PFR_Err_Invalid_Table;
550 FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
551 goto Exit;
555 /* load a composite/compound glyph */
556 static FT_Error
557 pfr_glyph_load_compound( PFR_Glyph glyph,
558 FT_Byte* p,
559 FT_Byte* limit )
561 FT_Error error = 0;
562 FT_GlyphLoader loader = glyph->loader;
563 FT_Memory memory = loader->memory;
564 PFR_SubGlyph subglyph;
565 FT_UInt flags, i, count, org_count;
566 FT_Int x_pos, y_pos;
569 PFR_CHECK( 1 );
570 flags = PFR_NEXT_BYTE( p );
572 /* test for composite glyphs */
573 if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
574 goto Failure;
576 count = flags & 0x3F;
578 /* ignore extra items when present */
579 /* */
580 if ( flags & PFR_GLYPH_EXTRA_ITEMS )
582 error = pfr_extra_items_skip( &p, limit );
583 if (error) goto Exit;
586 /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */
587 /* the PFR format is dumb, using direct file offsets to point to the */
588 /* sub-glyphs (instead of glyph indices). Sigh. */
589 /* */
590 /* For now, we load the list of sub-glyphs into a different array */
591 /* but this will prevent us from using the auto-hinter at its best */
592 /* quality. */
593 /* */
594 org_count = glyph->num_subs;
596 if ( org_count + count > glyph->max_subs )
598 FT_UInt new_max = ( org_count + count + 3 ) & (FT_UInt)-4;
601 if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
602 goto Exit;
604 glyph->max_subs = new_max;
607 subglyph = glyph->subs + org_count;
609 for ( i = 0; i < count; i++, subglyph++ )
611 FT_UInt format;
614 x_pos = 0;
615 y_pos = 0;
617 PFR_CHECK( 1 );
618 format = PFR_NEXT_BYTE( p );
620 /* read scale when available */
621 subglyph->x_scale = 0x10000L;
622 if ( format & PFR_SUBGLYPH_XSCALE )
624 PFR_CHECK( 2 );
625 subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
628 subglyph->y_scale = 0x10000L;
629 if ( format & PFR_SUBGLYPH_YSCALE )
631 PFR_CHECK( 2 );
632 subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
635 /* read offset */
636 switch ( format & 3 )
638 case 1:
639 PFR_CHECK( 2 );
640 x_pos = PFR_NEXT_SHORT( p );
641 break;
643 case 2:
644 PFR_CHECK( 1 );
645 x_pos += PFR_NEXT_INT8( p );
646 break;
648 default:
652 switch ( ( format >> 2 ) & 3 )
654 case 1:
655 PFR_CHECK( 2 );
656 y_pos = PFR_NEXT_SHORT( p );
657 break;
659 case 2:
660 PFR_CHECK( 1 );
661 y_pos += PFR_NEXT_INT8( p );
662 break;
664 default:
668 subglyph->x_delta = x_pos;
669 subglyph->y_delta = y_pos;
671 /* read glyph position and size now */
672 if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
674 PFR_CHECK( 2 );
675 subglyph->gps_size = PFR_NEXT_USHORT( p );
677 else
679 PFR_CHECK( 1 );
680 subglyph->gps_size = PFR_NEXT_BYTE( p );
683 if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
685 PFR_CHECK( 3 );
686 subglyph->gps_offset = PFR_NEXT_LONG( p );
688 else
690 PFR_CHECK( 2 );
691 subglyph->gps_offset = PFR_NEXT_USHORT( p );
694 glyph->num_subs++;
697 Exit:
698 return error;
700 Failure:
701 Too_Short:
702 error = PFR_Err_Invalid_Table;
703 FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
704 goto Exit;
708 static FT_Error
709 pfr_glyph_load_rec( PFR_Glyph glyph,
710 FT_Stream stream,
711 FT_ULong gps_offset,
712 FT_ULong offset,
713 FT_ULong size )
715 FT_Error error;
716 FT_Byte* p;
717 FT_Byte* limit;
720 if ( FT_STREAM_SEEK( gps_offset + offset ) ||
721 FT_FRAME_ENTER( size ) )
722 goto Exit;
724 p = (FT_Byte*)stream->cursor;
725 limit = p + size;
727 if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
729 FT_Int n, old_count, count;
730 FT_GlyphLoader loader = glyph->loader;
731 FT_Outline* base = &loader->base.outline;
734 old_count = glyph->num_subs;
736 /* this is a compound glyph - load it */
737 error = pfr_glyph_load_compound( glyph, p, limit );
739 FT_FRAME_EXIT();
741 if ( error )
742 goto Exit;
744 count = glyph->num_subs - old_count;
746 /* now, load each individual glyph */
747 for ( n = 0; n < count; n++ )
749 FT_Int i, old_points, num_points;
750 PFR_SubGlyph subglyph;
753 subglyph = glyph->subs + old_count + n;
754 old_points = base->n_points;
756 error = pfr_glyph_load_rec( glyph, stream, gps_offset,
757 subglyph->gps_offset,
758 subglyph->gps_size );
759 if ( error )
760 goto Exit;
762 /* note that `glyph->subs' might have been re-allocated */
763 subglyph = glyph->subs + old_count + n;
764 num_points = base->n_points - old_points;
766 /* translate and eventually scale the new glyph points */
767 if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
769 FT_Vector* vec = base->points + old_points;
772 for ( i = 0; i < num_points; i++, vec++ )
774 vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
775 subglyph->x_delta;
776 vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
777 subglyph->y_delta;
780 else
782 FT_Vector* vec = loader->base.outline.points + old_points;
785 for ( i = 0; i < num_points; i++, vec++ )
787 vec->x += subglyph->x_delta;
788 vec->y += subglyph->y_delta;
792 /* proceed to next sub-glyph */
795 else
797 /* load a simple glyph */
798 error = pfr_glyph_load_simple( glyph, p, limit );
800 FT_FRAME_EXIT();
803 Exit:
804 return error;
811 FT_LOCAL_DEF( FT_Error )
812 pfr_glyph_load( PFR_Glyph glyph,
813 FT_Stream stream,
814 FT_ULong gps_offset,
815 FT_ULong offset,
816 FT_ULong size )
818 /* initialize glyph loader */
819 FT_GlyphLoader_Rewind( glyph->loader );
821 glyph->num_subs = 0;
823 /* load the glyph, recursively when needed */
824 return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
828 /* END */