00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pfrgload.h"
00020 #include "pfrsbit.h"
00021 #include "pfrload.h"
00022 #include FT_INTERNAL_DEBUG_H
00023
00024 #include "pfrerror.h"
00025
00026 #undef FT_COMPONENT
00027 #define FT_COMPONENT trace_pfr
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 FT_LOCAL_DEF( void )
00040 pfr_glyph_init( PFR_Glyph glyph,
00041 FT_GlyphLoader loader )
00042 {
00043 FT_ZERO( glyph );
00044
00045 glyph->loader = loader;
00046 glyph->path_begun = 0;
00047
00048 FT_GlyphLoader_Rewind( loader );
00049 }
00050
00051
00052 FT_LOCAL_DEF( void )
00053 pfr_glyph_done( PFR_Glyph glyph )
00054 {
00055 FT_Memory memory = glyph->loader->memory;
00056
00057
00058 FT_FREE( glyph->x_control );
00059 glyph->y_control = NULL;
00060
00061 glyph->max_xy_control = 0;
00062 #if 0
00063 glyph->num_x_control = 0;
00064 glyph->num_y_control = 0;
00065 #endif
00066
00067 FT_FREE( glyph->subs );
00068
00069 glyph->max_subs = 0;
00070 glyph->num_subs = 0;
00071
00072 glyph->loader = NULL;
00073 glyph->path_begun = 0;
00074 }
00075
00076
00077
00078 static void
00079 pfr_glyph_close_contour( PFR_Glyph glyph )
00080 {
00081 FT_GlyphLoader loader = glyph->loader;
00082 FT_Outline* outline = &loader->current.outline;
00083 FT_Int last, first;
00084
00085
00086 if ( !glyph->path_begun )
00087 return;
00088
00089
00090 last = outline->n_points - 1;
00091 first = 0;
00092 if ( outline->n_contours > 0 )
00093 first = outline->contours[outline->n_contours - 1];
00094
00095
00096
00097 if ( last > first )
00098 {
00099 FT_Vector* p1 = outline->points + first;
00100 FT_Vector* p2 = outline->points + last;
00101
00102
00103 if ( p1->x == p2->x && p1->y == p2->y )
00104 {
00105 outline->n_points--;
00106 last--;
00107 }
00108 }
00109
00110
00111 if ( last >= first )
00112 outline->contours[outline->n_contours++] = (short)last;
00113
00114 glyph->path_begun = 0;
00115 }
00116
00117
00118
00119 static void
00120 pfr_glyph_start( PFR_Glyph glyph )
00121 {
00122 glyph->path_begun = 0;
00123 }
00124
00125
00126 static FT_Error
00127 pfr_glyph_line_to( PFR_Glyph glyph,
00128 FT_Vector* to )
00129 {
00130 FT_GlyphLoader loader = glyph->loader;
00131 FT_Outline* outline = &loader->current.outline;
00132 FT_Error error;
00133
00134
00135
00136 if ( !glyph->path_begun )
00137 {
00138 error = PFR_Err_Invalid_Table;
00139 FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
00140 goto Exit;
00141 }
00142
00143 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
00144 if ( !error )
00145 {
00146 FT_UInt n = outline->n_points;
00147
00148
00149 outline->points[n] = *to;
00150 outline->tags [n] = FT_CURVE_TAG_ON;
00151
00152 outline->n_points++;
00153 }
00154
00155 Exit:
00156 return error;
00157 }
00158
00159
00160 static FT_Error
00161 pfr_glyph_curve_to( PFR_Glyph glyph,
00162 FT_Vector* control1,
00163 FT_Vector* control2,
00164 FT_Vector* to )
00165 {
00166 FT_GlyphLoader loader = glyph->loader;
00167 FT_Outline* outline = &loader->current.outline;
00168 FT_Error error;
00169
00170
00171
00172 if ( !glyph->path_begun )
00173 {
00174 error = PFR_Err_Invalid_Table;
00175 FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
00176 goto Exit;
00177 }
00178
00179 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
00180 if ( !error )
00181 {
00182 FT_Vector* vec = outline->points + outline->n_points;
00183 FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
00184
00185
00186 vec[0] = *control1;
00187 vec[1] = *control2;
00188 vec[2] = *to;
00189 tag[0] = FT_CURVE_TAG_CUBIC;
00190 tag[1] = FT_CURVE_TAG_CUBIC;
00191 tag[2] = FT_CURVE_TAG_ON;
00192
00193 outline->n_points = (FT_Short)( outline->n_points + 3 );
00194 }
00195
00196 Exit:
00197 return error;
00198 }
00199
00200
00201 static FT_Error
00202 pfr_glyph_move_to( PFR_Glyph glyph,
00203 FT_Vector* to )
00204 {
00205 FT_GlyphLoader loader = glyph->loader;
00206 FT_Error error;
00207
00208
00209
00210 pfr_glyph_close_contour( glyph );
00211
00212
00213 glyph->path_begun = 1;
00214
00215
00216 error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
00217 if ( !error )
00218
00219 error = pfr_glyph_line_to( glyph, to );
00220
00221 return error;
00222 }
00223
00224
00225 static void
00226 pfr_glyph_end( PFR_Glyph glyph )
00227 {
00228
00229 pfr_glyph_close_contour( glyph );
00230
00231
00232 FT_GlyphLoader_Add( glyph->loader );
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 static FT_Error
00247 pfr_glyph_load_simple( PFR_Glyph glyph,
00248 FT_Byte* p,
00249 FT_Byte* limit )
00250 {
00251 FT_Error error = 0;
00252 FT_Memory memory = glyph->loader->memory;
00253 FT_UInt flags, x_count, y_count, i, count, mask;
00254 FT_Int x;
00255
00256
00257 PFR_CHECK( 1 );
00258 flags = PFR_NEXT_BYTE( p );
00259
00260
00261 if ( flags & PFR_GLYPH_IS_COMPOUND )
00262 goto Failure;
00263
00264 x_count = 0;
00265 y_count = 0;
00266
00267 if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
00268 {
00269 PFR_CHECK( 1 );
00270 count = PFR_NEXT_BYTE( p );
00271 x_count = ( count & 15 );
00272 y_count = ( count >> 4 );
00273 }
00274 else
00275 {
00276 if ( flags & PFR_GLYPH_XCOUNT )
00277 {
00278 PFR_CHECK( 1 );
00279 x_count = PFR_NEXT_BYTE( p );
00280 }
00281
00282 if ( flags & PFR_GLYPH_YCOUNT )
00283 {
00284 PFR_CHECK( 1 );
00285 y_count = PFR_NEXT_BYTE( p );
00286 }
00287 }
00288
00289 count = x_count + y_count;
00290
00291
00292 if ( count > glyph->max_xy_control )
00293 {
00294 FT_UInt new_max = FT_PAD_CEIL( count, 8 );
00295
00296
00297 if ( FT_RENEW_ARRAY( glyph->x_control,
00298 glyph->max_xy_control,
00299 new_max ) )
00300 goto Exit;
00301
00302 glyph->max_xy_control = new_max;
00303 }
00304
00305 glyph->y_control = glyph->x_control + x_count;
00306
00307 mask = 0;
00308 x = 0;
00309
00310 for ( i = 0; i < count; i++ )
00311 {
00312 if ( ( i & 7 ) == 0 )
00313 {
00314 PFR_CHECK( 1 );
00315 mask = PFR_NEXT_BYTE( p );
00316 }
00317
00318 if ( mask & 1 )
00319 {
00320 PFR_CHECK( 2 );
00321 x = PFR_NEXT_SHORT( p );
00322 }
00323 else
00324 {
00325 PFR_CHECK( 1 );
00326 x += PFR_NEXT_BYTE( p );
00327 }
00328
00329 glyph->x_control[i] = x;
00330
00331 mask >>= 1;
00332 }
00333
00334
00335
00336
00337 if ( flags & PFR_GLYPH_EXTRA_ITEMS )
00338 {
00339 error = pfr_extra_items_skip( &p, limit );
00340 if ( error )
00341 goto Exit;
00342 }
00343
00344 pfr_glyph_start( glyph );
00345
00346
00347 {
00348 FT_Vector pos[4];
00349 FT_Vector* cur;
00350
00351
00352 pos[0].x = pos[0].y = 0;
00353 pos[3] = pos[0];
00354
00355 for (;;)
00356 {
00357 FT_UInt format, format_low, args_format = 0, args_count, n;
00358
00359
00360
00361
00362
00363 PFR_CHECK( 1 );
00364 format = PFR_NEXT_BYTE( p );
00365 format_low = format & 15;
00366
00367 switch ( format >> 4 )
00368 {
00369 case 0:
00370 FT_TRACE6(( "- end glyph" ));
00371 args_count = 0;
00372 break;
00373
00374 case 1:
00375 FT_TRACE6(( "- general line" ));
00376 goto Line1;
00377
00378 case 4:
00379 FT_TRACE6(( "- move to inside" ));
00380 goto Line1;
00381
00382 case 5:
00383 FT_TRACE6(( "- move to outside" ));
00384 Line1:
00385 args_format = format_low;
00386 args_count = 1;
00387 break;
00388
00389 case 2:
00390 FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
00391 if ( format_low > x_count )
00392 goto Failure;
00393 pos[0].x = glyph->x_control[format_low];
00394 pos[0].y = pos[3].y;
00395 pos[3] = pos[0];
00396 args_count = 0;
00397 break;
00398
00399 case 3:
00400 FT_TRACE6(( "- vertical line to cy.%d", format_low ));
00401 if ( format_low > y_count )
00402 goto Failure;
00403 pos[0].x = pos[3].x;
00404 pos[0].y = glyph->y_control[format_low];
00405 pos[3] = pos[0];
00406 args_count = 0;
00407 break;
00408
00409 case 6:
00410 FT_TRACE6(( "- hv curve " ));
00411 args_format = 0xB8E;
00412 args_count = 3;
00413 break;
00414
00415 case 7:
00416 FT_TRACE6(( "- vh curve" ));
00417 args_format = 0xE2B;
00418 args_count = 3;
00419 break;
00420
00421 default:
00422 FT_TRACE6(( "- general curve" ));
00423 args_count = 4;
00424 args_format = format_low;
00425 }
00426
00427
00428
00429
00430 cur = pos;
00431 for ( n = 0; n < args_count; n++ )
00432 {
00433 FT_UInt idx;
00434 FT_Int delta;
00435
00436
00437
00438 switch ( args_format & 3 )
00439 {
00440 case 0:
00441 PFR_CHECK( 1 );
00442 idx = PFR_NEXT_BYTE( p );
00443 if ( idx > x_count )
00444 goto Failure;
00445 cur->x = glyph->x_control[idx];
00446 FT_TRACE7(( " cx#%d", idx ));
00447 break;
00448
00449 case 1:
00450 PFR_CHECK( 2 );
00451 cur->x = PFR_NEXT_SHORT( p );
00452 FT_TRACE7(( " x.%d", cur->x ));
00453 break;
00454
00455 case 2:
00456 PFR_CHECK( 1 );
00457 delta = PFR_NEXT_INT8( p );
00458 cur->x = pos[3].x + delta;
00459 FT_TRACE7(( " dx.%d", delta ));
00460 break;
00461
00462 default:
00463 FT_TRACE7(( " |" ));
00464 cur->x = pos[3].x;
00465 }
00466
00467
00468 switch ( ( args_format >> 2 ) & 3 )
00469 {
00470 case 0:
00471 PFR_CHECK( 1 );
00472 idx = PFR_NEXT_BYTE( p );
00473 if ( idx > y_count )
00474 goto Failure;
00475 cur->y = glyph->y_control[idx];
00476 FT_TRACE7(( " cy#%d", idx ));
00477 break;
00478
00479 case 1:
00480 PFR_CHECK( 2 );
00481 cur->y = PFR_NEXT_SHORT( p );
00482 FT_TRACE7(( " y.%d", cur->y ));
00483 break;
00484
00485 case 2:
00486 PFR_CHECK( 1 );
00487 delta = PFR_NEXT_INT8( p );
00488 cur->y = pos[3].y + delta;
00489 FT_TRACE7(( " dy.%d", delta ));
00490 break;
00491
00492 default:
00493 FT_TRACE7(( " -" ));
00494 cur->y = pos[3].y;
00495 }
00496
00497
00498 if ( n == 0 && args_count == 4 )
00499 {
00500 PFR_CHECK( 1 );
00501 args_format = PFR_NEXT_BYTE( p );
00502 args_count--;
00503 }
00504 else
00505 args_format >>= 4;
00506
00507
00508 pos[3] = cur[0];
00509 cur++;
00510 }
00511
00512 FT_TRACE7(( "\n" ));
00513
00514
00515
00516
00517 switch ( format >> 4 )
00518 {
00519 case 0:
00520 pfr_glyph_end( glyph );
00521 goto Exit;
00522
00523 case 1:
00524 case 2:
00525 case 3:
00526 error = pfr_glyph_line_to( glyph, pos );
00527 goto Test_Error;
00528
00529 case 4:
00530 case 5:
00531 error = pfr_glyph_move_to( glyph, pos );
00532 goto Test_Error;
00533
00534 default:
00535 error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
00536
00537 Test_Error:
00538 if ( error )
00539 goto Exit;
00540 }
00541 }
00542 }
00543
00544 Exit:
00545 return error;
00546
00547 Failure:
00548 Too_Short:
00549 error = PFR_Err_Invalid_Table;
00550 FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
00551 goto Exit;
00552 }
00553
00554
00555
00556 static FT_Error
00557 pfr_glyph_load_compound( PFR_Glyph glyph,
00558 FT_Byte* p,
00559 FT_Byte* limit )
00560 {
00561 FT_Error error = 0;
00562 FT_GlyphLoader loader = glyph->loader;
00563 FT_Memory memory = loader->memory;
00564 PFR_SubGlyph subglyph;
00565 FT_UInt flags, i, count, org_count;
00566 FT_Int x_pos, y_pos;
00567
00568
00569 PFR_CHECK( 1 );
00570 flags = PFR_NEXT_BYTE( p );
00571
00572
00573 if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
00574 goto Failure;
00575
00576 count = flags & 0x3F;
00577
00578
00579
00580 if ( flags & PFR_GLYPH_EXTRA_ITEMS )
00581 {
00582 error = pfr_extra_items_skip( &p, limit );
00583 if (error) goto Exit;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 org_count = glyph->num_subs;
00595
00596 if ( org_count + count > glyph->max_subs )
00597 {
00598 FT_UInt new_max = ( org_count + count + 3 ) & (FT_UInt)-4;
00599
00600
00601 if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
00602 goto Exit;
00603
00604 glyph->max_subs = new_max;
00605 }
00606
00607 subglyph = glyph->subs + org_count;
00608
00609 for ( i = 0; i < count; i++, subglyph++ )
00610 {
00611 FT_UInt format;
00612
00613
00614 x_pos = 0;
00615 y_pos = 0;
00616
00617 PFR_CHECK( 1 );
00618 format = PFR_NEXT_BYTE( p );
00619
00620
00621 subglyph->x_scale = 0x10000L;
00622 if ( format & PFR_SUBGLYPH_XSCALE )
00623 {
00624 PFR_CHECK( 2 );
00625 subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
00626 }
00627
00628 subglyph->y_scale = 0x10000L;
00629 if ( format & PFR_SUBGLYPH_YSCALE )
00630 {
00631 PFR_CHECK( 2 );
00632 subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
00633 }
00634
00635
00636 switch ( format & 3 )
00637 {
00638 case 1:
00639 PFR_CHECK( 2 );
00640 x_pos = PFR_NEXT_SHORT( p );
00641 break;
00642
00643 case 2:
00644 PFR_CHECK( 1 );
00645 x_pos += PFR_NEXT_INT8( p );
00646 break;
00647
00648 default:
00649 ;
00650 }
00651
00652 switch ( ( format >> 2 ) & 3 )
00653 {
00654 case 1:
00655 PFR_CHECK( 2 );
00656 y_pos = PFR_NEXT_SHORT( p );
00657 break;
00658
00659 case 2:
00660 PFR_CHECK( 1 );
00661 y_pos += PFR_NEXT_INT8( p );
00662 break;
00663
00664 default:
00665 ;
00666 }
00667
00668 subglyph->x_delta = x_pos;
00669 subglyph->y_delta = y_pos;
00670
00671
00672 if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
00673 {
00674 PFR_CHECK( 2 );
00675 subglyph->gps_size = PFR_NEXT_USHORT( p );
00676 }
00677 else
00678 {
00679 PFR_CHECK( 1 );
00680 subglyph->gps_size = PFR_NEXT_BYTE( p );
00681 }
00682
00683 if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
00684 {
00685 PFR_CHECK( 3 );
00686 subglyph->gps_offset = PFR_NEXT_LONG( p );
00687 }
00688 else
00689 {
00690 PFR_CHECK( 2 );
00691 subglyph->gps_offset = PFR_NEXT_USHORT( p );
00692 }
00693
00694 glyph->num_subs++;
00695 }
00696
00697 Exit:
00698 return error;
00699
00700 Failure:
00701 Too_Short:
00702 error = PFR_Err_Invalid_Table;
00703 FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
00704 goto Exit;
00705 }
00706
00707
00708 static FT_Error
00709 pfr_glyph_load_rec( PFR_Glyph glyph,
00710 FT_Stream stream,
00711 FT_ULong gps_offset,
00712 FT_ULong offset,
00713 FT_ULong size )
00714 {
00715 FT_Error error;
00716 FT_Byte* p;
00717 FT_Byte* limit;
00718
00719
00720 if ( FT_STREAM_SEEK( gps_offset + offset ) ||
00721 FT_FRAME_ENTER( size ) )
00722 goto Exit;
00723
00724 p = (FT_Byte*)stream->cursor;
00725 limit = p + size;
00726
00727 if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
00728 {
00729 FT_Int n, old_count, count;
00730 FT_GlyphLoader loader = glyph->loader;
00731 FT_Outline* base = &loader->base.outline;
00732
00733
00734 old_count = glyph->num_subs;
00735
00736
00737 error = pfr_glyph_load_compound( glyph, p, limit );
00738
00739 FT_FRAME_EXIT();
00740
00741 if ( error )
00742 goto Exit;
00743
00744 count = glyph->num_subs - old_count;
00745
00746
00747 for ( n = 0; n < count; n++ )
00748 {
00749 FT_Int i, old_points, num_points;
00750 PFR_SubGlyph subglyph;
00751
00752
00753 subglyph = glyph->subs + old_count + n;
00754 old_points = base->n_points;
00755
00756 error = pfr_glyph_load_rec( glyph, stream, gps_offset,
00757 subglyph->gps_offset,
00758 subglyph->gps_size );
00759 if ( error )
00760 goto Exit;
00761
00762
00763 subglyph = glyph->subs + old_count + n;
00764 num_points = base->n_points - old_points;
00765
00766
00767 if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
00768 {
00769 FT_Vector* vec = base->points + old_points;
00770
00771
00772 for ( i = 0; i < num_points; i++, vec++ )
00773 {
00774 vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
00775 subglyph->x_delta;
00776 vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
00777 subglyph->y_delta;
00778 }
00779 }
00780 else
00781 {
00782 FT_Vector* vec = loader->base.outline.points + old_points;
00783
00784
00785 for ( i = 0; i < num_points; i++, vec++ )
00786 {
00787 vec->x += subglyph->x_delta;
00788 vec->y += subglyph->y_delta;
00789 }
00790 }
00791
00792
00793 }
00794 }
00795 else
00796 {
00797
00798 error = pfr_glyph_load_simple( glyph, p, limit );
00799
00800 FT_FRAME_EXIT();
00801 }
00802
00803 Exit:
00804 return error;
00805 }
00806
00807
00808
00809
00810
00811 FT_LOCAL_DEF( FT_Error )
00812 pfr_glyph_load( PFR_Glyph glyph,
00813 FT_Stream stream,
00814 FT_ULong gps_offset,
00815 FT_ULong offset,
00816 FT_ULong size )
00817 {
00818
00819 FT_GlyphLoader_Rewind( glyph->loader );
00820
00821 glyph->num_subs = 0;
00822
00823
00824 return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
00825 }
00826
00827
00828