mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-12-01 18:50:30 +00:00
839 lines
24 KiB
C
839 lines
24 KiB
C
|
/*
|
|||
|
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 Mike’s textLength change, because he hasn’t 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 don’t 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"
|
|||
|
|
|||
|
/** FontScaler’s 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;
|
|||
|
}
|