... |
... |
@@ -457,7 +457,8 @@ |
457
|
457
|
FT_UShort format;
|
458
|
458
|
FT_ULong region_offset;
|
459
|
459
|
FT_UInt i, j, k;
|
460
|
|
- FT_UInt shortDeltaCount;
|
|
460
|
+ FT_UInt wordDeltaCount;
|
|
461
|
+ FT_Bool long_words;
|
461
|
462
|
|
462
|
463
|
GX_Blend blend = face->blend;
|
463
|
464
|
GX_ItemVarData varData;
|
... |
... |
@@ -572,15 +573,18 @@ |
572
|
573
|
goto Exit;
|
573
|
574
|
|
574
|
575
|
if ( FT_READ_USHORT( varData->itemCount ) ||
|
575
|
|
- FT_READ_USHORT( shortDeltaCount ) ||
|
|
576
|
+ FT_READ_USHORT( wordDeltaCount ) ||
|
576
|
577
|
FT_READ_USHORT( varData->regionIdxCount ) )
|
577
|
578
|
goto Exit;
|
578
|
579
|
|
|
580
|
+ long_words = !!( wordDeltaCount & 0x8000 );
|
|
581
|
+ wordDeltaCount &= 0x7FFF;
|
|
582
|
+
|
579
|
583
|
/* check some data consistency */
|
580
|
|
- if ( shortDeltaCount > varData->regionIdxCount )
|
|
584
|
+ if ( wordDeltaCount > varData->regionIdxCount )
|
581
|
585
|
{
|
582
|
586
|
FT_TRACE2(( "bad short count %d or region count %d\n",
|
583
|
|
- shortDeltaCount,
|
|
587
|
+ wordDeltaCount,
|
584
|
588
|
varData->regionIdxCount ));
|
585
|
589
|
error = FT_THROW( Invalid_Table );
|
586
|
590
|
goto Exit;
|
... |
... |
@@ -616,39 +620,52 @@ |
616
|
620
|
|
617
|
621
|
/* Parse delta set. */
|
618
|
622
|
/* */
|
619
|
|
- /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes */
|
620
|
|
- /* each; on output, deltas are expanded to `regionIdxCount' shorts */
|
621
|
|
- /* each. */
|
|
623
|
+ /* On input, deltas are (wordDeltaCount + regionIdxCount) bytes */
|
|
624
|
+ /* each if `long_words` isn't set, and twice as much otherwise. */
|
|
625
|
+ /* */
|
|
626
|
+ /* On output, deltas are expanded to `regionIdxCount` shorts each. */
|
622
|
627
|
if ( FT_NEW_ARRAY( varData->deltaSet,
|
623
|
628
|
varData->regionIdxCount * varData->itemCount ) )
|
624
|
629
|
goto Exit;
|
625
|
630
|
|
626
|
|
- /* the delta set is stored as a 2-dimensional array of shorts; */
|
627
|
|
- /* sign-extend signed bytes to signed shorts */
|
628
|
|
- for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
|
|
631
|
+ /* the delta set is stored as a 2-dimensional array of shorts */
|
|
632
|
+ if ( long_words )
|
|
633
|
+ {
|
|
634
|
+ /* new in OpenType 1.9, currently for 'COLR' table only; */
|
|
635
|
+ /* the deltas are interpreted as 16.16 fixed-point scaling values */
|
|
636
|
+
|
|
637
|
+ /* not supported yet */
|
|
638
|
+
|
|
639
|
+ error = FT_THROW( Invalid_Table );
|
|
640
|
+ goto Exit;
|
|
641
|
+ }
|
|
642
|
+ else
|
629
|
643
|
{
|
630
|
|
- for ( k = 0; k < shortDeltaCount; k++, j++ )
|
|
644
|
+ for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
|
631
|
645
|
{
|
632
|
|
- /* read the short deltas */
|
633
|
|
- FT_Short delta;
|
|
646
|
+ for ( k = 0; k < wordDeltaCount; k++, j++ )
|
|
647
|
+ {
|
|
648
|
+ /* read the short deltas */
|
|
649
|
+ FT_Short delta;
|
634
|
650
|
|
635
|
651
|
|
636
|
|
- if ( FT_READ_SHORT( delta ) )
|
637
|
|
- goto Exit;
|
|
652
|
+ if ( FT_READ_SHORT( delta ) )
|
|
653
|
+ goto Exit;
|
638
|
654
|
|
639
|
|
- varData->deltaSet[j] = delta;
|
640
|
|
- }
|
|
655
|
+ varData->deltaSet[j] = delta;
|
|
656
|
+ }
|
641
|
657
|
|
642
|
|
- for ( ; k < varData->regionIdxCount; k++, j++ )
|
643
|
|
- {
|
644
|
|
- /* read the (signed) byte deltas */
|
645
|
|
- FT_Char delta;
|
|
658
|
+ for ( ; k < varData->regionIdxCount; k++, j++ )
|
|
659
|
+ {
|
|
660
|
+ /* read the (signed) byte deltas */
|
|
661
|
+ FT_Char delta;
|
646
|
662
|
|
647
|
663
|
|
648
|
|
- if ( FT_READ_CHAR( delta ) )
|
649
|
|
- goto Exit;
|
|
664
|
+ if ( FT_READ_CHAR( delta ) )
|
|
665
|
+ goto Exit;
|
650
|
666
|
|
651
|
|
- varData->deltaSet[j] = delta;
|
|
667
|
+ varData->deltaSet[j] = delta;
|
|
668
|
+ }
|
652
|
669
|
}
|
653
|
670
|
}
|
654
|
671
|
}
|
... |
... |
@@ -664,37 +681,66 @@ |
664
|
681
|
ft_var_load_delta_set_index_mapping( TT_Face face,
|
665
|
682
|
FT_ULong offset,
|
666
|
683
|
GX_DeltaSetIdxMap map,
|
667
|
|
- GX_ItemVarStore itemStore )
|
|
684
|
+ GX_ItemVarStore itemStore,
|
|
685
|
+ FT_ULong table_len )
|
668
|
686
|
{
|
669
|
687
|
FT_Stream stream = FT_FACE_STREAM( face );
|
670
|
688
|
FT_Memory memory = stream->memory;
|
671
|
689
|
|
672
|
|
- FT_Error error;
|
|
690
|
+ FT_Error error;
|
673
|
691
|
|
674
|
|
- FT_UShort format;
|
675
|
|
- FT_UInt entrySize;
|
676
|
|
- FT_UInt innerBitCount;
|
677
|
|
- FT_UInt innerIndexMask;
|
678
|
|
- FT_UInt i, j;
|
|
692
|
+ FT_Byte format;
|
|
693
|
+ FT_Byte entryFormat;
|
|
694
|
+ FT_UInt entrySize;
|
|
695
|
+ FT_UInt innerBitCount;
|
|
696
|
+ FT_UInt innerIndexMask;
|
|
697
|
+ FT_ULong i;
|
|
698
|
+ FT_UInt j;
|
679
|
699
|
|
680
|
700
|
|
681
|
|
- if ( FT_STREAM_SEEK( offset ) ||
|
682
|
|
- FT_READ_USHORT( format ) ||
|
683
|
|
- FT_READ_USHORT( map->mapCount ) )
|
|
701
|
+ if ( FT_STREAM_SEEK( offset ) ||
|
|
702
|
+ FT_READ_BYTE( format ) ||
|
|
703
|
+ FT_READ_BYTE( entryFormat ) )
|
684
|
704
|
goto Exit;
|
685
|
705
|
|
686
|
|
- if ( format & 0xFFC0 )
|
|
706
|
+ if ( format == 0 )
|
|
707
|
+ {
|
|
708
|
+ if ( FT_READ_USHORT( map->mapCount ) )
|
|
709
|
+ goto Exit;
|
|
710
|
+ }
|
|
711
|
+ else if ( format == 1 ) /* new in OpenType 1.9 */
|
|
712
|
+ {
|
|
713
|
+ if ( FT_READ_ULONG( map->mapCount ) )
|
|
714
|
+ goto Exit;
|
|
715
|
+ }
|
|
716
|
+ else
|
687
|
717
|
{
|
688
|
718
|
FT_TRACE2(( "bad map format %d\n", format ));
|
689
|
719
|
error = FT_THROW( Invalid_Table );
|
690
|
720
|
goto Exit;
|
691
|
721
|
}
|
692
|
722
|
|
|
723
|
+ if ( entryFormat & 0xC0 )
|
|
724
|
+ {
|
|
725
|
+ FT_TRACE2(( "bad entry format %d\n", format ));
|
|
726
|
+ error = FT_THROW( Invalid_Table );
|
|
727
|
+ goto Exit;
|
|
728
|
+ }
|
|
729
|
+
|
693
|
730
|
/* bytes per entry: 1, 2, 3, or 4 */
|
694
|
|
- entrySize = ( ( format & 0x0030 ) >> 4 ) + 1;
|
695
|
|
- innerBitCount = ( format & 0x000F ) + 1;
|
|
731
|
+ entrySize = ( ( entryFormat & 0x30 ) >> 4 ) + 1;
|
|
732
|
+ innerBitCount = ( entryFormat & 0x0F ) + 1;
|
696
|
733
|
innerIndexMask = ( 1 << innerBitCount ) - 1;
|
697
|
734
|
|
|
735
|
+ /* rough sanity check */
|
|
736
|
+ if ( map->mapCount * entrySize > table_len )
|
|
737
|
+ {
|
|
738
|
+ FT_TRACE1(( "ft_var_load_delta_set_index_mapping:"
|
|
739
|
+ " invalid number of delta-set index mappings\n" ));
|
|
740
|
+ error = FT_THROW( Invalid_Table );
|
|
741
|
+ goto Exit;
|
|
742
|
+ }
|
|
743
|
+
|
698
|
744
|
if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) )
|
699
|
745
|
goto Exit;
|
700
|
746
|
|
... |
... |
@@ -723,7 +769,7 @@ |
723
|
769
|
|
724
|
770
|
if ( outerIndex >= itemStore->dataCount )
|
725
|
771
|
{
|
726
|
|
- FT_TRACE2(( "outerIndex[%d] == %d out of range\n",
|
|
772
|
+ FT_TRACE2(( "outerIndex[%ld] == %d out of range\n",
|
727
|
773
|
i,
|
728
|
774
|
outerIndex ));
|
729
|
775
|
error = FT_THROW( Invalid_Table );
|
... |
... |
@@ -736,7 +782,7 @@ |
736
|
782
|
|
737
|
783
|
if ( innerIndex >= itemStore->varData[outerIndex].itemCount )
|
738
|
784
|
{
|
739
|
|
- FT_TRACE2(( "innerIndex[%d] == %d out of range\n",
|
|
785
|
+ FT_TRACE2(( "innerIndex[%ld] == %d out of range\n",
|
740
|
786
|
i,
|
741
|
787
|
innerIndex ));
|
742
|
788
|
error = FT_THROW( Invalid_Table );
|
... |
... |
@@ -861,7 +907,8 @@ |
861
|
907
|
face,
|
862
|
908
|
table_offset + widthMap_offset,
|
863
|
909
|
&table->widthMap,
|
864
|
|
- &table->itemStore );
|
|
910
|
+ &table->itemStore,
|
|
911
|
+ table_len );
|
865
|
912
|
if ( error )
|
866
|
913
|
goto Exit;
|
867
|
914
|
}
|