00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_CALC_H
00023 #include FT_INTERNAL_STREAM_H
00024 #include FT_INTERNAL_SFNT_H
00025 #include FT_TRUETYPE_TAGS_H
00026 #include FT_OUTLINE_H
00027
00028 #include "ttgload.h"
00029 #include "ttpload.h"
00030
00031 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00032 #include "ttgxvar.h"
00033 #endif
00034
00035 #include "tterrors.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044 #undef FT_COMPONENT
00045 #define FT_COMPONENT trace_ttgload
00046
00047
00048
00049
00050
00051
00052 #define ARGS_ARE_WORDS 0x0001
00053 #define ARGS_ARE_XY_VALUES 0x0002
00054 #define ROUND_XY_TO_GRID 0x0004
00055 #define WE_HAVE_A_SCALE 0x0008
00056
00057 #define MORE_COMPONENTS 0x0020
00058 #define WE_HAVE_AN_XY_SCALE 0x0040
00059 #define WE_HAVE_A_2X2 0x0080
00060 #define WE_HAVE_INSTR 0x0100
00061 #define USE_MY_METRICS 0x0200
00062 #define OVERLAP_COMPOUND 0x0400
00063 #define SCALED_COMPONENT_OFFSET 0x0800
00064 #define UNSCALED_COMPONENT_OFFSET 0x1000
00065
00066
00067
00068
00069
00070
00071
00072
00073 FT_LOCAL_DEF( void )
00074 TT_Get_HMetrics( TT_Face face,
00075 FT_UInt idx,
00076 FT_Bool check,
00077 FT_Short* lsb,
00078 FT_UShort* aw )
00079 {
00080 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
00081
00082 if ( check && face->postscript.isFixedPitch )
00083 *aw = face->horizontal.advance_Width_Max;
00084
00085 FT_TRACE5(( " advance width (font units): %d\n", *aw ));
00086 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 FT_LOCAL_DEF( void )
00104 TT_Get_VMetrics( TT_Face face,
00105 FT_UInt idx,
00106 FT_Bool check,
00107 FT_Short* tsb,
00108 FT_UShort* ah )
00109 {
00110 FT_UNUSED( check );
00111
00112 if ( face->vertical_info )
00113 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
00114
00115 #if 1
00116
00117 else
00118 {
00119 *tsb = 0;
00120 *ah = face->root.units_per_EM;
00121 }
00122
00123 #else
00124
00125 else if ( face->os2.version != 0xFFFFU )
00126 {
00127 *tsb = face->os2.sTypoAscender;
00128 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
00129 }
00130 else
00131 {
00132 *tsb = face->horizontal.Ascender;
00133 *ah = face->horizontal.Ascender - face->horizontal.Descender;
00134 }
00135
00136 #endif
00137
00138 FT_TRACE5(( " advance height (font units): %d\n", *ah ));
00139 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
00140 }
00141
00142
00143 static void
00144 tt_get_metrics( TT_Loader loader,
00145 FT_UInt glyph_index )
00146 {
00147 TT_Face face = (TT_Face)loader->face;
00148
00149 FT_Short left_bearing = 0, top_bearing = 0;
00150 FT_UShort advance_width = 0, advance_height = 0;
00151
00152
00153 TT_Get_HMetrics( face, glyph_index,
00154 (FT_Bool)!( loader->load_flags &
00155 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
00156 &left_bearing,
00157 &advance_width );
00158 TT_Get_VMetrics( face, glyph_index,
00159 (FT_Bool)!( loader->load_flags &
00160 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
00161 &top_bearing,
00162 &advance_height );
00163
00164 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00165
00166
00167
00168 if ( face->root.internal->incremental_interface &&
00169 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
00170 {
00171 FT_Incremental_MetricsRec metrics;
00172 FT_Error error;
00173
00174
00175 metrics.bearing_x = left_bearing;
00176 metrics.bearing_y = 0;
00177 metrics.advance = advance_width;
00178 metrics.advance_v = 0;
00179
00180 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00181 face->root.internal->incremental_interface->object,
00182 glyph_index, FALSE, &metrics );
00183 if ( error )
00184 goto Exit;
00185
00186 left_bearing = (FT_Short)metrics.bearing_x;
00187 advance_width = (FT_UShort)metrics.advance;
00188
00189 #if 0
00190
00191
00192 metrics.bearing_x = 0;
00193 metrics.bearing_y = top_bearing;
00194 metrics.advance = advance_height;
00195
00196 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
00197 face->root.internal->incremental_interface->object,
00198 glyph_index, TRUE, &metrics );
00199 if ( error )
00200 goto Exit;
00201
00202 top_bearing = (FT_Short)metrics.bearing_y;
00203 advance_height = (FT_UShort)metrics.advance;
00204
00205 #endif
00206
00207 }
00208
00209 Exit:
00210
00211 #endif
00212
00213 loader->left_bearing = left_bearing;
00214 loader->advance = advance_width;
00215 loader->top_bearing = top_bearing;
00216 loader->vadvance = advance_height;
00217
00218 if ( !loader->linear_def )
00219 {
00220 loader->linear_def = 1;
00221 loader->linear = advance_width;
00222 }
00223 }
00224
00225
00226
00227
00228
00229
00230 static void
00231 translate_array( FT_UInt n,
00232 FT_Vector* coords,
00233 FT_Pos delta_x,
00234 FT_Pos delta_y )
00235 {
00236 FT_UInt k;
00237
00238
00239 if ( delta_x )
00240 for ( k = 0; k < n; k++ )
00241 coords[k].x += delta_x;
00242
00243 if ( delta_y )
00244 for ( k = 0; k < n; k++ )
00245 coords[k].y += delta_y;
00246 }
00247
00248
00249 #undef IS_HINTED
00250 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 FT_CALLBACK_DEF( FT_Error )
00262 TT_Access_Glyph_Frame( TT_Loader loader,
00263 FT_UInt glyph_index,
00264 FT_ULong offset,
00265 FT_UInt byte_count )
00266 {
00267 FT_Error error;
00268 FT_Stream stream = loader->stream;
00269
00270
00271 FT_UNUSED( glyph_index );
00272
00273
00274 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
00275
00276
00277 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
00278 return error;
00279
00280 loader->cursor = stream->cursor;
00281 loader->limit = stream->limit;
00282
00283 return TT_Err_Ok;
00284 }
00285
00286
00287 FT_CALLBACK_DEF( void )
00288 TT_Forget_Glyph_Frame( TT_Loader loader )
00289 {
00290 FT_Stream stream = loader->stream;
00291
00292
00293 FT_FRAME_EXIT();
00294 }
00295
00296
00297 FT_CALLBACK_DEF( FT_Error )
00298 TT_Load_Glyph_Header( TT_Loader loader )
00299 {
00300 FT_Byte* p = loader->cursor;
00301 FT_Byte* limit = loader->limit;
00302
00303
00304 if ( p + 10 > limit )
00305 return TT_Err_Invalid_Outline;
00306
00307 loader->n_contours = FT_NEXT_SHORT( p );
00308
00309 loader->bbox.xMin = FT_NEXT_SHORT( p );
00310 loader->bbox.yMin = FT_NEXT_SHORT( p );
00311 loader->bbox.xMax = FT_NEXT_SHORT( p );
00312 loader->bbox.yMax = FT_NEXT_SHORT( p );
00313
00314 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
00315 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
00316 loader->bbox.xMax ));
00317 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
00318 loader->bbox.yMax ));
00319 loader->cursor = p;
00320
00321 return TT_Err_Ok;
00322 }
00323
00324
00325 FT_CALLBACK_DEF( FT_Error )
00326 TT_Load_Simple_Glyph( TT_Loader load )
00327 {
00328 FT_Error error;
00329 FT_Byte* p = load->cursor;
00330 FT_Byte* limit = load->limit;
00331 FT_GlyphLoader gloader = load->gloader;
00332 FT_Int n_contours = load->n_contours;
00333 FT_Outline* outline;
00334 TT_Face face = (TT_Face)load->face;
00335 FT_UShort n_ins;
00336 FT_Int n_points;
00337
00338 FT_Byte *flag, *flag_limit;
00339 FT_Byte c, count;
00340 FT_Vector *vec, *vec_limit;
00341 FT_Pos x;
00342 FT_Short *cont, *cont_limit, prev_cont;
00343 FT_Int xy_size = 0;
00344
00345
00346
00347 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
00348 if ( error )
00349 goto Fail;
00350
00351
00352 cont = gloader->current.outline.contours;
00353 cont_limit = cont + n_contours;
00354
00355
00356 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
00357 goto Invalid_Outline;
00358
00359 prev_cont = FT_NEXT_USHORT( p );
00360
00361 if ( n_contours > 0 )
00362 cont[0] = prev_cont;
00363
00364 for ( cont++; cont < cont_limit; cont++ )
00365 {
00366 cont[0] = FT_NEXT_USHORT( p );
00367 if ( cont[0] <= prev_cont )
00368 {
00369
00370 error = FT_Err_Invalid_Table;
00371 goto Fail;
00372 }
00373 prev_cont = cont[0];
00374 }
00375
00376 n_points = 0;
00377 if ( n_contours > 0 )
00378 {
00379 n_points = cont[-1] + 1;
00380 if ( n_points < 0 )
00381 goto Invalid_Outline;
00382 }
00383
00384
00385 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
00386 if ( error )
00387 goto Fail;
00388
00389
00390 outline = &gloader->current.outline;
00391
00392 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
00393 if ( cont[-1] >= cont[0] )
00394 goto Invalid_Outline;
00395
00396
00397 load->glyph->control_len = 0;
00398 load->glyph->control_data = 0;
00399
00400 if ( p + 2 > limit )
00401 goto Invalid_Outline;
00402
00403 n_ins = FT_NEXT_USHORT( p );
00404
00405 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
00406
00407 if ( n_ins > face->max_profile.maxSizeOfInstructions )
00408 {
00409 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
00410 n_ins ));
00411 error = TT_Err_Too_Many_Hints;
00412 goto Fail;
00413 }
00414
00415 if ( ( limit - p ) < n_ins )
00416 {
00417 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
00418 error = TT_Err_Too_Many_Hints;
00419 goto Fail;
00420 }
00421
00422 #ifdef TT_USE_BYTECODE_INTERPRETER
00423
00424 if ( IS_HINTED( load->load_flags ) )
00425 {
00426 load->glyph->control_len = n_ins;
00427 load->glyph->control_data = load->exec->glyphIns;
00428
00429 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
00430 }
00431
00432 #endif
00433
00434 p += n_ins;
00435
00436
00437 flag = (FT_Byte*)outline->tags;
00438 flag_limit = flag + n_points;
00439
00440 FT_ASSERT( flag != NULL );
00441
00442 while ( flag < flag_limit )
00443 {
00444 if ( p + 1 > limit )
00445 goto Invalid_Outline;
00446
00447 *flag++ = c = FT_NEXT_BYTE( p );
00448 if ( c & 8 )
00449 {
00450 if ( p + 1 > limit )
00451 goto Invalid_Outline;
00452
00453 count = FT_NEXT_BYTE( p );
00454 if ( flag + (FT_Int)count > flag_limit )
00455 goto Invalid_Outline;
00456
00457 for ( ; count > 0; count-- )
00458 *flag++ = c;
00459 }
00460 }
00461
00462
00463
00464 vec = outline->points;
00465 vec_limit = vec + n_points;
00466 flag = (FT_Byte*)outline->tags;
00467 x = 0;
00468
00469 if ( p + xy_size > limit )
00470 goto Invalid_Outline;
00471
00472 for ( ; vec < vec_limit; vec++, flag++ )
00473 {
00474 FT_Pos y = 0;
00475 FT_Byte f = *flag;
00476
00477
00478 if ( f & 2 )
00479 {
00480 if ( p + 1 > limit )
00481 goto Invalid_Outline;
00482
00483 y = (FT_Pos)FT_NEXT_BYTE( p );
00484 if ( ( f & 16 ) == 0 )
00485 y = -y;
00486 }
00487 else if ( ( f & 16 ) == 0 )
00488 {
00489 if ( p + 2 > limit )
00490 goto Invalid_Outline;
00491
00492 y = (FT_Pos)FT_NEXT_SHORT( p );
00493 }
00494
00495 x += y;
00496 vec->x = x;
00497
00498 *flag = (FT_Byte)( f & ~( 2 | 16 ) );
00499 }
00500
00501
00502
00503 vec = gloader->current.outline.points;
00504 vec_limit = vec + n_points;
00505 flag = (FT_Byte*)outline->tags;
00506 x = 0;
00507
00508 for ( ; vec < vec_limit; vec++, flag++ )
00509 {
00510 FT_Pos y = 0;
00511 FT_Byte f = *flag;
00512
00513
00514 if ( f & 4 )
00515 {
00516 if ( p + 1 > limit )
00517 goto Invalid_Outline;
00518
00519 y = (FT_Pos)FT_NEXT_BYTE( p );
00520 if ( ( f & 32 ) == 0 )
00521 y = -y;
00522 }
00523 else if ( ( f & 32 ) == 0 )
00524 {
00525 if ( p + 2 > limit )
00526 goto Invalid_Outline;
00527
00528 y = (FT_Pos)FT_NEXT_SHORT( p );
00529 }
00530
00531 x += y;
00532 vec->y = x;
00533
00534 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
00535 }
00536
00537 outline->n_points = (FT_UShort)n_points;
00538 outline->n_contours = (FT_Short) n_contours;
00539
00540 load->cursor = p;
00541
00542 Fail:
00543 return error;
00544
00545 Invalid_Outline:
00546 error = TT_Err_Invalid_Outline;
00547 goto Fail;
00548 }
00549
00550
00551 FT_CALLBACK_DEF( FT_Error )
00552 TT_Load_Composite_Glyph( TT_Loader loader )
00553 {
00554 FT_Error error;
00555 FT_Byte* p = loader->cursor;
00556 FT_Byte* limit = loader->limit;
00557 FT_GlyphLoader gloader = loader->gloader;
00558 FT_SubGlyph subglyph;
00559 FT_UInt num_subglyphs;
00560
00561
00562 num_subglyphs = 0;
00563
00564 do
00565 {
00566 FT_Fixed xx, xy, yy, yx;
00567 FT_UInt count;
00568
00569
00570
00571 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
00572 if ( error )
00573 goto Fail;
00574
00575
00576 if ( p + 4 > limit )
00577 goto Invalid_Composite;
00578
00579 subglyph = gloader->current.subglyphs + num_subglyphs;
00580
00581 subglyph->arg1 = subglyph->arg2 = 0;
00582
00583 subglyph->flags = FT_NEXT_USHORT( p );
00584 subglyph->index = FT_NEXT_USHORT( p );
00585
00586
00587 count = 2;
00588 if ( subglyph->flags & ARGS_ARE_WORDS )
00589 count += 2;
00590 if ( subglyph->flags & WE_HAVE_A_SCALE )
00591 count += 2;
00592 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00593 count += 4;
00594 else if ( subglyph->flags & WE_HAVE_A_2X2 )
00595 count += 8;
00596
00597 if ( p + count > limit )
00598 goto Invalid_Composite;
00599
00600
00601 if ( subglyph->flags & ARGS_ARE_WORDS )
00602 {
00603 subglyph->arg1 = FT_NEXT_SHORT( p );
00604 subglyph->arg2 = FT_NEXT_SHORT( p );
00605 }
00606 else
00607 {
00608 subglyph->arg1 = FT_NEXT_CHAR( p );
00609 subglyph->arg2 = FT_NEXT_CHAR( p );
00610 }
00611
00612
00613 xx = yy = 0x10000L;
00614 xy = yx = 0;
00615
00616 if ( subglyph->flags & WE_HAVE_A_SCALE )
00617 {
00618 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00619 yy = xx;
00620 }
00621 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
00622 {
00623 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00624 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00625 }
00626 else if ( subglyph->flags & WE_HAVE_A_2X2 )
00627 {
00628 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00629 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00630 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00631 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
00632 }
00633
00634 subglyph->transform.xx = xx;
00635 subglyph->transform.xy = xy;
00636 subglyph->transform.yx = yx;
00637 subglyph->transform.yy = yy;
00638
00639 num_subglyphs++;
00640
00641 } while ( subglyph->flags & MORE_COMPONENTS );
00642
00643 gloader->current.num_subglyphs = num_subglyphs;
00644
00645 #ifdef TT_USE_BYTECODE_INTERPRETER
00646
00647 {
00648 FT_Stream stream = loader->stream;
00649
00650
00651
00652
00653
00654
00655 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
00656 p - limit );
00657 }
00658
00659 #endif
00660
00661 loader->cursor = p;
00662
00663 Fail:
00664 return error;
00665
00666 Invalid_Composite:
00667 error = TT_Err_Invalid_Composite;
00668 goto Fail;
00669 }
00670
00671
00672 FT_LOCAL_DEF( void )
00673 TT_Init_Glyph_Loading( TT_Face face )
00674 {
00675 face->access_glyph_frame = TT_Access_Glyph_Frame;
00676 face->read_glyph_header = TT_Load_Glyph_Header;
00677 face->read_simple_glyph = TT_Load_Simple_Glyph;
00678 face->read_composite_glyph = TT_Load_Composite_Glyph;
00679 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
00680 }
00681
00682
00683 static void
00684 tt_prepare_zone( TT_GlyphZone zone,
00685 FT_GlyphLoad load,
00686 FT_UInt start_point,
00687 FT_UInt start_contour )
00688 {
00689 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
00690 zone->n_contours = (FT_Short) ( load->outline.n_contours -
00691 start_contour );
00692 zone->org = load->extra_points + start_point;
00693 zone->cur = load->outline.points + start_point;
00694 zone->orus = load->extra_points2 + start_point;
00695 zone->tags = (FT_Byte*)load->outline.tags + start_point;
00696 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
00697 zone->first_point = (FT_UShort)start_point;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 static FT_Error
00711 TT_Hint_Glyph( TT_Loader loader,
00712 FT_Bool is_composite )
00713 {
00714 TT_GlyphZone zone = &loader->zone;
00715 FT_Pos origin;
00716
00717 #ifdef TT_USE_BYTECODE_INTERPRETER
00718 FT_UInt n_ins;
00719 #else
00720 FT_UNUSED( is_composite );
00721 #endif
00722
00723
00724 #ifdef TT_USE_BYTECODE_INTERPRETER
00725 if ( loader->glyph->control_len > 0xFFFFL )
00726 {
00727 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
00728 FT_TRACE1(( "(0x%lx byte) is truncated\n",
00729 loader->glyph->control_len ));
00730 }
00731 n_ins = (FT_UInt)( loader->glyph->control_len );
00732 #endif
00733
00734 origin = zone->cur[zone->n_points - 4].x;
00735 origin = FT_PIX_ROUND( origin ) - origin;
00736 if ( origin )
00737 translate_array( zone->n_points, zone->cur, origin, 0 );
00738
00739 #ifdef TT_USE_BYTECODE_INTERPRETER
00740
00741 if ( n_ins > 0 )
00742 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
00743
00744
00745 loader->exec->GS = ((TT_Size)loader->size)->GS;
00746
00747
00748
00749 if ( is_composite )
00750 {
00751 loader->exec->metrics.x_scale = 1 << 16;
00752 loader->exec->metrics.y_scale = 1 << 16;
00753
00754 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
00755 }
00756 else
00757 {
00758 loader->exec->metrics.x_scale =
00759 ((TT_Size)loader->size)->metrics.x_scale;
00760 loader->exec->metrics.y_scale =
00761 ((TT_Size)loader->size)->metrics.y_scale;
00762 }
00763 #endif
00764
00765
00766 zone->cur[zone->n_points - 3].x =
00767 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
00768 zone->cur[zone->n_points - 1].y =
00769 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
00770
00771 #ifdef TT_USE_BYTECODE_INTERPRETER
00772
00773 if ( n_ins > 0 )
00774 {
00775 FT_Bool debug;
00776 FT_Error error;
00777
00778 FT_GlyphLoader gloader = loader->gloader;
00779 FT_Outline current_outline = gloader->current.outline;
00780
00781
00782 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
00783 loader->exec->glyphIns, n_ins );
00784 if ( error )
00785 return error;
00786
00787 loader->exec->is_composite = is_composite;
00788 loader->exec->pts = *zone;
00789
00790 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
00791 ((TT_Size)loader->size)->debug );
00792
00793 error = TT_Run_Context( loader->exec, debug );
00794 if ( error && loader->exec->pedantic_hinting )
00795 return error;
00796
00797
00798 current_outline.tags[0] |=
00799 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
00800 }
00801
00802 #endif
00803
00804
00805 if ( !loader->preserve_pps )
00806 {
00807 loader->pp1 = zone->cur[zone->n_points - 4];
00808 loader->pp2 = zone->cur[zone->n_points - 3];
00809 loader->pp3 = zone->cur[zone->n_points - 2];
00810 loader->pp4 = zone->cur[zone->n_points - 1];
00811 }
00812
00813 return TT_Err_Ok;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 static FT_Error
00828 TT_Process_Simple_Glyph( TT_Loader loader )
00829 {
00830 FT_GlyphLoader gloader = loader->gloader;
00831 FT_Error error = TT_Err_Ok;
00832 FT_Outline* outline;
00833 FT_Int n_points;
00834
00835
00836 outline = &gloader->current.outline;
00837 n_points = outline->n_points;
00838
00839
00840
00841 outline->points[n_points ] = loader->pp1;
00842 outline->points[n_points + 1] = loader->pp2;
00843 outline->points[n_points + 2] = loader->pp3;
00844 outline->points[n_points + 3] = loader->pp4;
00845
00846 outline->tags[n_points ] = 0;
00847 outline->tags[n_points + 1] = 0;
00848 outline->tags[n_points + 2] = 0;
00849 outline->tags[n_points + 3] = 0;
00850
00851 n_points += 4;
00852
00853 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00854
00855 if ( ((TT_Face)loader->face)->doblend )
00856 {
00857
00858 FT_Vector* deltas;
00859 FT_Memory memory = loader->face->memory;
00860 FT_Int i;
00861
00862
00863 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
00864 loader->glyph_index,
00865 &deltas,
00866 n_points );
00867 if ( error )
00868 return error;
00869
00870 for ( i = 0; i < n_points; ++i )
00871 {
00872 outline->points[i].x += deltas[i].x;
00873 outline->points[i].y += deltas[i].y;
00874 }
00875
00876 FT_FREE( deltas );
00877 }
00878
00879 #endif
00880
00881 if ( IS_HINTED( loader->load_flags ) )
00882 {
00883 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
00884
00885 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
00886 loader->zone.n_points + 4 );
00887 }
00888
00889
00890 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
00891 {
00892 FT_Vector* vec = outline->points;
00893 FT_Vector* limit = outline->points + n_points;
00894 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
00895 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
00896
00897
00898 for ( ; vec < limit; vec++ )
00899 {
00900 vec->x = FT_MulFix( vec->x, x_scale );
00901 vec->y = FT_MulFix( vec->y, y_scale );
00902 }
00903
00904 loader->pp1 = outline->points[n_points - 4];
00905 loader->pp2 = outline->points[n_points - 3];
00906 loader->pp3 = outline->points[n_points - 2];
00907 loader->pp4 = outline->points[n_points - 1];
00908 }
00909
00910 if ( IS_HINTED( loader->load_flags ) )
00911 {
00912 loader->zone.n_points += 4;
00913
00914 error = TT_Hint_Glyph( loader, 0 );
00915 }
00916
00917 return error;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 static FT_Error
00931 TT_Process_Composite_Component( TT_Loader loader,
00932 FT_SubGlyph subglyph,
00933 FT_UInt start_point,
00934 FT_UInt num_base_points )
00935 {
00936 FT_GlyphLoader gloader = loader->gloader;
00937 FT_Vector* base_vec = gloader->base.outline.points;
00938 FT_UInt num_points = gloader->base.outline.n_points;
00939 FT_Bool have_scale;
00940 FT_Pos x, y;
00941
00942
00943 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
00944 WE_HAVE_AN_XY_SCALE |
00945 WE_HAVE_A_2X2 ) );
00946
00947
00948 if ( have_scale )
00949 {
00950 FT_UInt i;
00951
00952
00953 for ( i = num_base_points; i < num_points; i++ )
00954 FT_Vector_Transform( base_vec + i, &subglyph->transform );
00955 }
00956
00957
00958 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
00959 {
00960 FT_UInt k = subglyph->arg1;
00961 FT_UInt l = subglyph->arg2;
00962 FT_Vector* p1;
00963 FT_Vector* p2;
00964
00965
00966
00967
00968
00969
00970 k += start_point;
00971 l += num_base_points;
00972 if ( k >= num_base_points ||
00973 l >= num_points )
00974 return TT_Err_Invalid_Composite;
00975
00976 p1 = gloader->base.outline.points + k;
00977 p2 = gloader->base.outline.points + l;
00978
00979 x = p1->x - p2->x;
00980 y = p1->y - p2->y;
00981 }
00982 else
00983 {
00984 x = subglyph->arg1;
00985 y = subglyph->arg2;
00986
00987 if ( !x && !y )
00988 return TT_Err_Ok;
00989
00990
00991
00992
00993
00994 if ( have_scale &&
00995 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
00996 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
00997 #else
00998 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
00999 #endif
01000 {
01001
01002 #if 0
01003
01004
01005
01006
01007
01008 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
01009 : -subglyph->transform.xx;
01010 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
01011 : -subglyph->transform.yx;
01012 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
01013 : -subglyph->transform.xy;
01014 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
01015 : -subglyph->transform.yy;
01016 int m = a > b ? a : b;
01017 int n = c > d ? c : d;
01018
01019
01020 if ( a - b <= 33 && a - b >= -33 )
01021 m *= 2;
01022 if ( c - d <= 33 && c - d >= -33 )
01023 n *= 2;
01024 x = FT_MulFix( x, m );
01025 y = FT_MulFix( y, n );
01026
01027 #else
01028
01029
01030
01031
01032
01033 FT_Fixed mac_xscale = FT_SqrtFixed(
01034 (FT_Int32)FT_MulFix( subglyph->transform.xx,
01035 subglyph->transform.xx ) +
01036 (FT_Int32)FT_MulFix( subglyph->transform.xy,
01037 subglyph->transform.xy ) );
01038 FT_Fixed mac_yscale = FT_SqrtFixed(
01039 (FT_Int32)FT_MulFix( subglyph->transform.yy,
01040 subglyph->transform.yy ) +
01041 (FT_Int32)FT_MulFix( subglyph->transform.yx,
01042 subglyph->transform.yx ) );
01043
01044
01045 x = FT_MulFix( x, mac_xscale );
01046 y = FT_MulFix( y, mac_yscale );
01047
01048 #endif
01049
01050 }
01051
01052 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01053 {
01054 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01055 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01056
01057
01058 x = FT_MulFix( x, x_scale );
01059 y = FT_MulFix( y, y_scale );
01060
01061 if ( subglyph->flags & ROUND_XY_TO_GRID )
01062 {
01063 x = FT_PIX_ROUND( x );
01064 y = FT_PIX_ROUND( y );
01065 }
01066 }
01067 }
01068
01069 if ( x || y )
01070 translate_array( num_points - num_base_points,
01071 base_vec + num_base_points,
01072 x, y );
01073
01074 return TT_Err_Ok;
01075 }
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 static FT_Error
01089 TT_Process_Composite_Glyph( TT_Loader loader,
01090 FT_UInt start_point,
01091 FT_UInt start_contour )
01092 {
01093 FT_Error error;
01094 FT_Outline* outline;
01095 FT_UInt i;
01096
01097
01098 outline = &loader->gloader->base.outline;
01099
01100
01101 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
01102 outline->n_points + 4,
01103 0 );
01104 if ( error )
01105 return error;
01106
01107 outline->points[outline->n_points ] = loader->pp1;
01108 outline->points[outline->n_points + 1] = loader->pp2;
01109 outline->points[outline->n_points + 2] = loader->pp3;
01110 outline->points[outline->n_points + 3] = loader->pp4;
01111
01112 outline->tags[outline->n_points ] = 0;
01113 outline->tags[outline->n_points + 1] = 0;
01114 outline->tags[outline->n_points + 2] = 0;
01115 outline->tags[outline->n_points + 3] = 0;
01116
01117 #ifdef TT_USE_BYTECODE_INTERPRETER
01118
01119 {
01120 FT_Stream stream = loader->stream;
01121 FT_UShort n_ins;
01122
01123
01124
01125
01126 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
01127 FT_READ_USHORT( n_ins ) )
01128 return error;
01129
01130 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
01131
01132
01133 if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
01134 {
01135 FT_TRACE0(( "TT_Process_Composite_Glyph: too many instructions (%d)\n",
01136 n_ins ));
01137
01138 return TT_Err_Too_Many_Hints;
01139 }
01140 else if ( n_ins == 0 )
01141 return TT_Err_Ok;
01142
01143 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
01144 return error;
01145
01146 loader->glyph->control_data = loader->exec->glyphIns;
01147 loader->glyph->control_len = n_ins;
01148 }
01149
01150 #endif
01151
01152 tt_prepare_zone( &loader->zone, &loader->gloader->base,
01153 start_point, start_contour );
01154
01155
01156
01157 for ( i = start_point; i < loader->zone.n_points; i++ )
01158 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
01159
01160 loader->zone.n_points += 4;
01161
01162 return TT_Hint_Glyph( loader, 1 );
01163 }
01164
01165
01166
01167
01168
01169 #define TT_LOADER_SET_PP( loader ) \
01170 do { \
01171 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
01172 (loader)->pp1.y = 0; \
01173 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
01174 (loader)->pp2.y = 0; \
01175 (loader)->pp3.x = 0; \
01176 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
01177 (loader)->pp4.x = 0; \
01178 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
01179 } while ( 0 )
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 static FT_Error
01192 load_truetype_glyph( TT_Loader loader,
01193 FT_UInt glyph_index,
01194 FT_UInt recurse_count,
01195 FT_Bool header_only )
01196 {
01197 FT_Error error = TT_Err_Ok;
01198 FT_Fixed x_scale, y_scale;
01199 FT_ULong offset;
01200 TT_Face face = (TT_Face)loader->face;
01201 FT_GlyphLoader gloader = loader->gloader;
01202 FT_Bool opened_frame = 0;
01203
01204 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01205 FT_Vector* deltas = NULL;
01206 #endif
01207
01208 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01209 FT_StreamRec inc_stream;
01210 FT_Data glyph_data;
01211 FT_Bool glyph_data_loaded = 0;
01212 #endif
01213
01214
01215
01216
01217 if ( recurse_count > 1 &&
01218 recurse_count > face->max_profile.maxComponentDepth )
01219 {
01220 error = TT_Err_Invalid_Composite;
01221 goto Exit;
01222 }
01223
01224
01225 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
01226 {
01227 error = TT_Err_Invalid_Glyph_Index;
01228 goto Exit;
01229 }
01230
01231 loader->glyph_index = glyph_index;
01232
01233 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01234 {
01235 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
01236 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
01237 }
01238 else
01239 {
01240 x_scale = 0x10000L;
01241 y_scale = 0x10000L;
01242 }
01243
01244 tt_get_metrics( loader, glyph_index );
01245
01246
01247
01248
01249
01250 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01251
01252
01253
01254
01255 if ( face->root.internal->incremental_interface )
01256 {
01257 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
01258 face->root.internal->incremental_interface->object,
01259 glyph_index, &glyph_data );
01260 if ( error )
01261 goto Exit;
01262
01263 glyph_data_loaded = 1;
01264 offset = 0;
01265 loader->byte_len = glyph_data.length;
01266
01267 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
01268 FT_Stream_OpenMemory( &inc_stream,
01269 glyph_data.pointer, glyph_data.length );
01270
01271 loader->stream = &inc_stream;
01272 }
01273 else
01274
01275 #endif
01276
01277 offset = tt_face_get_location( face, glyph_index,
01278 (FT_UInt*)&loader->byte_len );
01279
01280 if ( loader->byte_len > 0 )
01281 {
01282 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01283
01284 if ( !loader->glyf_offset &&
01285 !face->root.internal->incremental_interface )
01286 #else
01287 if ( !loader->glyf_offset )
01288 #endif
01289 {
01290 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
01291 error = TT_Err_Invalid_Table;
01292 goto Exit;
01293 }
01294
01295 error = face->access_glyph_frame( loader, glyph_index,
01296 loader->glyf_offset + offset,
01297 loader->byte_len );
01298 if ( error )
01299 goto Exit;
01300
01301 opened_frame = 1;
01302
01303
01304 error = face->read_glyph_header( loader );
01305 if ( error || header_only )
01306 goto Exit;
01307 }
01308
01309 if ( loader->byte_len == 0 || loader->n_contours == 0 )
01310 {
01311 loader->bbox.xMin = 0;
01312 loader->bbox.xMax = 0;
01313 loader->bbox.yMin = 0;
01314 loader->bbox.yMax = 0;
01315
01316 if ( header_only )
01317 goto Exit;
01318
01319 TT_LOADER_SET_PP( loader );
01320
01321 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01322
01323 if ( ((TT_Face)(loader->face))->doblend )
01324 {
01325
01326 FT_Memory memory = loader->face->memory;
01327
01328
01329 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
01330 glyph_index, &deltas, 4 );
01331 if ( error )
01332 goto Exit;
01333
01334 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
01335 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
01336 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
01337 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
01338
01339 FT_FREE( deltas );
01340 }
01341
01342 #endif
01343
01344 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01345 {
01346 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01347 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01348 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01349 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01350 }
01351
01352 error = TT_Err_Ok;
01353 goto Exit;
01354 }
01355
01356 TT_LOADER_SET_PP( loader );
01357
01358
01359
01360
01361
01362
01363
01364 if ( loader->n_contours > 0 )
01365 {
01366 error = face->read_simple_glyph( loader );
01367 if ( error )
01368 goto Exit;
01369
01370
01371 face->forget_glyph_frame( loader );
01372 opened_frame = 0;
01373
01374 error = TT_Process_Simple_Glyph( loader );
01375 if ( error )
01376 goto Exit;
01377
01378 FT_GlyphLoader_Add( gloader );
01379 }
01380
01381
01382
01383
01384
01385
01386 else if ( loader->n_contours == -1 )
01387 {
01388 FT_UInt start_point;
01389 FT_UInt start_contour;
01390 FT_ULong ins_pos;
01391
01392
01393 start_point = gloader->base.outline.n_points;
01394 start_contour = gloader->base.outline.n_contours;
01395
01396
01397 error = face->read_composite_glyph( loader );
01398 if ( error )
01399 goto Exit;
01400
01401
01402 ins_pos = loader->ins_pos;
01403
01404
01405 face->forget_glyph_frame( loader );
01406 opened_frame = 0;
01407
01408 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
01409
01410 if ( face->doblend )
01411 {
01412 FT_Int i, limit;
01413 FT_SubGlyph subglyph;
01414 FT_Memory memory = face->root.memory;
01415
01416
01417
01418
01419
01420 if ( ( error = TT_Vary_Get_Glyph_Deltas(
01421 face,
01422 glyph_index,
01423 &deltas,
01424 gloader->current.num_subglyphs + 4 )) != 0 )
01425 goto Exit;
01426
01427 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
01428 limit = gloader->current.num_subglyphs;
01429
01430 for ( i = 0; i < limit; ++i, ++subglyph )
01431 {
01432 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
01433 {
01434
01435
01436
01437 subglyph->arg1 += (FT_Int16)deltas[i].x;
01438 subglyph->arg2 += (FT_Int16)deltas[i].y;
01439 }
01440 }
01441
01442 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
01443 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
01444 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
01445 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
01446
01447 FT_FREE( deltas );
01448 }
01449
01450 #endif
01451
01452 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01453 {
01454 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
01455 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
01456 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
01457 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
01458 }
01459
01460
01461
01462
01463 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
01464 {
01465 FT_GlyphLoader_Add( gloader );
01466 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
01467
01468 goto Exit;
01469 }
01470
01471
01472
01473
01474
01475 {
01476 FT_UInt n, num_base_points;
01477 FT_SubGlyph subglyph = 0;
01478
01479 FT_UInt num_points = start_point;
01480 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
01481 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
01482
01483 FT_Stream old_stream = loader->stream;
01484
01485
01486 FT_GlyphLoader_Add( gloader );
01487
01488
01489 for ( n = 0; n < num_subglyphs; n++ )
01490 {
01491 FT_Vector pp[4];
01492
01493
01494
01495
01496
01497
01498 subglyph = gloader->base.subglyphs + num_base_subgs + n;
01499
01500 pp[0] = loader->pp1;
01501 pp[1] = loader->pp2;
01502 pp[2] = loader->pp3;
01503 pp[3] = loader->pp4;
01504
01505 num_base_points = gloader->base.outline.n_points;
01506
01507 error = load_truetype_glyph( loader, subglyph->index,
01508 recurse_count + 1, FALSE );
01509 if ( error )
01510 goto Exit;
01511
01512
01513 subglyph = gloader->base.subglyphs + num_base_subgs + n;
01514
01515 if ( !( subglyph->flags & USE_MY_METRICS ) )
01516 {
01517 loader->pp1 = pp[0];
01518 loader->pp2 = pp[1];
01519 loader->pp3 = pp[2];
01520 loader->pp4 = pp[3];
01521 }
01522
01523 num_points = gloader->base.outline.n_points;
01524
01525 if ( num_points == num_base_points )
01526 continue;
01527
01528
01529
01530
01531
01532
01533
01534 TT_Process_Composite_Component( loader, subglyph, start_point,
01535 num_base_points );
01536 }
01537
01538 loader->stream = old_stream;
01539
01540
01541 loader->ins_pos = ins_pos;
01542 if ( IS_HINTED( loader->load_flags ) &&
01543
01544 #ifdef TT_USE_BYTECODE_INTERPRETER
01545
01546 subglyph->flags & WE_HAVE_INSTR &&
01547
01548 #endif
01549
01550 num_points > start_point )
01551 TT_Process_Composite_Glyph( loader, start_point, start_contour );
01552
01553 }
01554 }
01555 else
01556 {
01557
01558 error = TT_Err_Invalid_Outline;
01559 goto Exit;
01560 }
01561
01562
01563
01564
01565
01566 Exit:
01567
01568 if ( opened_frame )
01569 face->forget_glyph_frame( loader );
01570
01571 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01572
01573 if ( glyph_data_loaded )
01574 face->root.internal->incremental_interface->funcs->free_glyph_data(
01575 face->root.internal->incremental_interface->object,
01576 &glyph_data );
01577
01578 #endif
01579
01580 return error;
01581 }
01582
01583
01584 static FT_Error
01585 compute_glyph_metrics( TT_Loader loader,
01586 FT_UInt glyph_index )
01587 {
01588 FT_BBox bbox;
01589 TT_Face face = (TT_Face)loader->face;
01590 FT_Fixed y_scale;
01591 TT_GlyphSlot glyph = loader->glyph;
01592 TT_Size size = (TT_Size)loader->size;
01593
01594
01595 y_scale = 0x10000L;
01596 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
01597 y_scale = size->root.metrics.y_scale;
01598
01599 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
01600 FT_Outline_Get_CBox( &glyph->outline, &bbox );
01601 else
01602 bbox = loader->bbox;
01603
01604
01605
01606 {
01607 FT_Pos advance = loader->linear;
01608
01609
01610
01611
01612
01613
01614
01615 if ( face->postscript.isFixedPitch &&
01616 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
01617 advance = face->horizontal.advance_Width_Max;
01618
01619
01620
01621 glyph->linearHoriAdvance = advance;
01622 }
01623
01624 glyph->metrics.horiBearingX = bbox.xMin;
01625 glyph->metrics.horiBearingY = bbox.yMax;
01626 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
01627
01628
01629 if ( !face->postscript.isFixedPitch &&
01630 IS_HINTED( loader->load_flags ) )
01631 {
01632 FT_Byte* widthp;
01633
01634
01635 widthp = tt_face_get_device_metrics( face,
01636 size->root.metrics.x_ppem,
01637 glyph_index );
01638
01639 if ( widthp )
01640 glyph->metrics.horiAdvance = *widthp << 6;
01641 }
01642
01643
01644 glyph->metrics.width = bbox.xMax - bbox.xMin;
01645 glyph->metrics.height = bbox.yMax - bbox.yMin;
01646
01647
01648
01649
01650 {
01651 FT_Pos top;
01652 FT_Pos advance;
01653
01654
01655
01656 if ( face->vertical_info &&
01657 face->vertical.number_Of_VMetrics > 0 )
01658 {
01659 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
01660 y_scale );
01661
01662 if ( loader->pp3.y <= loader->pp4.y )
01663 advance = 0;
01664 else
01665 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
01666 y_scale );
01667 }
01668 else
01669 {
01670 FT_Pos height;
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
01682 y_scale );
01683 if ( face->os2.version != 0xFFFFU )
01684 advance = (FT_Pos)( face->os2.sTypoAscender -
01685 face->os2.sTypoDescender );
01686 else
01687 advance = (FT_Pos)( face->horizontal.Ascender -
01688 face->horizontal.Descender );
01689
01690 top = ( advance - height ) / 2;
01691 }
01692
01693 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01694 {
01695 FT_Incremental_InterfaceRec* incr;
01696 FT_Incremental_MetricsRec metrics;
01697 FT_Error error;
01698
01699
01700 incr = face->root.internal->incremental_interface;
01701
01702
01703
01704 if ( incr && incr->funcs->get_glyph_metrics )
01705 {
01706 metrics.bearing_x = 0;
01707 metrics.bearing_y = top;
01708 metrics.advance = advance;
01709
01710 error = incr->funcs->get_glyph_metrics( incr->object,
01711 glyph_index,
01712 TRUE,
01713 &metrics );
01714 if ( error )
01715 return error;
01716
01717 top = metrics.bearing_y;
01718 advance = metrics.advance;
01719 }
01720 }
01721
01722
01723
01724 #endif
01725
01726 glyph->linearVertAdvance = advance;
01727
01728
01729 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
01730 {
01731 top = FT_MulFix( top, y_scale );
01732 advance = FT_MulFix( advance, y_scale );
01733 }
01734
01735
01736
01737
01738 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
01739 glyph->metrics.horiAdvance / 2;
01740 glyph->metrics.vertBearingY = top;
01741 glyph->metrics.vertAdvance = advance;
01742 }
01743
01744 return 0;
01745 }
01746
01747
01748 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
01749
01750 static FT_Error
01751 load_sbit_image( TT_Size size,
01752 TT_GlyphSlot glyph,
01753 FT_UInt glyph_index,
01754 FT_Int32 load_flags )
01755 {
01756 TT_Face face;
01757 SFNT_Service sfnt;
01758 FT_Stream stream;
01759 FT_Error error;
01760 TT_SBit_MetricsRec metrics;
01761
01762
01763 face = (TT_Face)glyph->face;
01764 sfnt = (SFNT_Service)face->sfnt;
01765 stream = face->root.stream;
01766
01767 error = sfnt->load_sbit_image( face,
01768 size->strike_index,
01769 glyph_index,
01770 (FT_Int)load_flags,
01771 stream,
01772 &glyph->bitmap,
01773 &metrics );
01774 if ( !error )
01775 {
01776 glyph->outline.n_points = 0;
01777 glyph->outline.n_contours = 0;
01778
01779 glyph->metrics.width = (FT_Pos)metrics.width << 6;
01780 glyph->metrics.height = (FT_Pos)metrics.height << 6;
01781
01782 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
01783 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
01784 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
01785
01786 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
01787 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
01788 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
01789
01790 glyph->format = FT_GLYPH_FORMAT_BITMAP;
01791
01792 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
01793 {
01794 glyph->bitmap_left = metrics.vertBearingX;
01795 glyph->bitmap_top = metrics.vertBearingY;
01796 }
01797 else
01798 {
01799 glyph->bitmap_left = metrics.horiBearingX;
01800 glyph->bitmap_top = metrics.horiBearingY;
01801 }
01802 }
01803
01804 return error;
01805 }
01806
01807 #endif
01808
01809
01810 static FT_Error
01811 tt_loader_init( TT_Loader loader,
01812 TT_Size size,
01813 TT_GlyphSlot glyph,
01814 FT_Int32 load_flags,
01815 FT_Bool glyf_table_only )
01816 {
01817 TT_Face face;
01818 FT_Stream stream;
01819
01820
01821 face = (TT_Face)glyph->face;
01822 stream = face->root.stream;
01823
01824 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
01825
01826 #ifdef TT_USE_BYTECODE_INTERPRETER
01827
01828
01829 if ( IS_HINTED( load_flags ) && !glyf_table_only )
01830 {
01831 TT_ExecContext exec;
01832 FT_Bool grayscale;
01833
01834
01835 if ( !size->cvt_ready )
01836 {
01837 FT_Error error = tt_size_ready_bytecode( size );
01838 if ( error )
01839 return error;
01840 }
01841
01842
01843 exec = size->debug ? size->context
01844 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
01845 if ( !exec )
01846 return TT_Err_Could_Not_Find_Context;
01847
01848 grayscale =
01849 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
01850
01851 TT_Load_Context( exec, face, size );
01852
01853
01854
01855 if ( grayscale != exec->grayscale )
01856 {
01857 FT_UInt i;
01858
01859
01860 exec->grayscale = grayscale;
01861
01862 for ( i = 0; i < size->cvt_size; i++ )
01863 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
01864 tt_size_run_prep( size );
01865 }
01866
01867
01868 if ( exec->GS.instruct_control & 1 )
01869 load_flags |= FT_LOAD_NO_HINTING;
01870
01871
01872 if ( exec->GS.instruct_control & 2 )
01873 exec->GS = tt_default_graphics_state;
01874
01875 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
01876 loader->exec = exec;
01877 loader->instructions = exec->glyphIns;
01878 }
01879
01880 #endif
01881
01882
01883
01884
01885
01886 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01887
01888 if ( face->root.internal->incremental_interface )
01889 loader->glyf_offset = 0;
01890 else
01891
01892 #endif
01893
01894 {
01895 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
01896
01897
01898 if ( error == TT_Err_Table_Missing )
01899 loader->glyf_offset = 0;
01900 else if ( error )
01901 {
01902 FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
01903 return error;
01904 }
01905 else
01906 loader->glyf_offset = FT_STREAM_POS();
01907 }
01908
01909
01910 if ( !glyf_table_only )
01911 {
01912 FT_GlyphLoader gloader = glyph->internal->loader;
01913
01914
01915 FT_GlyphLoader_Rewind( gloader );
01916 loader->gloader = gloader;
01917 }
01918
01919 loader->load_flags = load_flags;
01920
01921 loader->face = (FT_Face)face;
01922 loader->size = (FT_Size)size;
01923 loader->glyph = (FT_GlyphSlot)glyph;
01924 loader->stream = stream;
01925
01926 return TT_Err_Ok;
01927 }
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957 FT_LOCAL_DEF( FT_Error )
01958 TT_Load_Glyph( TT_Size size,
01959 TT_GlyphSlot glyph,
01960 FT_UInt glyph_index,
01961 FT_Int32 load_flags )
01962 {
01963 TT_Face face;
01964 FT_Error error;
01965 TT_LoaderRec loader;
01966
01967
01968 face = (TT_Face)glyph->face;
01969 error = TT_Err_Ok;
01970
01971 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
01972
01973
01974
01975
01976
01977 if ( size->strike_index != 0xFFFFFFFFUL &&
01978 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
01979 {
01980 error = load_sbit_image( size, glyph, glyph_index, load_flags );
01981 if ( !error )
01982 {
01983 FT_Face root = &face->root;
01984
01985
01986 if ( FT_IS_SCALABLE( root ) )
01987 {
01988
01989 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
01990 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
01991 glyph->linearHoriAdvance = loader.linear;
01992 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
01993 loader.vadvance;
01994 if ( face->postscript.isFixedPitch &&
01995 ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
01996 glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
01997 }
01998
01999 return TT_Err_Ok;
02000 }
02001 }
02002
02003 #endif
02004
02005
02006 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
02007 return TT_Err_Invalid_Size_Handle;
02008
02009 if ( load_flags & FT_LOAD_SBITS_ONLY )
02010 return TT_Err_Invalid_Argument;
02011
02012 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
02013 if ( error )
02014 return error;
02015
02016 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
02017 glyph->num_subglyphs = 0;
02018 glyph->outline.flags = 0;
02019
02020
02021 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
02022 if ( !error )
02023 {
02024 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
02025 {
02026 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
02027 glyph->subglyphs = loader.gloader->base.subglyphs;
02028 }
02029 else
02030 {
02031 glyph->outline = loader.gloader->base.outline;
02032 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
02033
02034
02035
02036 if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
02037 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
02038 }
02039
02040 #ifdef TT_USE_BYTECODE_INTERPRETER
02041
02042 if ( IS_HINTED( load_flags ) )
02043 {
02044 if ( loader.exec->GS.scan_control )
02045 {
02046
02047 switch ( loader.exec->GS.scan_type )
02048 {
02049 case 0:
02050 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
02051 break;
02052 case 1:
02053
02054 break;
02055 case 4:
02056 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
02057 FT_OUTLINE_INCLUDE_STUBS;
02058 break;
02059 case 5:
02060 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
02061 break;
02062
02063 default:
02064 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02065 break;
02066 }
02067 }
02068 else
02069 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
02070 }
02071
02072 #endif
02073
02074 compute_glyph_metrics( &loader, glyph_index );
02075 }
02076
02077
02078
02079
02080
02081 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
02082 size->root.metrics.y_ppem < 24 )
02083 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
02084
02085 return error;
02086 }
02087
02088
02089