mirror of https://github.com/lianthony/NT4.0
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.
2649 lines
80 KiB
2649 lines
80 KiB
/*
|
|
File: FontScaler.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):
|
|
|
|
<11> 11/27/90 MR Need two scalars: one for (possibly rounded) outlines and cvt,
|
|
and one (always fractional) metrics. [rb]
|
|
<10> 11/21/90 RB Allow client to disable DropOutControl by returning a NIL
|
|
pointer to memoryarea[7]. Also make it clear that we inhibit
|
|
DOControl whenever we band. [This is a reversion to 8, so mr's
|
|
initials are added by proxy]
|
|
<9> 11/13/90 MR (dnf) Revert back to revision 7 to fix a memmory-trashing bug
|
|
(we hope). Also fix signed/unsigned comparison bug in outline
|
|
caching.
|
|
<8> 11/13/90 RB Fix banding so that we can band down to one row, using only
|
|
enough bitmap memory and auxillary memory for one row.[mr]
|
|
<7> 11/9/90 MR Add Default return to fs_dropoutval. Continue to fiddle with
|
|
banding. [rb]
|
|
<6> 11/5/90 MR Remove FixMath.h from include list. Clean up Stamp macros. [rb]
|
|
<5> 10/31/90 MR Conditionalize call to ComputeMapping (to avoid linking
|
|
MapString) [ha]
|
|
<4> 10/31/90 MR Add bit-field option for integer or fractional scaling [rb]
|
|
<3> 10/30/90 RB [MR] Inhibit DropOutControl when Banding
|
|
<2> 10/20/90 MR Restore changes since project died. Converting to smart math
|
|
routines, integer ppem scaling. [rb]
|
|
<16> 7/26/90 MR don't include ToolUtils.h
|
|
<15> 7/18/90 MR Fix return bug in GetAdvanceWidth, internal errors are now ints.
|
|
<14> 7/14/90 MR remove unused fields from FSInfo
|
|
<13> 7/13/90 MR Ansi-C fixes, rev. for union in FSInput
|
|
<11> 6/29/90 RB Thus endeth the too long life of encryption
|
|
<10> 6/21/90 MR Add calls to ReleaseSfntFrag
|
|
<9> 6/21/90 RB add scanKind info to fs_dropoutVal
|
|
<8> 6/5/90 MR remove fs_MapCharCodes
|
|
<7> 6/1/90 MR Did someone say MVT? Yuck!!! Out, routine.
|
|
<6> 6/1/90 RB fixed bandingbug under dropout control
|
|
<4> 5/3/90 RB added dropoutval function. simplified restore outlines.
|
|
support for new scanconverter in contourscan, findbitmapsize,
|
|
saveoutlines, restoreoutlines.
|
|
<3> 3/20/90 CL Changed to use fpem (16.16) instead of pixelsPerEm (int) Removed
|
|
call to AdjustTransformation (not needed with fpem) Added call
|
|
to RunXFormPgm Removed WECANNOTDOTHIS #ifdef Added
|
|
fs_MapCharCodes
|
|
<2> 2/27/90 CL New error code for missing but needed table. (0x1409). New
|
|
CharToIndexMap Table format.
|
|
Fixed transformed component bug.
|
|
<3.6> 11/15/89 CEL Put an else for the ifdef WeCanNotDoThis so Printer compile
|
|
could use more effecient code.
|
|
<3.5> 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. The
|
|
transformation is internally automatically normalized. This
|
|
should also solve the overflow problem we had. 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 ! Five unnecessary element in the
|
|
output data structure have been deleted. (All the information is
|
|
passed out in the bitmap data structure) fs_FindBMSize now also
|
|
returns the bounding box.
|
|
<3.4> 9/28/89 CEL fs_newglyph did not initialize the output error. Caused routine
|
|
to return error from previous routines.
|
|
<3.3> 9/27/89 CEL Took out devAdvanceWidth & devLeftSideBearing.
|
|
<3.2> 9/25/89 CEL Changed the NEED_PROTOTYPE ifdef to use the NOT_ON_THE_MAC flag
|
|
that existed previously.
|
|
<3.1> 9/15/89 CEL Changed dispatch scheme. Calling conventions through a trap
|
|
needed to match Macintosh pascal. Pascal can not call C unless
|
|
there is extra mucky glue. Bug that caused text not to appear.
|
|
The font scaler state was set up correctly but the sfnt was
|
|
purged. It was reloaded and the clientid changed but was still
|
|
the same font. Under the rules of the FontScaler fs_newsfnt
|
|
should not have to be called again to reset the state. The extra
|
|
checks sent back a BAD_CLIENTID_ERROR so QuickDraw would think
|
|
it was a bad font and not continue to draw.
|
|
<3.0> 8/28/89 sjk Cleanup and one transformation bugfix
|
|
<2.4> 8/17/89 sjk Coded around MPW C3.0 bug
|
|
<2.3> 8/14/89 sjk 1 point contours now OK
|
|
<2.2> 8/8/89 sjk Improved encryption handling
|
|
<2.1> 8/2/89 sjk Fixed outline caching bug
|
|
<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 Conditionalized error checking in fs_SetUpKey.
|
|
Compiler option for stamping memmory areas for debugging
|
|
Removed error field from FSInfo structure.
|
|
Added call to RunFontProgram
|
|
Added private function prototypes.
|
|
Optimizations from diet clinic
|
|
|
|
*/
|
|
|
|
|
|
// added by bodind, speed optimization
|
|
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
|
|
/** FontScaler's Includes **/
|
|
|
|
#include "fserror.h"
|
|
#include "fscdefs.h"
|
|
#include "fontmath.h" /* For numeric conversion macros */
|
|
#include "fnt.h"
|
|
#include "scentry.h"
|
|
#include "sfntaccs.h"
|
|
#include "fsglue.h"
|
|
#include "sbit.h"
|
|
#include "fscaler.h" // moved this to be the last include file [bodind]
|
|
|
|
#include "stat.h" /* STAT timing card prototypes */
|
|
boolean gbTimer = FALSE; /* set true when timer running */
|
|
|
|
|
|
/** Private Structures **/
|
|
// removed fs_SplineKey from here and put in the include file [bodind]
|
|
|
|
|
|
/* CONSTANTS */
|
|
|
|
/* Change this if the format for cached outlines change. */
|
|
/* Someone might be caching old stuff for years on a disk */
|
|
|
|
#define OUTLINESTAMP 0x2BADADBE
|
|
#define OUTLINESTAMP2 0xA5
|
|
|
|
#define BITMAP_MEMORY_COUNT 4 /* now for gray scale we need 4 */
|
|
|
|
/* for the key->ulState field */
|
|
#define INITIALIZED 0x0000L
|
|
#define NEWSFNT 0x0002L
|
|
#define NEWTRANS 0x0004L
|
|
#define GOTINDEX 0x0008L
|
|
#define GOTGLYPH 0x0010L
|
|
#define SIZEKNOWN 0x0020L
|
|
|
|
#define STAMPEXTRA 4
|
|
|
|
/* 'sfnt' in ASCII */
|
|
#define STAMP 0x73666E74
|
|
|
|
/*** Memory shared between all fonts and sizes and transformations ***/
|
|
#define KEY_PTR_BASE 0 /* Constant Size ! */
|
|
#define VOID_FUNC_PTR_BASE 1 /* Constant Size ! */
|
|
#define SCAN_PTR_BASE 2 /* Constant Size ! */
|
|
#define WORK_SPACE_BASE 3 /* size is sfnt dependent, can't be shared between grid-fitting and scan-conversion */
|
|
/*** Memory that can not be shared between fonts and different sizes, can not dissappear after InitPreProgram () ***/
|
|
#define PRIVATE_FONT_SPACE_BASE 4 /* size is sfnt dependent */
|
|
/* Only needs to exist when ContourScan is called, and it can be shared */
|
|
#define BITMAP_PTR_1 5 /* the bitmap - size is glyph size dependent */
|
|
#define BITMAP_PTR_2 6 /* size is proportional to number of rows */
|
|
#define BITMAP_PTR_3 7 /* used for dropout control - glyph size dependent */
|
|
#define BITMAP_PTR_4 8 /* used in gray scale for overscaled bitmap */
|
|
|
|
static const transMatrix IdentTransform =
|
|
{{{ONEFIX, 0, 0},
|
|
{ 0, ONEFIX, 0},
|
|
{ 0, 0, ONEFIX}}};
|
|
|
|
/* PRIVATE DEFINITIONS */
|
|
|
|
FS_PRIVATE fs_SplineKey * fs_SetUpKey (fs_GlyphInputType* inptr, uint32 ulStateBits, ErrorCode * error);
|
|
FS_PRIVATE void fs_InitializeKey(fs_SplineKey * key);
|
|
FS_PRIVATE int32 fs__Contour (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr, boolean useHints);
|
|
FS_PRIVATE void fs_SetState(fs_SplineKey * key, uint32 ulState);
|
|
FS_PRIVATE void FS_CALLBACK_PROTO dummyReleaseSfntFrag (voidPtr p);
|
|
FS_PRIVATE void CHECKSTAMP(char * p);
|
|
FS_PRIVATE void SETSTAMP(char * p);
|
|
|
|
FS_PRIVATE FS_ENTRY fs__FindSize (fs_GlyphInputType*, fs_GlyphInfoType*, boolean);
|
|
FS_PRIVATE FS_ENTRY fs__FindBandingSize (fs_GlyphInputType*, fs_GlyphInfoType*, boolean);
|
|
FS_PRIVATE FS_ENTRY fs__ContourScan (fs_GlyphInputType*, fs_GlyphInfoType*, boolean);
|
|
FS_PRIVATE FS_ENTRY LookForSbitWidth(fs_SplineKey *key, uint16 usGlyphIndex, uint16 usPPEMX,
|
|
uint16 usPPEMY, uint16 usRotation, boolean *pbBitmapFound, point *pf26DevAdvanceWidth );
|
|
FS_PRIVATE FS_ENTRY LookForSbitVertMetrics(fs_SplineKey *key, uint16 usGlyphIndex,
|
|
uint16 usPPEMX, uint16 usPPEMY, uint16 usRotation, boolean *pbBitmapFound,
|
|
point *pf26DevAdvanceHeight, point *pf26DevTopSideBearing );
|
|
|
|
|
|
#ifdef DEBUGSTAMP
|
|
|
|
/* FUNCTIONS */
|
|
|
|
FS_PRIVATE void SETSTAMP(char * p)
|
|
{
|
|
* ((uint32 *) ((p) - STAMPEXTRA)) = STAMP;
|
|
}
|
|
|
|
|
|
FS_PRIVATE void CHECKSTAMP(char * p)
|
|
{
|
|
if (* ((uint32 *) ((p) - STAMPEXTRA)) != STAMP)
|
|
{
|
|
#ifdef NOT_ON_THE_MAC
|
|
Assert(FALSE);
|
|
#else
|
|
DEBUGGER ();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#define CHECKSTAMP(p)
|
|
#define SETSTAMP(p)
|
|
|
|
#endif
|
|
|
|
|
|
FS_PRIVATE void FS_CALLBACK_PROTO dummyReleaseSfntFrag (voidPtr p)
|
|
{
|
|
FS_UNUSED_PARAMETER(p);
|
|
}
|
|
|
|
FS_PRIVATE void fs_SetState(fs_SplineKey * key, uint32 ulState)
|
|
{
|
|
key->ulState = ulState;
|
|
}
|
|
|
|
/*
|
|
* Set up the key in case memmory has moved or been purged.
|
|
*/
|
|
FS_PRIVATE fs_SplineKey * fs_SetUpKey (
|
|
fs_GlyphInputType * inptr,
|
|
uint32 ulStateBits,
|
|
ErrorCode * error)
|
|
{
|
|
fs_SplineKey * key;
|
|
|
|
key = (fs_SplineKey *)inptr->memoryBases[KEY_PTR_BASE];
|
|
if (key == NULL)
|
|
{
|
|
*error = NULL_KEY_ERR;
|
|
return 0;
|
|
}
|
|
|
|
key->memoryBases = inptr->memoryBases;
|
|
if(key->memoryBases == NULL)
|
|
{
|
|
*error = NULL_MEMORY_BASES_ERR;
|
|
return 0;
|
|
}
|
|
key->ClientInfo.GetSfntFragmentPtr = inptr->GetSfntFragmentPtr;
|
|
if(key->ClientInfo.GetSfntFragmentPtr == NULL)
|
|
{
|
|
*error = NULL_SFNT_FRAG_PTR_ERR;
|
|
return 0;
|
|
}
|
|
|
|
key->ClientInfo.ReleaseSfntFrag = inptr->ReleaseSfntFrag;
|
|
if (!(key->ClientInfo.ReleaseSfntFrag))
|
|
{
|
|
key->ClientInfo.ReleaseSfntFrag = dummyReleaseSfntFrag;
|
|
}
|
|
|
|
#if 0 // do not want this even in the debug version [bodind]
|
|
if ((key->ulState & ulStateBits) != ulStateBits)
|
|
{
|
|
*error = OUT_OFF_SEQUENCE_CALL_ERR;
|
|
return 0;
|
|
}
|
|
#endif // do not want this even in the debug version [bodind]
|
|
|
|
key->ClientInfo.lClientID = inptr->clientID;
|
|
*error = NO_ERR;
|
|
|
|
return key;
|
|
}
|
|
|
|
FS_PRIVATE void fs_InitializeKey(fs_SplineKey * key)
|
|
{
|
|
MEMSET(key, 0, sizeof(fs_SplineKey));
|
|
key->TransformInfo.currentTMatrix = IdentTransform;
|
|
}
|
|
|
|
/*** FONT SCALER INTERFACE ***/
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_OpenFonts (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
if ( outputPtr )
|
|
{
|
|
outputPtr->memorySizes[KEY_PTR_BASE] = (int32)sizeof (fs_SplineKey) + STAMPEXTRA;
|
|
outputPtr->memorySizes[VOID_FUNC_PTR_BASE] = 0;
|
|
outputPtr->memorySizes[SCAN_PTR_BASE] = 0;
|
|
outputPtr->memorySizes[WORK_SPACE_BASE] = 0; /* we need the sfnt for this */
|
|
outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE] = 0; /* we need the sfnt for this */
|
|
outputPtr->memorySizes[BITMAP_PTR_1] = 0; /* we need the grid fitted outline for this */
|
|
outputPtr->memorySizes[BITMAP_PTR_2] = 0; /* we need the grid fitted outline for this */
|
|
outputPtr->memorySizes[BITMAP_PTR_3] = 0; /* we need the grid fitted outline for this */
|
|
outputPtr->memorySizes[BITMAP_PTR_4] = 0; /* gray scale memory */
|
|
}
|
|
else
|
|
{
|
|
return NULL_OUTPUT_PTR_ERR;
|
|
}
|
|
if ( inputPtr )
|
|
{
|
|
inputPtr->memoryBases[KEY_PTR_BASE] = NULL;
|
|
inputPtr->memoryBases[VOID_FUNC_PTR_BASE] = NULL;
|
|
inputPtr->memoryBases[SCAN_PTR_BASE] = NULL;
|
|
inputPtr->memoryBases[WORK_SPACE_BASE] = NULL;
|
|
inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] = NULL;
|
|
inputPtr->memoryBases[BITMAP_PTR_1] = NULL;
|
|
inputPtr->memoryBases[BITMAP_PTR_2] = NULL;
|
|
inputPtr->memoryBases[BITMAP_PTR_3] = NULL;
|
|
inputPtr->memoryBases[BITMAP_PTR_4] = NULL;
|
|
}
|
|
else
|
|
{
|
|
return NULL_INPUT_PTR_ERR;
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_Initialize (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
fs_SplineKey * key;
|
|
|
|
FS_UNUSED_PARAMETER(outputPtr);
|
|
|
|
key = (fs_SplineKey *)inputPtr->memoryBases[KEY_PTR_BASE];
|
|
SETSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
fs_InitializeKey(key);
|
|
|
|
key->memoryBases = inputPtr->memoryBases;
|
|
|
|
fs_SetState(key, INITIALIZED);
|
|
|
|
fsc_Initialize(); /* initialize scan converter */
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*
|
|
* This guy asks for memmory for points, instructions, fdefs and idefs
|
|
*/
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_NewSfnt (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
ErrorCode error;
|
|
fs_SplineKey * key;
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
STAT_ON_NEWSFNT; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, INITIALIZED, &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
error = sfac_DoOffsetTableMap (&key->ClientInfo); /* Map offset and length table */
|
|
|
|
if(error != NO_ERR)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
error = sfac_LoadCriticalSfntMetrics(
|
|
&key->ClientInfo,
|
|
&key->TransformInfo.usEmResolution,
|
|
&key->TransformInfo.bIntegerScaling,
|
|
&key->maxProfile);
|
|
|
|
if(error != NO_ERR)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE] = (int32)fsg_PrivateFontSpaceSize (&key->ClientInfo, &key->maxProfile, &key->PrivateSpaceOffsets) + STAMPEXTRA;
|
|
outputPtr->memorySizes[WORK_SPACE_BASE] = (int32)fsg_WorkSpaceSetOffsets (&key->maxProfile, &key->WorkSpaceOffsets, &key->lExtraWorkSpace) + STAMPEXTRA;
|
|
|
|
|
|
error = sfac_ComputeMapping (
|
|
&key->ClientInfo,
|
|
inputPtr->param.newsfnt.platformID,
|
|
inputPtr->param.newsfnt.specificID);
|
|
|
|
if(error != NO_ERR)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT));
|
|
|
|
/*
|
|
* Can't run font program yet, we don't have any memory for the
|
|
* graphic state. Mark it to be run in NewTransformation.
|
|
*/
|
|
|
|
key->bExecuteFontPgm = TRUE;
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
STAT_OFF_NEWSFNT; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_NewTransformation (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
void * pvGlobalGS;
|
|
void * pvStack;
|
|
void * pvTwilightZone;
|
|
void * pvFontProgram;
|
|
void * pvPreProgram;
|
|
ErrorCode error;
|
|
fs_SplineKey * key;
|
|
|
|
if((inputPtr->memoryBases[WORK_SPACE_BASE] == NULL) ||
|
|
(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] == NULL))
|
|
{
|
|
return NULL_MEMORY_BASES_ERR;
|
|
}
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
SETSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
SETSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_ON_NEWTRAN; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvStack = fsg_QueryStack(&key->pWorkSpaceAddr);
|
|
|
|
fsg_UpdatePrivateSpaceAddresses(
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets),
|
|
pvStack,
|
|
&pvFontProgram,
|
|
&pvPreProgram);
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
pvTwilightZone = fsg_QueryTwilightElement(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
|
|
/* Load the font program and pre program if necessary */
|
|
|
|
if (key->bExecuteFontPgm)
|
|
{
|
|
error = sfac_CopyFontAndPrePrograms(
|
|
&key->ClientInfo,
|
|
pvFontProgram,
|
|
pvPreProgram);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
|
|
key->TransformInfo.currentTMatrix = *inputPtr->param.newtrans.transformMatrix;
|
|
key->TransformInfo.fxPixelDiameter = inputPtr->param.newtrans.pixelDiameter;
|
|
|
|
error = fsg_InitInterpreterTrans (
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
inputPtr->param.newtrans.pointSize,
|
|
inputPtr->param.newtrans.xResolution,
|
|
inputPtr->param.newtrans.yResolution);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (key->bExecuteFontPgm)
|
|
{
|
|
error = fsg_RunFontProgram (pvGlobalGS, &key->pWorkSpaceAddr, pvTwilightZone);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
key->bExecuteFontPgm = FALSE;
|
|
}
|
|
|
|
key->bExecutePrePgm = (boolean) !inputPtr->param.newtrans.traceFunc;
|
|
|
|
if (!key->bExecutePrePgm)
|
|
{
|
|
|
|
/* Do this now so we do not confuse font editors */
|
|
/* Run the pre program and scale the control value table */
|
|
/* Sets key->bExecutePrePgm to false */
|
|
|
|
error = fsg_RunPreProgram (
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
&key->pWorkSpaceAddr,
|
|
pvTwilightZone,
|
|
inputPtr->param.newtrans.traceFunc);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
|
|
fsg_GetScaledCVT(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&key->PrivateSpaceOffsets,
|
|
&outputPtr->scaledCVT);
|
|
|
|
error = sbit_NewTransform(&key->SbitMono); /* setup for sbits */
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT | NEWTRANS));
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_OFF_NEWTRAN; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute the glyph index from the character code.
|
|
*/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_NewGlyph (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
ErrorCode error;
|
|
fs_SplineKey * key;
|
|
void * pvGlobalGS;
|
|
uint16 usPPEMX; /* for sbits */
|
|
uint16 usPPEMY;
|
|
uint16 usRotation;
|
|
|
|
#if 0 // do not want this even in the debug version [bodind]
|
|
|
|
if((inputPtr->memoryBases[WORK_SPACE_BASE] == NULL) ||
|
|
(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] == NULL))
|
|
{
|
|
return NULL_MEMORY_BASES_ERR;
|
|
}
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
#endif // do not want this even in the debug version
|
|
|
|
STAT_ON_NEWGLYPH; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (inputPtr->param.newglyph.characterCode != NONVALID)
|
|
{
|
|
error = sfac_GetGlyphIndex(
|
|
&key->ClientInfo,
|
|
inputPtr->param.newglyph.characterCode);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
outputPtr->numberOfBytesTaken = 2; /* !!!DISCUSS */
|
|
outputPtr->glyphIndex = key->ClientInfo.usGlyphIndex;
|
|
}
|
|
else
|
|
{
|
|
key->ClientInfo.usGlyphIndex = inputPtr->param.newglyph.glyphIndex;
|
|
outputPtr->glyphIndex = inputPtr->param.newglyph.glyphIndex;
|
|
outputPtr->numberOfBytesTaken = 0;
|
|
}
|
|
|
|
if( key->ClientInfo.usGlyphIndex > key->maxProfile.numGlyphs - 1)
|
|
{
|
|
return INVALID_GLYPH_INDEX;
|
|
}
|
|
|
|
// the if (inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE]) clause is
|
|
// added by bodind to prevent gpfault when calling fs_NewGlyph out of
|
|
// order on NT.
|
|
|
|
if (inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE])
|
|
{
|
|
// begin bodind's clause
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
fsg_QueryPPEMXY(pvGlobalGS, &key->TransformInfo,
|
|
&usPPEMX, &usPPEMY, &usRotation);
|
|
|
|
error = sbit_SearchForBitmap(
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
usPPEMX,
|
|
usPPEMY,
|
|
usRotation,
|
|
key->ClientInfo.usGlyphIndex,
|
|
&outputPtr->usBitmapFound );
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
// end of bodind's clause
|
|
}
|
|
|
|
/* clear all other bits */
|
|
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX));
|
|
|
|
#if 0 // do not want this even in the debug version [bodind]
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
#endif // do not want this even in the debug version
|
|
|
|
STAT_OFF_NEWGLYPH; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*
|
|
* this call is optional.
|
|
*
|
|
* can be called right after fs_NewGlyph ()
|
|
*/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_GetAdvanceWidth (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
ErrorCode error;
|
|
int16 sNonScaledLSB;
|
|
fs_SplineKey * key;
|
|
void * pvGlobalGS;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
error = sfac_ReadGlyphMetrics (
|
|
&key->ClientInfo,
|
|
key->ClientInfo.usGlyphIndex,
|
|
&key->usNonScaledAW,
|
|
&sNonScaledLSB);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fsg_UpdateAdvanceWidth (&key->TransformInfo, pvGlobalGS, key->usNonScaledAW,
|
|
&outputPtr->metricInfo.advanceWidth);
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
FS_PRIVATE int32 fs__Contour (fs_GlyphInputType*inputPtr, fs_GlyphInfoType*outputPtr, boolean useHints)
|
|
{
|
|
ErrorCode error;
|
|
void * pvGlobalGS;
|
|
fs_SplineKey * key;
|
|
point f26DevAdvanceWidth;
|
|
void * pvTwilightZone;
|
|
void * pvStack;
|
|
void * pvFontProgram;
|
|
void * pvPreProgram;
|
|
|
|
if((inputPtr->memoryBases[WORK_SPACE_BASE] == NULL) ||
|
|
(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] == NULL))
|
|
{
|
|
return NULL_MEMORY_BASES_ERR;
|
|
}
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_ON_GRIDFIT; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if((key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE]) ||
|
|
(key->apbPrevMemoryBases[PRIVATE_FONT_SPACE_BASE] != key->memoryBases[PRIVATE_FONT_SPACE_BASE]))
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvStack = fsg_QueryStack(&key->pWorkSpaceAddr);
|
|
|
|
fsg_UpdatePrivateSpaceAddresses(
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets),
|
|
pvStack,
|
|
&pvFontProgram,
|
|
&pvPreProgram);
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
/* The element data structures need to be updated here because if the */
|
|
/* WorkSpace memory is shared, the pointers will not be correct. Since */
|
|
/* fs_Contour[No]GridFit - fs_ContourScan must have the same shared */
|
|
/* base, these address do not have to be updated explicitly between */
|
|
/* each call, only if the memory base has physically moved. */
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
pvTwilightZone = fsg_QueryTwilightElement(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
/* potentially do delayed pre program execution */
|
|
|
|
if (key->bExecutePrePgm)
|
|
{
|
|
/* Run the pre program and scale the control value table */
|
|
|
|
key->bExecutePrePgm = FALSE;
|
|
|
|
error = fsg_RunPreProgram (
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
&key->pWorkSpaceAddr,
|
|
pvTwilightZone,
|
|
NULL);
|
|
|
|
if(error)
|
|
{
|
|
/* If the pre-program fails, prevent further glyphs from being called */
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT));
|
|
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
|
|
if (inputPtr->param.gridfit.bSkipIfBitmap && sbit_IfBitmapFound(&key->SbitMono))
|
|
{
|
|
key->bGridFitSkipped = TRUE; /* disallow grayscale, outline caching, banding */
|
|
|
|
error = sbit_GetDevAdvanceWidth (
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
&f26DevAdvanceWidth );
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
else /* if we're using the outline */
|
|
{
|
|
key->bGridFitSkipped = FALSE; /* allow grayscale, outline caching, banding */
|
|
|
|
/* THE CALL */
|
|
|
|
error = fsg_GridFit (
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
&key->pWorkSpaceAddr,
|
|
pvTwilightZone,
|
|
inputPtr->param.gridfit.traceFunc,
|
|
useHints,
|
|
&key->usScanType,
|
|
&key->bGlyphHasOutline,
|
|
&key->usNonScaledAW);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fsg_GetContourData(
|
|
&key->pWorkSpaceAddr,
|
|
&outputPtr->xPtr,
|
|
&outputPtr->yPtr,
|
|
&outputPtr->startPtr,
|
|
&outputPtr->endPtr,
|
|
&outputPtr->onCurve,
|
|
&outputPtr->numberOfContours);
|
|
|
|
fsg_GetDevAdvanceWidth(
|
|
&key->pWorkSpaceAddr,
|
|
&f26DevAdvanceWidth);
|
|
}
|
|
|
|
outputPtr->metricInfo.devAdvanceWidth.x = DOT6TOFIX(f26DevAdvanceWidth.x);
|
|
outputPtr->metricInfo.devAdvanceWidth.y = DOT6TOFIX(f26DevAdvanceWidth.y);
|
|
|
|
outputPtr->outlinesExist = (uint16)key->bGlyphHasOutline;
|
|
|
|
fsg_GetScaledCVT(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&key->PrivateSpaceOffsets,
|
|
&outputPtr->scaledCVT);
|
|
|
|
key->usOverScale = 0; /* default to monochrome */
|
|
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH));
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_OFF_GRIDFIT; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_ContourNoGridFit (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__Contour (inputPtr, outputPtr, FALSE);
|
|
}
|
|
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_ContourGridFit (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__Contour (inputPtr, outputPtr, TRUE);
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Calculate scan conversion memory requirements */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_FindBitMapSize (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__FindSize(inputPtr, outputPtr, FALSE);
|
|
}
|
|
|
|
/* This function serves fs_FindBitMapSize and fs_FindGraySize */
|
|
|
|
FS_PRIVATE FS_ENTRY fs__FindSize (
|
|
fs_GlyphInputType *inputPtr,
|
|
fs_GlyphInfoType *outputPtr,
|
|
boolean bGrayScale )
|
|
{
|
|
|
|
ErrorCode error;
|
|
BitMap * pBMI;
|
|
|
|
ContourList CList; /* newscan contour list type */
|
|
void * pvGlobalGS;
|
|
fs_SplineKey * key;
|
|
|
|
point f26DevAdvanceWidth;
|
|
point f26DevLeftSideBearing;
|
|
point f26LeftSideBearing;
|
|
point f26DevLeftSideBearingLine;
|
|
point f26LeftSideBearingLine;
|
|
|
|
uint16 usOverScale; /* gray scale magnification */
|
|
int16 sOverScale;
|
|
uint16 usRoundXMin;
|
|
Rect * pOrigB; /* original outline bounding box */
|
|
Rect * pOverB; /* over scaled outline bounding box */
|
|
GlyphBitMap * pOverG; /* over scaled glyph bitmap struct */
|
|
GlyphBitMap * pGBMap; /* orig or over pointer */
|
|
|
|
uint16 usRowBytes;
|
|
uint32 ulSbitOutSize; /* sbit output memory */
|
|
uint32 ulSbitWorkSize; /* sbit workspace memory */
|
|
int16 sNonScaledLSB; /* for non-dev metrics calc */
|
|
|
|
|
|
if((inputPtr->memoryBases[WORK_SPACE_BASE] == NULL) ||
|
|
(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] == NULL))
|
|
{
|
|
return NULL_MEMORY_BASES_ERR;
|
|
}
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_ON_FINDBMS; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (key->usOverScale != 0) /* has FindGraySize been called? */
|
|
{
|
|
return GRAY_SEQUENCE_ERR;
|
|
}
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
if (key->bGridFitSkipped)
|
|
{
|
|
return GRAY_NO_OUTLINE_ERR; /* should have set bSkipIfBitmap false */
|
|
}
|
|
|
|
usOverScale = inputPtr->param.gray.usOverScale; /* read input param */
|
|
if (((1 << (usOverScale - 1)) & FS_GRAY_VALUE_MASK) == 0)
|
|
{
|
|
return BAD_GRAY_LEVEL_ERR;
|
|
}
|
|
key->usOverScale = usOverScale; /* save for later */
|
|
}
|
|
|
|
if(key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE])
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
pOrigB = &key->GBMap.rectBounds; /* local copy of bounds pointer */
|
|
|
|
if (sbit_IfBitmapFound(&key->SbitMono) && /* if using an embedded bitmap */
|
|
(!bGrayScale)) /* and not requesting grayscale */
|
|
{
|
|
error = sbit_GetMetrics ( /* get device metrics */
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
&f26DevAdvanceWidth,
|
|
&f26DevLeftSideBearing,
|
|
&f26LeftSideBearing,
|
|
pOrigB,
|
|
&usRowBytes,
|
|
&ulSbitOutSize,
|
|
&ulSbitWorkSize );
|
|
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
outputPtr->metricInfo.devAdvanceWidth.x = DOT6TOFIX(f26DevAdvanceWidth.x);
|
|
outputPtr->metricInfo.devAdvanceWidth.y = DOT6TOFIX(f26DevAdvanceWidth.y);
|
|
outputPtr->metricInfo.devLeftSideBearing.x = DOT6TOFIX(f26DevLeftSideBearing.x);
|
|
outputPtr->metricInfo.devLeftSideBearing.y = DOT6TOFIX(f26DevLeftSideBearing.y);
|
|
outputPtr->metricInfo.leftSideBearing.x = DOT6TOFIX(f26LeftSideBearing.x);
|
|
outputPtr->metricInfo.leftSideBearing.y = DOT6TOFIX(f26LeftSideBearing.y);
|
|
|
|
/* just copy to 'Line' metrics */
|
|
|
|
outputPtr->metricInfo.devLeftSideBearingLine.x = outputPtr->metricInfo.devLeftSideBearing.x;
|
|
outputPtr->metricInfo.devLeftSideBearingLine.y = outputPtr->metricInfo.devLeftSideBearing.y;
|
|
outputPtr->metricInfo.leftSideBearingLine.x = outputPtr->metricInfo.leftSideBearing.x;
|
|
outputPtr->metricInfo.leftSideBearingLine.y = outputPtr->metricInfo.leftSideBearing.y;
|
|
|
|
error = sfac_ReadGlyphMetrics ( /* get non-dev adv width */
|
|
&key->ClientInfo,
|
|
key->ClientInfo.usGlyphIndex,
|
|
&key->usNonScaledAW,
|
|
&sNonScaledLSB);
|
|
|
|
if(error != NO_ERR)
|
|
{
|
|
return error;
|
|
}
|
|
|
|
fsg_UpdateAdvanceWidth (
|
|
&key->TransformInfo, /* scale the design adv width */
|
|
pvGlobalGS,
|
|
key->usNonScaledAW,
|
|
&outputPtr->metricInfo.advanceWidth );
|
|
|
|
pBMI = &outputPtr->bitMapInfo;
|
|
pBMI->bounds.left = pOrigB->left; /* return bbox to client */
|
|
pBMI->bounds.right = pOrigB->right;
|
|
pBMI->bounds.top = pOrigB->bottom; /* reversed! */
|
|
pBMI->bounds.bottom = pOrigB->top;
|
|
pBMI->rowBytes = (int16)usRowBytes;
|
|
pBMI->baseAddr = 0L;
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_1] = ulSbitOutSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_2] = ulSbitWorkSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_3] = 0L;
|
|
outputPtr->memorySizes[BITMAP_PTR_4] = 0L;
|
|
}
|
|
else /* if rasterizing from a contour */
|
|
{
|
|
if (key->TransformInfo.bPhaseShift)
|
|
{
|
|
fsg_45DegreePhaseShift (&key->pWorkSpaceAddr);
|
|
}
|
|
|
|
fsg_GetContourData(
|
|
&key->pWorkSpaceAddr,
|
|
&CList.afxXCoord,
|
|
&CList.afxYCoord,
|
|
&CList.asStartPoint,
|
|
&CList.asEndPoint,
|
|
&CList.abyOnCurve,
|
|
&CList.usContourCount);
|
|
|
|
error = fsc_RemoveDups(&CList); /* collapse dup'd points */
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
pGBMap = &key->GBMap; /* default to usual structure */
|
|
usRoundXMin = 1;
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
error = fsc_OverScaleOutline(&CList, usOverScale);
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
pGBMap = &key->OverGBMap; /* measure overscaled structure */
|
|
usRoundXMin = key->usOverScale;
|
|
}
|
|
|
|
fsg_GetWorkSpaceExtra(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->WScan.pchRBuffer));
|
|
key->WScan.lRMemSize = key->lExtraWorkSpace; /* use extra for MeasureGlyph workspace */
|
|
|
|
error = fsc_MeasureGlyph(
|
|
&CList,
|
|
pGBMap,
|
|
&key->WScan,
|
|
key->usScanType,
|
|
usRoundXMin);
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
Assert(key->WScan.lRMemSize < key->lExtraWorkSpace);
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
sOverScale = (int16)usOverScale;
|
|
|
|
if (inputPtr->param.gray.bMatchBBox) /* if bounding box is fixed */
|
|
{ /* the calc as if orig monochrome */
|
|
pOverG = &key->OverGBMap;
|
|
pOrigB->left = (int16)((mth_DivShiftLong(pOverG->fxMinX, sOverScale) + 31L) >> 6);
|
|
pOrigB->right = (int16)((mth_DivShiftLong(pOverG->fxMaxX, sOverScale) + 32L) >> 6);
|
|
pOrigB->bottom = (int16)((mth_DivShiftLong(pOverG->fxMinY, sOverScale) + 31L) >> 6);
|
|
pOrigB->top = (int16)((mth_DivShiftLong(pOverG->fxMaxY, sOverScale) + 32L) >> 6);
|
|
}
|
|
else /* if bounding box can grow */
|
|
{ /* then size to gray box */
|
|
pOverB = &key->OverGBMap.rectBounds;
|
|
pOrigB->left = mth_DivShiftShort(pOverB->left, sOverScale);
|
|
pOrigB->right = mth_DivShiftShort((int16)(pOverB->right + sOverScale - 1), sOverScale);
|
|
pOrigB->bottom = mth_DivShiftShort(pOverB->bottom, sOverScale);
|
|
pOrigB->top = mth_DivShiftShort((int16)(pOverB->top + sOverScale - 1), sOverScale);
|
|
}
|
|
}
|
|
|
|
fsg_CalcLSBsAndAdvanceWidths( /* use original size for all metrics */
|
|
&key->pWorkSpaceAddr,
|
|
INTTODOT6(pOrigB->left),
|
|
INTTODOT6(pOrigB->top),
|
|
&f26DevAdvanceWidth,
|
|
&f26DevLeftSideBearing,
|
|
&f26LeftSideBearing,
|
|
&f26DevLeftSideBearingLine,
|
|
&f26LeftSideBearingLine);
|
|
|
|
outputPtr->metricInfo.devAdvanceWidth.x = DOT6TOFIX(f26DevAdvanceWidth.x);
|
|
outputPtr->metricInfo.devAdvanceWidth.y = DOT6TOFIX(f26DevAdvanceWidth.y);
|
|
outputPtr->metricInfo.devLeftSideBearing.x = DOT6TOFIX(f26DevLeftSideBearing.x);
|
|
outputPtr->metricInfo.devLeftSideBearing.y = DOT6TOFIX(f26DevLeftSideBearing.y);
|
|
outputPtr->metricInfo.leftSideBearing.x = DOT6TOFIX(f26LeftSideBearing.x);
|
|
outputPtr->metricInfo.leftSideBearing.y = DOT6TOFIX(f26LeftSideBearing.y);
|
|
outputPtr->metricInfo.devLeftSideBearingLine.x = DOT6TOFIX(f26DevLeftSideBearingLine.x);
|
|
outputPtr->metricInfo.devLeftSideBearingLine.y = DOT6TOFIX(f26DevLeftSideBearingLine.y);
|
|
outputPtr->metricInfo.leftSideBearingLine.x = DOT6TOFIX(f26LeftSideBearingLine.x);
|
|
outputPtr->metricInfo.leftSideBearingLine.y = DOT6TOFIX(f26LeftSideBearingLine.y);
|
|
|
|
fsg_UpdateAdvanceWidth (&key->TransformInfo, pvGlobalGS, key->usNonScaledAW,
|
|
&outputPtr->metricInfo.advanceWidth);
|
|
|
|
MEMCPY(&key->metricInfo, &outputPtr->metricInfo, sizeof( metricsType ));
|
|
|
|
pBMI = &outputPtr->bitMapInfo;
|
|
pBMI->bounds.left = pOrigB->left; /* return bbox to client */
|
|
pBMI->bounds.right = pOrigB->right;
|
|
pBMI->bounds.top = pOrigB->bottom; /* reversed! */
|
|
pBMI->bounds.bottom = pOrigB->top;
|
|
pBMI->rowBytes = key->GBMap.sRowBytes;
|
|
pBMI->baseAddr = 0;
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
pBMI->rowBytes = ((pOrigB->right - pOrigB->left) + 3) & (-4);
|
|
key->GBMap.lMMemSize = (int32)pBMI->rowBytes * (int32)(pOrigB->top - pOrigB->bottom);
|
|
outputPtr->memorySizes[BITMAP_PTR_4] = (FS_MEMORY_SIZE) key->OverGBMap.lMMemSize;
|
|
}
|
|
outputPtr->usOverScale = key->usOverScale; /* only exists if gray scale defined */
|
|
|
|
key->GBMap.sRowBytes = pBMI->rowBytes;
|
|
outputPtr->memorySizes[BITMAP_PTR_1] = (FS_MEMORY_SIZE) key->GBMap.lMMemSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_2] = (FS_MEMORY_SIZE) key->WScan.lHMemSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_3] = (FS_MEMORY_SIZE) key->WScan.lVMemSize;
|
|
|
|
}
|
|
fsg_CheckWorkSpaceForFit(
|
|
&(key->WorkSpaceOffsets),
|
|
key->lExtraWorkSpace,
|
|
key->WScan.lRMemSize,
|
|
&(outputPtr->memorySizes[BITMAP_PTR_2]),
|
|
&(outputPtr->memorySizes[BITMAP_PTR_3]));
|
|
|
|
key->usBandType = FS_BANDINGOLD; /* assume old banding */
|
|
key->usBandWidth = 0;
|
|
key->bOutlineIsCached = FALSE; /* assume no caching */
|
|
|
|
fs_SetState(key,(INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH | SIZEKNOWN));
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[PRIVATE_FONT_SPACE_BASE] + outputPtr->memorySizes[PRIVATE_FONT_SPACE_BASE]);
|
|
|
|
STAT_OFF_FINDBMS; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_SizeOfOutlines (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
fs_SplineKey * key;
|
|
int32 ulSize;
|
|
ErrorCode error;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTGLYPH | SIZEKNOWN), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (sbit_IfBitmapFound(&key->SbitMono) && (key->usOverScale == 0))
|
|
{
|
|
return SBIT_OUTLINE_CACHE_ERR; /* can't cache sbits */
|
|
}
|
|
|
|
if(key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE])
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
key->WScan.pchRBuffer = (char *)fsg_QueryReusableMemory(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets));
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
ulSize = (uint32)sizeof( uint32 ); /* OUTLINESTAMP */
|
|
ulSize += (uint32)( sizeof( FS_MEMORY_SIZE ) * BITMAP_MEMORY_COUNT ); /* Memory Bases */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Outlines Exist (padded) */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Scan Type (padded) */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Glyph Index (padded) */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Outline Cache Size */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Gray Scale Over Factor */
|
|
ulSize += (uint32)( sizeof( uint32 )); /* Grid Fit Skipped Boolean */
|
|
ulSize += (uint32)sizeof( metricsType ); /* Metrics information */
|
|
ulSize += (uint32)sizeof( GlyphBitMap ); /* Glyph Bitmap */
|
|
ulSize += (uint32)sizeof( GlyphBitMap ); /* Gray Overscaled Bitmap */
|
|
ulSize += (uint32)sizeof( WorkScan ); /* Scanconverter Workspace */
|
|
ulSize += (uint32)key->WScan.lRMemSize; /* Reversal list */
|
|
ulSize += fsg_GetContourDataSize(&key->pWorkSpaceAddr); /* Contour Data */
|
|
ulSize += (uint32)sizeof( uint32 ); /* OUTLINESTAMP2 */
|
|
ALIGN(uint32, ulSize);
|
|
|
|
outputPtr->outlineCacheSize = ulSize;
|
|
key->ulGlyphOutlineSize = ulSize;
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_SaveOutlines (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
uint8 * pbyDest;
|
|
|
|
fs_SplineKey * key;
|
|
ErrorCode error;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTGLYPH | SIZEKNOWN), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if(key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE])
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
if( (outputPtr->memorySizes[BITMAP_PTR_2] == 0L) || (outputPtr->memorySizes[BITMAP_PTR_3] == 0L))
|
|
{
|
|
fsg_GetRealBitmapSizes(
|
|
&(key->WorkSpaceOffsets),
|
|
&outputPtr->memorySizes[BITMAP_PTR_2],
|
|
&outputPtr->memorySizes[BITMAP_PTR_3]);
|
|
}
|
|
|
|
pbyDest = (uint8 *)inputPtr->param.outlineCache;
|
|
|
|
*((uint32 *)pbyDest) = OUTLINESTAMP;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
*((FS_MEMORY_SIZE *)pbyDest) = outputPtr->memorySizes[BITMAP_PTR_1];
|
|
pbyDest += sizeof( FS_MEMORY_SIZE );
|
|
|
|
*((FS_MEMORY_SIZE *)pbyDest) = outputPtr->memorySizes[BITMAP_PTR_2];
|
|
pbyDest += sizeof( FS_MEMORY_SIZE );
|
|
|
|
*((FS_MEMORY_SIZE *)pbyDest) = outputPtr->memorySizes[BITMAP_PTR_3];
|
|
pbyDest += sizeof( FS_MEMORY_SIZE );
|
|
|
|
*((FS_MEMORY_SIZE *)pbyDest) = outputPtr->memorySizes[BITMAP_PTR_4];
|
|
pbyDest += sizeof( FS_MEMORY_SIZE );
|
|
|
|
/* Outlines exist state */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->bGlyphHasOutline;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Dropout control state */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->usScanType;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Glyph Index */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->ClientInfo.usGlyphIndex;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Outline Cache Size */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->ulGlyphOutlineSize;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Gray Over Scale Factor */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->usOverScale;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Grid Fit Skipped Boolean */
|
|
|
|
*((uint32 *)pbyDest) = (uint32)key->bGridFitSkipped;
|
|
pbyDest += sizeof( uint32 );
|
|
|
|
/* Glyph metrics */
|
|
|
|
MEMCPY(pbyDest, &key->metricInfo, sizeof(metricsType));
|
|
pbyDest += sizeof(metricsType);
|
|
|
|
/* Scan Converter Data Structures */
|
|
|
|
MEMCPY(pbyDest, &key->GBMap, sizeof(GlyphBitMap));
|
|
pbyDest += sizeof(GlyphBitMap);
|
|
|
|
MEMCPY(pbyDest, &key->OverGBMap, sizeof(GlyphBitMap));
|
|
pbyDest += sizeof(GlyphBitMap);
|
|
|
|
MEMCPY(pbyDest, &key->WScan, sizeof(WorkScan));
|
|
pbyDest += sizeof(WorkScan);
|
|
|
|
MEMCPY(pbyDest, key->WScan.pchRBuffer, (size_t)key->WScan.lRMemSize);
|
|
pbyDest += key->WScan.lRMemSize;
|
|
|
|
/*** save charData ***/
|
|
|
|
fsg_DumpContourData(&key->pWorkSpaceAddr, &pbyDest);
|
|
|
|
*((uint32 *)pbyDest) = OUTLINESTAMP2;
|
|
|
|
fs_SetState(key,(INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH | SIZEKNOWN));
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_RestoreOutlines (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
fs_SplineKey * key;
|
|
uint8 * pbySrc;
|
|
ErrorCode error;
|
|
|
|
key = fs_SetUpKey(inputPtr, INITIALIZED, &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
pbySrc = (uint8 *)inputPtr->param.outlineCache;
|
|
|
|
if ( *((uint32 *)pbySrc) != OUTLINESTAMP )
|
|
{
|
|
return TRASHED_OUTLINE_CACHE;
|
|
}
|
|
pbySrc += sizeof(uint32);
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_1] = *((FS_MEMORY_SIZE *)pbySrc);
|
|
pbySrc += sizeof( FS_MEMORY_SIZE );
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_2] = *((FS_MEMORY_SIZE *)pbySrc);
|
|
pbySrc += sizeof( FS_MEMORY_SIZE );
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_3] = *((FS_MEMORY_SIZE *)pbySrc);
|
|
pbySrc += sizeof( FS_MEMORY_SIZE );
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_4] = *((FS_MEMORY_SIZE *)pbySrc);
|
|
pbySrc += sizeof( FS_MEMORY_SIZE );
|
|
|
|
/* Read in GlyphHasOutline */
|
|
|
|
outputPtr->outlinesExist = (uint16)(*((uint32 *)pbySrc));
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Read ScanType state */
|
|
|
|
key->usScanType = (uint16)(*((uint32 *)pbySrc));
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Read Glyph Index */
|
|
|
|
outputPtr->glyphIndex = (uint16)(*((uint32 *)pbySrc));
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Read Size of Outline Cache */
|
|
|
|
outputPtr->outlineCacheSize = (uint16)(*((uint32 *)pbySrc));
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Read Gray Over Scale Factor */
|
|
|
|
key->usOverScale = (uint16)(*((uint32 *)pbySrc));
|
|
outputPtr->usOverScale = key->usOverScale;
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Grid Fit Skipped Boolean */
|
|
|
|
key->bGridFitSkipped = (boolean)(*((uint32 *)pbySrc));
|
|
pbySrc += sizeof( uint32 );
|
|
|
|
/* Load fs_FindBitmapSize metrics */
|
|
|
|
MEMCPY(&outputPtr->metricInfo, pbySrc, sizeof(metricsType));
|
|
pbySrc += sizeof(metricsType);
|
|
|
|
/* Load ScanConverter data structures */
|
|
|
|
MEMCPY(&key->GBMap, pbySrc, sizeof(GlyphBitMap));
|
|
pbySrc += sizeof(GlyphBitMap);
|
|
|
|
MEMCPY(&key->OverGBMap, pbySrc, sizeof(GlyphBitMap));
|
|
pbySrc += sizeof(GlyphBitMap);
|
|
|
|
MEMCPY(&key->WScan, pbySrc, sizeof(WorkScan));
|
|
pbySrc += sizeof(WorkScan);
|
|
|
|
key->WScan.pchRBuffer = (char *)pbySrc;
|
|
pbySrc += key->WScan.lRMemSize;
|
|
|
|
fsg_RestoreContourData(
|
|
&pbySrc,
|
|
&outputPtr->xPtr,
|
|
&outputPtr->yPtr,
|
|
&outputPtr->startPtr,
|
|
&outputPtr->endPtr,
|
|
&outputPtr->onCurve,
|
|
&outputPtr->numberOfContours);
|
|
|
|
outputPtr->bitMapInfo.baseAddr = NULL;
|
|
outputPtr->bitMapInfo.rowBytes = key->GBMap.sRowBytes;
|
|
outputPtr->bitMapInfo.bounds.left = key->GBMap.rectBounds.left;
|
|
outputPtr->bitMapInfo.bounds.right = key->GBMap.rectBounds.right;
|
|
outputPtr->bitMapInfo.bounds.top = key->GBMap.rectBounds.bottom; /* reversed! */
|
|
outputPtr->bitMapInfo.bounds.bottom = key->GBMap.rectBounds.top;
|
|
|
|
outputPtr->scaledCVT = NULL;
|
|
outputPtr->numberOfBytesTaken = 0;
|
|
|
|
key->usBandType = FS_BANDINGOLD; /* assume old banding */
|
|
key->usBandWidth = 0;
|
|
key->apbPrevMemoryBases[BITMAP_PTR_2] = NULL; /* for fast/faster check */
|
|
key->apbPrevMemoryBases[BITMAP_PTR_3] = NULL;
|
|
|
|
key->bOutlineIsCached = TRUE;
|
|
|
|
fs_SetState(key,(INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH | SIZEKNOWN));
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Calculate memory requirements for banding */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_FindBandingSize (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__FindBandingSize(inputPtr, outputPtr, FALSE);
|
|
}
|
|
|
|
/* This function serves fs_FindBandingSize and fs_FindGrayBandingSize */
|
|
|
|
FS_PRIVATE FS_ENTRY fs__FindBandingSize (
|
|
fs_GlyphInputType *inputPtr,
|
|
fs_GlyphInfoType *outputPtr,
|
|
boolean bGrayScale )
|
|
{
|
|
ErrorCode error;
|
|
fs_SplineKey * key;
|
|
uint8 * pbyOutline;
|
|
int16 sMaxOvershoot;
|
|
int16 sHiOvershoot;
|
|
int16 sLoOvershoot;
|
|
GlyphBitMap * pGBMap; /* orig or over pointer */
|
|
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH | SIZEKNOWN), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if ((bGrayScale && (key->usOverScale == 0)) || (!bGrayScale && (key->usOverScale != 0)))
|
|
{
|
|
return GRAY_SEQUENCE_ERR;
|
|
}
|
|
if (key->bGridFitSkipped)
|
|
{
|
|
return SBIT_BANDING_ERR; /* can't band sbits */
|
|
}
|
|
|
|
if( !key->bOutlineIsCached )
|
|
{
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
key->WScan.pchRBuffer = (char *)fsg_QueryReusableMemory(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets));
|
|
}
|
|
else
|
|
{
|
|
/* Unload the outline cache */
|
|
|
|
pbyOutline = (uint8 *)inputPtr->param.band.outlineCache;
|
|
|
|
if( *((uint32 *)pbyOutline) != OUTLINESTAMP )
|
|
{
|
|
return TRASHED_OUTLINE_CACHE;
|
|
}
|
|
|
|
pbyOutline += sizeof( uint32 ) +
|
|
(BITMAP_MEMORY_COUNT * sizeof (FS_MEMORY_SIZE)) /* !!! Skip over stamp & 3 bitmap sizes */
|
|
+ sizeof( uint32 ) /* Outlines Exist (padded) */
|
|
+ sizeof( uint32 ) /* Scan Type (padded) */
|
|
+ sizeof( uint32 ) /* Glyph Index (padded) */
|
|
+ sizeof( uint32 ) /* Outline Cache Size */
|
|
+ sizeof( uint32 ) /* Gray Over Scale Factor */
|
|
+ sizeof( uint32 ) /* Grid Fit Skipped Boolean */
|
|
+ sizeof( metricsType ) /* Metrics information */
|
|
+ sizeof( GlyphBitMap )
|
|
+ sizeof( GlyphBitMap ) /* Over Scale structure */
|
|
+ sizeof( WorkScan );
|
|
|
|
key->WScan.pchRBuffer = (char *)pbyOutline;
|
|
|
|
/* No need to further unload outline cache */
|
|
}
|
|
|
|
pGBMap = &key->GBMap; /* default usual structure */
|
|
key->usBandWidth = inputPtr->param.band.usBandWidth;
|
|
key->usBandType = inputPtr->param.band.usBandType;
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
pGBMap = &key->OverGBMap; /* measure overscaled structure */
|
|
key->usBandWidth *= key->usOverScale;
|
|
/*
|
|
* Band width for the over scaled bitmap is basically just the requested band
|
|
* width times the overscale factor. However! if the gray scaled bounding
|
|
* box has been trimmed to match the monochrome box (i.e. bMatchBBox = TRUE),
|
|
* then top and bottom bands must be made bigger to include the entire over
|
|
* scaled bitmap. If this were not done it would break dropout control, and
|
|
* bitmaps would change with banding. So that's why we do this messing around
|
|
* with overshoot in the key->usBandWidth calculation.
|
|
*/
|
|
sMaxOvershoot = 0;
|
|
sHiOvershoot = (int16)(key->OverGBMap.rectBounds.top -
|
|
key->GBMap.rectBounds.top * (int16)key->usOverScale);
|
|
if (sHiOvershoot > sMaxOvershoot)
|
|
{
|
|
sMaxOvershoot = sHiOvershoot;
|
|
}
|
|
sLoOvershoot = (int16)(key->GBMap.rectBounds.bottom * (int16)key->usOverScale -
|
|
key->OverGBMap.rectBounds.bottom);
|
|
if (sLoOvershoot > sMaxOvershoot)
|
|
{
|
|
sMaxOvershoot = sLoOvershoot;
|
|
}
|
|
key->usBandWidth += (uint16)sMaxOvershoot;
|
|
}
|
|
|
|
error = fsc_MeasureBand(
|
|
pGBMap, /* orig or over scaled bounding box, etc. */
|
|
&key->WScan,
|
|
key->usBandType,
|
|
key->usBandWidth, /* worst case band width */
|
|
key->usScanType );
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
if (bGrayScale) /* if doing gray scale */
|
|
{
|
|
key->GBMap.lMMemSize = (int32)key->GBMap.sRowBytes * (int32)inputPtr->param.band.usBandWidth;
|
|
outputPtr->memorySizes[BITMAP_PTR_4] = (FS_MEMORY_SIZE) key->OverGBMap.lMMemSize;
|
|
}
|
|
|
|
outputPtr->memorySizes[BITMAP_PTR_1] = (FS_MEMORY_SIZE) key->GBMap.lMMemSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_2] = (FS_MEMORY_SIZE) key->WScan.lHMemSize;
|
|
outputPtr->memorySizes[BITMAP_PTR_3] = (FS_MEMORY_SIZE) key->WScan.lVMemSize;
|
|
|
|
if( !key->bOutlineIsCached )
|
|
{
|
|
fsg_CheckWorkSpaceForFit(
|
|
&(key->WorkSpaceOffsets),
|
|
key->lExtraWorkSpace,
|
|
key->WScan.lRMemSize, /* MeasureGlyph workspace */
|
|
&(outputPtr->memorySizes[BITMAP_PTR_2]),
|
|
&(outputPtr->memorySizes[BITMAP_PTR_3]));
|
|
}
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
if( !key->bOutlineIsCached )
|
|
{
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
}
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
/* Generate a bitmap */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_ContourScan (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__ContourScan(inputPtr, outputPtr, FALSE);
|
|
}
|
|
|
|
/* This function serves fs_ContourScan and fs_ContourGrayScan */
|
|
|
|
FS_PRIVATE FS_ENTRY fs__ContourScan (
|
|
fs_GlyphInputType *inputPtr,
|
|
fs_GlyphInfoType *outputPtr,
|
|
boolean bGrayScale )
|
|
{
|
|
ContourList CList; /* newscan contour list type */
|
|
fs_SplineKey * key;
|
|
char * pBitmapPtr2;
|
|
char * pBitmapPtr3;
|
|
uint8 * pbyOutline;
|
|
ErrorCode error;
|
|
GlyphBitMap * pGBMap; /* orig or over pointer */
|
|
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
|
|
STAT_ON_SCAN; /* start STAT timer */
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH | SIZEKNOWN), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if ((bGrayScale && (key->usOverScale == 0)) || (!bGrayScale && (key->usOverScale != 0)))
|
|
{
|
|
return GRAY_SEQUENCE_ERR;
|
|
}
|
|
|
|
if( !key->bOutlineIsCached ) /* if outline or embedded bitmap */
|
|
{
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
|
|
if(key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE])
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
key->apbPrevMemoryBases[WORK_SPACE_BASE] = key->memoryBases[WORK_SPACE_BASE];
|
|
}
|
|
|
|
fsg_SetUpWorkSpaceBitmapMemory(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
key->memoryBases[BITMAP_PTR_2],
|
|
key->memoryBases[BITMAP_PTR_3],
|
|
&pBitmapPtr2, /* sbits may need Ptr2 */
|
|
&pBitmapPtr3);
|
|
|
|
/* check for embedded bitmap, quick return if found */
|
|
|
|
if (sbit_IfBitmapFound(&key->SbitMono) && /* if using an embedded bitmap */
|
|
(!bGrayScale)) /* and not requesting grayscale */
|
|
{
|
|
if ((inputPtr->param.scan.topClip > inputPtr->param.scan.bottomClip) && /* if legal band */
|
|
((inputPtr->param.scan.topClip < key->GBMap.rectBounds.top) ||
|
|
(inputPtr->param.scan.bottomClip > key->GBMap.rectBounds.bottom)))
|
|
{
|
|
return SBIT_BANDING_ERR; /* can't band sbits */
|
|
}
|
|
|
|
error = sbit_GetBitmap (
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
(uint8 *) inputPtr->memoryBases[BITMAP_PTR_1],
|
|
(uint8 *) pBitmapPtr2 );
|
|
|
|
if (error != NO_ERR)
|
|
{
|
|
return((FS_ENTRY)error);
|
|
}
|
|
outputPtr->bitMapInfo.baseAddr = key->memoryBases[BITMAP_PTR_1]; /* return bitmap addr */
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
|
|
STAT_OFF_SCAN; /* stop STAT timer */
|
|
|
|
return NO_ERR; /* return now with an sbit */
|
|
}
|
|
else /* if scan converting an outline */
|
|
{
|
|
fsg_GetWorkSpaceExtra(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->WScan.pchRBuffer));
|
|
|
|
fsg_GetContourData(
|
|
&key->pWorkSpaceAddr,
|
|
&CList.afxXCoord,
|
|
&CList.afxYCoord,
|
|
&CList.asStartPoint,
|
|
&CList.asEndPoint,
|
|
&CList.abyOnCurve,
|
|
&CList.usContourCount);
|
|
}
|
|
}
|
|
else /* Unload the outline cache */
|
|
{
|
|
pbyOutline = (uint8 *)inputPtr->param.scan.outlineCache;
|
|
|
|
if( *((uint32 *)pbyOutline) != OUTLINESTAMP )
|
|
{
|
|
return TRASHED_OUTLINE_CACHE;
|
|
}
|
|
|
|
pbyOutline += sizeof( uint32 ) +
|
|
(BITMAP_MEMORY_COUNT * sizeof (FS_MEMORY_SIZE)) /* !!! Skip over stamp & 3 bitmap sizes */
|
|
+ sizeof( uint32 ) /* Outlines Exist (padded) */
|
|
+ sizeof( uint32 ) /* Scan Type (padded) */
|
|
+ sizeof( uint32 ) /* Glyph Index (padded) */
|
|
+ sizeof( uint32 ) /* Outline Cache Size */
|
|
+ sizeof( uint32 ) /* Gray Over Scale Factor */
|
|
+ sizeof( uint32 ) /* Grid Fit Skipped Boolean */
|
|
+ sizeof( metricsType ) /* Metrics information */
|
|
+ sizeof( GlyphBitMap )
|
|
+ sizeof( GlyphBitMap ) /* Over Scale structure */
|
|
+ sizeof( WorkScan );
|
|
|
|
key->WScan.pchRBuffer = (char *)pbyOutline;
|
|
pbyOutline += key->WScan.lRMemSize;
|
|
|
|
fsg_RestoreContourData(
|
|
&pbyOutline,
|
|
&CList.afxXCoord,
|
|
&CList.afxYCoord,
|
|
&CList.asStartPoint,
|
|
&CList.asEndPoint,
|
|
&CList.abyOnCurve,
|
|
&CList.usContourCount);
|
|
|
|
if( *((uint32 *)pbyOutline) != OUTLINESTAMP2 )
|
|
{
|
|
return TRASHED_OUTLINE_CACHE;
|
|
}
|
|
|
|
pBitmapPtr2 = key->memoryBases[BITMAP_PTR_2];
|
|
pBitmapPtr3 = key->memoryBases[BITMAP_PTR_3];
|
|
}
|
|
|
|
if (pBitmapPtr3 == NULL) /* Allow client to turn off DOControl */
|
|
{
|
|
key->usScanType = SK_NODROPOUT;
|
|
}
|
|
|
|
key->GBMap.pchBitMap = inputPtr->memoryBases[BITMAP_PTR_1];
|
|
key->GBMap.sHiBand = inputPtr->param.scan.topClip;
|
|
key->GBMap.sLoBand = inputPtr->param.scan.bottomClip;
|
|
|
|
if (key->GBMap.sHiBand <= key->GBMap.sLoBand) /* if negative or no band */
|
|
{
|
|
key->GBMap.sHiBand = key->GBMap.rectBounds.top; /* then for Apple compatiblity */
|
|
key->GBMap.sLoBand = key->GBMap.rectBounds.bottom; /* do the entire bitmap */
|
|
}
|
|
if (key->GBMap.sHiBand > key->GBMap.rectBounds.top)
|
|
{
|
|
key->GBMap.sHiBand = key->GBMap.rectBounds.top; /* clip to bounding box */
|
|
}
|
|
if (key->GBMap.sLoBand < key->GBMap.rectBounds.bottom)
|
|
{
|
|
key->GBMap.sLoBand = key->GBMap.rectBounds.bottom; /* clip to bounding box */
|
|
}
|
|
|
|
if ((key->usBandType == FS_BANDINGFASTER) &&
|
|
((key->apbPrevMemoryBases[BITMAP_PTR_2] != pBitmapPtr2) ||
|
|
(key->apbPrevMemoryBases[BITMAP_PTR_3] != pBitmapPtr3)))
|
|
{
|
|
key->usBandType = FS_BANDINGFAST; /* to recalculate memory */
|
|
}
|
|
|
|
if (key->usBandType == FS_BANDINGOLD) /* if FindGrayBandingSize wasn't called */
|
|
{
|
|
if ((key->GBMap.sHiBand != key->GBMap.rectBounds.top) ||
|
|
(key->GBMap.sLoBand != key->GBMap.rectBounds.bottom)) /* if banding */
|
|
{
|
|
if (bGrayScale)
|
|
{
|
|
return GRAY_OLD_BANDING_ERR; /* gray scale fails with old banding */
|
|
}
|
|
key->usScanType = SK_NODROPOUT; /* else force dropout off */
|
|
}
|
|
}
|
|
else if (key->usBandType == FS_BANDINGSMALL) /* if small mem type */
|
|
{
|
|
if (key->GBMap.sHiBand - key->GBMap.sLoBand > (int16)key->usBandWidth)
|
|
{
|
|
return BAND_TOO_BIG_ERR; /* don't let band exceed calc'd size */
|
|
}
|
|
key->usScanType = SK_NODROPOUT; /* turn off dropout control */
|
|
}
|
|
pGBMap = &key->GBMap; /* default to usual structure */
|
|
|
|
if (bGrayScale)
|
|
{
|
|
pGBMap = &key->OverGBMap; /* measure overscaled structure */
|
|
|
|
if (key->GBMap.sHiBand == key->GBMap.rectBounds.top) /* if gray band at top */
|
|
{
|
|
key->OverGBMap.sHiBand = key->OverGBMap.rectBounds.top; /* use over top */
|
|
}
|
|
else
|
|
{
|
|
key->OverGBMap.sHiBand = (int16)(key->GBMap.sHiBand * (int16)key->usOverScale);
|
|
if (key->OverGBMap.sHiBand > key->OverGBMap.rectBounds.top)
|
|
{
|
|
key->OverGBMap.sHiBand = key->OverGBMap.rectBounds.top; /* clip */
|
|
}
|
|
}
|
|
if (key->GBMap.sLoBand == key->GBMap.rectBounds.bottom) /* if gray band at bottom */
|
|
{
|
|
key->OverGBMap.sLoBand = key->OverGBMap.rectBounds.bottom; /* use over bottom */
|
|
}
|
|
else
|
|
{
|
|
key->OverGBMap.sLoBand = (int16)(key->GBMap.sLoBand * (int16)key->usOverScale);
|
|
if (key->OverGBMap.sLoBand < key->OverGBMap.rectBounds.bottom)
|
|
{
|
|
key->OverGBMap.sLoBand = key->OverGBMap.rectBounds.bottom; /* clip */
|
|
}
|
|
}
|
|
key->OverGBMap.pchBitMap = inputPtr->memoryBases[BITMAP_PTR_4];
|
|
}
|
|
|
|
key->WScan.pchHBuffer = pBitmapPtr2;
|
|
key->WScan.pchVBuffer = pBitmapPtr3;
|
|
|
|
error = fsc_FillGlyph(
|
|
&CList,
|
|
pGBMap,
|
|
&key->WScan,
|
|
key->usBandType,
|
|
key->usScanType
|
|
);
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
if (bGrayScale)
|
|
{
|
|
error = fsc_CalcGrayMap(
|
|
&key->OverGBMap,
|
|
&key->GBMap,
|
|
key->usOverScale
|
|
);
|
|
if (error != NO_ERR)
|
|
{
|
|
return((FS_ENTRY)error);
|
|
}
|
|
}
|
|
|
|
/* Setting the Band Type to FS_BANDINGFASTER will allow the next call */
|
|
/* to fsc_FillGlyph to skip the rendering phase of scan conversion and */
|
|
/* get right to the bitmap fill. If the client moves either memoryBase[6] */
|
|
/* or memoryBase[7] between fs_ContourScan calls, then we must reset the */
|
|
/* band type to FS_BANDINGFAST to regenerate the data structures. */
|
|
|
|
if (key->usBandType == FS_BANDINGFAST)
|
|
{
|
|
key->usBandType = FS_BANDINGFASTER; /* to save re-rendering */
|
|
key->apbPrevMemoryBases[BITMAP_PTR_2] = pBitmapPtr2;
|
|
key->apbPrevMemoryBases[BITMAP_PTR_3] = pBitmapPtr3;
|
|
}
|
|
|
|
outputPtr->bitMapInfo.baseAddr = key->memoryBases[BITMAP_PTR_1]; /* return bitmap addr */
|
|
|
|
CHECKSTAMP(inputPtr->memoryBases[KEY_PTR_BASE] + outputPtr->memorySizes[KEY_PTR_BASE]);
|
|
if( !key->bOutlineIsCached )
|
|
{
|
|
CHECKSTAMP(inputPtr->memoryBases[WORK_SPACE_BASE] + outputPtr->memorySizes[WORK_SPACE_BASE]);
|
|
}
|
|
|
|
STAT_OFF_SCAN; /* stop STAT timer */
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_CloseFonts (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
FS_UNUSED_PARAMETER(inputPtr);
|
|
FS_UNUSED_PARAMETER(outputPtr);
|
|
return NO_ERR;
|
|
}
|
|
|
|
#ifdef FSCFG_NO_INITIALIZED_DATA
|
|
FS_PUBLIC void FS_ENTRY_PROTO fs_InitializeData (void)
|
|
{
|
|
fsg_InitializeData ();
|
|
}
|
|
#endif
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/*** Gray Scale Functions ***/
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Calculate gray scale scan conversion memory requirements */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_FindGraySize (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__FindSize(inputPtr, outputPtr, TRUE);
|
|
}
|
|
|
|
/* Calculate gray scale memory requirements for banding */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_FindGrayBandingSize (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__FindBandingSize(inputPtr, outputPtr, TRUE);
|
|
}
|
|
|
|
/* Generate a gray scale bitmap */
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_ContourGrayScan (fs_GlyphInputType *inputPtr, fs_GlyphInfoType *outputPtr)
|
|
{
|
|
return fs__ContourScan(inputPtr, outputPtr, TRUE);
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_GetScaledAdvanceWidths (
|
|
fs_GlyphInputType * inputPtr,
|
|
uint16 usFirstGlyph,
|
|
uint16 usLastGlyph,
|
|
int16 * psGlyphWidths)
|
|
{
|
|
fs_SplineKey * key;
|
|
void * pvGlobalGS;
|
|
void * pvStack;
|
|
void * pvFontProgram;
|
|
void * pvPreProgram;
|
|
void * pvTwilightZone;
|
|
uint16 usCurrentGlyphIndex;
|
|
uint16 usGlyphIndex;
|
|
uint16 usPPEm;
|
|
uint16 usPPEMX;
|
|
uint16 usPPEMY;
|
|
uint16 usRotation;
|
|
int16 sNonScaledLSB;
|
|
vectorType fxGlyphWidth;
|
|
point f26DevAdvanceWidth;
|
|
boolean bHdmxEntryExist;
|
|
boolean bBitmapFound;
|
|
ErrorCode error;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS ), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if((key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE]) ||
|
|
(key->apbPrevMemoryBases[PRIVATE_FONT_SPACE_BASE] != key->memoryBases[PRIVATE_FONT_SPACE_BASE]))
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvStack = fsg_QueryStack(&key->pWorkSpaceAddr);
|
|
|
|
fsg_UpdatePrivateSpaceAddresses(
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets),
|
|
pvStack,
|
|
&pvFontProgram,
|
|
&pvPreProgram);
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
/* Initialization */
|
|
|
|
bHdmxEntryExist = FALSE;
|
|
|
|
/* Save current glyph index */
|
|
|
|
usCurrentGlyphIndex = key->ClientInfo.usGlyphIndex;
|
|
|
|
/* Check input parameters */
|
|
|
|
if( (usLastGlyph > key->maxProfile.numGlyphs ) ||
|
|
(usLastGlyph < usFirstGlyph))
|
|
{
|
|
return INVALID_GLYPH_INDEX;
|
|
}
|
|
|
|
if( psGlyphWidths == NULL )
|
|
{
|
|
return NULL_INPUT_PTR_ERR;
|
|
}
|
|
|
|
/* Find our current PPEm */
|
|
|
|
fsg_QueryPPEM(pvGlobalGS, &usPPEm);
|
|
fsg_QueryPPEMXY(pvGlobalGS, &key->TransformInfo, &usPPEMX, &usPPEMY, &usRotation);
|
|
|
|
/* Only Grab 'hdmx' if not stretched or rotated */
|
|
|
|
if( (!fsg_IsTransformStretched( &key->TransformInfo )) &&
|
|
(!fsg_IsTransformRotated( &key->TransformInfo )) )
|
|
{
|
|
|
|
/* Check if we can quickly grab the widths from the 'hdmx' table */
|
|
|
|
error = sfac_CopyHdmxEntry(
|
|
&key->ClientInfo,
|
|
usPPEm,
|
|
&bHdmxEntryExist,
|
|
usFirstGlyph,
|
|
usLastGlyph,
|
|
psGlyphWidths);
|
|
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
/* If we got a hit on the 'hdmx' we are done */
|
|
|
|
if( bHdmxEntryExist )
|
|
{
|
|
return NO_ERR;
|
|
}
|
|
}
|
|
|
|
/* No hit on 'hmdx', now it is time for the dirty work */
|
|
|
|
/* We need to prepare ourselves here for a potential grid fit */
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvTwilightZone = fsg_QueryTwilightElement(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
/* potentially do delayed pre program execution */
|
|
|
|
if (key->bExecutePrePgm)
|
|
{
|
|
/* Run the pre program and scale the control value table */
|
|
|
|
key->bExecutePrePgm = FALSE;
|
|
|
|
error = fsg_RunPreProgram (
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
&key->pWorkSpaceAddr,
|
|
pvTwilightZone,
|
|
NULL);
|
|
|
|
if(error)
|
|
{
|
|
/* If the pre-program fails, prevent further glyphs from being called */
|
|
fs_SetState(key, (INITIALIZED | NEWSFNT));
|
|
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
|
|
/* Now check 'LTSH' table for linear cutoff information */
|
|
|
|
error = sfac_GetLTSHEntries(
|
|
&key->ClientInfo,
|
|
usPPEm,
|
|
usFirstGlyph,
|
|
usLastGlyph,
|
|
psGlyphWidths);
|
|
|
|
/* The pfxGlyphWidths array contains a boolean for each glyph (from */
|
|
/* first glyph to last glyph) that indicates if the glyph scales */
|
|
/* linearly. */
|
|
|
|
/* Handle each glyph */
|
|
|
|
for( usGlyphIndex = usFirstGlyph; usGlyphIndex <= usLastGlyph; usGlyphIndex++)
|
|
{
|
|
if( (psGlyphWidths[usGlyphIndex - usFirstGlyph]) &&
|
|
(!fsg_IsTransformStretched( &key->TransformInfo )) &&
|
|
(!fsg_IsTransformRotated( &key->TransformInfo )) )
|
|
{
|
|
/* Glyph Scales Linearly */
|
|
|
|
error = sfac_ReadGlyphMetrics (
|
|
&key->ClientInfo,
|
|
usGlyphIndex,
|
|
&key->usNonScaledAW,
|
|
&sNonScaledLSB);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fsg_UpdateAdvanceWidth (
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
key->usNonScaledAW,
|
|
&fxGlyphWidth);
|
|
|
|
psGlyphWidths[usGlyphIndex - usFirstGlyph] = (int16)((fxGlyphWidth.x + ONEHALFFIX) >> 16);
|
|
}
|
|
else /* Glyph does not scale linearly */
|
|
{
|
|
error = LookForSbitWidth (
|
|
key,
|
|
usGlyphIndex,
|
|
usPPEMX,
|
|
usPPEMY,
|
|
usRotation,
|
|
&bBitmapFound,
|
|
&f26DevAdvanceWidth ); /* value returned if found */
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (bBitmapFound == FALSE)
|
|
{
|
|
/* Glyph needs to be grid fitted */
|
|
|
|
key->ClientInfo.usGlyphIndex = usGlyphIndex;
|
|
|
|
error = fsg_GridFit (
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
&key->pWorkSpaceAddr,
|
|
pvTwilightZone,
|
|
(FntTraceFunc)NULL,
|
|
TRUE,
|
|
&key->usScanType,
|
|
&key->bGlyphHasOutline,
|
|
&key->usNonScaledAW );
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fsg_GetDevAdvanceWidth (
|
|
&key->pWorkSpaceAddr,
|
|
&f26DevAdvanceWidth );
|
|
}
|
|
psGlyphWidths[(size_t)(usGlyphIndex - usFirstGlyph)] = (int16)((f26DevAdvanceWidth.x + DOT6ONEHALF) >> 6);
|
|
}
|
|
}
|
|
|
|
/* Restore current glyph */
|
|
|
|
key->ClientInfo.usGlyphIndex = usCurrentGlyphIndex;
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Look for an embedded bitmap, if found return the advance width */
|
|
|
|
FS_PRIVATE FS_ENTRY LookForSbitWidth(
|
|
fs_SplineKey *key,
|
|
uint16 usGlyphIndex,
|
|
uint16 usPPEMX,
|
|
uint16 usPPEMY,
|
|
uint16 usRotation,
|
|
boolean *pbBitmapFound,
|
|
point *pf26DevAdvanceWidth )
|
|
{
|
|
uint16 usFoundCode;
|
|
ErrorCode error;
|
|
|
|
*pbBitmapFound = FALSE; /* default value */
|
|
|
|
error = sbit_SearchForBitmap(
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
usPPEMX,
|
|
usPPEMY,
|
|
usRotation,
|
|
usGlyphIndex,
|
|
&usFoundCode );
|
|
|
|
if (error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (usFoundCode != 0)
|
|
{
|
|
error = sbit_GetDevAdvanceWidth (
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
pf26DevAdvanceWidth );
|
|
|
|
if (error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
*pbBitmapFound = TRUE;
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Vertical Metrics Helper Function */
|
|
|
|
/* returns AdvanceHeight and TopSideBearing vectors for glyph range */
|
|
|
|
/*********************************************************************/
|
|
|
|
extern FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_GetScaledVerticalMetrics (
|
|
fs_GlyphInputType * inputPtr,
|
|
uint16 usFirstGlyph,
|
|
uint16 usLastGlyph,
|
|
shortVector * psvAdvanceHeights,
|
|
shortVector * psvTopSideBearings)
|
|
{
|
|
fs_SplineKey * key;
|
|
void * pvGlobalGS;
|
|
void * pvFontProgram;
|
|
void * pvPreProgram;
|
|
void * pvStack;
|
|
uint16 usGlyphIndex;
|
|
uint16 usPPEm;
|
|
uint16 usPPEMX;
|
|
uint16 usPPEMY;
|
|
uint16 usRotation;
|
|
uint16 usNumLongVertMetrics; /* number of entries with AH */
|
|
uint16 usNonScaledAH; /* advance height from vmtx */
|
|
int16 sNonScaledTSB; /* top side bearing from vmtx */
|
|
shortVector svDevAdvanceHeight; /* advance height from sbits */
|
|
shortVector svDevTopSideBearing; /* top side bearing from sbits */
|
|
vectorType vecAdvanceHeight;
|
|
vectorType vecTopSideBearing;
|
|
point f26DevAdvanceHeight;
|
|
point f26DevTopSideBearing;
|
|
boolean bBitmapFound;
|
|
ErrorCode error;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS ), &error);
|
|
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if((key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE]) ||
|
|
(key->apbPrevMemoryBases[PRIVATE_FONT_SPACE_BASE] != key->memoryBases[PRIVATE_FONT_SPACE_BASE]))
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
pvStack = fsg_QueryStack(&key->pWorkSpaceAddr);
|
|
|
|
fsg_UpdatePrivateSpaceAddresses(
|
|
&key->ClientInfo,
|
|
&key->maxProfile,
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets),
|
|
pvStack,
|
|
&pvFontProgram,
|
|
&pvPreProgram);
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
pvGlobalGS = fsg_QueryGlobalGS(
|
|
key->memoryBases[PRIVATE_FONT_SPACE_BASE],
|
|
&(key->PrivateSpaceOffsets));
|
|
|
|
/* Check input parameters */
|
|
|
|
if( (usLastGlyph > key->maxProfile.numGlyphs ) ||
|
|
(usLastGlyph < usFirstGlyph))
|
|
{
|
|
return INVALID_GLYPH_INDEX;
|
|
}
|
|
|
|
/* At least one of the output pointers should be real */
|
|
|
|
if(( psvAdvanceHeights == NULL ) && ( psvTopSideBearings == NULL ))
|
|
{
|
|
return NULL_INPUT_PTR_ERR;
|
|
}
|
|
|
|
/* Find our current PPEm */
|
|
|
|
fsg_QueryPPEM(pvGlobalGS, &usPPEm);
|
|
fsg_QueryPPEMXY(pvGlobalGS, &key->TransformInfo, &usPPEMX, &usPPEMY, &usRotation);
|
|
|
|
/* Check the limits of the vmtx table */
|
|
|
|
error = sfac_ReadNumLongVertMetrics(&key->ClientInfo, &usNumLongVertMetrics);
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
/* Handle each glyph */
|
|
|
|
for( usGlyphIndex = usFirstGlyph; usGlyphIndex <= usLastGlyph; usGlyphIndex++)
|
|
{
|
|
error = LookForSbitVertMetrics (
|
|
key,
|
|
usGlyphIndex,
|
|
usPPEMX,
|
|
usPPEMY,
|
|
usRotation,
|
|
&bBitmapFound,
|
|
&f26DevAdvanceHeight,
|
|
&f26DevTopSideBearing ); /* values returned if found */
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (bBitmapFound) /* if bitmap metrics found */
|
|
{
|
|
svDevAdvanceHeight.x = (int16)((f26DevAdvanceHeight.x + DOT6ONEHALF) >> 6);
|
|
svDevAdvanceHeight.y = (int16)((f26DevAdvanceHeight.y + DOT6ONEHALF) >> 6);
|
|
svDevTopSideBearing.x = (int16)((f26DevTopSideBearing.x + DOT6ONEHALF) >> 6);
|
|
svDevTopSideBearing.y = (int16)((f26DevTopSideBearing.y + DOT6ONEHALF) >> 6);
|
|
}
|
|
else /* if (bBitmapFound == FALSE) if no bitmap, read vmtx */
|
|
{
|
|
error = sfac_ReadVerticalMetrics (
|
|
&key->ClientInfo,
|
|
usGlyphIndex,
|
|
usNumLongVertMetrics,
|
|
&usNonScaledAH,
|
|
&sNonScaledTSB);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
fsg_ScaleVerticalMetrics (
|
|
&key->TransformInfo,
|
|
pvGlobalGS,
|
|
usNonScaledAH,
|
|
sNonScaledTSB,
|
|
&vecAdvanceHeight,
|
|
&vecTopSideBearing);
|
|
|
|
svDevAdvanceHeight.x = (int16)((vecAdvanceHeight.x + ONEHALFFIX) >> 16);
|
|
svDevAdvanceHeight.y = (int16)((vecAdvanceHeight.y + ONEHALFFIX) >> 16);
|
|
svDevTopSideBearing.x = (int16)((vecTopSideBearing.x + ONEHALFFIX) >> 16);
|
|
svDevTopSideBearing.y = (int16)((vecTopSideBearing.y + ONEHALFFIX) >> 16);
|
|
}
|
|
|
|
if( psvAdvanceHeights != NULL )
|
|
{
|
|
*psvAdvanceHeights++ = svDevAdvanceHeight;
|
|
}
|
|
if( psvTopSideBearings != NULL )
|
|
{
|
|
*psvTopSideBearings++ = svDevTopSideBearing;
|
|
}
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Look for an embedded bitmap, if found return the advance width */
|
|
|
|
FS_PRIVATE FS_ENTRY LookForSbitVertMetrics(
|
|
fs_SplineKey *key,
|
|
uint16 usGlyphIndex,
|
|
uint16 usPPEMX,
|
|
uint16 usPPEMY,
|
|
uint16 usRotation,
|
|
boolean *pbBitmapFound,
|
|
point *pf26DevAdvanceHeight,
|
|
point *pf26DevTopSideBearing )
|
|
{
|
|
uint16 usFoundCode;
|
|
ErrorCode error;
|
|
|
|
*pbBitmapFound = FALSE; /* default value */
|
|
|
|
error = sbit_SearchForBitmap(
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
usPPEMX,
|
|
usPPEMY,
|
|
usRotation,
|
|
usGlyphIndex,
|
|
&usFoundCode );
|
|
|
|
if (error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
if (usFoundCode != 0)
|
|
{
|
|
error = sbit_GetVerticalMetrics (
|
|
&key->SbitMono,
|
|
&key->ClientInfo,
|
|
pbBitmapFound, /* set true if Vert metrics found */
|
|
pf26DevAdvanceHeight,
|
|
pf26DevTopSideBearing );
|
|
|
|
if (error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Char Code to Glyph ID Helper Function */
|
|
|
|
/* returns glyph IDs for array or range of character codes */
|
|
|
|
/*********************************************************************/
|
|
|
|
extern FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_GetGlyphIDs (
|
|
fs_GlyphInputType * inputPtr,
|
|
uint16 usCharCount,
|
|
uint16 usFirstChar,
|
|
uint16 * pusCharCode,
|
|
uint16 * pusGlyphID)
|
|
{
|
|
ErrorCode error;
|
|
fs_SplineKey * key;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
|
|
error = sfac_GetMultiGlyphIDs(
|
|
&key->ClientInfo,
|
|
usCharCount,
|
|
usFirstChar,
|
|
pusCharCode,
|
|
pusGlyphID);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Char Code to Glyph ID Helper Function */
|
|
|
|
/* specific to Win95 - needs no font context, just a cmap pointer */
|
|
|
|
/*********************************************************************/
|
|
|
|
extern FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_Win95GetGlyphIDs (
|
|
uint8 * pbyCmapSubTable,
|
|
uint16 usCharCount,
|
|
uint16 usFirstChar,
|
|
uint16 * pusCharCode,
|
|
uint16 * pusGlyphID)
|
|
{
|
|
ErrorCode error;
|
|
|
|
error = sfac_GetWin95GlyphIDs(
|
|
pbyCmapSubTable,
|
|
usCharCount,
|
|
usFirstChar,
|
|
pusCharCode,
|
|
pusGlyphID);
|
|
|
|
if(error)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
return NO_ERR;
|
|
}
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Outline Coordinates Helper Function */
|
|
|
|
/* returns (x,y) coordinates of array of points on the glyph outline */
|
|
|
|
/*********************************************************************/
|
|
|
|
extern FS_PUBLIC FS_ENTRY FS_ENTRY_PROTO fs_GetOutlineCoordinates (
|
|
fs_GlyphInputType * inputPtr,
|
|
uint16 usPointCount,
|
|
uint16 * pusPointIndex,
|
|
shortVector * psvCoordinates)
|
|
{
|
|
ErrorCode error;
|
|
ContourList CList; /* newscan contour list type */
|
|
fs_SplineKey * key;
|
|
|
|
key = fs_SetUpKey(inputPtr, (INITIALIZED | NEWSFNT | NEWTRANS | GOTINDEX | GOTGLYPH), &error);
|
|
if(!key)
|
|
{
|
|
return (FS_ENTRY)error;
|
|
}
|
|
if (key->ulState & SIZEKNOWN) /* fail a call after FindBimapSize */
|
|
{
|
|
return OUT_OFF_SEQUENCE_CALL_ERR;
|
|
}
|
|
|
|
if (key->bGlyphHasOutline == FALSE)
|
|
{
|
|
return BAD_POINT_INDEX_ERR; /* no meaning if no outlines */
|
|
}
|
|
|
|
if(key->apbPrevMemoryBases[WORK_SPACE_BASE] != key->memoryBases[WORK_SPACE_BASE])
|
|
{
|
|
fsg_UpdateWorkSpaceAddresses(
|
|
key->memoryBases[WORK_SPACE_BASE],
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
fsg_UpdateWorkSpaceElement(
|
|
&(key->WorkSpaceOffsets),
|
|
&(key->pWorkSpaceAddr));
|
|
|
|
MEMCPY(key->apbPrevMemoryBases, key->memoryBases, sizeof(char *) * (size_t)MEMORYFRAGMENTS);
|
|
}
|
|
|
|
fsg_GetContourData(
|
|
&key->pWorkSpaceAddr,
|
|
&CList.afxXCoord,
|
|
&CList.afxYCoord,
|
|
&CList.asStartPoint,
|
|
&CList.asEndPoint,
|
|
&CList.abyOnCurve,
|
|
&CList.usContourCount);
|
|
|
|
error = fsc_GetCoords(&CList, usPointCount, pusPointIndex, (PixCoord *)psvCoordinates);
|
|
if (error != NO_ERR)
|
|
{
|
|
return(error);
|
|
}
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*********************************************************************/
|