sys7.1-doc-wip/Toolbox/FontMgr/sfnt.c
2019-07-27 22:37:48 +08:00

839 lines
24 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
File: sfnt.c
Contains: xxx put contents here (or delete the whole line) xxx
Written by: xxx put name of writer here (or delete the whole line) xxx
Copyright: © 1989-1991 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<9> 11/22/91 JH Fix for bug found by Ops/Tech in Japan. In sfnt_ReadSFNTMetrics
the calculation for the LeftSideBearingOffset was doing
(glyphIndex-1) it should be (glyphIndex). The subtraction is
unnecessary.
<8> 10/22/91 RB Add support for sfnt-embedded-bitmaps
<7> 9/25/91 jlf Rolled in modifications from Pacific TrueType project:
sfnt_getglyphlocation and sfnt_readsfntmetrics no longer load
the location and horizontal metrics tables into memory. A single
location or horizontal metric table entry is read instead.
NumberOfBytesTaken is initialized to two instead of one in
sfnt_computemapping. Corrected numberofBytes problem in
sfnt_computeindex2. Moved sfnt_PackedSplineFormat into
sfnt.h.
<6> 12/18/90 RB Move ReleaseSfntFrag into block where table is defined. [mr]
<5> 12/11/90 MR Support platform==-1 meaning this sfnt has no cmap, don't return
an error.
<4> 11/16/90 MR Fix bogus call to SWAPW in ReadSfnt for instructions after
components. [rb]
<3> 11/5/90 MR Remove mac include files, clean up release macros. [rb]
<2> 10/20/90 MR Removed unused tables in sfnt_Classify. [rb]
<17> 8/10/90 MR Pass nil for textLength parameter to MapString2, checked in
other files to their precious little system will BUILD. Talk
about touchy!
<16> 8/10/90 gbm rolling out Mikes textLength change, because he hasnt checked
in all the relevant files, and the build is BROKEN!
<15> 8/10/90 MR Add textLength arg to MapString2
<14> 7/26/90 MR dont include ToolUtils.h
<13> 7/23/90 MR Change computeindex routines to call functins in MapString.c
<12> 7/18/90 MR Add SWAPW macro for INTEL
<11> 7/13/90 MR Lots of Ansi-C stuff, change behavior of ComputeMapping to take
platform and script
<9> 6/27/90 MR Changes for modified format 4: range is now times two, loose pad
word between first two arrays. Eric Mader
<8> 6/21/90 MR Add calls to ReleaseSfntFrag
<7> 6/5/90 MR remove vector mapping functions
<6> 6/4/90 MR Remove MVT
<5> 5/3/90 RB simplified decryption.
<4> 4/10/90 CL Fixed mapping table routines for double byte codes.
<3> 3/20/90 CL Joe found bug in mappingtable format 6 Added vector mapping
functions use pointer-loops in sfnt_UnfoldCurve, changed z from
int32 to int16
<2> 2/27/90 CL New error code for missing but needed table. (0x1409 ) New
CharToIndexMap Table format.
Assume subtablenumber zero for old sfnt format. Fixed
transformed component bug.
<3.2> 11/14/89 CEL Left Side Bearing should work right for any transformation. The
phantom points are in, even for components in a composite glyph.
They should also work for transformations. Device metric are
passed out in the output data structure. This should also work
with transformations. Another leftsidebearing along the advance
width vector is also passed out. whatever the metrics are for
the component at it's level. Instructions are legal in
components. Instructions are legal in components. Glyph-length 0
bug in sfnt.c is fixed. Now it is legal to pass in zero as the
address of memory when a piece of the sfnt is requested by the
scaler. If this happens the scaler will simply exit with an
error code ! Fixed bug with instructions in components.
<3.1> 9/27/89 CEL Removed phantom points.
<3.0> 8/28/89 sjk Cleanup and one transformation bugfix
<2.2> 8/14/89 sjk 1 point contours now OK
<2.1> 8/8/89 sjk Improved encryption handling
<2.0> 8/2/89 sjk Just fixed EASE comment
<1.5> 8/1/89 sjk Added composites and encryption. Plus some enhancements…
<1.4> 6/13/89 SJK Comment
<1.3> 6/2/89 CEL 16.16 scaling of metrics, minimum recommended ppem, point size 0
bug, correct transformed integralized ppem behavior, pretty much
so
<1.2> 5/26/89 CEL EASE messed up on “c” comments
<•1.1> 5/26/89 CEL Integrated the new Font Scaler 1.0 into Spline Fonts
<1.0> 5/25/89 CEL Integrated 1.0 Font scaler into Bass code for the first time…
To Do:
*/
#define BYTEREAD
#include "setjmp.h"
/** FontScalers Includes **/
#include "FSError.h"
#include "FSCdefs.h"
#include "FontMath.h"
#include "sfnt.h"
#include "fnt.h"
#include "sc.h"
#include "FontScaler.h"
#include "FSglue.h"
#include "privateSFNT.h"
#include "MapString.h"
#if TheFuture /* <8 > EBITMAP */
#include "embeddedBitmap.h"
#endif
#define GetUnsignedByte( p ) ((uint8)(*p++))
/** <4> **/
#define fsg_MxCopy(a, b) (*(b) = *(a))
/* PRIVATE PROTOTYES */
int sfnt_UnfoldCurve(fsg_SplineKey *key, sfnt_PackedSplineFormat *charData, int32 *sizeOfInstructions, uint8 **instructionPtr, int32 length, int16 *elementCount);
void sfnt_Classify(fsg_SplineKey *key, sfnt_TableTag tag, int16 index);
void* sfnt_GetDataPtr(fsg_SplineKey *key, int32 offset, int32 length, sfnt_tableIndex n, boolean mustHaveTable);
uint16 sfnt_ComputeUnkownIndex(fsg_SplineKey *key, uint16 charCode);
uint16 sfnt_ComputeIndex0(fsg_SplineKey *key, uint16 charCode);
uint16 sfnt_ComputeIndex2(fsg_SplineKey *key, uint16 charCode);
uint16 sfnt_ComputeIndex4(fsg_SplineKey *key, uint16 charCode);
uint16 sfnt_ComputeIndex6(fsg_SplineKey *key, uint16 charCode);
void sfnt_GetGlyphLocation( fsg_SplineKey* key, uint16 gIndex, int32* offset, int32* length );
#ifdef SEGMENT_LINK
#pragma segment SFNT_C
#endif
/*
*
* sfnt_UnfoldCurve <3>
*
* ERROR: return NON-ZERO
*
*/
static int sfnt_UnfoldCurve( fsg_SplineKey* key,
sfnt_PackedSplineFormat* charData,
int32* sizeOfInstructions,
uint8** instructionPtr,
int32 length,
int16* elementCount )
{
register int z;
register uint8 flag, *byteP, *byteP2;
register int8 *p;
register F26Dot6* longP;
fnt_ElementType *elementPtr;
int numPoints;
elementPtr = &(key->elementInfoRec.interpreterElements[GLYPHELEMENT]);
if ( *elementCount == GLYPHELEMENT ) {
key->totalContours = 0;
fsg_SetUpElement( key, GLYPHELEMENT );
} else {
/* # of points in previous component */
fsg_IncrementElement( key, GLYPHELEMENT, key->numberOfRealPointsInComponent, elementPtr->nc );
}
key->totalComponents = *elementCount;
(*elementCount)++;
key->glyphLength = length;
if ( length <= 0 ) {
elementPtr->nc = 1;
key->totalContours += 1;
elementPtr->sp[0] = 0;
elementPtr->ep[0] = 0;
*sizeOfInstructions = 0;
elementPtr->onCurve[0] = ONCURVE;
elementPtr->oox[0] = 0;
elementPtr->ooy[0] = 0;
return NO_ERR; /***************** exit here ! *****************/
}
elementPtr->nc = charData->numberContours;
z = (int)elementPtr->nc;
key->totalContours += z;
if ( z < 0 || z > (int)key->maxProfile.maxContours )
return CONTOUR_DATA_ERR;
{ /* <4> */
register int16* sp = elementPtr->sp;
register int16* ep = elementPtr->ep;
int16* charDataEP = charData->endPoints;
register LoopCount i;
*sp++ = 0;
*ep = SWAPWINC(charDataEP);
for (i = z - 2; i >= 0; --i)
{
*sp++ = *ep++ + 1;
*ep = SWAPWINC(charDataEP);
}
}
numPoints = elementPtr->ep[elementPtr->nc - 1] + 1;
key->numberOfRealPointsInComponent = (uint16)numPoints;
if (numPoints < 0 || numPoints > (int)key->maxProfile.maxPoints)
return POINTS_DATA_ERR;
*sizeOfInstructions = charData->numberInstructions;
z = (int)charData->numberInstructions;
if ( z < 0 || z > (int)key->maxProfile.maxSizeOfInstructions )
return INSTRUCTION_SIZE_ERR;
*instructionPtr = charData->instructions;
/* Do flags */
p = (int8*)charData->flags;
byteP = elementPtr->onCurve;
byteP2 = byteP + numPoints; /* only need to set this guy once */
while (byteP < byteP2)
{
*byteP++ = flag = GetUnsignedByte( p );
if ( flag & REPEAT_FLAGS ) {
LoopCount count = GetUnsignedByte( p );
for (--count; count >= 0; --count)
*byteP++ = flag;
}
}
/* Do X first */
z = 0;
byteP = elementPtr->onCurve;
longP = elementPtr->oox;
while (byteP < byteP2)
{
if ( (flag = *byteP++) & XSHORT ) {
if ( flag & SHORT_X_IS_POS )
z += GetUnsignedByte( p );
else
z -= GetUnsignedByte( p );
} else if ( !(flag & NEXT_X_IS_ZERO) ) { /* This means we have a int32 (2 byte) vector */
#ifdef BYTEREAD
z += (int16)(*p++) << 8;
z += (uint8)*p++;
#else
z += *((int16 *)p); p += sizeof( int16 );
#endif
}
*longP++ = (F26Dot6)z;
}
/* Now Do Y */
z = 0;
byteP = elementPtr->onCurve;
longP = elementPtr->ooy;
while (byteP < byteP2)
{
if ( (flag = *byteP) & YSHORT ) {
if ( flag & SHORT_Y_IS_POS )
z += GetUnsignedByte( p );
else
z -= GetUnsignedByte( p );
} else if ( !(flag & NEXT_Y_IS_ZERO) ) { /* This means we have a int32 (2 byte) vector */
#ifdef BYTEREAD
z += (int16)(*p++) << 8;
z += (uint8)*p++;
#else
z += *((int16 *)p); p += sizeof( int16 );
#endif
}
*longP++ = (F26Dot6)z;
*byteP++ = flag & (uint8)ONCURVE; /* Filter out unwanted stuff */
}
if ( !(key->compFlags & NON_OVERLAPPING) ) {
elementPtr->onCurve[0] |= OVERLAP;
}
return NO_ERR;
}
/*
* Internal routine (make this an array and do a look up?)
*/
static void sfnt_Classify( register fsg_SplineKey *key,
register sfnt_TableTag tag,
int16 index )
{
switch ( tag ) {
case tag_FontHeader:
key->offsetTableMap[sfnt_fontHeader] = index;
break;
case tag_HoriHeader:
key->offsetTableMap[sfnt_horiHeader] = index;
break;
case tag_IndexToLoc:
key->offsetTableMap[sfnt_indexToLoc] = index;
break;
case tag_MaxProfile:
key->offsetTableMap[sfnt_maxProfile] = index;
break;
case tag_ControlValue:
key->offsetTableMap[sfnt_controlValue] = index;
break;
case tag_PreProgram:
key->offsetTableMap[sfnt_preProgram] = index;
break;
case tag_GlyphData:
key->offsetTableMap[sfnt_glyphData] = index;
break;
case tag_HorizontalMetrics:
key->offsetTableMap[sfnt_horizontalMetrics] = index;
break;
case tag_CharToIndexMap:
key->offsetTableMap[sfnt_charToIndexMap] = index;
break;
case tag_FontProgram:
key->offsetTableMap[sfnt_fontProgram] = index; /* <4> */
break;
#if TheFuture /* <8 > EBITMAP */
case tag_BitmapLocation:
key->offsetTableMap[sfnt_bitmapLocation] = index;
break;
case tag_BitmapData:
key->offsetTableMap[sfnt_bitmapData] = index;
break;
#endif
}
}
/*
* Creates mapping for finding offset table <4>
*/
void sfnt_DoOffsetTableMap( register fsg_SplineKey *key )
{
register int16 i;
{
register int16* table = key->offsetTableMap;
for ( i = sfnt_NUMTABLEINDEX-1; i >= 0; --i )
*table++ = -1; /* Initialize */
}
{
uint16 last = SWAPW(key->sfntDirectory->numOffsets) - 1;
register sfnt_DirectoryEntry* dir = &key->sfntDirectory->table[last];
for ( i = last; i >= 0; --i )
{
sfnt_Classify( key, dir->tag, i );
--dir;
}
}
}
/*
* Returns offset and length for table n <4>
*/
void sfnt_GetOffsetAndLength( register fsg_SplineKey *key,
int32 *offsetT,
unsigned *lengthT,
register sfnt_tableIndex n)
{
register ArrayIndex tableNumber = key->offsetTableMap[n];
if ( tableNumber >= 0 )
{
sfnt_DirectoryEntry* dir = &key->sfntDirectory->table[tableNumber];
*lengthT = (unsigned)dir->length;
*offsetT = dir->offset;
} else {
*lengthT = 0; *offsetT = 0; /* missing table */
}
}
/*
* Use this when the whole table is neded.
*
* n is the table number.
*/
void* sfnt_GetTablePtr( register fsg_SplineKey *key,
register sfnt_tableIndex n,
register boolean mustHaveTable )
{
return sfnt_GetDataPtr( key, 0, -1L, n, mustHaveTable ); /* 0, -1 means give me whole table */
}
/*
* Use this function when only part of the table is needed.
*
* n is the table number.
* offset is within table.
* length is length of data needed.
* To get an entire table, pass length = -1 <4>
*/
static void* sfnt_GetDataPtr( register fsg_SplineKey *key,
register int32 offset,
register int32 length,
register sfnt_tableIndex n,
register boolean mustHaveTable )
{
int32 offsetT;
unsigned lengthT;
void* fragment;
sfnt_GetOffsetAndLength( key, &offsetT, &lengthT, n );
if ( lengthT ) {
if (length == -1) length = lengthT;
offset += offsetT;
fragment = key->GetSfntFragmentPtr( key->clientID, offset, length );
if ( fragment ) {
return fragment;
} else {
longjmp( key->env, CLIENT_RETURNED_NULL ); /* Do a gracefull recovery */
}
} else {
if ( mustHaveTable )
longjmp( key->env, MISSING_SFNT_TABLE ); /* Do a gracefull recovery */
else
return 0;
}
}
/*
* This, is when we don't know what is going on
*/
static uint16 sfnt_ComputeUnkownIndex( fsg_SplineKey* key, uint16 charCode)
{
#pragma unused(key, charCode)
return 0;
}
/*
* Byte Table Mapping 256->256 <4>
*/
static uint16 sfnt_ComputeIndex0( register fsg_SplineKey *key,
register uint16 charCode)
{
if (charCode & ~(255)) return 0;
{
uint8 *mappingPtr = (uint8*)sfnt_GetTablePtr( key, sfnt_charToIndexMap, true );
register uint8* mapping = mappingPtr;
uint16 glyph;
mapping += key->mappOffset; /* Point at mapping table offset. */
glyph = mapping[charCode];
RELEASESFNTFRAG(key, mappingPtr);
return glyph;
}
}
/*
* High byte mapping through table
*
* Useful for the national standards for Japanese, Chinese, and Korean characters.
*
* Dedicated in spirit and logic to Mark Davis and the International group.
*
* Algorithm: (I think)
* First byte indexes into KeyOffset table. If the offset is 0, keep going, else use second byte.
* That offset is from beginning of data into subHeader, which has 4 words per entry.
* entry, extent, delta, range
*
*/
uint16 sfnt_ComputeIndex2( fsg_SplineKey* key, uint16 charCode )
{
void* mappingPtr = sfnt_GetTablePtr( key, sfnt_charToIndexMap, true );
uint8* mapping = (uint8*)mappingPtr;
uint16 index;
long numberOfBytes = 2;
mapping += key->mappOffset; /* Point at mapping table offset. */
MapString2((uint16*)mapping, (uint8*)&charCode, (int16*)&index, 1, &numberOfBytes);
key->numberOfBytesTaken = numberOfBytes;
RELEASESFNTFRAG(key, mappingPtr);
return index;
}
/*
* Segment mapping to delta values, Yack.. !
*
* In memory of Peter Edberg. Initial code taken from code example supplied by Peter.
*/
uint16 sfnt_ComputeIndex4( fsg_SplineKey *key, uint16 charCode)
{
void* mappingPtr = sfnt_GetTablePtr( key, sfnt_charToIndexMap, true );
uint8* mapping = (uint8*)mappingPtr;
uint16 index;
mapping += key->mappOffset; /* Point at mapping table offset. */
MapString4_16((uint16*)mapping, &charCode, (int16*)&index, 1);
RELEASESFNTFRAG(key, mappingPtr);
return index;
}
/*
* Trimmed Table Mapping
*/
uint16 sfnt_ComputeIndex6( fsg_SplineKey* key, uint16 charCode )
{
void* mappingPtr = sfnt_GetTablePtr( key, sfnt_charToIndexMap, true );
uint8* mapping = (uint8*)mappingPtr;
uint16 index;
mapping += key->mappOffset; /* Point at mapping table offset. */
MapString6_16((uint16*)mapping, &charCode, (int16*)&index, 1);
RELEASESFNTFRAG(key, mappingPtr);
return index;
}
/*
* Sets up our mapping function pointer.
*/
int sfnt_ComputeMapping(register fsg_SplineKey *key, uint16 platformID, uint16 specificID)
{
int result = NO_ERR;
key->numberOfBytesTaken = 1; /* Initialize */
if (platformID == 0xffff)
key->mappingF = sfnt_ComputeUnkownIndex;
else
{
sfnt_char2IndexDirectory *table= (sfnt_char2IndexDirectory*)sfnt_GetTablePtr( key, sfnt_charToIndexMap, true );
uint8 *mapping = (uint8 *)table;
register uint16 format = -1;
register int16 i;
int16 found = false;
if ( table->version == 0 )
{
register sfnt_platformEntry* plat = table->platform; /* <4> */
for ( i = SWAPW(table->numTables)-1; i >= 0; --i )
{
if ( SWAPW(plat->platformID) == platformID && SWAPW(plat->specificID) == specificID)
{
found = true;
key->mappOffset = SWAPL(plat->offset) + 6; /* skip header */
break;
}
++plat;
}
}
if ( !found )
{
key->mappingF = sfnt_ComputeUnkownIndex;
result = OUT_OF_RANGE_SUBTABLE;
}
else
{
mapping += key->mappOffset - 6; /* back up for header */
format = *(uint16 *)mapping;
switch ( format ) {
case 0:
key->mappingF = sfnt_ComputeIndex0;
break;
case 2:
key->mappingF = sfnt_ComputeIndex2;
break;
case 4:
key->mappingF = sfnt_ComputeIndex4;
break;
case 6:
key->mappingF = sfnt_ComputeIndex6;
break;
default:
key->mappingF = sfnt_ComputeUnkownIndex;
result = UNKNOWN_CMAP_FORMAT;
break;
}
}
RELEASESFNTFRAG(key, table);
}
return result;
}
/*
*
*/
void sfnt_ReadSFNTMetrics( fsg_SplineKey* key,
register uint16 glyphIndex )
{
register uint16 numberOf_LongHorMetrics = key->numberOf_LongHorMetrics;
if ( glyphIndex < numberOf_LongHorMetrics ) {
register sfnt_HorizontalMetrics *glyphHorizontalMetricsPointer;
glyphHorizontalMetricsPointer = (sfnt_HorizontalMetrics*) sfnt_GetDataPtr( key, glyphIndex * sizeof( sfnt_HorizontalMetrics ),
sizeof( sfnt_HorizontalMetrics ),
sfnt_horizontalMetrics, true );
if ( glyphHorizontalMetricsPointer ) {
key->nonScaledAW = SWAPW(glyphHorizontalMetricsPointer->advanceWidth);
key->nonScaledLSB = SWAPW(glyphHorizontalMetricsPointer->leftSideBearing);
RELEASESFNTFRAG( key, glyphHorizontalMetricsPointer );
}
} else {
uint32 lastGlyphHorizontalMetricsOffset;
register sfnt_HorizontalMetrics *lastGlyphHorizontalMetricsPointer;
lastGlyphHorizontalMetricsOffset = (numberOf_LongHorMetrics - 1) * sizeof( sfnt_HorizontalMetrics );
lastGlyphHorizontalMetricsPointer = (sfnt_HorizontalMetrics*) sfnt_GetDataPtr( key, lastGlyphHorizontalMetricsOffset,
sizeof( sfnt_HorizontalMetrics ),
sfnt_horizontalMetrics, true );
if ( lastGlyphHorizontalMetricsPointer ) {
int32 glyphLeftSideBearingOffset;
int16 *glyphLeftSideBearingPointer;
glyphLeftSideBearingOffset = lastGlyphHorizontalMetricsOffset + sizeof( sfnt_HorizontalMetrics ) +
((glyphIndex - numberOf_LongHorMetrics) * sizeof( int16 )); /* <9> <JH, 11-22-91> change (glyphIndex -1) to glyphIndex */
glyphLeftSideBearingPointer = (int16*) sfnt_GetDataPtr( key, glyphLeftSideBearingOffset, sizeof( int16 ),
sfnt_horizontalMetrics, true );
if ( glyphLeftSideBearingPointer ) {
key->nonScaledLSB = SWAPW(*glyphLeftSideBearingPointer);
key->nonScaledAW = SWAPW(lastGlyphHorizontalMetricsPointer->advanceWidth);
RELEASESFNTFRAG( key, glyphLeftSideBearingPointer );
}
RELEASESFNTFRAG( key, lastGlyphHorizontalMetricsPointer );
}
}
}
void sfnt_GetGlyphLocation( fsg_SplineKey* key, uint16 gIndex, int32* offset, int32* length )
{
sfnt_FontHeader* fontHead = (sfnt_FontHeader*)sfnt_GetTablePtr( key, sfnt_fontHeader, true );
if ( fontHead->indexToLocFormat == SHORT_INDEX_TO_LOC_FORMAT )
{
register uint16* shortIndexToLoc = (uint16*) sfnt_GetDataPtr( key, gIndex * sizeof( uint16 ), 2 * sizeof( uint16 ), sfnt_indexToLoc, true );
if ( shortIndexToLoc ) {
*offset = (int32)*shortIndexToLoc++ << 1;
*length = ((int32)*shortIndexToLoc << 1) - *offset;
RELEASESFNTFRAG( key, shortIndexToLoc );
}
}
else
{
register uint32* longIndexToLoc = (uint32*) sfnt_GetDataPtr( key, gIndex * sizeof( uint32 ), 2 * sizeof( uint32 ), sfnt_indexToLoc, true );
if ( longIndexToLoc ) {
*offset = *longIndexToLoc++;
*length = *longIndexToLoc - *offset;
RELEASESFNTFRAG( key, longIndexToLoc );
}
}
RELEASESFNTFRAG(key, fontHead);
}
/*
* <4>
*/
int sfnt_ReadSFNT( register fsg_SplineKey *key,
int16 *elementCount,
register uint16 gIndex,
boolean useHints,
voidFunc traceFunc)
{
int32 sizeOfInstructions;
uint8* instructionPtr;
int32 length, offset;
int result = NO_ERR;
int16* shortP;
void* glyphDataPtr = 0; /* to signal ReleaseSfntFrag if we never asked for it */
sfnt_PackedSplineFormat charData;
sfnt_ReadSFNTMetrics( key, gIndex );
sfnt_GetGlyphLocation( key, gIndex, &offset, &length );
if ( length > 0 )
{
glyphDataPtr = sfnt_GetDataPtr( key, offset, length, sfnt_glyphData, true );
shortP = (int16*)glyphDataPtr;
charData.numberContours = SWAPWINC(shortP);
charData.bbox.xMin = SWAPWINC(shortP);
charData.bbox.yMin = SWAPWINC(shortP);
charData.bbox.xMax = SWAPWINC(shortP);
charData.bbox.yMax = SWAPWINC(shortP);
}
else
charData.numberContours = 1;
if ( charData.numberContours >= 0 ) /* Not a component glyph */
{
key->lastGlyph = !( key->weGotComponents && (key->compFlags & MORE_COMPONENTS) );
if ( length > 0 )
{
charData.endPoints = shortP;
shortP += charData.numberContours;
charData.numberInstructions = SWAPWINC(shortP);
charData.instructions = (uint8*)shortP;
charData.flags = (uint8*)shortP + charData.numberInstructions;
}
if ( result = sfnt_UnfoldCurve( key, &charData, &sizeOfInstructions, &instructionPtr, length, elementCount ))
goto EXIT;
if ( result = fsg_InnerGridFit( key, useHints, traceFunc, &charData.bbox, sizeOfInstructions, instructionPtr, false ) )
goto EXIT;
}
else if ( key->weGotComponents = (charData.numberContours == -1) )
{
uint16 flags;
boolean transformTrashed = false;
do {
transMatrix ctmSaveT, localSaveT;
uint16 glyphIndex;
int16 arg1, arg2;
flags = (uint16)SWAPWINC(shortP);
glyphIndex = (uint16)SWAPWINC(shortP);
if ( flags & ARG_1_AND_2_ARE_WORDS ) {
arg1 = SWAPWINC(shortP);
arg2 = SWAPWINC(shortP);
} else {
int8* byteP = (int8*)shortP;
if ( flags & ARGS_ARE_XY_VALUES ) {
/* offsets are signed */
arg1 = *byteP++;
arg2 = *byteP;
} else {
/* anchor points are unsigned */
arg1 = (uint8)*byteP++;
arg2 = (uint8)*byteP;
}
++shortP;
}
if ( flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO) )
{
fsg_MxCopy( &key->currentTMatrix, &ctmSaveT );
fsg_MxCopy( &key->localTMatrix, &localSaveT );
transformTrashed = true;
if ( flags & WE_HAVE_A_TWO_BY_TWO )
{
register Fixed multiplier;
transMatrix mulT;
multiplier = SWAPWINC(shortP); /* read 2.14 */
mulT.transform[0][0] = (multiplier << 2); /* turn into 16.16 */
multiplier = SWAPWINC(shortP); /* read 2.14 */
mulT.transform[0][1] = (multiplier << 2); /* turn into 16.16 */
multiplier = SWAPWINC(shortP); /* read 2.14 */
mulT.transform[1][0] = (multiplier << 2); /* turn into 16.16 */
multiplier = SWAPWINC(shortP); /* read 2.14 */
mulT.transform[1][1] = (multiplier << 2); /* turn into 16.16 */
fsg_MxConcat2x2( &mulT, &key->currentTMatrix );
fsg_MxConcat2x2( &mulT, &key->localTMatrix );
}
else
{
Fixed xScale, yScale;
if ( flags & WE_HAVE_AN_X_AND_Y_SCALE )
{
xScale = (Fixed)SWAPWINC(shortP); /* read 2.14 */
xScale <<= 2; /* turn into 16.16 */
yScale = (Fixed)SWAPWINC(shortP); /* read 2.14 */
yScale <<= 2; /* turn into 16.16 */
} else {
xScale = (Fixed)SWAPWINC(shortP); /* read 2.14 */
xScale <<= 2; /* turn into 16.16 */
yScale = xScale;
}
fsg_MxScaleAB( xScale, yScale, &key->currentTMatrix );
fsg_MxScaleAB( xScale, yScale, &key->localTMatrix );
}
fsg_InitInterpreterTrans( key ); /*** Compute global stretch etc. ***/
key->localTIsIdentity = false;
}
key->compFlags = flags;
key->arg1 = arg1;
key->arg2 = arg2;
result = sfnt_ReadSFNT( key, elementCount, glyphIndex, useHints, traceFunc );
if ( transformTrashed )
{
fsg_MxCopy( &ctmSaveT, &key->currentTMatrix );
fsg_InitInterpreterTrans( key ); /** Restore global stretch etc. ***/
fsg_MxCopy( &localSaveT, &key->localTMatrix );
transformTrashed = false;
}
} while ( flags & MORE_COMPONENTS && result == NO_ERR );
/* Do Final Composite Pass */
sfnt_ReadSFNTMetrics( key, gIndex ); /* read metrics again */
if ( flags & WE_HAVE_INSTRUCTIONS ) {
sizeOfInstructions = (uint16)SWAPW(*shortP);
instructionPtr = (uint8*)(++shortP);
} else {
sizeOfInstructions = 0;
instructionPtr = 0;
}
if ( result = fsg_InnerGridFit( key, useHints, traceFunc, &charData.bbox, sizeOfInstructions, instructionPtr, true ) )
goto EXIT;
}
else
result = UNKNOWN_COMPOSITE_VERSION;
EXIT:
SOFTRELEASESFNTFRAG(key, glyphDataPtr);
return result;
}