Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2879 lines
83 KiB

/*
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: (c) 1987-1990, 1992 by Apple Computer, Inc., all rights reserved.
(c) 1989-1993. Microsoft Corporation, all rights reserved.
Change History (most recent first):
<17+> 10/9/90 MR,rb Remove classification of unused tables in sfnt_Classify
<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 toolutil.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
<y1.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:
<3+> 3/20/90 mrr Fixed mapping table routines for double byte codes.
Added support for font program.
Changed count from uint16 to int16 in vector char2index routines.
*/
// added by bodind, speed optimization
#include "nt.h"
#include "ntrtl.h"
/** FontScaler's Includes **/
#include "fserror.h"
#include "fscdefs.h"
#include "sfntaccs.h"
#include "sfntoff.h"
/*#include "MapString.h" */
#include "stat.h" /* STAT timing card prototypes */
/* CONSTANTS */
#define MISSING_GLYPH_INDEX 0
#define MAX_FORMAT0_CHAR_INDEX 256
#define MAX_LINEAR_X2 16
static const transMatrix IdentTransform =
{{{ONEFIX, 0, 0},
{ 0, ONEFIX, 0},
{ 0, 0, ONEFIX}}};
/* MACROS */
#define GETSFNTFRAG(ClientInfo,lOffset,lLength) (ClientInfo)->GetSfntFragmentPtr((int32)ClientInfo->lClientID, lOffset, lLength)
#define RELEASESFNTFRAG(ClientInfo,data) (ClientInfo)->ReleaseSfntFrag((voidPtr)data)
#define SFAC_BINARYITERATION \
newP = (uint16 *) ((char *)tableP + (usSearchRange >>= 1)); \
if (charCode > (uint16) SWAPW (*newP)) tableP = newP;
#define SFAC_GETUNSIGNEDBYTEINC( p ) ((uint8)(*p++))
/* PRIVATE PROTOTYES */
FS_PRIVATE void sfac_Classify (
sfac_OffsetLength * TableDirectory,
uint8 * dir);
uint16 FS_ENTRY_PROTO sfac_ComputeUnkownIndex (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo);
uint16 FS_ENTRY_PROTO sfac_ComputeIndex0 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo);
uint16 FS_ENTRY_PROTO sfac_ComputeIndex2 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo);
uint16 FS_ENTRY_PROTO sfac_ComputeIndex4 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo);
uint16 FS_ENTRY_PROTO sfac_ComputeIndex6 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo);
FS_PRIVATE ErrorCode sfac_GetGlyphLocation (
sfac_ClientRec * ClientInfo,
uint16 gIndex,
uint32 * ulOffset,
uint32 * ulLength,
sfnt_tableIndex* pGlyphTableIndex);
FS_PRIVATE ErrorCode sfac_GetDataPtr (
sfac_ClientRec * ClientInfo,
uint32 ulOffset,
uint32 ulLength,
sfnt_tableIndex TableRef,
boolean bMustHaveTable,
const void * * ppvTablePtr);
FS_PRIVATE ErrorCode sfac_GetGlyphIDs (
MappingFunc pfnGlyphMapping, /* mapping func char to glyph */
const uint8 * mapOffsetPtr, /* cmap subtable past header */
sfac_ClientRec * ClientInfo, /* Sfnt Client information */
uint16 usCharCount, /* Number of chars to convert */
uint16 usCharCode, /* First char code */
uint16 * pusCharCode, /* or Pointer to char code list */
uint16 * pusGlyphID); /* Output glyph ID array */
FS_PRIVATE void sfac_ComputeBinarySearchParams(
uint16 usSegCount, /* INPUT */
uint16 * pusSearchRange, /* OUTPUT */
uint16 * pusEntrySelector, /* OUTPUT */
uint16 * pusRangeShift); /* OUTPUT */
/*
* Internal routine (make this an array and do a look up?)
*/
FS_PRIVATE void sfac_Classify (
sfac_OffsetLength * TableDirectory,
uint8 * dir)
{
int32 Index;
switch ((uint32)SWAPL(*((sfnt_TableTag *)&dir[SFNT_DIRECTORYENTRY_TAG])))
{
case tag_FontHeader:
Index = (int32)sfnt_fontHeader;
break;
case tag_HoriHeader:
Index = (int32)sfnt_horiHeader;
break;
case tag_IndexToLoc:
Index = (int32)sfnt_indexToLoc;
break;
case tag_MaxProfile:
Index = (int32)sfnt_maxProfile;
break;
case tag_ControlValue:
Index = (int32)sfnt_controlValue;
break;
case tag_PreProgram:
Index = (int32)sfnt_preProgram;
break;
case tag_GlyphData:
Index = (int32)sfnt_glyphData;
break;
case tag_HorizontalMetrics:
Index = (int32)sfnt_horizontalMetrics;
break;
case tag_CharToIndexMap:
Index = (int32)sfnt_charToIndexMap;
break;
case tag_FontProgram:
Index = (int32)sfnt_fontProgram; /* <4> */
break;
case tag_GlyphDirectory: /* Used for GlyphDirectory Download */
Index = (int32)sfnt_GlyphDirectory;
break;
case tag_HoriDeviceMetrics:
Index = (int32)sfnt_HoriDeviceMetrics;
break;
case tag_LinearThreshold:
Index = (int32)sfnt_LinearThreshold;
break;
case tag_BitmapData:
Index = (int32)sfnt_BitmapData;
break;
case tag_BitmapLocation:
Index = (int32)sfnt_BitmapLocation;
break;
case tag_BitmapScale:
Index = (int32)sfnt_BitmapScale;
break;
case tag_VertHeader:
Index = (int32)sfnt_vertHeader;
break;
case tag_VerticalMetrics:
Index = (int32)sfnt_verticalMetrics;
break;
default:
Index = -1;
break;
}
if (Index >= 0)
{
TableDirectory[Index].ulOffset = (uint32) SWAPL (*((uint32 *)&dir[SFNT_DIRECTORYENTRY_TABLEOFFSET]));
TableDirectory[Index].ulLength = (uint32) SWAPL (*((uint32 *)&dir[SFNT_DIRECTORYENTRY_TABLELENGTH]));
}
}
/*
* Creates mapping for finding offset table <4>
*/
FS_PUBLIC ErrorCode sfac_DoOffsetTableMap (
sfac_ClientRec * ClientInfo) /* Sfnt Client information */
{
int32 i;
uint8 * sfntDirectory;
int32 cTables;
uint8 * dir;
STAT_OFF_CALLBACK; /* pause STAT timer */
sfntDirectory = (uint8 *) GETSFNTFRAG (ClientInfo, 0L, (int32)SIZEOF_SFNT_OFFSETTABLE);
STAT_ON_CALLBACK; /* restart STAT timer */
if (sfntDirectory != NULL)
{
cTables = (int32) SWAPW (*((uint16 *)&sfntDirectory[SFNT_OFFSETTABLE_NUMOFFSETS]));
RELEASESFNTFRAG(ClientInfo, sfntDirectory);
STAT_OFF_CALLBACK; /* pause STAT timer */
sfntDirectory = (uint8 *) GETSFNTFRAG (
ClientInfo,
0L,
((int32)SIZEOF_SFNT_OFFSETTABLE + (int32)SIZEOF_SFNT_DIRECTORYENTRY * (int32)(cTables)));
STAT_ON_CALLBACK; /* restart STAT timer */
}
else
{
return(NULL_SFNT_DIR_ERR);
}
/* Initialize */
MEMSET (ClientInfo->TableDirectory, 0, sizeof (ClientInfo->TableDirectory));
dir = &sfntDirectory[SFNT_OFFSETTABLE_TABLE];
for (i = 0; i < cTables; i++)
{
sfac_Classify (ClientInfo->TableDirectory, dir);
dir += SIZEOF_SFNT_DIRECTORYENTRY;
}
/* Used when glyphs are accessed from the base of memory */
ClientInfo->TableDirectory[(int32)sfnt_BeginningOfFont].ulOffset = 0U;
ClientInfo->TableDirectory[(int32)sfnt_BeginningOfFont].ulLength = ~0U;
RELEASESFNTFRAG(ClientInfo, sfntDirectory);
return NO_ERR;
}
/*
* 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 = ULONG_MAX <4>
*/
FS_PRIVATE ErrorCode sfac_GetDataPtr (
sfac_ClientRec * ClientInfo,
uint32 ulOffset,
uint32 ulLength,
sfnt_tableIndex TableRef,
boolean bMustHaveTable,
const void ** ppvTablePtr)
{
uint32 ulTableLength;
ulTableLength = SFAC_LENGTH(ClientInfo, TableRef);
if (ulTableLength > 0)
{
if(ulLength == ULONG_MAX)
{
ulLength = ulTableLength;
}
STAT_OFF_CALLBACK; /* pause STAT timer */
*ppvTablePtr = (void *)GETSFNTFRAG (
ClientInfo,
(int32)(ulOffset + ClientInfo->TableDirectory[(int32)TableRef].ulOffset),
(int32)ulLength);
STAT_ON_CALLBACK; /* restart STAT timer */
if (*ppvTablePtr == NULL)
{
return CLIENT_RETURNED_NULL; /* Do a gracefull recovery */
}
}
else
{
*ppvTablePtr = (void *)NULL;
if (bMustHaveTable)
{
return MISSING_SFNT_TABLE; /* Do a gracefull recovery */
}
}
return NO_ERR;
}
/*
* This, is when we don't know what is going on
*/
uint16 FS_ENTRY_PROTO sfac_ComputeUnkownIndex (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo)
{
FS_UNUSED_PARAMETER(mapping);
FS_UNUSED_PARAMETER(charCode);
FS_UNUSED_PARAMETER(ClientInfo);
return MISSING_GLYPH_INDEX;
}
/*
* Byte Table Mapping 256->256 <4>
*/
uint16 FS_ENTRY_PROTO sfac_ComputeIndex0 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo)
{
FS_UNUSED_PARAMETER(ClientInfo);
if (charCode < MAX_FORMAT0_CHAR_INDEX)
{
return (uint16)mapping[charCode];
}
else
{
return MISSING_GLYPH_INDEX;
}
}
/*
* 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 FS_ENTRY_PROTO sfac_ComputeIndex2 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo)
{
uint16 usIndex;
uint16 usMapMe;
uint16 usHighByte;
uint16 usGlyph;
const uint8 * Table2;
const uint8 * subHeader;
FS_UNUSED_PARAMETER(ClientInfo);
Table2 = (const uint8 *) mapping;
usHighByte = (uint16)(charCode >> 8);
if (((uint16 *)&Table2[SFNT_MAPPINGTABLE2_SUBHEADERSKEYS]) [usHighByte])
{
usMapMe = (uint16)(charCode & 0xFF); /* We also need the low byte. */
}
else
{
#ifdef FSCFG_MICROSOFT_KK
if(usHighByte != 0)
{
usMapMe = usHighByte;
}
else
{
usMapMe = (uint16)(charCode & 0xFF);
}
#else
usMapMe = usHighByte;
#endif
}
subHeader = (const uint8 *) ((char *)&Table2[SFNT_MAPPINGTABLE2_SUBHEADERS] +
(uint16)SWAPW (((uint16 *)&Table2[SFNT_MAPPINGTABLE2_SUBHEADERSKEYS]) [usHighByte]));
usMapMe -= (uint16)SWAPW (*((uint16 *)&subHeader[SFNT_SUBHEADER2_FIRSTCODE])); /* Subtract first code. */
if (usMapMe < (uint16)SWAPW (*((uint16 *)&subHeader[SFNT_SUBHEADER2_ENTRYCOUNT])))
{ /* See if within range. */
usGlyph = (uint16)(* ((uint16 *) ((char *) &subHeader[SFNT_SUBHEADER2_IDRANGEOFFSET] +
(uint16)SWAPW (*((uint16 *)&subHeader[SFNT_SUBHEADER2_IDRANGEOFFSET]))) + usMapMe));
if (usGlyph != 0) /* Note: usGlyph has not been swapped yet */
{
usIndex = (uint16)((int32)(uint32)(uint16)SWAPW(usGlyph) + (int32)SWAPW (*((int16 *)&subHeader[SFNT_SUBHEADER2_IDDELTA])));
}
else
{
usIndex = MISSING_GLYPH_INDEX;
}
}
else
{
usIndex = MISSING_GLYPH_INDEX;
}
return usIndex;
}
/*
* Segment mapping to delta values, Yack.. !
*
* In memory of Peter Edberg. Initial code taken from code example supplied by Peter.
*/
uint16 FS_ENTRY_PROTO sfac_ComputeIndex4 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo)
{
const uint16 * tableP;
const uint8 * Table4;
uint16 usIdDelta;
uint16 usOffset;
uint16 usIndex;
uint16 usSegCountX2;
uint16 usSearchRange;
uint16 usEntrySelector;
uint16 usRangeShift;
const uint16 * newP; /* temporary pointer for binary iteration */
uint16 usStartCount;
Table4 = (const uint8 *)mapping;
usSegCountX2 = (uint16) SWAPW(*((uint16 *)&Table4[SFNT_MAPPINGTABLE4_SEGCOUNTX2]));
tableP = (const uint16 *)&Table4[SFNT_MAPPINGTABLE4_ENDCOUNT];
/* If there are just a few segments, skip straight to the linear search */
if (usSegCountX2 >= MAX_LINEAR_X2 && charCode > 0xFF)
{
/* start with unrolled binary search */
/* tableP points at endCount[] */
if( ClientInfo == NULL )
{
sfac_ComputeBinarySearchParams(
(uint16)(usSegCountX2 / 2),
&usSearchRange,
&usEntrySelector,
&usRangeShift);
}
else
{
usSearchRange = ClientInfo->usFormat4SearchRange;
/* Assert(SWAPW(*((uint16 *)&Table4[SFNT_MAPPINGTABLE4_RANGESHIFT])) == ClientInfo->usFormat4RangeShift); */
usRangeShift = ClientInfo->usFormat4RangeShift;
/* Assert((uint16)SWAPW(*((uint16 *)&Table4[SFNT_MAPPINGTABLE4_ENTRYSELECTOR])) == ClientInfo->usFormat4EntrySelector); */
usEntrySelector = ClientInfo->usFormat4EntrySelector;
}
if (charCode >= (uint16) SWAPW (* ((uint16 *) ((char *)tableP + usSearchRange))))
{
tableP = (uint16 *) ((char *)tableP + usRangeShift); /* range to low shift it up */
}
switch( usEntrySelector )
{
case 15:
SFAC_BINARYITERATION;
/* fall through */
case 14:
SFAC_BINARYITERATION;
/* fall through */
case 13:
SFAC_BINARYITERATION;
/* fall through */
case 12:
SFAC_BINARYITERATION;
/* fall through */
case 11:
SFAC_BINARYITERATION;
/* fall through */
case 10:
SFAC_BINARYITERATION;
/* fall through */
case 9:
SFAC_BINARYITERATION;
/* fall through */
case 8:
SFAC_BINARYITERATION;
/* fall through */
case 7:
SFAC_BINARYITERATION;
/* fall through */
case 6:
SFAC_BINARYITERATION;
/* fall through */
case 5:
SFAC_BINARYITERATION;
/* fall through */
case 4:
SFAC_BINARYITERATION;
/* fall through */
case 3:
case 2: /* drop through */
case 1:
case 0:
break;
default:
Assert(FALSE);
break;
}
}
/* Now do linear search */
while(charCode > (uint16) SWAPW(*tableP))
{
tableP++;
}
tableP++; /* Skip Past reservedPad word */
/* End of search, now do mapping */
tableP = (uint16 *) ((char *)tableP + usSegCountX2); /* point at startCount[] */
usStartCount = (uint16) SWAPW (*tableP);
if (charCode >= usStartCount)
{
usOffset = (uint16)(charCode - (uint16) SWAPW (*tableP));
tableP = (uint16 *) ((char *)tableP + usSegCountX2); /* point to idDelta[] */
usIdDelta = (uint16) SWAPW (*tableP);
tableP = (uint16 *) ((char *)tableP + usSegCountX2); /* point to idRangeOffset[] */
if ((uint16) SWAPW (*tableP) == 0)
{
usIndex = (uint16)(charCode + usIdDelta);
}
else
{
/* Use glyphIdArray to access index */
usOffset += usOffset; /* make word offset */
tableP = (uint16 *) ((char *)tableP + (uint16) SWAPW (*tableP) + usOffset); /* point to glyphIndexArray[] */
if((uint16)SWAPW (*tableP) != MISSING_GLYPH_INDEX)
{
usIndex = (uint16)((uint16) SWAPW (*tableP) + usIdDelta);
}
else
{
usIndex = MISSING_GLYPH_INDEX;
}
}
}
else
{
usIndex = MISSING_GLYPH_INDEX;
}
return usIndex;
}
/*
* Trimmed Table Mapping
*/
uint16 FS_ENTRY_PROTO sfac_ComputeIndex6 (const uint8 * mapping, uint16 charCode, sfac_ClientRec * ClientInfo)
{
const uint8 *Table6;
FS_UNUSED_PARAMETER(ClientInfo);
Table6 = (const uint8 *) mapping;
charCode -= (uint16)SWAPW (*((uint16 *)&Table6[SFNT_MAPPINGTABLE6_FIRSTCODE]));
if (charCode < (uint16) SWAPW (*((uint16 *)&Table6[SFNT_MAPPINGTABLE6_ENTRYCOUNT])))
{
return ((uint16) SWAPW (((uint16 *)&Table6[SFNT_MAPPINGTABLE6_GLYPHIDARRAY]) [charCode]));
}
else
{
return MISSING_GLYPH_INDEX;
}
}
/*
* Sets up our mapping function pointer.
*/
FS_PUBLIC ErrorCode sfac_ComputeMapping (
sfac_ClientRec * ClientInfo,
uint16 usPlatformID,
uint16 usSpecificID)
{
const uint8 * table;
const uint8 * MappingTable;
const uint8 * Table4;
boolean bFound;
ErrorCode Ret;
const uint8 * plat;
uint16 usSegCountX2;
bFound = FALSE;
/* APPLE Code
if(usPlatformID == 0xFFFF)
{
ClientInfo->GlyphMappingF = sfac_ComputeUnkownIndex;
return NO_ERR;
}
*/
Ret = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_charToIndexMap, FALSE, (const void **)&table);
if(Ret != NO_ERR)
{
return Ret;
}
if (table == NULL)
{
/* If no "cmap" is present, permits access to characters by glyph index */
ClientInfo->GlyphMappingF = sfac_ComputeUnkownIndex;
return NO_ERR;
}
/* APPLE Code
if(*((uint16 *)&table[SFNT_CHAR2INDEXDIRECTORY_VERSION]) != 0)
{
ClientInfo->GlyphMappingF = sfac_ComputeUnkownIndex;
RELEASESFNTFRAG(ClientInfo, table);
return OUT_OF_RANGE_SUBTABLE;
}
*/
/* mapping */
plat = (uint8 *) &table[SFNT_CHAR2INDEXDIRECTORY_PLATFORM]; /* <4> */
while(plat < (uint8 *)&table[SFNT_CHAR2INDEXDIRECTORY_PLATFORM + ((uint16)SWAPW(*((uint16 *)&table[SFNT_CHAR2INDEXDIRECTORY_NUMTABLES])) *
SIZEOF_SFNT_PLATFORMENTRY)] && !bFound)
{
if (((uint16)SWAPW(*((uint16 *)&plat[SFNT_PLATFORMENTRY_PLATFORMID])) == usPlatformID) &&
((uint16)SWAPW(*((uint16 *)&plat[SFNT_PLATFORMENTRY_SPECIFICID])) == usSpecificID))
{
bFound = TRUE;
ClientInfo->ulMapOffset = (uint32) SWAPL (*((uint32 *)&plat[SFNT_PLATFORMENTRY_PLATFORMOFFSET])); /* skip header */
}
plat += SIZEOF_SFNT_PLATFORMENTRY;
}
if (!bFound)
{
ClientInfo->ulMapOffset = 0;
ClientInfo->GlyphMappingF = sfac_ComputeUnkownIndex;
RELEASESFNTFRAG(ClientInfo, table);
return OUT_OF_RANGE_SUBTABLE;
}
else
{
Assert(Ret == NO_ERR);
MappingTable = (uint8 *)((uint8 *)table + ClientInfo->ulMapOffset); /* back up for header */
ClientInfo->ulMapOffset += (uint32)SIZEOF_SFNT_MAPPINGTABLE;
}
ClientInfo->usMappingFormat = (uint16)SWAPW (*((uint16 *)&MappingTable[SFNT_MAPPINGTABLE_FORMAT]));
switch (ClientInfo->usMappingFormat)
{
case 0:
ClientInfo->GlyphMappingF = sfac_ComputeIndex0;
break;
case 2:
ClientInfo->GlyphMappingF = sfac_ComputeIndex2;
break;
case 4:
ClientInfo->GlyphMappingF = sfac_ComputeIndex4;
/* Pre-compute several values used for Index 4 lookups */
/* This becomes necessary because of several font vendors who */
/* have placed incorrect values in the TrueType font file. */
Table4 = (uint8 *)((uint8 *)table + ClientInfo->ulMapOffset);
usSegCountX2 = (uint16) SWAPW(*((uint16 *)&Table4[SFNT_MAPPINGTABLE4_SEGCOUNTX2]));
sfac_ComputeBinarySearchParams(
(uint16)(usSegCountX2 / 2),
&ClientInfo->usFormat4SearchRange,
&ClientInfo->usFormat4EntrySelector,
&ClientInfo->usFormat4RangeShift);
break;
case 6:
ClientInfo->GlyphMappingF = sfac_ComputeIndex6;
break;
default:
ClientInfo->GlyphMappingF = sfac_ComputeUnkownIndex;
Ret = UNKNOWN_CMAP_FORMAT;
break;
}
RELEASESFNTFRAG(ClientInfo, table);
return Ret;
}
FS_PRIVATE void sfac_ComputeBinarySearchParams(
uint16 usSegCount, /* INPUT */
uint16 * pusSearchRange, /* OUTPUT */
uint16 * pusEntrySelector, /* OUTPUT */
uint16 * pusRangeShift) /* OUTPUT */
{
uint16 usLog;
uint16 usPowerOf2;
usLog = 0;
usPowerOf2 = 1;
while((2 * usPowerOf2) <= usSegCount )
{
usPowerOf2 *= 2;
usLog++;
}
*pusSearchRange = 2 * usPowerOf2;
*pusEntrySelector = usLog;
*pusRangeShift = (2 * usSegCount) - (2 * usPowerOf2);
}
FS_PUBLIC ErrorCode sfac_GetGlyphIndex(
sfac_ClientRec * ClientInfo,
uint16 usCharacterCode)
{
const uint8 * mappingPtr;
ErrorCode error;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_charToIndexMap, TRUE, (const void **)&mappingPtr);
if(error != NO_ERR)
{
return error;
}
ClientInfo->usGlyphIndex = ClientInfo->GlyphMappingF (mappingPtr + ClientInfo->ulMapOffset, usCharacterCode, ClientInfo);
RELEASESFNTFRAG(ClientInfo, mappingPtr);
return NO_ERR;
}
/* return glyph ID's for a range or for an array of character codes */
FS_PUBLIC ErrorCode sfac_GetMultiGlyphIDs (
sfac_ClientRec * ClientInfo, /* Sfnt Client information */
uint16 usCharCount, /* Number of chars to convert */
uint16 usFirstChar, /* First char code */
uint16 * pusCharCode, /* or Pointer to char code list */
uint16 * pusGlyphID) /* Output glyph ID array */
{
const uint8 * mappingPtr;
const uint8 * mapOffsetPtr;
ErrorCode errCode;
if ((ClientInfo->usMappingFormat != 0) &&
(ClientInfo->usMappingFormat != 2) &&
(ClientInfo->usMappingFormat != 4) &&
(ClientInfo->usMappingFormat != 6))
{
return UNKNOWN_CMAP_FORMAT;
}
errCode = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_charToIndexMap, TRUE, (const void **)&mappingPtr);
if(errCode != NO_ERR)
{
return errCode;
}
mapOffsetPtr = mappingPtr + ClientInfo->ulMapOffset;
errCode = sfac_GetGlyphIDs (
ClientInfo->GlyphMappingF,
mapOffsetPtr,
ClientInfo,
usCharCount,
usFirstChar,
pusCharCode,
pusGlyphID);
RELEASESFNTFRAG(ClientInfo, mappingPtr);
return errCode;
}
/* special version for Win95 doesn't require a font context */
FS_PUBLIC ErrorCode sfac_GetWin95GlyphIDs (
uint8 * pbyCmapSubTable, /* Pointer to cmap sub table */
uint16 usCharCount, /* Number of chars to convert */
uint16 usFirstChar, /* First char code */
uint16 * pusCharCode, /* or Pointer to char code list */
uint16 * pusGlyphID) /* Output glyph ID array */
{
uint16 usMappingFormat; /* cmap subtable format code */
MappingFunc pfnGlyphMapping; /* mapping func char to glyph */
const uint8 * pbyCmapData; /* past subtable header */
ErrorCode errCode;
usMappingFormat = (uint16)SWAPW (*((uint16 *)&pbyCmapSubTable[SFNT_MAPPINGTABLE_FORMAT]));
switch (usMappingFormat)
{
case 0:
pfnGlyphMapping = sfac_ComputeIndex0;
break;
case 2:
pfnGlyphMapping = sfac_ComputeIndex2;
break;
case 4:
pfnGlyphMapping = sfac_ComputeIndex4;
break;
case 6:
pfnGlyphMapping = sfac_ComputeIndex6;
break;
default:
return UNKNOWN_CMAP_FORMAT;
}
pbyCmapData = pbyCmapSubTable + SIZEOF_SFNT_MAPPINGTABLE;
errCode = sfac_GetGlyphIDs (
pfnGlyphMapping,
pbyCmapData,
NULL, /* ClientInfo */
usCharCount,
usFirstChar,
pusCharCode,
pusGlyphID );
return errCode;
}
/* common code for the two get glyph ID helper routines */
FS_PRIVATE ErrorCode sfac_GetGlyphIDs (
MappingFunc pfnGlyphMapping, /* mapping func char to glyph */
const uint8 * mapOffsetPtr, /* cmap subtable past header */
sfac_ClientRec * ClientInfo, /* May be NULL! */
uint16 usCharCount, /* Number of chars to convert */
uint16 usCharCode, /* First char code */
uint16 * pusCharCode, /* or Pointer to char code list */
uint16 * pusGlyphID) /* Output glyph ID array */
{
if (pusCharCode == NULL) /* Null pointer implies character code range */
{
if (((uint32)usCharCode + (uint32)usCharCount) > 0x0000FFFFL)
{
return INVALID_CHARCODE_ERR; /* trap an illegal range */
}
while (usCharCount > 0)
{
*pusGlyphID = pfnGlyphMapping (mapOffsetPtr, usCharCode, ClientInfo);
pusGlyphID++;
usCharCode++; /* next character in range */
usCharCount--;
}
}
else /* Valid pointer implies character code array */
{
while (usCharCount > 0)
{
if (*pusCharCode == 0xFFFF) /* trap illegal char code */
{
return INVALID_CHARCODE_ERR;
}
*pusGlyphID = pfnGlyphMapping (mapOffsetPtr, *pusCharCode, ClientInfo);
pusGlyphID++;
pusCharCode++; /* next character in array */
usCharCount--;
}
}
return NO_ERR;
}
/*********************************************************************/
FS_PUBLIC ErrorCode sfac_LoadCriticalSfntMetrics(
sfac_ClientRec * ClientInfo,
uint16 * pusEmResolution,
boolean * pbIntegerScaling,
LocalMaxProfile * pMaxProfile)
{
ErrorCode error;
const uint8 * fontHead;
const uint8 * horiHead;
const uint8 * pTempMaxProfile;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_fontHeader, TRUE, (const void **)&fontHead);
if(error != NO_ERR)
{
return error;
}
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_horiHeader, TRUE, (const void **)&horiHead);
if(error != NO_ERR)
{
return error;
}
if ((uint32)SWAPL (*((uint32 *)&fontHead[SFNT_FONTHEADER_MAGICNUMBER])) != SFNT_MAGIC)
{
return BAD_MAGIC_ERR;
}
*pusEmResolution = (uint16)SWAPW (*((uint16 *)&fontHead[SFNT_FONTHEADER_UNITSPEREM]));
*pbIntegerScaling = (((uint16)SWAPW (*((uint16 *)&fontHead[SFNT_FONTHEADER_FLAGS]))& USE_INTEGER_SCALING) ==
USE_INTEGER_SCALING);
ClientInfo->usNumberOf_LongHorMetrics = (uint16)SWAPW (*((uint16 *)&horiHead[SFNT_HORIZONTALHEADER_NUMBEROF_LONGHORMETRICS]));
ClientInfo->sIndexToLocFormat = SWAPW (*((int16 *)&fontHead[SFNT_FONTHEADER_INDEXTOLOCFORMAT]));
RELEASESFNTFRAG(ClientInfo, horiHead);
RELEASESFNTFRAG(ClientInfo, fontHead);
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_maxProfile, TRUE, (const void **)&pTempMaxProfile);
if(error != NO_ERR)
{
return error;
}
pMaxProfile->version = (Fixed)SWAPL(*((Fixed *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_VERSION]));
pMaxProfile->numGlyphs = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_NUMGLYPHS]));
pMaxProfile->maxPoints = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXPOINTS]));
pMaxProfile->maxContours = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXCONTOURS]));
pMaxProfile->maxCompositePoints = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXCOMPOSITEPOINTS]));
pMaxProfile->maxCompositeContours = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXCOMPOSITECONTOURS]));
pMaxProfile->maxElements = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXELEMENTS]));
pMaxProfile->maxTwilightPoints = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXTWILIGHTPOINTS]));
pMaxProfile->maxStorage = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXSTORAGE]));
pMaxProfile->maxFunctionDefs = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXFUNCTIONDEFS]));
pMaxProfile->maxInstructionDefs = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXINSTRUCTIONDEFS]));
pMaxProfile->maxStackElements = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXSTACKELEMENTS]));
pMaxProfile->maxSizeOfInstructions =(uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXSIZEOFINSTRUCTIONS]));
pMaxProfile->maxComponentElements = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXCOMPONENTELEMENTS]));
pMaxProfile->maxComponentDepth = (uint16)SWAPW(*((uint16 *)&pTempMaxProfile[SFNT_MAXPROFILETABLE_MAXCOMPONENTDEPTH]));
RELEASESFNTFRAG(ClientInfo, pTempMaxProfile);
return NO_ERR;
}
/*
*
*/
FS_PUBLIC ErrorCode sfac_ReadGlyphMetrics (
sfac_ClientRec * ClientInfo,
uint16 glyphIndex,
uint16 * pusNonScaledAW,
int16 * psNonScaledLSB)
{
const uint8 * horizMetricPtr;
uint16 numberOf_LongHorMetrics;
ErrorCode error;
int16 * lsb;
numberOf_LongHorMetrics = ClientInfo->usNumberOf_LongHorMetrics;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_horizontalMetrics, TRUE, (const void **)&horizMetricPtr);
if(error != NO_ERR)
{
return error;
}
if (glyphIndex < numberOf_LongHorMetrics)
{
*pusNonScaledAW = (uint16)SWAPW (*((uint16 *)&horizMetricPtr[(glyphIndex * SIZEOF_SFNT_HORIZONTALMETRICS) + SFNT_HORIZONTALMETRICS_ADVANCEWIDTH]));
*psNonScaledLSB = SWAPW (*((int16 *)&horizMetricPtr[(glyphIndex * SIZEOF_SFNT_HORIZONTALMETRICS) + SFNT_HORIZONTALMETRICS_LEFTSIDEBEARING]));
}
else
{
lsb = (int16 *) (char *)& horizMetricPtr[numberOf_LongHorMetrics * SIZEOF_SFNT_HORIZONTALMETRICS]; /* first entry after[AW,LSB] array */
*pusNonScaledAW = (uint16)SWAPW (*((uint16 *)&horizMetricPtr[((numberOf_LongHorMetrics-1) * SIZEOF_SFNT_HORIZONTALMETRICS) + SFNT_HORIZONTALMETRICS_ADVANCEWIDTH]));
*psNonScaledLSB = SWAPW (lsb[glyphIndex - numberOf_LongHorMetrics]);
}
RELEASESFNTFRAG(ClientInfo, horizMetricPtr);
return NO_ERR;
}
/*
* Read Number of Long Vertical Metrics from vhea table
*/
FS_PUBLIC ErrorCode sfac_ReadNumLongVertMetrics(
sfac_ClientRec * ClientInfo,
uint16 * pusNumLongVertMetrics )
{
ErrorCode error;
const uint8 * vertHead;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_vertHeader, TRUE, (const void **)&vertHead);
if(error != NO_ERR)
{
return error;
}
*pusNumLongVertMetrics = (uint16)SWAPW (*((uint16 *)&vertHead[SFNT_VERTICALHEADER_NUMBEROF_LONGVERTMETRICS]));
RELEASESFNTFRAG(ClientInfo, vertHead);
return NO_ERR;
}
/*
* Read Advance Height and Top Side Bearing info from vmtx table
*/
FS_PUBLIC ErrorCode sfac_ReadVerticalMetrics (
sfac_ClientRec * ClientInfo,
uint16 usGlyphIndex,
uint16 usNumLongVertMetrics,
uint16 * pusNonScaledAH,
int16 * psNonScaledTSB)
{
const uint8 * vertMetricPtr;
ErrorCode error;
int16 * psTSB;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_verticalMetrics, TRUE, (const void **)&vertMetricPtr);
if(error != NO_ERR)
{
return error;
}
if (usGlyphIndex < usNumLongVertMetrics)
{
*pusNonScaledAH = (uint16)SWAPW (*((uint16 *)&vertMetricPtr[(usGlyphIndex * SIZEOF_SFNT_VERTICALMETRICS) + SFNT_VERTICALMETRICS_ADVANCEHEIGHT]));
*psNonScaledTSB = SWAPW (*((int16 *)&vertMetricPtr[(usGlyphIndex * SIZEOF_SFNT_VERTICALMETRICS) + SFNT_VERTICALMETRICS_TOPSIDEBEARING]));
}
else
{
psTSB = (int16 *) (char *)& vertMetricPtr[usNumLongVertMetrics * SIZEOF_SFNT_VERTICALMETRICS]; /* first entry after[AW,TSB] array */
*pusNonScaledAH = (uint16)SWAPW (*((uint16 *)&vertMetricPtr[((usNumLongVertMetrics-1) * SIZEOF_SFNT_VERTICALMETRICS) + SFNT_VERTICALMETRICS_ADVANCEHEIGHT]));
*psNonScaledTSB = SWAPW (psTSB[usGlyphIndex - usNumLongVertMetrics]);
}
RELEASESFNTFRAG(ClientInfo, vertMetricPtr);
return NO_ERR;
}
FS_PRIVATE ErrorCode sfac_GetGlyphLocation (
sfac_ClientRec * ClientInfo,
uint16 gIndex,
uint32 * ulOffset,
uint32 * ulLength,
sfnt_tableIndex* pGlyphTableIndex)
{
const void * indexPtr;
ErrorCode error;
uint16 * shortIndexToLoc;
uint32 * longIndexToLoc;
uint32 * offsetPtr;
uint16 * lengthPtr;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_GlyphDirectory, FALSE, (const void **)&indexPtr);
if(error != NO_ERR)
{
return error;
}
/* If there is a glyph directory, first check for the glyph there. */
if (indexPtr != NULL)
{
offsetPtr = (uint32 *)((char *)indexPtr+((int32)gIndex*(int32)(sizeof(int32)+sizeof(uint16))));
lengthPtr = (uint16 *)(char *)(offsetPtr+1);
*ulOffset = (uint32)SWAPL(*offsetPtr);
if(*ulOffset == 0L)
{
*ulLength = 0L;
}
else
{
*ulLength = (uint32) (uint16)SWAPW(*lengthPtr);
}
/* sfnt_BeginningOfFont references the beginning of memory */
*pGlyphTableIndex = sfnt_BeginningOfFont;
RELEASESFNTFRAG(ClientInfo, indexPtr);
return NO_ERR;
}
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_indexToLoc, TRUE, (const void **)&indexPtr);
if(error != NO_ERR)
{
return error;
}
if (ClientInfo->sIndexToLocFormat == SHORT_INDEX_TO_LOC_FORMAT)
{
shortIndexToLoc = (uint16 *)indexPtr + gIndex;
*ulOffset = (uint32) (uint16) (SWAPW (*shortIndexToLoc)) << 1;
shortIndexToLoc++;
*ulLength = (((uint32) (uint16) (SWAPW (*shortIndexToLoc)) << 1) - *ulOffset);
}
else
{
longIndexToLoc = (uint32 *)indexPtr + gIndex;
*ulOffset = (uint32) SWAPL (*longIndexToLoc);
longIndexToLoc++;
*ulLength = ((uint32)SWAPL (*longIndexToLoc) - *ulOffset);
}
*pGlyphTableIndex = sfnt_glyphData;
RELEASESFNTFRAG(ClientInfo, indexPtr);
return NO_ERR;
}
FS_PUBLIC ErrorCode sfac_CopyFontAndPrePrograms(
sfac_ClientRec * ClientInfo, /* Client Information */
char * pFontProgram, /* pointer to Font Program */
char * pPreProgram) /* pointer to Pre Program */
{
uint32 ulLength;
const char * pFragment;
ErrorCode error;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_fontProgram, FALSE, (const void **)&pFragment);
if(error)
{
return error;
}
ulLength = SFAC_LENGTH (ClientInfo, sfnt_fontProgram);
if (ulLength)
{
MEMCPY (pFontProgram, pFragment, ulLength);
RELEASESFNTFRAG(ClientInfo, pFragment);
}
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_preProgram, FALSE, (const void **)&pFragment);
if(error)
{
return error;
}
ulLength = SFAC_LENGTH (ClientInfo, sfnt_preProgram);
if (ulLength)
{
MEMCPY (pPreProgram, pFragment, ulLength);
RELEASESFNTFRAG(ClientInfo, pFragment);
}
return NO_ERR;
}
FS_PUBLIC ErrorCode sfac_CopyCVT(
sfac_ClientRec * ClientInfo, /* Client Information */
F26Dot6 * pCVT) /* pointer to CVT */
{
uint32 ulLength;
const int16 * pFragment;
int32 lNumCVT;
int32 lCVTCount;
const int16 * psSrcCVT;
F26Dot6 * pfxDstCVT;
ErrorCode error;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_controlValue, FALSE, (const void **)&pFragment);
if(error)
{
return error;
}
ulLength = SFAC_LENGTH (ClientInfo, sfnt_controlValue);
if (ulLength)
{
psSrcCVT = pFragment;
pfxDstCVT = pCVT;
lNumCVT = ((int32)ulLength / (int32)sizeof( sfnt_ControlValue));
for(lCVTCount = 0L; lCVTCount < lNumCVT; lCVTCount++)
{
pfxDstCVT[lCVTCount] = (F26Dot6)SWAPW(psSrcCVT[lCVTCount]);
}
RELEASESFNTFRAG(ClientInfo, pFragment);
}
return NO_ERR;
}
FS_PUBLIC ErrorCode sfac_CopyHdmxEntry(
sfac_ClientRec * ClientInfo, /* Client Information */
uint16 usPixelsPerEm, /* Current Pixels per Em */
boolean * pbFound, /* Flag indicating if entry found */
uint16 usFirstGlyph, /* First Glyph to copy */
uint16 usLastGlyph, /* Last Glyph to copy */
int16 * psBuffer) /* Buffer to save glyph sizes */
{
const uint8 * pHdmx;
const uint8 * pCurrentHdmxRecord;
uint32 ulHdmxRecordSize;
uint16 usRecordIndex;
uint16 usGlyphIndex;
ErrorCode error;
Assert( usFirstGlyph < usLastGlyph );
Assert( psBuffer != NULL );
*pbFound = FALSE;
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_HoriDeviceMetrics, FALSE, (const void **)&pHdmx);
if(error)
{
return error;
}
/* If no 'hdmx' return success and not found */
if( pHdmx == NULL )
{
return NO_ERR;
}
if((uint16)pHdmx[SFNT_HDMX_VERSION] == 0) /* NOTE: No SWAP for zero check */
{
ulHdmxRecordSize = (uint32)SWAPL(*((uint32 *)&pHdmx[SFNT_HDMX_LSIZERECORD]));
usRecordIndex = 0;
pCurrentHdmxRecord = &pHdmx[SFNT_HDMX_HDMXTABLE];
while ( (usRecordIndex < (uint16)SWAPW(*((uint16 *)&pHdmx[SFNT_HDMX_SNUMRECORDS]))) && !*pbFound )
{
if( usPixelsPerEm == (uint16)pCurrentHdmxRecord[SFNT_HDMXRECORD_BEMY] )
{
*pbFound = TRUE;
}
else
{
pCurrentHdmxRecord += ulHdmxRecordSize;
}
usRecordIndex++;
}
if ( *pbFound )
{
for( usGlyphIndex = usFirstGlyph; usGlyphIndex <= usLastGlyph; usGlyphIndex++)
{
*psBuffer = (int16)pCurrentHdmxRecord[SFNT_HDMXRECORD_BWIDTHS + usGlyphIndex];
psBuffer++;
}
}
}
RELEASESFNTFRAG(ClientInfo, pHdmx);
return NO_ERR;
}
FS_PUBLIC ErrorCode sfac_GetLTSHEntries(
sfac_ClientRec * ClientInfo, /* Client Information */
uint16 usPixelsPerEm, /* Current Pixels per Em */
uint16 usFirstGlyph, /* First Glyph to copy */
uint16 usLastGlyph, /* Last Glyph to copy */
int16 * psBuffer) /* Buffer to save glyph sizes */
{
const uint8 * pLTSH;
uint16 usGlyphIndex;
ErrorCode error;
MEMSET(psBuffer, FALSE, ((usLastGlyph - usFirstGlyph) + 1) * sizeof(int16));
error = sfac_GetDataPtr (ClientInfo, 0L, ULONG_MAX, sfnt_LinearThreshold, FALSE, (const void **)&pLTSH);
if(error)
{
return error;
}
if( pLTSH == NULL )
{
return NO_ERR;
}
if((uint16)pLTSH[SFNT_LTSH_VERSION] == 0) /* NOTE: No SWAP for zero check */
{
for( usGlyphIndex = usFirstGlyph; usGlyphIndex <= usLastGlyph; usGlyphIndex++ )
{
if( usPixelsPerEm >= (uint16)pLTSH[SFNT_LTSH_UBYPELSHEIGHT + usGlyphIndex] )
{
*psBuffer = TRUE;
}
else
{
*psBuffer = FALSE;
}
psBuffer++;
}
}
RELEASESFNTFRAG(ClientInfo, pLTSH);
return NO_ERR;
}
/***************************** Public Function ****************************\
* sfac_ReadGlyphHeader
*
* This routine sets up the glyph handle to a glyph, and returns the header
* information in the glyph.
*
* Effects:
*
* Error Returns:
*
* UNKNOWN_COMPOSITE_VERSION
*
* History:
* Wed 26-Aug-1992 09:55:19 -by- Greg Hitchcock [gregh]
* Added CodeReview fixes
* Tue 09-Jun-1992 18:42:51 -by- Greg Hitchcock [gregh]
* Initial version.
\***************************************************************************/
FS_PUBLIC ErrorCode sfac_ReadGlyphHeader(
sfac_ClientRec * ClientInfo, /* Client Information */
uint16 usGlyphIndex, /* Glyph index to read */
sfac_GHandle * hGlyph, /* Return glyph handle */
boolean * pbCompositeGlyph, /* Is glyph a composite? */
boolean * pbHasOutline, /* Does glyph have outlines? */
int16 * psNumberOfContours, /* Number of contours in glyph */
BBOX * pbbox) /* Glyph Bounding box */
{
uint32 ulLength;
uint32 ulOffset;
sfnt_tableIndex glyphTableIndex;
ErrorCode error;
const uint8 * GlyphHeader;
hGlyph->pvGlyphBaseAddress = NULL;
hGlyph->pvGlyphNextAddress = NULL;
/* Locate the glyph in the font file */
error = sfac_GetGlyphLocation(
ClientInfo,
usGlyphIndex,
&ulOffset,
&ulLength,
&glyphTableIndex);
if(error)
{
return error;
}
if( ulLength == 0 )
{
*psNumberOfContours = 1;
MEMSET(pbbox, 0, sizeof(BBOX));
*pbHasOutline = FALSE;
*pbCompositeGlyph = FALSE;
}
else
{
error = sfac_GetDataPtr(ClientInfo, ulOffset, ulLength,
glyphTableIndex, TRUE, (const void **)&hGlyph->pvGlyphBaseAddress);
if(error)
{
return error;
}
GlyphHeader = (uint8 *)hGlyph->pvGlyphBaseAddress;
*psNumberOfContours = SWAPW(*((int16 *)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_NUMBEROFCONTOURS]));
if( *psNumberOfContours < COMPONENTCTRCOUNT )
{
return UNKNOWN_COMPOSITE_VERSION;
}
if( *psNumberOfContours == COMPONENTCTRCOUNT )
{
*pbCompositeGlyph = TRUE;
*psNumberOfContours = 0;
*pbHasOutline = FALSE;
}
else
{
*pbCompositeGlyph = FALSE;
*pbHasOutline = TRUE;
}
pbbox->xMin = SWAPW(*((int16 *)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_BBOX+BBOX_XMIN]));
pbbox->yMin = SWAPW(*((int16 *)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_BBOX+BBOX_YMIN]));
pbbox->xMax = SWAPW(*((int16 *)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_BBOX+BBOX_XMAX]));
pbbox->yMax = SWAPW(*((int16 *)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_BBOX+BBOX_YMAX]));
if((pbbox->xMin > pbbox->xMax) || (pbbox->yMin > pbbox->yMax))
{
return SFNT_DATA_ERR;
}
if(pbHasOutline)
{
hGlyph->pvGlyphNextAddress = (voidPtr)&GlyphHeader[SFNT_PACKEDSPLINEFORMAT_ENDPOINTS];
}
}
return NO_ERR;
}
/***************************** Public Function ****************************\
* sfac_ReadOutlineData
*
* This routine reads the outline data from the font file. This information
* includes x and y coordinates, and on-curve indicators as well as start/end
* points, flags, and instruction data.
*
* Effects:
* hGlyph
*
* Error Returns:
* CONTOUR_DATA_ERR
*
* History:
* Wed 26-Aug-1992 09:55:49 -by- Greg Hitchcock [gregh]
* Added Code Review fixes
* Tue 09-Jun-1992 18:42:51 -by- Greg Hitchcock [gregh]
* Initial version.
\***************************************************************************/
FS_PUBLIC ErrorCode sfac_ReadOutlineData(
uint8 * abyOnCurve, /* Array of on curve indicators per point */
F26Dot6 * afxOoy, /* Array of ooy points for every point */
F26Dot6 * afxOox, /* Array of oox points for every point */
sfac_GHandle * hGlyph,
LocalMaxProfile * pMaxProfile, /* copy of profile */
boolean bHasOutline, /* Does glyph have outlines? */
int16 sNumberOfContours, /* Number of contours in glyph */
int16 * asStartPoints, /* Array of start points for every contour */
int16 * asEndPoints, /* Array of end points for every contour */
uint16 * pusSizeOfInstructions, /* Size of instructions in bytes */
uint8 ** pbyInstructions) /* Pointer to start of glyph instructions */
{
uint8 * pbyCurrentSfntLocation;
int16 * psCurrentLocation;
int16 * asSfntEndPoints;
uint8 * pbySfntFlags;
uint8 byRepeatFlag;
int32 lNumPoints;
int32 lContourIndex;
int32 lPointCount;
int32 lPointIndex;
uint16 usRepeatCount;
int16 sXValue;
int16 sYValue;
uint8 * pbyFlags;
F26Dot6 * pf26OrigX;
F26Dot6 * pf26OrigY;
/* Initialize Fields */
asStartPoints[0] = 0;
asEndPoints[0] = 0;
abyOnCurve[0] = ONCURVE;
afxOox[0] = 0;
afxOoy[0] = 0;
*pbyInstructions = NULL;
*pusSizeOfInstructions = 0;
/* If we don't have an outline, exit here */
if (!bHasOutline)
{
return NO_ERR;
}
/* Handle the case of outlines */
psCurrentLocation = (int16 *)hGlyph->pvGlyphNextAddress;
asSfntEndPoints = psCurrentLocation;
psCurrentLocation += sNumberOfContours;
*pusSizeOfInstructions = (uint16)SWAPWINC (psCurrentLocation);
*pbyInstructions = (uint8 *)psCurrentLocation;
pbySfntFlags = (uint8 *)((char *)psCurrentLocation + *pusSizeOfInstructions);
if (sNumberOfContours < 0 || sNumberOfContours > (int16)pMaxProfile->maxContours)
{
return CONTOUR_DATA_ERR;
}
lContourIndex = 0;
asStartPoints[lContourIndex] = 0;
asEndPoints[lContourIndex] = SWAPW (asSfntEndPoints[lContourIndex]);
for(lContourIndex = 1; lContourIndex < (int32)sNumberOfContours; lContourIndex++)
{
asStartPoints[lContourIndex] = (int16)(asEndPoints[lContourIndex - 1] + 1);
asEndPoints[lContourIndex] = SWAPW (asSfntEndPoints[lContourIndex]);
}
lNumPoints = (int32)asEndPoints[sNumberOfContours - 1] + 1;
if (lNumPoints > (int32)pMaxProfile->maxPoints)
{
return POINTS_DATA_ERR;
}
/* Do flags */
usRepeatCount = 0;
lPointCount = lNumPoints;
pbyFlags = abyOnCurve;
while(lPointCount > 0)
{
if(usRepeatCount == 0)
{
*pbyFlags = *pbySfntFlags;
if(*pbyFlags & REPEAT_FLAGS)
{
pbySfntFlags++;
usRepeatCount = (uint16)*pbySfntFlags;
}
pbySfntFlags++;
pbyFlags++;
lPointCount--;
}
else
{
byRepeatFlag = pbyFlags[-1];
lPointCount -= (int32)usRepeatCount;
while(usRepeatCount > 0)
{
*pbyFlags = byRepeatFlag;
pbyFlags++;
usRepeatCount--;
}
}
}
pbyCurrentSfntLocation = pbySfntFlags;
if(usRepeatCount > 0)
{
return POINTS_DATA_ERR;
}
/* Do X first */
sXValue = 0;
pf26OrigX = afxOox;
pbyFlags = abyOnCurve;
for(lPointIndex = 0; lPointIndex < lNumPoints; lPointIndex++)
{
if(*pbyFlags & XSHORT)
{
if(*pbyFlags & SHORT_X_IS_POS)
{
sXValue += (int16)SFAC_GETUNSIGNEDBYTEINC (pbyCurrentSfntLocation);
}
else
{
sXValue -= (int16)SFAC_GETUNSIGNEDBYTEINC (pbyCurrentSfntLocation);
}
}
else if (! (*pbyFlags & NEXT_X_IS_ZERO))
{
/* This means we have a two byte quantity */
sXValue += SWAPW(*((int16 *)pbyCurrentSfntLocation));
pbyCurrentSfntLocation += sizeof(int16);
}
*pf26OrigX = (F26Dot6)sXValue;
pf26OrigX++;
pbyFlags++;
}
/* Now Do Y */
sYValue = 0;
pf26OrigY = afxOoy;
pbyFlags = abyOnCurve;
for(lPointIndex = 0; lPointIndex < lNumPoints; lPointIndex++)
{
if(*pbyFlags & YSHORT)
{
if(*pbyFlags & SHORT_Y_IS_POS)
{
sYValue += (int16)SFAC_GETUNSIGNEDBYTEINC (pbyCurrentSfntLocation);
}
else
{
sYValue -= (int16)SFAC_GETUNSIGNEDBYTEINC (pbyCurrentSfntLocation);
}
}
else if (! (*pbyFlags & NEXT_Y_IS_ZERO))
{
/* This means we have a two byte quantity */
sYValue += SWAPW(*((int16 *)pbyCurrentSfntLocation));
pbyCurrentSfntLocation += sizeof(int16);
}
*pf26OrigY = (F26Dot6)sYValue;
pf26OrigY++;
/* Clear out extraneous bits in OnCurve */
*pbyFlags &= ONCURVE;
pbyFlags++;
}
hGlyph->pvGlyphNextAddress = (voidPtr)pbyCurrentSfntLocation;
return NO_ERR;
}
/***************************** Public Function ****************************\
*
* sfac_ReadComponentData
*
* This routine reads information from the font file for positioning and
* scaling a glyph component.
*
* Effects:
*
* Error Returns:
* none
*
* History:
* Wed 26-Aug-1992 09:56:29 -by- Greg Hitchcock [gregh]
* Added Code Review Fixes
* Tue 09-Jun-1992 18:42:51 -by- Greg Hitchcock [gregh]
* Initial version.
\***************************************************************************/
FS_PUBLIC ErrorCode sfac_ReadComponentData(
sfac_GHandle * hGlyph,
sfac_ComponentTypes * pMultiplexingIndicator, /* Indicator for Anchor vs offsets */
boolean * pbRoundXYToGrid, /* Round composite offsets to grid */
boolean * pbUseMyMetrics, /* Use component metrics */
boolean * pbWeHaveInstructions, /* Composite has instructions */
uint16 * pusComponentGlyphIndex, /* Glyph index of component */
int16 * psXOffset, /* X Offset of component (if app) */
int16 * psYOffset, /* Y Offset of component (if app) */
uint16 * pusAnchorPoint1, /* Anchor point 1 of component (if app) */
uint16 * pusAnchorPoint2, /* Anchor point 2 of component (if app) */
transMatrix *pMulT, /* Transformation matrix for component */
boolean * pbLastComponent) /* Is this the last component? */
{
int16 * psCurrentLocation;
uint16 usComponentFlags;
char * byteP;
Fixed fMultiplier;
psCurrentLocation = (int16 *)hGlyph->pvGlyphNextAddress;
/* Initialize values */
/* Initialize transformation matrix to identity */
*pMulT = IdentTransform;
*psXOffset = 0;
*psYOffset = 0;
*pusAnchorPoint1 = 0;
*pusAnchorPoint2 = 0;
usComponentFlags = (uint16)SWAPWINC(psCurrentLocation);
*pbWeHaveInstructions = ((usComponentFlags & WE_HAVE_INSTRUCTIONS) == WE_HAVE_INSTRUCTIONS);
*pbUseMyMetrics = ((usComponentFlags & USE_MY_METRICS) == USE_MY_METRICS);
*pbRoundXYToGrid = ((usComponentFlags & ROUND_XY_TO_GRID) == ROUND_XY_TO_GRID);
*pusComponentGlyphIndex = (uint16)SWAPWINC(psCurrentLocation);
if (usComponentFlags & ARGS_ARE_XY_VALUES)
{
*pMultiplexingIndicator = OffsetPoints;
}
else
{
*pMultiplexingIndicator = AnchorPoints;
}
/*
!!!APPLEBUG The rasterizer did not handle Word Anchor Points. This
!!!APPLEBUG has been corrected in our version of the rasterizer, but
!!!APPLEBUG we need to verify with the Apple source code. --GregH
*/
if (usComponentFlags & ARG_1_AND_2_ARE_WORDS)
{
if (usComponentFlags & ARGS_ARE_XY_VALUES)
{
*psXOffset = SWAPWINC (psCurrentLocation);
*psYOffset = SWAPWINC (psCurrentLocation);
}
else
{
*pusAnchorPoint1 = (uint16) SWAPWINC (psCurrentLocation);
*pusAnchorPoint2 = (uint16) SWAPWINC (psCurrentLocation);
}
}
else
{
byteP = (char *)psCurrentLocation;
if (usComponentFlags & ARGS_ARE_XY_VALUES)
{
/* offsets are signed */
*psXOffset = (int16)(int8)*byteP++;
*psYOffset = (int16)(int8)*byteP;
}
else
{
/* anchor points are unsigned */
*pusAnchorPoint1 = (uint16)(uint8) * byteP++;
*pusAnchorPoint2 = (uint16)(uint8) * byteP;
}
++psCurrentLocation;
}
if (usComponentFlags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO))
{
if (usComponentFlags & WE_HAVE_A_TWO_BY_TWO)
{
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[0][0] = (fMultiplier << 2); /* turn into 16.16 */
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[0][1] = (fMultiplier << 2); /* turn into 16.16 */
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[1][0] = (fMultiplier << 2); /* turn into 16.16 */
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[1][1] = (fMultiplier << 2); /* turn into 16.16 */
}
else
{
/* If we have a scale factor, build it into the transformation matrix */
pMulT->transform[0][1] = 0;
pMulT->transform[1][0] = 0;
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[0][0] = (fMultiplier <<= 2); /* turn into 16.16 */
if (usComponentFlags & WE_HAVE_AN_X_AND_Y_SCALE)
{
fMultiplier = (Fixed)SWAPWINC (psCurrentLocation); /* read 2.14 */
pMulT->transform[1][1] = (fMultiplier <<= 2); /* turn into 16.16 */
}
else
{
pMulT->transform[1][1] = pMulT->transform[0][0];
}
}
}
*pbLastComponent = !((usComponentFlags & MORE_COMPONENTS) == MORE_COMPONENTS);
hGlyph->pvGlyphNextAddress = (voidPtr)psCurrentLocation;
return NO_ERR;
}
/***************************** Public Function ****************************\
*
* sfac_ReadCompositeInstructions
*
* This routine returns the instructions for the composite
*
* Effects:
* none
*
* Error Returns:
* none
*
* History:
* Tue 09-Jun-1992 18:42:51 -by- Greg Hitchcock [gregh]
* Initial version.
\***************************************************************************/
FS_PUBLIC ErrorCode sfac_ReadCompositeInstructions(
sfac_GHandle * hGlyph,
uint8 ** pbyInstructions, /* Pointer to start of glyph instructions */
uint16 * pusSizeOfInstructions) /* Size of instructions in bytes */
{
int16 * psCurrentLocation;
psCurrentLocation = (int16 *)hGlyph->pvGlyphNextAddress;
*pusSizeOfInstructions = (uint16)SWAPWINC (psCurrentLocation);
*pbyInstructions = (uint8 *)psCurrentLocation;
psCurrentLocation += *pusSizeOfInstructions;
hGlyph->pvGlyphNextAddress = (voidPtr)psCurrentLocation;
return NO_ERR;
}
/***************************** Public Function ****************************\
*
* sfac_ReleaseGlyph
*
* This routine releases the glyph handle for the font file
*
* Effects:
* none
*
* Error Returns:
* none
*
* History:
* Tue 09-Jun-1992 18:42:51 -by- Greg Hitchcock [gregh]
* Initial version.
\***************************************************************************/
FS_PUBLIC ErrorCode sfac_ReleaseGlyph(
sfac_ClientRec * ClientInfo,
sfac_GHandle * hGlyph)
{
if(hGlyph->pvGlyphNextAddress)
{
RELEASESFNTFRAG(ClientInfo,(voidPtr)hGlyph->pvGlyphBaseAddress);
hGlyph->pvGlyphNextAddress = NULL;
hGlyph->pvGlyphBaseAddress = NULL;
}
return NO_ERR;
}
/***************************************************************************/
/* Embedded Bitmap (sbit) Access Routines */
/**********************************************************************/
/* Local constants */
#define SBIT_BLOC_TABLE 1 /* which table are metrics in */
#define SBIT_BDAT_TABLE 2
#define SBIT_HORIZ_METRICS 1 /* which kind of metrics */
#define SBIT_VERT_METRICS 2
#define SBIT_BIG_METRICS 3
typedef enum { /* metrics type */
flgHorizontal = 0x01,
flgVertical = 0x02
} bitmapFlags;
FS_PRIVATE boolean FindBlocStrike ( /* helper function prototype */
const uint8 *pbyBloc,
uint16 usPpemX,
uint16 usPpemY,
uint32 *pulStrikeOffset );
FS_PRIVATE boolean FindBscaStrike ( /* helper function prototype */
const uint8 *pbyBsca,
uint16 usPpemX,
uint16 usPpemY,
uint32 *pulStrikeOffset );
/* byte size bitmap range masks */
static uint8 achStartMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
static uint8 achStopMask[] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
/**********************************************************************/
FS_PUBLIC ErrorCode sfac_SearchForStrike (
sfac_ClientRec *pClientInfo,
uint16 usPpemX,
uint16 usPpemY,
uint16 *pusTableState,
uint16 *pusSubPpemX,
uint16 *pusSubPpemY,
uint32 *pulStrikeOffset )
{
const uint8 * pbyBloc;
const uint8 * pbyBsca;
ErrorCode ReturnCode;
*pusTableState = SBIT_NOT_FOUND; /* defaults */
*pulStrikeOffset = 0L;
*pusSubPpemX = 0;
*pusSubPpemY = 0;
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
0L, /* table start */
ULONG_MAX, /* read whole table */
sfnt_BitmapLocation, /* registered tag */
FALSE, /* doesn't have to be there */
(const void**)&pbyBloc ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
if (pbyBloc != NULL) /* if bloc exists */
{
if (FindBlocStrike (pbyBloc, usPpemX, usPpemY, pulStrikeOffset))
{
*pusTableState = SBIT_BLOC_FOUND; /* exact match */
}
else /* if bloc and NO match */
{
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
0L, /* table start */
ULONG_MAX, /* read whole table */
sfnt_BitmapScale, /* registered tag */
FALSE, /* doesn't have to be there */
(const void**)&pbyBsca ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
if (pbyBsca != NULL) /* if bsca exists */
{
if (FindBscaStrike (pbyBsca, usPpemX, usPpemY, pulStrikeOffset))
{
*pusSubPpemX = (uint16)pbyBsca[*pulStrikeOffset + SFNT_BSCA_SUBPPEMX];
*pusSubPpemY = (uint16)pbyBsca[*pulStrikeOffset + SFNT_BSCA_SUBPPEMY];
if (FindBlocStrike (pbyBloc, *pusSubPpemX, *pusSubPpemY, pulStrikeOffset))
{
*pusTableState = SBIT_BSCA_FOUND;
}
}
RELEASESFNTFRAG(pClientInfo, pbyBsca );
}
}
RELEASESFNTFRAG(pClientInfo, pbyBloc);
}
return NO_ERR;
}
/**********************************************************************/
/* Find a strike that matches ppemX & Y in the bloc table */
FS_PRIVATE boolean FindBlocStrike (
const uint8 *pbyBloc,
uint16 usPpemX,
uint16 usPpemY,
uint32 *pulStrikeOffset )
{
uint32 ulNumStrikes;
uint32 ulStrikeOffset;
uint32 ulColorRefOffset;
ulNumStrikes = (uint32)SWAPL(*((uint32*)&pbyBloc[SFNT_BLOC_NUMSIZES]));
ulStrikeOffset = SFNT_BLOC_FIRSTSTRIKE;
while (ulNumStrikes > 0)
{
if ((usPpemX == (uint16)pbyBloc[ulStrikeOffset + SFNT_BLOC_PPEMX]) &&
(usPpemY == (uint16)pbyBloc[ulStrikeOffset + SFNT_BLOC_PPEMY]))
{
ulColorRefOffset = (uint32)SWAPL(*((uint32*)&pbyBloc[ulStrikeOffset + SFNT_BLOC_COLORREF]));
if ((pbyBloc[ulStrikeOffset + SFNT_BLOC_BITDEPTH] == 1) && (ulColorRefOffset == 0L))
{
*pulStrikeOffset = ulStrikeOffset;
return TRUE; /* match found */
}
}
ulNumStrikes--;
ulStrikeOffset += SIZEOF_BLOC_SIZESUBTABLE;
}
return FALSE; /* match not found */
}
/**********************************************************************/
/* Find a strike that matches ppemX & Y in the bsca table */
FS_PRIVATE boolean FindBscaStrike (
const uint8 *pbyBsca,
uint16 usPpemX,
uint16 usPpemY,
uint32 *pulStrikeOffset )
{
uint32 ulNumStrikes;
uint32 ulStrikeOffset;
ulNumStrikes = (uint32)SWAPL(*((uint32*)&pbyBsca[SFNT_BSCA_NUMSIZES]));
ulStrikeOffset = SFNT_BSCA_FIRSTSTRIKE;
while (ulNumStrikes > 0)
{
if ((usPpemX == (uint16)pbyBsca[ulStrikeOffset + SFNT_BSCA_PPEMX]) &&
(usPpemY == (uint16)pbyBsca[ulStrikeOffset + SFNT_BSCA_PPEMY]))
{
*pulStrikeOffset = ulStrikeOffset;
return TRUE; /* match found */
}
ulNumStrikes--;
ulStrikeOffset += SIZEOF_BSCA_SIZESUBTABLE;
}
return FALSE; /* match not found */
}
/**********************************************************************/
/* Look for a glyph in a given strike */
FS_PUBLIC ErrorCode sfac_SearchForBitmap (
sfac_ClientRec *pClientInfo,
uint16 usGlyphCode,
uint32 ulStrikeOffset,
boolean *pbGlyphFound, /* return values */
uint16 *pusMetricsType,
uint16 *pusMetricsTable,
uint32 *pulMetricsOffset,
uint16 *pusBitmapFormat,
uint32 *pulBitmapOffset,
uint32 *pulBitmapLength )
{
const uint8 * pbyBloc;
ErrorCode ReturnCode;
uint32 ulNumIndexTables;
uint32 ulIndexArrayTop;
uint32 ulIndexArrayOffset;
uint32 ulSubTableOffset;
uint32 ulGlyphOffset;
uint32 ulNextGlyphOffset;
uint32 ulBitmapLength;
uint32 ulImageDataOffset;
uint32 ulNumGlyphs;
uint32 ulTop; /* binary search ranges */
uint32 ulBottom;
uint32 ulHit;
uint32 ulHitOffset;
uint16 usStartGlyph; /* for whole strike */
uint16 usEndGlyph;
uint16 usFirstGlyph; /* for one sub table */
uint16 usLastGlyph;
uint16 usIndexFormat;
uint16 usImageFormat;
uint16 usHitCode;
bitmapFlags bmfDirection; /* horiz or vert */
*pbGlyphFound = FALSE; /* default */
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
0L, /* table start */
ULONG_MAX, /* read whole table */
sfnt_BitmapLocation, /* registered tag */
TRUE, /* better be there now */
(const void**)&pbyBloc ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
usStartGlyph = (uint16)SWAPW(*((uint16*)&pbyBloc[ulStrikeOffset + SFNT_BLOC_STARTGLYPH]));
usEndGlyph = (uint16)SWAPW(*((uint16*)&pbyBloc[ulStrikeOffset + SFNT_BLOC_ENDGLYPH]));
if ((usStartGlyph > usGlyphCode) || (usEndGlyph < usGlyphCode))
{
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* glyph out of range */
}
ulNumIndexTables = (uint32)SWAPL(*((uint32*)&pbyBloc[ulStrikeOffset + SFNT_BLOC_NUMINDEXTABLES]));
ulIndexArrayTop = (uint32)SWAPL(*((uint32*)&pbyBloc[ulStrikeOffset + SFNT_BLOC_INDEXARRAYOFFSET]));
ulIndexArrayOffset = ulIndexArrayTop;
while ((ulNumIndexTables > 0) && (*pbGlyphFound == FALSE))
{
usFirstGlyph = (uint16)SWAPW(*((uint16*)&pbyBloc[ulIndexArrayOffset + SFNT_BLOC_FIRSTGLYPH]));
usLastGlyph = (uint16)SWAPW(*((uint16*)&pbyBloc[ulIndexArrayOffset + SFNT_BLOC_LASTGLYPH]));
if ((usFirstGlyph <= usGlyphCode) && (usLastGlyph >= usGlyphCode))
{
ulSubTableOffset = ulIndexArrayTop +
(uint32)SWAPL(*((uint32*)&pbyBloc[ulIndexArrayOffset + SFNT_BLOC_ADDITIONALOFFSET]));
usIndexFormat = (uint16)SWAPW(*((uint16*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_INDEXFORMAT]));
usImageFormat = (uint16)SWAPW(*((uint16*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IMAGEFORMAT]));
ulImageDataOffset = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IMAGEOFFSET]));
/* decode the individual index subtable formats */
switch(usIndexFormat) /* different search req's */
{
case 1:
ulSubTableOffset += SFNT_BLOC_OFFSETARRAY + sizeof(uint32) * (uint32)(usGlyphCode - usFirstGlyph);
ulGlyphOffset = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset]));
ulSubTableOffset += sizeof(uint32);
ulNextGlyphOffset = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset]));
ulBitmapLength = ulNextGlyphOffset - ulGlyphOffset;
if (ulBitmapLength == 0)
{
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* no bitmap data stored */
}
ulImageDataOffset += ulGlyphOffset;
*pulMetricsOffset = ulImageDataOffset;
*pusMetricsTable = SBIT_BDAT_TABLE;
break;
case 2:
ulBitmapLength = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IDX2IMAGESIZE]));
ulImageDataOffset += ulBitmapLength * (usGlyphCode - usFirstGlyph);
*pulBitmapOffset = ulImageDataOffset;
*pulMetricsOffset = ulSubTableOffset + SFNT_BLOC_IDX2METRICS;
*pusMetricsTable = SBIT_BLOC_TABLE;
*pusMetricsType = SBIT_BIG_METRICS;
break;
case 3:
ulSubTableOffset += SFNT_BLOC_OFFSETARRAY + sizeof(uint16) * (uint32)(usGlyphCode - usFirstGlyph);
ulGlyphOffset = (uint32)(uint16)SWAPW(*((uint16*)&pbyBloc[ulSubTableOffset]));
ulSubTableOffset += sizeof(uint16);
ulNextGlyphOffset = (uint32)(uint16)SWAPW(*((uint16*)&pbyBloc[ulSubTableOffset]));
ulBitmapLength = ulNextGlyphOffset - ulGlyphOffset;
if (ulBitmapLength == 0)
{
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* no bitmap data stored */
}
ulImageDataOffset += ulGlyphOffset;
*pulMetricsOffset = ulImageDataOffset;
*pusMetricsTable = SBIT_BDAT_TABLE;
break;
case 4:
ulNumGlyphs = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IDX4NUMGLYPHS]));
ulTop = 0L;
ulBottom = ulNumGlyphs - 1L;
ulSubTableOffset += SFNT_BLOC_IDX4OFFSETARRAY; /* array base */
ulHit = ulTop;
ulHitOffset = ulSubTableOffset;
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SFNT_BLOC_IDX4CODE]));
if (usHitCode != usGlyphCode)
{
ulHit = ulBottom;
ulHitOffset = ulSubTableOffset + (ulHit * SIZEOF_CODEOFFSETPAIR);
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SFNT_BLOC_IDX4CODE]));
while (usHitCode != usGlyphCode)
{
if (usHitCode < usGlyphCode) /* binary search for glyph code */
{
ulTop = ulHit;
}
else
{
ulBottom = ulHit;
}
if ((ulBottom - ulTop) < 2L)
{
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* glyph not found */
}
ulHit = (ulTop + ulBottom) >> 1L;
ulHitOffset = ulSubTableOffset + (ulHit * SIZEOF_CODEOFFSETPAIR);
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SFNT_BLOC_IDX4CODE]));
}
}
ulGlyphOffset = (uint32)(uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SFNT_BLOC_IDX4OFFSET]));
ulNextGlyphOffset = (uint32)(uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SIZEOF_CODEOFFSETPAIR + SFNT_BLOC_IDX4OFFSET]));
ulBitmapLength = ulNextGlyphOffset - ulGlyphOffset;
ulImageDataOffset += ulGlyphOffset;
*pulMetricsOffset = ulImageDataOffset;
*pusMetricsTable = SBIT_BDAT_TABLE;
break;
case 5:
ulBitmapLength = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IDX5IMAGESIZE]));
*pulMetricsOffset = ulSubTableOffset + SFNT_BLOC_IDX5METRICS;
*pusMetricsTable = SBIT_BLOC_TABLE;
*pusMetricsType = SBIT_BIG_METRICS;
ulNumGlyphs = (uint32)SWAPL(*((uint32*)&pbyBloc[ulSubTableOffset + SFNT_BLOC_IDX5NUMGLYPHS]));
ulTop = 0L;
ulBottom = ulNumGlyphs - 1L;
ulSubTableOffset += SFNT_BLOC_IDX5CODEARRAY; /* array base */
ulHit = ulTop;
ulHitOffset = ulSubTableOffset;
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset]));
if (usHitCode != usGlyphCode)
{
ulHit = ulBottom;
ulHitOffset = ulSubTableOffset + (ulHit * sizeof(uint16));
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset + SFNT_BLOC_IDX4CODE]));
while (usHitCode != usGlyphCode)
{
if (usHitCode < usGlyphCode) /* binary search for glyph code */
{
ulTop = ulHit;
}
else
{
ulBottom = ulHit;
}
if ((ulBottom - ulTop) < 2L)
{
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* glyph not found */
}
ulHit = (ulTop + ulBottom) >> 1L;
ulHitOffset = ulSubTableOffset + (ulHit * sizeof(uint16));
usHitCode = (uint16)SWAPW(*((uint16*)&pbyBloc[ulHitOffset]));
}
}
ulImageDataOffset += ulBitmapLength * ulHit;
*pulBitmapOffset = ulImageDataOffset;
break;
default:
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR; /* unknown format */
}
/* use the glyph formats to calculate metrics type & data offsets */
*pulBitmapLength = ulBitmapLength;
*pusBitmapFormat = usImageFormat; /* save for bitmap decoding */
bmfDirection = (bitmapFlags)pbyBloc[ulStrikeOffset + SFNT_BLOC_FLAGS];
switch(usImageFormat) /* different metrics sizes */
{
case 1: /* small glyph metrics */
case 2:
if (bmfDirection == flgHorizontal)
{
*pusMetricsType = SBIT_HORIZ_METRICS;
}
else
{
Assert(bmfDirection == flgVertical);
*pusMetricsType = SBIT_VERT_METRICS;
}
*pulBitmapOffset = ulImageDataOffset + SIZEOF_SBIT_SMALLMETRICS;
*pbGlyphFound = TRUE;
break;
case 3:
break;
case 4:
break;
case 5: /* bitmap offset and metrics type set above */
*pbGlyphFound = TRUE;
break;
case 6:
case 7:
case 9:
*pusMetricsType = SBIT_BIG_METRICS;
*pulBitmapOffset = ulImageDataOffset + SIZEOF_SBIT_BIGMETRICS;
*pbGlyphFound = TRUE;
break;
case 8:
if (bmfDirection == flgHorizontal)
{
*pusMetricsType = SBIT_HORIZ_METRICS;
}
else
{
Assert(bmfDirection == flgVertical);
*pusMetricsType = SBIT_VERT_METRICS;
}
*pulBitmapOffset = ulImageDataOffset + SIZEOF_SBIT_SMALLMETRICS + SIZEOF_SBIT_GLYPH8PAD;
*pbGlyphFound = TRUE;
break;
default:
break;
}
}
ulNumIndexTables--;
ulIndexArrayOffset += SIZEOF_BLOC_INDEXARRAY;
}
RELEASESFNTFRAG(pClientInfo, pbyBloc);
return NO_ERR;
}
/**********************************************************************/
/* fetch the horizontal metrics */
FS_PUBLIC ErrorCode sfac_GetSbitMetrics (
sfac_ClientRec *pClientInfo,
uint16 usMetricsType,
uint16 usMetricsTable,
uint32 ulMetricsOffset,
uint16 *pusHeight,
uint16 *pusWidth,
int16 *psBearingX,
int16 *psBearingY,
uint16 *pusAdvance )
{
const uint8 *pbyTable;
uint32 ulTableLength;
sfnt_tableIndex TableIndex;
ErrorCode ReturnCode;
if (usMetricsTable == SBIT_BDAT_TABLE) /* if metrics in bdat */
{
TableIndex = sfnt_BitmapData;
}
else /* if metrics in bloc */
{
TableIndex = sfnt_BitmapLocation;
}
if (usMetricsType == SBIT_BIG_METRICS) /* if both h & v metrics */
{
ulTableLength = SIZEOF_SBIT_BIGMETRICS;
}
else /* if only h or v metrics */
{
ulTableLength = SIZEOF_SBIT_SMALLMETRICS;
}
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
ulMetricsOffset, /* metrics start */
ulTableLength, /* read just metrics */
TableIndex, /* registered tag */
TRUE, /* should be there */
(const void**)&pbyTable ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
/* for horizontal metrics, offsets are the same for both big & small */
*pusHeight = (uint16)pbyTable[SFNT_SBIT_HEIGHT];
*pusWidth = (uint16)pbyTable[SFNT_SBIT_WIDTH];
*psBearingX = (int16)(*((int8*)&pbyTable[SFNT_SBIT_BEARINGX]));
*psBearingY = (int16)(*((int8*)&pbyTable[SFNT_SBIT_BEARINGY]));
*pusAdvance = (uint16)pbyTable[SFNT_SBIT_ADVANCE];
RELEASESFNTFRAG(pClientInfo, pbyTable);
return NO_ERR;
}
/**********************************************************************/
/* shave the white space from horizontal metrics for bitmap format 5 */
#define ROWSIZE 16 /* 16 bytes = 128 bits max */
FS_PUBLIC ErrorCode sfac_ShaveSbitMetrics (
sfac_ClientRec *pClientInfo,
uint16 usBitmapFormat,
uint32 ulBitmapOffset,
uint32 ulBitmapLength,
uint16 usHeight,
uint16 *pusWidth,
uint16 *pusShaveLeft,
uint16 *pusShaveRight,
int16 *psBearingX
)
{
uint8 abyBitRow[ROWSIZE]; /* or bitmap into one row */
const uint8 *pbyTable;
const uint8 *pbyBdat;
uint8 *pbyBitMap;
uint8 byMask;
uint16 usBitData;
uint16 usFreshBits;
uint16 usOutBits;
uint16 usStopBit;
uint16 usShaveLeft;
uint16 usShaveRight;
uint16 usStart;
ErrorCode ReturnCode;
*pusShaveLeft = 0; /* defaults */
*pusShaveRight = 0;
if (usBitmapFormat != 5) /* if not constant metrics data */
{
return NO_ERR;
}
if (*pusWidth > (ROWSIZE << 3))
{
return NO_ERR; /* punt huge bitmaps */
}
MEMSET(abyBitRow, 0, ROWSIZE); /* clear to zeros */
/* read the bitmap data */
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
ulBitmapOffset, /* metrics start */
ulBitmapLength, /* read bitmap data */
sfnt_BitmapData, /* registered tag */
TRUE, /* should be there */
(const void**)&pbyTable ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
pbyBdat = pbyTable;
usBitData = 0; /* up to 16 bits of bdat */
usFreshBits = 0; /* read & unwritten */
/* 'or' the bitmap data into a single row */
while (usHeight > 0)
{
pbyBitMap = abyBitRow;
usOutBits = *pusWidth;
usStopBit = 8;
while (usOutBits > 0) /* if more to do */
{
if (usFreshBits < 8) /* if room for fresh data */
{
usBitData <<= 8;
if (ulBitmapLength > 0) /* prevent read past data end */
{
usBitData |= (uint16)*pbyBdat++;
ulBitmapLength--;
}
usFreshBits += 8;
}
if (usStopBit > usOutBits)
{
usStopBit = usOutBits;
}
byMask = achStopMask[usStopBit];
*pbyBitMap++ |= (uint8)((usBitData >> (usFreshBits - 8)) & byMask);
usFreshBits -= usStopBit;
usOutBits -= usStopBit;
}
usHeight--;
}
RELEASESFNTFRAG(pClientInfo, pbyTable);
/* calculate white space on the left */
pbyBitMap = abyBitRow;
byMask = 0x80;
usShaveLeft = 0;
while ((*pbyBitMap & byMask) == 0)
{
usShaveLeft++;
if (usShaveLeft == *pusWidth)
{
return NO_ERR; /* no black found, don't shave */
}
byMask >>= 1;
if (byMask == 0)
{
byMask = 0x80;
pbyBitMap++;
}
}
/* calculate white space on the right */
usStart = *pusWidth - 1;
pbyBitMap = &abyBitRow[usStart >> 3];
byMask = 0x80 >> (usStart & 0x0007);
usShaveRight = 0;
while ((*pbyBitMap & byMask) == 0)
{
usShaveRight++;
if (byMask == 0x80)
{
byMask = 0x01;
pbyBitMap--;
}
else
{
byMask <<= 1;
}
}
/* correct the width and sidebearing */
*pusShaveLeft = usShaveLeft;
*pusShaveRight = usShaveRight;
*pusWidth -= usShaveLeft + usShaveRight;
*psBearingX += (int16)usShaveLeft;
return NO_ERR;
}
/**********************************************************************/
FS_PUBLIC ErrorCode sfac_GetSbitVertMetrics(
sfac_ClientRec *pClientInfo,
uint16 usMetricsType,
uint16 usMetricsTable,
uint32 ulMetricsOffset,
boolean *pbMetricsFound,
int16 *psTopSBy,
uint16 *pusAdvHeight
)
{
const uint8 *pbyTable;
uint32 ulTableLength;
sfnt_tableIndex TableIndex;
ErrorCode ReturnCode;
*pbMetricsFound = FALSE; /* default */
if (usMetricsTable == SBIT_BDAT_TABLE) /* if metrics in bdat */
{
TableIndex = sfnt_BitmapData;
}
else /* if metrics in bloc */
{
TableIndex = sfnt_BitmapLocation;
}
if (usMetricsType == SBIT_BIG_METRICS) /* if both h & v metrics */
{
ulTableLength = SIZEOF_SBIT_BIGMETRICS;
}
else if (usMetricsType == SBIT_VERT_METRICS)
{
ulTableLength = SIZEOF_SBIT_SMALLMETRICS;
}
else
{
return NO_ERR; /* only horizontal metrics */
}
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
ulMetricsOffset, /* metrics start */
ulTableLength, /* read just metrics */
TableIndex, /* registered tag */
TRUE, /* should be there */
(const void**)&pbyTable ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
/* SWAP macros not needed here because all values fetch just 8 bits */
if (usMetricsType == SBIT_BIG_METRICS) /* if both h & v metrics */
{
*psTopSBy = (int16)(*((int8*)&pbyTable[SFNT_SBIT_VERTBEARINGY]));
*pusAdvHeight = (uint16)pbyTable[SFNT_SBIT_VERTADVANCE];
}
else /* if (usMetricsType == SBIT_VERT_METRICS) */
{
*psTopSBy = (int16)(*((int8*)&pbyTable[SFNT_SBIT_BEARINGY]));
*pusAdvHeight = (uint16)pbyTable[SFNT_SBIT_ADVANCE];
}
*pbMetricsFound = TRUE;
RELEASESFNTFRAG(pClientInfo, pbyTable);
return NO_ERR;
}
/**********************************************************************/
/* fetch the bitmap */
/* Currently supporting the following bdat formats:
1 - Small metrics; Byte aligned data
2 - Small metrics; Bit aligned data
5 - Const metrics; Bit aligned data
6 - Big metrics; Byte aligned data
7 - Big metrics; Bit aligned data
8 - Small metrics; Composite data
9 - Big metrics; Composite data
*/
FS_PUBLIC ErrorCode sfac_GetSbitBitmap (
sfac_ClientRec *pClientInfo,
uint16 usBitmapFormat,
uint32 ulBitmapOffset,
uint32 ulBitmapLength,
uint16 usHeight,
uint16 usWidth,
uint16 usShaveLeft, /* for white space in fmt 5 */
uint16 usShaveRight,
uint16 usXOffset,
uint16 usYOffset,
uint16 usDstRowBytes,
uint8 *pbyBitMap,
uint16 *pusCompCount )
{
const uint8 *pbyTable;
const uint8 *pbyBdat;
uint8 *pbyBitRow; /* start of bitmap row */
uint16 usSrcRowBytes; /* bytes per row in bdat */
ErrorCode ReturnCode;
uint16 usBitData; /* bdat data read into 16 bits */
uint16 usOutBits; /* num of bits to put to bitmap */
uint16 usCount;
uint16 usXOffBytes;
uint16 usXOffBits;
uint16 usStartBit;
uint16 usStopBit;
int16 sFreshBits; /* num of bits read not written */
uint8 byMask; /* for partial bytes */
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
ulBitmapOffset, /* metrics start */
ulBitmapLength, /* read bitmap data */
sfnt_BitmapData, /* registered tag */
TRUE, /* should be there */
(const void**)&pbyTable ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
pbyBdat = pbyTable;
*pusCompCount = 0; /* usual case */
pbyBitRow = pbyBitMap + (usDstRowBytes * usYOffset);
usXOffBytes = usXOffset >> 3;
usXOffBits = usXOffset & 0x07;
switch(usBitmapFormat)
{
case 1: /* byte aligned */
case 6:
usSrcRowBytes = (usWidth + 7) / 8;
if (usXOffBits == 0) /* if byte aligned */
{
while (usHeight > 0)
{
pbyBitMap = pbyBitRow + usXOffBytes; /* adjust left */
for (usCount = 0; usCount < usSrcRowBytes; usCount++)
{
*pbyBitMap++ |= *pbyBdat++;
}
pbyBitRow += usDstRowBytes;
usHeight--;
}
}
else /* if offset in x */
{
while (usHeight > 0)
{
pbyBitMap = pbyBitRow + usXOffBytes; /* adjust left */
usBitData = 0;
for (usCount = 0; usCount < usSrcRowBytes; usCount++)
{
usBitData |= (uint16)*pbyBdat++;
*pbyBitMap++ |= (usBitData >> usXOffBits) & 0x00FF;
usBitData <<= 8;
}
*pbyBitMap |= (usBitData >> usXOffBits) & 0x00FF;
pbyBitRow += usDstRowBytes;
usHeight--;
}
}
break;
case 2: /* bit aligned data */
case 5:
case 7:
usBitData = 0; /* up to 16 bits of bdat */
sFreshBits = 0; /* read & unwritten */
while (usHeight > 0) /* for each row */
{
pbyBitMap = pbyBitRow + usXOffBytes; /* adjust left */
usOutBits = usWidth;
usStartBit = usXOffBits;
usStopBit = 8;
sFreshBits -= (int16)usShaveLeft; /* skip the left white bits */
while (usOutBits > 0) /* if more to do */
{
while (sFreshBits < 8) /* if room for fresh data */
{
usBitData <<= 8;
if (ulBitmapLength > 0) /* prevent read past data end */
{
usBitData |= (uint16)*pbyBdat++;
ulBitmapLength--;
}
sFreshBits += 8;
}
if (usStopBit > usOutBits + usStartBit)
{
usStopBit = usStartBit + usOutBits;
}
byMask = achStartMask[usStartBit] & achStopMask[usStopBit];
*pbyBitMap++ |= (uint8)((usBitData >> (sFreshBits + (int16)usStartBit - 8)) & byMask);
sFreshBits -= (int16)(usStopBit - usStartBit);
usOutBits -= usStopBit - usStartBit;
usStartBit = 0;
}
sFreshBits -= (int16)usShaveRight; /* skip the right white bits */
pbyBitRow += usDstRowBytes; /* next row */
usHeight--;
}
break;
case 3: /* various */
case 4:
break;
case 8: /* composites */
case 9: /* just return count */
*pusCompCount = (uint16)SWAPW(*((uint16*)&pbyBdat[SFNT_BDAT_COMPCOUNT]));
break;
default:
break;
}
RELEASESFNTFRAG(pClientInfo, pbyTable);
return NO_ERR;
}
/**********************************************************************/
FS_PUBLIC ErrorCode sfac_GetSbitComponentInfo (
sfac_ClientRec *pClientInfo,
uint16 usComponent,
uint32 ulBitmapOffset,
uint32 ulBitmapLength,
uint16 *pusCompGlyphCode,
uint16 *pusCompXOffset,
uint16 *pusCompYOffset
)
{
const uint8 * pbyBdat;
ErrorCode ReturnCode;
ReturnCode = sfac_GetDataPtr (
pClientInfo, /* callback etc. */
ulBitmapOffset, /* metrics start */
ulBitmapLength, /* read bitmap data */
sfnt_BitmapData, /* registered tag */
TRUE, /* should be there */
(const void**)&pbyBdat ); /* data pointer */
if (ReturnCode != NO_ERR) return ReturnCode;
pbyBdat += SFNT_BDAT_FIRSTCOMP + (SIZEOF_SBIT_BDATCOMPONENT * usComponent);
*pusCompGlyphCode = (uint16)SWAPW(*((uint16*)&pbyBdat[SFNT_BDAT_COMPGLYPH]));
*pusCompXOffset = (uint16)pbyBdat[SFNT_BDAT_COMPXOFF];
*pusCompYOffset = (uint16)pbyBdat[SFNT_BDAT_COMPYOFF];
RELEASESFNTFRAG(pClientInfo, pbyBdat);
return NO_ERR;
}
/**********************************************************************/