00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <ft2build.h>
00047 #include FT_INTERNAL_DEBUG_H
00048 #include FT_CONFIG_CONFIG_H
00049 #include FT_INTERNAL_STREAM_H
00050 #include FT_INTERNAL_SFNT_H
00051 #include FT_TRUETYPE_TAGS_H
00052 #include FT_MULTIPLE_MASTERS_H
00053
00054 #include "ttpload.h"
00055 #include "ttgxvar.h"
00056
00057 #include "tterrors.h"
00058
00059
00060 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00061
00062
00063 #define FT_Stream_FTell( stream ) \
00064 ( (stream)->cursor - (stream)->base )
00065 #define FT_Stream_SeekSet( stream, off ) \
00066 ( (stream)->cursor = (stream)->base+(off) )
00067
00068
00069
00070
00071
00072
00073
00074
00075 #undef FT_COMPONENT
00076 #define FT_COMPONENT trace_ttgxvar
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #define ALL_POINTS (FT_UShort*)( -1 )
00095
00096
00097 #define GX_PT_POINTS_ARE_WORDS 0x80
00098 #define GX_PT_POINT_RUN_COUNT_MASK 0x7F
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 static FT_UShort*
00123 ft_var_readpackedpoints( FT_Stream stream,
00124 FT_UInt *point_cnt )
00125 {
00126 FT_UShort *points;
00127 FT_Int n;
00128 FT_Int runcnt;
00129 FT_Int i;
00130 FT_Int j;
00131 FT_Int first;
00132 FT_Memory memory = stream->memory;
00133 FT_Error error = TT_Err_Ok;
00134
00135 FT_UNUSED( error );
00136
00137
00138 *point_cnt = n = FT_GET_BYTE();
00139 if ( n == 0 )
00140 return ALL_POINTS;
00141
00142 if ( n & GX_PT_POINTS_ARE_WORDS )
00143 n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );
00144
00145 if ( FT_NEW_ARRAY( points, n ) )
00146 return NULL;
00147
00148 i = 0;
00149 while ( i < n )
00150 {
00151 runcnt = FT_GET_BYTE();
00152 if ( runcnt & GX_PT_POINTS_ARE_WORDS )
00153 {
00154 runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
00155 first = points[i++] = FT_GET_USHORT();
00156
00157 if ( runcnt < 1 )
00158 goto Exit;
00159
00160
00161 for ( j = 0; j < runcnt; ++j )
00162 points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
00163 }
00164 else
00165 {
00166 first = points[i++] = FT_GET_BYTE();
00167
00168 if ( runcnt < 1 )
00169 goto Exit;
00170
00171 for ( j = 0; j < runcnt; ++j )
00172 points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
00173 }
00174 }
00175
00176 Exit:
00177 return points;
00178 }
00179
00180
00181 enum
00182 {
00183 GX_DT_DELTAS_ARE_ZERO = 0x80,
00184 GX_DT_DELTAS_ARE_WORDS = 0x40,
00185 GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
00186 };
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 static FT_Short*
00210 ft_var_readpackeddeltas( FT_Stream stream,
00211 FT_Offset delta_cnt )
00212 {
00213 FT_Short *deltas;
00214 FT_UInt runcnt;
00215 FT_Offset i;
00216 FT_UInt j;
00217 FT_Memory memory = stream->memory;
00218 FT_Error error = TT_Err_Ok;
00219
00220 FT_UNUSED( error );
00221
00222
00223 if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
00224 return NULL;
00225
00226 i = 0;
00227 while ( i < delta_cnt )
00228 {
00229 runcnt = FT_GET_BYTE();
00230 if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
00231 {
00232
00233 for ( j = 0;
00234 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
00235 ++j )
00236 deltas[i++] = 0;
00237 }
00238 else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
00239 {
00240
00241 for ( j = 0;
00242 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
00243 ++j )
00244 deltas[i++] = FT_GET_SHORT();
00245 }
00246 else
00247 {
00248
00249 for ( j = 0;
00250 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
00251 ++j )
00252 deltas[i++] = FT_GET_CHAR();
00253 }
00254
00255 if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )
00256 {
00257
00258 FT_FREE( deltas );
00259 return NULL;
00260 }
00261 }
00262
00263 return deltas;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 static void
00280 ft_var_load_avar( TT_Face face )
00281 {
00282 FT_Stream stream = FT_FACE_STREAM(face);
00283 FT_Memory memory = stream->memory;
00284 GX_Blend blend = face->blend;
00285 GX_AVarSegment segment;
00286 FT_Error error = TT_Err_Ok;
00287 FT_ULong version;
00288 FT_Long axisCount;
00289 FT_Int i, j;
00290 FT_ULong table_len;
00291
00292 FT_UNUSED( error );
00293
00294
00295 blend->avar_checked = TRUE;
00296 if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )
00297 return;
00298
00299 if ( FT_FRAME_ENTER( table_len ) )
00300 return;
00301
00302 version = FT_GET_LONG();
00303 axisCount = FT_GET_LONG();
00304
00305 if ( version != 0x00010000L ||
00306 axisCount != (FT_Long)blend->mmvar->num_axis )
00307 goto Exit;
00308
00309 if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
00310 goto Exit;
00311
00312 segment = &blend->avar_segment[0];
00313 for ( i = 0; i < axisCount; ++i, ++segment )
00314 {
00315 segment->pairCount = FT_GET_USHORT();
00316 if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
00317 {
00318
00319
00320
00321 for ( j = i - 1; j >= 0; --j )
00322 FT_FREE( blend->avar_segment[j].correspondence );
00323
00324 FT_FREE( blend->avar_segment );
00325 blend->avar_segment = NULL;
00326 goto Exit;
00327 }
00328
00329 for ( j = 0; j < segment->pairCount; ++j )
00330 {
00331 segment->correspondence[j].fromCoord =
00332 FT_GET_SHORT() << 2;
00333 segment->correspondence[j].toCoord =
00334 FT_GET_SHORT()<<2;
00335 }
00336 }
00337
00338 Exit:
00339 FT_FRAME_EXIT();
00340 }
00341
00342
00343 typedef struct GX_GVar_Head_
00344 {
00345 FT_Long version;
00346 FT_UShort axisCount;
00347 FT_UShort globalCoordCount;
00348 FT_ULong offsetToCoord;
00349 FT_UShort glyphCount;
00350 FT_UShort flags;
00351 FT_ULong offsetToData;
00352
00353 } GX_GVar_Head;
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 static FT_Error
00372 ft_var_load_gvar( TT_Face face )
00373 {
00374 FT_Stream stream = FT_FACE_STREAM(face);
00375 FT_Memory memory = stream->memory;
00376 GX_Blend blend = face->blend;
00377 FT_Error error;
00378 FT_UInt i, j;
00379 FT_ULong table_len;
00380 FT_ULong gvar_start;
00381 FT_ULong offsetToData;
00382 GX_GVar_Head gvar_head;
00383
00384 static const FT_Frame_Field gvar_fields[] =
00385 {
00386
00387 #undef FT_STRUCTURE
00388 #define FT_STRUCTURE GX_GVar_Head
00389
00390 FT_FRAME_START( 20 ),
00391 FT_FRAME_LONG ( version ),
00392 FT_FRAME_USHORT( axisCount ),
00393 FT_FRAME_USHORT( globalCoordCount ),
00394 FT_FRAME_ULONG ( offsetToCoord ),
00395 FT_FRAME_USHORT( glyphCount ),
00396 FT_FRAME_USHORT( flags ),
00397 FT_FRAME_ULONG ( offsetToData ),
00398 FT_FRAME_END
00399 };
00400
00401 if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )
00402 goto Exit;
00403
00404 gvar_start = FT_STREAM_POS( );
00405 if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
00406 goto Exit;
00407
00408 blend->tuplecount = gvar_head.globalCoordCount;
00409 blend->gv_glyphcnt = gvar_head.glyphCount;
00410 offsetToData = gvar_start + gvar_head.offsetToData;
00411
00412 if ( gvar_head.version != (FT_Long)0x00010000L ||
00413 gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
00414 {
00415 error = TT_Err_Invalid_Table;
00416 goto Exit;
00417 }
00418
00419 if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
00420 goto Exit;
00421
00422 if ( gvar_head.flags & 1 )
00423 {
00424
00425 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
00426 goto Exit;
00427
00428 for ( i = 0; i <= blend->gv_glyphcnt; ++i )
00429 blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();
00430
00431 FT_FRAME_EXIT();
00432 }
00433 else
00434 {
00435
00436 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
00437 goto Exit;
00438
00439 for ( i = 0; i <= blend->gv_glyphcnt; ++i )
00440 blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
00441
00442
00443 FT_FRAME_EXIT();
00444 }
00445
00446 if ( blend->tuplecount != 0 )
00447 {
00448 if ( FT_NEW_ARRAY( blend->tuplecoords,
00449 gvar_head.axisCount * blend->tuplecount ) )
00450 goto Exit;
00451
00452 if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
00453 FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
00454 goto Exit;
00455
00456 for ( i = 0; i < blend->tuplecount; ++i )
00457 for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j )
00458 blend->tuplecoords[i * gvar_head.axisCount + j] =
00459 FT_GET_SHORT() << 2;
00460
00461 FT_FRAME_EXIT();
00462 }
00463
00464 Exit:
00465 return error;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 static FT_Fixed
00497 ft_var_apply_tuple( GX_Blend blend,
00498 FT_UShort tupleIndex,
00499 FT_Fixed* tuple_coords,
00500 FT_Fixed* im_start_coords,
00501 FT_Fixed* im_end_coords )
00502 {
00503 FT_UInt i;
00504 FT_Fixed apply;
00505 FT_Fixed temp;
00506
00507
00508 apply = 0x10000L;
00509 for ( i = 0; i < blend->num_axis; ++i )
00510 {
00511 if ( tuple_coords[i] == 0 )
00512
00513
00514
00515
00516 continue;
00517
00518 else if ( blend->normalizedcoords[i] == 0 ||
00519 ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
00520 ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
00521 {
00522 apply = 0;
00523 break;
00524 }
00525
00526 else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
00527
00528 apply = FT_MulDiv( apply,
00529 blend->normalizedcoords[i] > 0
00530 ? blend->normalizedcoords[i]
00531 : -blend->normalizedcoords[i],
00532 0x10000L );
00533
00534 else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
00535 blend->normalizedcoords[i] >= im_end_coords[i] )
00536 {
00537 apply = 0;
00538 break;
00539 }
00540
00541 else if ( blend->normalizedcoords[i] < tuple_coords[i] )
00542 {
00543 temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i],
00544 0x10000L,
00545 tuple_coords[i] - im_start_coords[i]);
00546 apply = FT_MulDiv( apply, temp, 0x10000L );
00547 }
00548
00549 else
00550 {
00551 temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i],
00552 0x10000L,
00553 im_end_coords[i] - tuple_coords[i] );
00554 apply = FT_MulDiv( apply, temp, 0x10000L );
00555 }
00556 }
00557
00558 return apply;
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 typedef struct GX_FVar_Head_
00572 {
00573 FT_Long version;
00574 FT_UShort offsetToData;
00575 FT_UShort countSizePairs;
00576 FT_UShort axisCount;
00577 FT_UShort axisSize;
00578 FT_UShort instanceCount;
00579 FT_UShort instanceSize;
00580
00581 } GX_FVar_Head;
00582
00583
00584 typedef struct fvar_axis_
00585 {
00586 FT_ULong axisTag;
00587 FT_ULong minValue;
00588 FT_ULong defaultValue;
00589 FT_ULong maxValue;
00590 FT_UShort flags;
00591 FT_UShort nameID;
00592
00593 } GX_FVar_Axis;
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 FT_LOCAL_DEF( FT_Error )
00616 TT_Get_MM_Var( TT_Face face,
00617 FT_MM_Var* *master )
00618 {
00619 FT_Stream stream = face->root.stream;
00620 FT_Memory memory = face->root.memory;
00621 FT_ULong table_len;
00622 FT_Error error = TT_Err_Ok;
00623 FT_ULong fvar_start;
00624 FT_Int i, j;
00625 FT_MM_Var* mmvar;
00626 FT_Fixed* next_coords;
00627 FT_String* next_name;
00628 FT_Var_Axis* a;
00629 FT_Var_Named_Style* ns;
00630 GX_FVar_Head fvar_head;
00631
00632 static const FT_Frame_Field fvar_fields[] =
00633 {
00634
00635 #undef FT_STRUCTURE
00636 #define FT_STRUCTURE GX_FVar_Head
00637
00638 FT_FRAME_START( 16 ),
00639 FT_FRAME_LONG ( version ),
00640 FT_FRAME_USHORT( offsetToData ),
00641 FT_FRAME_USHORT( countSizePairs ),
00642 FT_FRAME_USHORT( axisCount ),
00643 FT_FRAME_USHORT( axisSize ),
00644 FT_FRAME_USHORT( instanceCount ),
00645 FT_FRAME_USHORT( instanceSize ),
00646 FT_FRAME_END
00647 };
00648
00649 static const FT_Frame_Field fvaraxis_fields[] =
00650 {
00651
00652 #undef FT_STRUCTURE
00653 #define FT_STRUCTURE GX_FVar_Axis
00654
00655 FT_FRAME_START( 20 ),
00656 FT_FRAME_ULONG ( axisTag ),
00657 FT_FRAME_ULONG ( minValue ),
00658 FT_FRAME_ULONG ( defaultValue ),
00659 FT_FRAME_ULONG ( maxValue ),
00660 FT_FRAME_USHORT( flags ),
00661 FT_FRAME_USHORT( nameID ),
00662 FT_FRAME_END
00663 };
00664
00665
00666 if ( face->blend == NULL )
00667 {
00668
00669 if ( (error = face->goto_table( face, TTAG_gvar,
00670 stream, &table_len )) != 0 )
00671 goto Exit;
00672
00673 if ( (error = face->goto_table( face, TTAG_fvar,
00674 stream, &table_len )) != 0 )
00675 goto Exit;
00676
00677 fvar_start = FT_STREAM_POS( );
00678
00679 if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
00680 goto Exit;
00681
00682 if ( fvar_head.version != (FT_Long)0x00010000L ||
00683 fvar_head.countSizePairs != 2 ||
00684 fvar_head.axisSize != 20 ||
00685 fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount ||
00686 fvar_head.offsetToData + fvar_head.axisCount * 20U +
00687 fvar_head.instanceCount * fvar_head.instanceSize > table_len )
00688 {
00689 error = TT_Err_Invalid_Table;
00690 goto Exit;
00691 }
00692
00693 if ( FT_NEW( face->blend ) )
00694 goto Exit;
00695
00696
00697 face->blend->mmvar_len =
00698 sizeof ( FT_MM_Var ) +
00699 fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
00700 fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
00701 fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
00702 5 * fvar_head.axisCount;
00703
00704 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
00705 goto Exit;
00706 face->blend->mmvar = mmvar;
00707
00708 mmvar->num_axis =
00709 fvar_head.axisCount;
00710 mmvar->num_designs =
00711 (FT_UInt)-1;
00712
00713
00714 mmvar->num_namedstyles =
00715 fvar_head.instanceCount;
00716 mmvar->axis =
00717 (FT_Var_Axis*)&(mmvar[1]);
00718 mmvar->namedstyle =
00719 (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);
00720
00721 next_coords =
00722 (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);
00723 for ( i = 0; i < fvar_head.instanceCount; ++i )
00724 {
00725 mmvar->namedstyle[i].coords = next_coords;
00726 next_coords += fvar_head.axisCount;
00727 }
00728
00729 next_name = (FT_String*)next_coords;
00730 for ( i = 0; i < fvar_head.axisCount; ++i )
00731 {
00732 mmvar->axis[i].name = next_name;
00733 next_name += 5;
00734 }
00735
00736 if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
00737 goto Exit;
00738
00739 a = mmvar->axis;
00740 for ( i = 0; i < fvar_head.axisCount; ++i )
00741 {
00742 GX_FVar_Axis axis_rec;
00743
00744
00745 if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
00746 goto Exit;
00747 a->tag = axis_rec.axisTag;
00748 a->minimum = axis_rec.minValue;
00749 a->def = axis_rec.defaultValue;
00750 a->maximum = axis_rec.maxValue;
00751 a->strid = axis_rec.nameID;
00752
00753 a->name[0] = (FT_String)( a->tag >> 24 );
00754 a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
00755 a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF );
00756 a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
00757 a->name[4] = 0;
00758
00759 ++a;
00760 }
00761
00762 ns = mmvar->namedstyle;
00763 for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns )
00764 {
00765 if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
00766 goto Exit;
00767
00768 ns->strid = FT_GET_USHORT();
00769 (void) FT_GET_USHORT();
00770
00771 for ( j = 0; j < fvar_head.axisCount; ++j )
00772 ns->coords[j] = FT_GET_ULONG();
00773
00774 FT_FRAME_EXIT();
00775 }
00776 }
00777
00778 if ( master != NULL )
00779 {
00780 FT_UInt n;
00781
00782
00783 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
00784 goto Exit;
00785 FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
00786
00787 mmvar->axis =
00788 (FT_Var_Axis*)&(mmvar[1]);
00789 mmvar->namedstyle =
00790 (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);
00791 next_coords =
00792 (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);
00793
00794 for ( n = 0; n < mmvar->num_namedstyles; ++n )
00795 {
00796 mmvar->namedstyle[n].coords = next_coords;
00797 next_coords += mmvar->num_axis;
00798 }
00799
00800 a = mmvar->axis;
00801 next_name = (FT_String*)next_coords;
00802 for ( n = 0; n < mmvar->num_axis; ++n )
00803 {
00804 a->name = next_name;
00805
00806
00807 if ( a->tag == TTAG_wght )
00808 a->name = (char *)"Weight";
00809 else if ( a->tag == TTAG_wdth )
00810 a->name = (char *)"Width";
00811 else if ( a->tag == TTAG_opsz )
00812 a->name = (char *)"OpticalSize";
00813 else if ( a->tag == TTAG_slnt )
00814 a->name = (char *)"Slant";
00815
00816 next_name += 5;
00817 ++a;
00818 }
00819
00820 *master = mmvar;
00821 }
00822
00823 Exit:
00824 return error;
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 FT_LOCAL_DEF( FT_Error )
00851 TT_Set_MM_Blend( TT_Face face,
00852 FT_UInt num_coords,
00853 FT_Fixed* coords )
00854 {
00855 FT_Error error = TT_Err_Ok;
00856 GX_Blend blend;
00857 FT_MM_Var* mmvar;
00858 FT_UInt i;
00859 FT_Memory memory = face->root.memory;
00860
00861 enum
00862 {
00863 mcvt_retain,
00864 mcvt_modify,
00865 mcvt_load
00866
00867 } manageCvt;
00868
00869
00870 face->doblend = FALSE;
00871
00872 if ( face->blend == NULL )
00873 {
00874 if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )
00875 goto Exit;
00876 }
00877
00878 blend = face->blend;
00879 mmvar = blend->mmvar;
00880
00881 if ( num_coords != mmvar->num_axis )
00882 {
00883 error = TT_Err_Invalid_Argument;
00884 goto Exit;
00885 }
00886
00887 for ( i = 0; i < num_coords; ++i )
00888 if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
00889 {
00890 error = TT_Err_Invalid_Argument;
00891 goto Exit;
00892 }
00893
00894 if ( blend->glyphoffsets == NULL )
00895 if ( (error = ft_var_load_gvar( face )) != 0 )
00896 goto Exit;
00897
00898 if ( blend->normalizedcoords == NULL )
00899 {
00900 if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )
00901 goto Exit;
00902
00903 manageCvt = mcvt_modify;
00904
00905
00906
00907
00908 }
00909 else
00910 {
00911 manageCvt = mcvt_retain;
00912 for ( i = 0; i < num_coords; ++i )
00913 {
00914 if ( blend->normalizedcoords[i] != coords[i] )
00915 {
00916 manageCvt = mcvt_load;
00917 break;
00918 }
00919 }
00920
00921
00922
00923
00924
00925 }
00926
00927 blend->num_axis = num_coords;
00928 FT_MEM_COPY( blend->normalizedcoords,
00929 coords,
00930 num_coords * sizeof ( FT_Fixed ) );
00931
00932 face->doblend = TRUE;
00933
00934 if ( face->cvt != NULL )
00935 {
00936 switch ( manageCvt )
00937 {
00938 case mcvt_load:
00939
00940
00941 FT_FREE( face->cvt );
00942 face->cvt = NULL;
00943
00944 tt_face_load_cvt( face, face->root.stream );
00945 break;
00946
00947 case mcvt_modify:
00948
00949
00950 tt_face_vary_cvt( face, face->root.stream );
00951 break;
00952
00953 case mcvt_retain:
00954
00955 break;
00956 }
00957 }
00958
00959 Exit:
00960 return error;
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 FT_LOCAL_DEF( FT_Error )
00987 TT_Set_Var_Design( TT_Face face,
00988 FT_UInt num_coords,
00989 FT_Fixed* coords )
00990 {
00991 FT_Error error = TT_Err_Ok;
00992 FT_Fixed* normalized = NULL;
00993 GX_Blend blend;
00994 FT_MM_Var* mmvar;
00995 FT_UInt i, j;
00996 FT_Var_Axis* a;
00997 GX_AVarSegment av;
00998 FT_Memory memory = face->root.memory;
00999
01000
01001 if ( face->blend == NULL )
01002 {
01003 if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )
01004 goto Exit;
01005 }
01006
01007 blend = face->blend;
01008 mmvar = blend->mmvar;
01009
01010 if ( num_coords != mmvar->num_axis )
01011 {
01012 error = TT_Err_Invalid_Argument;
01013 goto Exit;
01014 }
01015
01016
01017
01018
01019
01020 if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
01021 goto Exit;
01022
01023 a = mmvar->axis;
01024 for ( i = 0; i < mmvar->num_axis; ++i, ++a )
01025 {
01026 if ( coords[i] > a->maximum || coords[i] < a->minimum )
01027 {
01028 error = TT_Err_Invalid_Argument;
01029 goto Exit;
01030 }
01031
01032 if ( coords[i] < a->def )
01033 {
01034 normalized[i] = -FT_MulDiv( coords[i] - a->def,
01035 0x10000L,
01036 a->minimum - a->def );
01037 }
01038 else if ( a->maximum == a->def )
01039 normalized[i] = 0;
01040 else
01041 {
01042 normalized[i] = FT_MulDiv( coords[i] - a->def,
01043 0x10000L,
01044 a->maximum - a->def );
01045 }
01046 }
01047
01048 if ( !blend->avar_checked )
01049 ft_var_load_avar( face );
01050
01051 if ( blend->avar_segment != NULL )
01052 {
01053 av = blend->avar_segment;
01054 for ( i = 0; i < mmvar->num_axis; ++i, ++av )
01055 {
01056 for ( j = 1; j < (FT_UInt)av->pairCount; ++j )
01057 if ( normalized[i] < av->correspondence[j].fromCoord )
01058 {
01059 normalized[i] =
01060 FT_MulDiv(
01061 FT_MulDiv(
01062 normalized[i] - av->correspondence[j - 1].fromCoord,
01063 0x10000L,
01064 av->correspondence[j].fromCoord -
01065 av->correspondence[j - 1].fromCoord ),
01066 av->correspondence[j].toCoord -
01067 av->correspondence[j - 1].toCoord,
01068 0x10000L ) +
01069 av->correspondence[j - 1].toCoord;
01070 break;
01071 }
01072 }
01073 }
01074
01075 error = TT_Set_MM_Blend( face, num_coords, normalized );
01076
01077 Exit:
01078 FT_FREE( normalized );
01079 return error;
01080 }
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 FT_LOCAL_DEF( FT_Error )
01114 tt_face_vary_cvt( TT_Face face,
01115 FT_Stream stream )
01116 {
01117 FT_Error error;
01118 FT_Memory memory = stream->memory;
01119 FT_ULong table_start;
01120 FT_ULong table_len;
01121 FT_UInt tupleCount;
01122 FT_ULong offsetToData;
01123 FT_ULong here;
01124 FT_UInt i, j;
01125 FT_Fixed* tuple_coords = NULL;
01126 FT_Fixed* im_start_coords = NULL;
01127 FT_Fixed* im_end_coords = NULL;
01128 GX_Blend blend = face->blend;
01129 FT_UInt point_count;
01130 FT_UShort* localpoints;
01131 FT_Short* deltas;
01132
01133
01134 FT_TRACE2(( "CVAR " ));
01135
01136 if ( blend == NULL )
01137 {
01138 FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
01139
01140 error = TT_Err_Ok;
01141 goto Exit;
01142 }
01143
01144 if ( face->cvt == NULL )
01145 {
01146 FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
01147
01148 error = TT_Err_Ok;
01149 goto Exit;
01150 }
01151
01152 error = face->goto_table( face, TTAG_cvar, stream, &table_len );
01153 if ( error )
01154 {
01155 FT_TRACE2(( "is missing\n" ));
01156
01157 error = TT_Err_Ok;
01158 goto Exit;
01159 }
01160
01161 if ( FT_FRAME_ENTER( table_len ) )
01162 {
01163 error = TT_Err_Ok;
01164 goto Exit;
01165 }
01166
01167 table_start = FT_Stream_FTell( stream );
01168 if ( FT_GET_LONG() != 0x00010000L )
01169 {
01170 FT_TRACE2(( "bad table version\n" ));
01171
01172 error = TT_Err_Ok;
01173 goto FExit;
01174 }
01175
01176 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
01177 FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
01178 FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
01179 goto FExit;
01180
01181 tupleCount = FT_GET_USHORT();
01182 offsetToData = table_start + FT_GET_USHORT();
01183
01184
01185
01186
01187
01188 for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
01189 {
01190 FT_UInt tupleDataSize;
01191 FT_UInt tupleIndex;
01192 FT_Fixed apply;
01193
01194
01195 tupleDataSize = FT_GET_USHORT();
01196 tupleIndex = FT_GET_USHORT();
01197
01198
01199
01200
01201 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
01202 {
01203 for ( j = 0; j < blend->num_axis; ++j )
01204 tuple_coords[j] = FT_GET_SHORT() << 2;
01205
01206 }
01207 else
01208 {
01209
01210
01211 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
01212 for ( j = 0; j < 2 * blend->num_axis; ++j )
01213 (void)FT_GET_SHORT();
01214
01215 offsetToData += tupleDataSize;
01216 continue;
01217 }
01218
01219 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
01220 {
01221 for ( j = 0; j < blend->num_axis; ++j )
01222 im_start_coords[j] = FT_GET_SHORT() << 2;
01223 for ( j = 0; j < blend->num_axis; ++j )
01224 im_end_coords[j] = FT_GET_SHORT() << 2;
01225 }
01226
01227 apply = ft_var_apply_tuple( blend,
01228 (FT_UShort)tupleIndex,
01229 tuple_coords,
01230 im_start_coords,
01231 im_end_coords );
01232 if (
01233 apply == 0 ||
01234
01235
01236 !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
01237 {
01238 offsetToData += tupleDataSize;
01239 continue;
01240 }
01241
01242 here = FT_Stream_FTell( stream );
01243
01244 FT_Stream_SeekSet( stream, offsetToData );
01245
01246 localpoints = ft_var_readpackedpoints( stream, &point_count );
01247 deltas = ft_var_readpackeddeltas( stream,
01248 point_count == 0 ? face->cvt_size
01249 : point_count );
01250 if ( localpoints == NULL || deltas == NULL )
01251 ;
01252
01253 else if ( localpoints == ALL_POINTS )
01254 {
01255
01256 for ( j = 0; j < face->cvt_size; ++j )
01257 face->cvt[j] = (FT_Short)( face->cvt[j] +
01258 FT_MulFix( deltas[j], apply ) );
01259 }
01260
01261 else
01262 {
01263 for ( j = 0; j < point_count; ++j )
01264 {
01265 int pindex = localpoints[j];
01266
01267 face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
01268 FT_MulFix( deltas[j], apply ) );
01269 }
01270 }
01271
01272 if ( localpoints != ALL_POINTS )
01273 FT_FREE( localpoints );
01274 FT_FREE( deltas );
01275
01276 offsetToData += tupleDataSize;
01277
01278 FT_Stream_SeekSet( stream, here );
01279 }
01280
01281 FExit:
01282 FT_FRAME_EXIT();
01283
01284 Exit:
01285 FT_FREE( tuple_coords );
01286 FT_FREE( im_start_coords );
01287 FT_FREE( im_end_coords );
01288
01289 return error;
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315 FT_LOCAL_DEF( FT_Error )
01316 TT_Vary_Get_Glyph_Deltas( TT_Face face,
01317 FT_UInt glyph_index,
01318 FT_Vector* *deltas,
01319 FT_UInt n_points )
01320 {
01321 FT_Stream stream = face->root.stream;
01322 FT_Memory memory = stream->memory;
01323 GX_Blend blend = face->blend;
01324 FT_Vector* delta_xy;
01325
01326 FT_Error error;
01327 FT_ULong glyph_start;
01328 FT_UInt tupleCount;
01329 FT_ULong offsetToData;
01330 FT_ULong here;
01331 FT_UInt i, j;
01332 FT_Fixed* tuple_coords = NULL;
01333 FT_Fixed* im_start_coords = NULL;
01334 FT_Fixed* im_end_coords = NULL;
01335 FT_UInt point_count, spoint_count = 0;
01336 FT_UShort* sharedpoints = NULL;
01337 FT_UShort* localpoints = NULL;
01338 FT_UShort* points;
01339 FT_Short *deltas_x, *deltas_y;
01340
01341
01342 if ( !face->doblend || blend == NULL )
01343 return TT_Err_Invalid_Argument;
01344
01345
01346 if ( FT_NEW_ARRAY( delta_xy, n_points ) )
01347 goto Exit;
01348 *deltas = delta_xy;
01349
01350 if ( glyph_index >= blend->gv_glyphcnt ||
01351 blend->glyphoffsets[glyph_index] ==
01352 blend->glyphoffsets[glyph_index + 1] )
01353 return TT_Err_Ok;
01354
01355 if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
01356 FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
01357 blend->glyphoffsets[glyph_index] ) )
01358 goto Fail1;
01359
01360 glyph_start = FT_Stream_FTell( stream );
01361
01362
01363
01364
01365 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
01366 FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
01367 FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
01368 goto Fail2;
01369
01370 tupleCount = FT_GET_USHORT();
01371 offsetToData = glyph_start + FT_GET_USHORT();
01372
01373 if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
01374 {
01375 here = FT_Stream_FTell( stream );
01376
01377 FT_Stream_SeekSet( stream, offsetToData );
01378
01379 sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
01380 offsetToData = FT_Stream_FTell( stream );
01381
01382 FT_Stream_SeekSet( stream, here );
01383 }
01384
01385 for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
01386 {
01387 FT_UInt tupleDataSize;
01388 FT_UInt tupleIndex;
01389 FT_Fixed apply;
01390
01391
01392 tupleDataSize = FT_GET_USHORT();
01393 tupleIndex = FT_GET_USHORT();
01394
01395 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
01396 {
01397 for ( j = 0; j < blend->num_axis; ++j )
01398 tuple_coords[j] = FT_GET_SHORT() << 2;
01399
01400 }
01401 else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
01402 {
01403 error = TT_Err_Invalid_Table;
01404 goto Fail3;
01405 }
01406 else
01407 {
01408 FT_MEM_COPY(
01409 tuple_coords,
01410 &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
01411 blend->num_axis * sizeof ( FT_Fixed ) );
01412 }
01413
01414 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
01415 {
01416 for ( j = 0; j < blend->num_axis; ++j )
01417 im_start_coords[j] = FT_GET_SHORT() << 2;
01418 for ( j = 0; j < blend->num_axis; ++j )
01419 im_end_coords[j] = FT_GET_SHORT() << 2;
01420 }
01421
01422 apply = ft_var_apply_tuple( blend,
01423 (FT_UShort)tupleIndex,
01424 tuple_coords,
01425 im_start_coords,
01426 im_end_coords );
01427
01428 if ( apply == 0 )
01429 {
01430 offsetToData += tupleDataSize;
01431 continue;
01432 }
01433
01434 here = FT_Stream_FTell( stream );
01435
01436 if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
01437 {
01438 FT_Stream_SeekSet( stream, offsetToData );
01439
01440 localpoints = ft_var_readpackedpoints( stream, &point_count );
01441 points = localpoints;
01442 }
01443 else
01444 {
01445 points = sharedpoints;
01446 point_count = spoint_count;
01447 }
01448
01449 deltas_x = ft_var_readpackeddeltas( stream,
01450 point_count == 0 ? n_points
01451 : point_count );
01452 deltas_y = ft_var_readpackeddeltas( stream,
01453 point_count == 0 ? n_points
01454 : point_count );
01455
01456 if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
01457 ;
01458
01459 else if ( points == ALL_POINTS )
01460 {
01461
01462 for ( j = 0; j < n_points; ++j )
01463 {
01464 delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
01465 delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
01466 }
01467 }
01468
01469 else
01470 {
01471 for ( j = 0; j < point_count; ++j )
01472 {
01473 delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
01474 delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
01475 }
01476 }
01477
01478 if ( localpoints != ALL_POINTS )
01479 FT_FREE( localpoints );
01480 FT_FREE( deltas_x );
01481 FT_FREE( deltas_y );
01482
01483 offsetToData += tupleDataSize;
01484
01485 FT_Stream_SeekSet( stream, here );
01486 }
01487
01488 Fail3:
01489 FT_FREE( tuple_coords );
01490 FT_FREE( im_start_coords );
01491 FT_FREE( im_end_coords );
01492
01493 Fail2:
01494 FT_FRAME_EXIT();
01495
01496 Fail1:
01497 if ( error )
01498 {
01499 FT_FREE( delta_xy );
01500 *deltas = NULL;
01501 }
01502
01503 Exit:
01504 return error;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516 FT_LOCAL_DEF( void )
01517 tt_done_blend( FT_Memory memory,
01518 GX_Blend blend )
01519 {
01520 if ( blend != NULL )
01521 {
01522 FT_UInt i;
01523
01524
01525 FT_FREE( blend->normalizedcoords );
01526 FT_FREE( blend->mmvar );
01527
01528 if ( blend->avar_segment != NULL )
01529 {
01530 for ( i = 0; i < blend->num_axis; ++i )
01531 FT_FREE( blend->avar_segment[i].correspondence );
01532 FT_FREE( blend->avar_segment );
01533 }
01534
01535 FT_FREE( blend->tuplecoords );
01536 FT_FREE( blend->glyphoffsets );
01537 FT_FREE( blend );
01538 }
01539 }
01540
01541 #endif
01542
01543
01544