mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-22 23:29:27 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
437 lines
16 KiB
C
437 lines
16 KiB
C
/*
|
|
File: MacExtra.c
|
|
|
|
Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
This file is used in these builds: BigBang
|
|
|
|
Change History (most recent first):
|
|
|
|
<13> 6/22/92 JH #1033107 <AMW>: In Map256Chars, GetEncodingTable is called to
|
|
get the script ID and then GetFontMapInfo is called to get the
|
|
index to the cmap table. GetFontMapInfo uses the script ID
|
|
returned by GetEncodingTable, which now returns the right script
|
|
ID. However, with the old roman coded cmaps for Arabic using the
|
|
right script ID means these fonts won't get a proper widthtable
|
|
and will draw very, very poorly. To try and fix that if the
|
|
script ID isn't Roman and GetFontMapInfo returned 0, we call
|
|
GetFontMapInfo again using smRoman has the script ID the second
|
|
time around.
|
|
<12> 9/25/91 jlf Rolled in Pacific TrueType modifications.
|
|
Removed all 'sfnt' functions at bottom of file; functions have
|
|
been rewritten for partial font support. Modified fs_FillWidthTable:
|
|
doesn't load entire hmtx into memory now (necessary for Pacific
|
|
fonts); replaced references to sfnt_GetTablePtr with GetFontTablePtr;
|
|
replaced references to RELEASESFNTFRAG with QDUngetFontFrag. Added
|
|
doublebyte support to Map256Chars - doublebyte character widths are
|
|
mapped to the width of the missing glyph.
|
|
<11> 4/4/91 KON mrr, WRKSHT# RBN-BS-005: Outline condensed text was producing
|
|
negative width tables because styleExtra was negative. The fix
|
|
is if styleExtra is negative, pin the values in the width table
|
|
to zero.
|
|
<10> 12/15/90 PKE (with KSM) Delete include of OutlineCalls.h, which is now
|
|
obsolete since Darin moved everything in it into Fonts.h.
|
|
<9> 12/11/90 MR Undo "intelligent" rounding of descent and leading. [rb]
|
|
<8> 12/5/90 RB Detect case where scaled ymax-ymin is greater than QD coordinate
|
|
space. Return error.[CEL]
|
|
<7> 12/5/90 MR Device metrics now always fails if ppem > 255. Add SLOP to ymax
|
|
and ymin so quickdraw doesn't clip tall or low glyphs. [rb]
|
|
<6> 11/27/90 MR Be sure to use metricScalar for widthtable, corrected call to
|
|
FillDeviceWidths, changed Ceiling to ROUND, and added fancy
|
|
calculation for ascent and descent to improve accuracy. [rb]
|
|
<5> 11/13/90 MR New behavior: Never scale styleExtra, simply add it to the
|
|
(scaled) widths. [cl]
|
|
<4> 11/5/90 MR Look for device widths, even if the text is stretched. [rb]
|
|
<3> 10/30/90 CL (MR)Adding pascal glue for lowestRecPPEM.
|
|
<2> 10/20/90 MR Rev to use new math/scaling routines, simplify loops in
|
|
FillWidthTable, merge needed routines in from FontTools.c. [rb]
|
|
<20> 8/22/90 MR Change FillWidthTable to take sfnt handle and rsrc id and not
|
|
take fsInfoType
|
|
<19> 8/20/90 MR Add line-of-death to GetCheckSumAdj (which is now
|
|
fs_GetSfntInfo)
|
|
<18> 8/10/90 MR Rev. to new interface to ApplyFontMapping
|
|
<17> 7/23/90 MR Moved fonttool calls to fonttools.c
|
|
<16> 7/19/90 dba get rid of C warnings
|
|
<15> 7/18/90 MR Add call to Font2Script
|
|
<14> 7/14/90 MR undefined RELEASE_FRAG, changed DOUBLE_BYTE code, fillWidthTable
|
|
now builds glyph array up front instead of inline, cleaned up
|
|
parameters to charCode mapping functions in font toolbox
|
|
<13> 7/13/90 MR Add GetFontGlyph, use union in FSInput
|
|
<12> 6/26/90 MR Revise Toolbox calls, change script enums
|
|
<11> 6/21/90 MR Handle suffixIndex == 0 in GetPSFontName, add calls to
|
|
ReleaseSfntFrag
|
|
<10> 6/19/90 MR Add GetPSFontName and fixed bug in GetFontStringInfo and
|
|
GetFontMapInfo
|
|
<9> 6/5/90 MR Try adding FontUtilities
|
|
<8> 6/4/90 MR Clean up device metrics, simplify all loops
|
|
<7> 6/1/90 MR The MVT is dead! Let no one utter its foul name again.
|
|
<6> 5/29/90 CL Fixed double byte variables.
|
|
<5> 5/3/90 RB Mike added fs_GetCheckSumAdj.
|
|
<4> 4/10/90 CL Added script manager codes for Japanese.
|
|
mrr - Removed reference to fsinfo.error
|
|
<3> 3/20/90 CL Masks and macros for width table loops Added many greased loops
|
|
Modified to use fractional ppem (fpem) Added routine to return
|
|
CheckSumAdj Put x,y transform inline in FillLayoutInfo Add style
|
|
extra before stretch in rounded-xformed loop Changed c to INT
|
|
and use --count >= 0 in widthtable loops
|
|
<2> 2/27/90 CL New error code for missing but needed table. (0x1409 ). Fixed
|
|
transformed component bug.
|
|
<3.3> 11/14/89 CEL Adding in device metrics for width table.
|
|
<3.2> 9/25/89 CEL Added rounding of integer capability back in. This fixes the
|
|
smearing problem when fractenable is off.
|
|
<3.1> 9/15/89 CEL 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.3> 8/14/89 sjk 1 point contours now OK
|
|
<2.2> 8/8/89 sjk Improved encryption handling
|
|
<2.0> 8/2/89 sjk Just fixed EASE comment
|
|
<1.6> 8/1/89 sjk Added composites and encryption. Plus some enhancementsÉ
|
|
<1.5> 6/13/89 sjk updated for new mapping stuff
|
|
<1.4> 6/5/89 sjk Fixed stretching problem, with respect to some widthtable crap
|
|
<1.3> 6/2/89 CEL 16.16 scaling of metrics, minimum recommended ppem, point size 0
|
|
bug, correct transformed integralized ppem behavior, pretty much
|
|
so
|
|
<1.2> 5/26/89 CEL EASE messed up on ÒcÓ comments
|
|
<¥1.1> 5/26/89 CEL Integrated the new Font Scaler 1.0 into Spline Fonts
|
|
<1.0> 5/25/89 CEL Integrated 1.0 Font scaler into Bass code for the first timeÉ
|
|
|
|
To Do:
|
|
*/
|
|
/** System Includes **/
|
|
#include <setjmp.h>
|
|
#include <FixMath.h>
|
|
#include <ToolUtils.h>
|
|
#include <Memory.h>
|
|
#include <Fonts.h>
|
|
#include <Script.h>
|
|
|
|
/** FontScalerÕs Includes **/
|
|
#include "FSError.h"
|
|
#include "FSCdefs.h"
|
|
#include "FontMath.h"
|
|
#include "sfnt.h"
|
|
#include "sc.h"
|
|
#include "fnt.h"
|
|
#include "FontScaler.h"
|
|
#include "FSglue.h"
|
|
#include "privateSfnt.h"
|
|
#include "PartialFontExtensions.proto"
|
|
#include "MacExtra.h"
|
|
#include "Bass_Cache.h"
|
|
#include "MapString.h"
|
|
/* #include "OutlineCalls.h" */ /* <10> */
|
|
#include "DoubleByteBassCache.h"
|
|
|
|
extern pascal EncodingTablePointer GetEncodingTable( short fondID, uint16 *scriptCodePointer );
|
|
#define kMissingGlyph 1 /* character code 1 maps to the missing glyph */
|
|
|
|
#define YMAX_SLOP (3L << 16)
|
|
#define YMIN_SLOP (3L << 16)
|
|
|
|
#define FIXONE 0x00010000
|
|
#define FIXONEHALF 0x00008000
|
|
#define HIGHWORDMASK 0xFFFF0000
|
|
|
|
#define FIXROUND(n) FixRound(n)
|
|
#define ROUND(n) (((n) + FIXONEHALF) & HIGHWORDMASK)
|
|
|
|
#define SETJUMP(key, error) if ( error = setjmp(key->env) ) return( error )
|
|
|
|
/*** This guy is defined in FontScaler.c *****/
|
|
extern fsg_SplineKey* fs_SetUpKey(fs_GlyphInputType* inptr, int32 stateBits, int32* error);
|
|
|
|
static Boolean FillDeviceWidths(sfnt_DeviceMetrics* devMetricsPtr, Fixed* wt, int16* glyphs, Fixed styleExtra, Fixed fixedPpem)
|
|
{
|
|
uint8* devWidths = (uint8*)(devMetricsPtr + 1);
|
|
short numRecords = devMetricsPtr->numRecords;
|
|
long recordSize = devMetricsPtr->recordSize;
|
|
int ppem = FIXROUND(fixedPpem);
|
|
|
|
if (ppem > 255) return false;
|
|
|
|
for (--numRecords; numRecords >= 0; --numRecords)
|
|
{
|
|
if (*devWidths > ppem) /* widths are sorted small to large */
|
|
break;
|
|
if (*devWidths == ppem)
|
|
{
|
|
register int16* shortw = (int16*)wt;
|
|
register int16 shortStyleExtra = FIXROUND(styleExtra);
|
|
register int16 charCode;
|
|
|
|
devWidths += DEVEXTRA; /* skip the size and max byte */
|
|
for (charCode = 255; charCode >= 0; --charCode)
|
|
{
|
|
*shortw++ = devWidths[*glyphs++] + shortStyleExtra;
|
|
*shortw++ = 0;
|
|
}
|
|
return true;
|
|
}
|
|
devWidths += recordSize;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int32 Map256Chars(Handle sfnt, short* glyphs, short fondID)
|
|
{
|
|
short platformCode = plat_Macintosh;
|
|
uint16 scriptCode;
|
|
long characterMapIndex;
|
|
EncodingTable *encodingPtr;
|
|
|
|
encodingPtr = GetEncodingTable(fondID, &scriptCode);
|
|
characterMapIndex = GetFontMapInfo( sfnt, 0, PackStringClass( platformCode, scriptCode, 0 ) );
|
|
|
|
//
|
|
// if GetFontMapInfo failed (i.e. returned 0 for the index) and the scriptCode for
|
|
// this font is > Roman, this could be one of the old Arabic or Hebrew fonts
|
|
// that were released with a roman cmap. so try asking for a Roman cmap before
|
|
// bailing completely.
|
|
//
|
|
if ( characterMapIndex == 0 && scriptCode > smRoman )
|
|
characterMapIndex = GetFontMapInfo( sfnt, 0, PackStringClass( platformCode, smRoman, 0 ) );
|
|
|
|
|
|
if (characterMapIndex) {
|
|
unsigned short byteIndex;
|
|
unsigned char byteList[512];
|
|
unsigned char *bytePtr = byteList;
|
|
|
|
if (encodingPtr) {
|
|
for (byteIndex = 0; byteIndex < 256; byteIndex++) {
|
|
*bytePtr++ = byteIndex;
|
|
if (encodingPtr->fHighByte[byteIndex]) {
|
|
*(bytePtr - 1) = kMissingGlyph;
|
|
}
|
|
}
|
|
} else {
|
|
for (byteIndex = 0; byteIndex < 256; byteIndex++) {
|
|
*bytePtr++ = byteIndex;
|
|
}
|
|
}
|
|
|
|
|
|
ApplyFontMap(sfnt, characterMapIndex, glyphs, 256, byteList, 0);
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* fs_FillWidthTable: returns non-zero error code
|
|
*
|
|
*/
|
|
long fs_FillWidthTable(fs_GlyphInputType* inputPtr, Fixed* origWidthTable, Handle sfnt, Fixed styleExtra, short fondID, Boolean round)
|
|
{
|
|
register Fixed scaledLastAdvanceWidthPlusStyle;
|
|
register sfnt_HorizontalMetrics* metrics, *lastHorizontalMetricsPointer;
|
|
unsigned short numberOf_LongHorMetrics;
|
|
short lastAdvanceWidth, numGlyphs;
|
|
short glyphStorage[256];
|
|
short* glyphs = glyphStorage;
|
|
Fixed* wt = origWidthTable;
|
|
int32 error;
|
|
fsg_SplineKey* key = (fsg_SplineKey*)fs_SetUpKey(inputPtr, INITIALIZED | NEWSFNT | NEWTRANS, &error);
|
|
|
|
if (error) return error;
|
|
SETJUMP(key, error);
|
|
|
|
if (error = Map256Chars(sfnt, glyphs, fondID))
|
|
return error;
|
|
|
|
{
|
|
sfnt_HorizontalHeader* horiHead = (sfnt_HorizontalHeader*)GetFontTablePtr( sfnt, 0, tag_HoriHeader);
|
|
numberOf_LongHorMetrics = horiHead->numberOf_LongHorMetrics;
|
|
QDUngetFontFrag(sfnt, horiHead);
|
|
}
|
|
|
|
{
|
|
sfnt_maxProfileTable* profile = (sfnt_maxProfileTable*)GetFontTablePtr( sfnt, 0, tag_MaxProfile );
|
|
numGlyphs = profile->numGlyphs;
|
|
QDUngetFontFrag(sfnt, profile);
|
|
}
|
|
|
|
/* Precache the first 256 glyph entries of the 'hmtx' table. We're assuming that the first 256 entries
|
|
map, more or less, to the 256 characters in the ascii chart. This is mainly for the benefit of huge
|
|
double-byte fonts since we don't really want to load in an 88k htmx table into our 100k partial font
|
|
heap. For most single-byte fonts, this should have the same affect as loading in the entire table.
|
|
Character codes in the 0..255 range that map to glyph index greater than 255 will result in a
|
|
partial font call (read: this is painful).
|
|
*/
|
|
|
|
metrics = (sfnt_HorizontalMetrics*) PartialGetFontTablePtr( sfnt, 0, 256 * sizeof( sfnt_HorizontalMetrics ), 0, tag_HorizontalMetrics );
|
|
lastHorizontalMetricsPointer = PartialGetFontTablePtr( sfnt, (numberOf_LongHorMetrics - 1) * sizeof( sfnt_HorizontalMetrics ), sizeof( sfnt_HorizontalMetrics ), 0, tag_HorizontalMetrics );
|
|
lastAdvanceWidth = lastHorizontalMetricsPointer->advanceWidth;
|
|
scaledLastAdvanceWidthPlusStyle = ShortMulDiv( key->metricScalar, lastAdvanceWidth, key->emResolution ) + styleExtra;
|
|
/*
|
|
* Since we NEVER have perspective, and widths only look at x-component,
|
|
* all we need to use is the xScale.
|
|
*/
|
|
{
|
|
register short charCode;
|
|
short upem = key->emResolution;
|
|
Fixed xScale = FixMul(key->currentTMatrix.transform[0][0], key->metricScalar);
|
|
|
|
if (numberOf_LongHorMetrics < numGlyphs)
|
|
scaledLastAdvanceWidthPlusStyle = ShortMulDiv( xScale, lastAdvanceWidth, upem ) + styleExtra;
|
|
|
|
/*
|
|
* FractEnable OFF
|
|
* Try to find cached device metrics. If that fails, round the scaled widths.
|
|
*/
|
|
if (round)
|
|
{
|
|
sfnt_DeviceMetrics* devMetricsPtr;
|
|
if (devMetricsPtr = (sfnt_DeviceMetrics*)GetFontTablePtr( sfnt, 0, tag_HoriDeviceMetrics))
|
|
{
|
|
Boolean success = FillDeviceWidths(devMetricsPtr, wt, glyphs, styleExtra, xScale);
|
|
QDUngetFontFrag(sfnt, devMetricsPtr);
|
|
if (success)
|
|
goto EXIT;
|
|
}
|
|
|
|
styleExtra += FIXONEHALF;
|
|
scaledLastAdvanceWidthPlusStyle = ROUND(scaledLastAdvanceWidthPlusStyle);
|
|
for (charCode = 255; charCode >= 0; --charCode)
|
|
{
|
|
int16 index = *glyphs++;
|
|
if ( index >= numberOf_LongHorMetrics ) {
|
|
|
|
*wt++ = scaledLastAdvanceWidthPlusStyle;
|
|
|
|
} else {
|
|
|
|
if ( index < 256 ) {
|
|
|
|
*wt++ = (ShortMulDiv( xScale, metrics[index].advanceWidth, upem ) + styleExtra) & HIWORDMASK;
|
|
|
|
} else {
|
|
|
|
sfnt_HorizontalMetrics* glyphMetricPointer;
|
|
|
|
glyphMetricPointer = PartialGetFontTablePtr( sfnt, index * sizeof( sfnt_HorizontalMetrics ), sizeof( sfnt_HorizontalMetrics ), 0, tag_HorizontalMetrics );
|
|
*wt++ = (ShortMulDiv( xScale, glyphMetricPointer->advanceWidth, upem ) + styleExtra) & HIWORDMASK;
|
|
QDUngetFontFrag( sfnt, glyphMetricPointer );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else /* FractEnable ON */
|
|
{
|
|
for (charCode = 255; charCode >= 0; --charCode)
|
|
{
|
|
int16 index = *glyphs++;
|
|
if ( index >= numberOf_LongHorMetrics ) {
|
|
|
|
*wt++ = scaledLastAdvanceWidthPlusStyle;
|
|
|
|
} else {
|
|
|
|
if ( index < 256 ) {
|
|
|
|
*wt++ = ShortMulDiv( xScale, metrics[index].advanceWidth, upem ) + styleExtra;
|
|
|
|
} else {
|
|
|
|
sfnt_HorizontalMetrics* glyphMetricPointer;
|
|
|
|
glyphMetricPointer = PartialGetFontTablePtr( sfnt, index * sizeof( sfnt_HorizontalMetrics ), sizeof( sfnt_HorizontalMetrics ), 0, tag_HorizontalMetrics );
|
|
*wt++ = ShortMulDiv( xScale, glyphMetricPointer->advanceWidth, upem ) + styleExtra;
|
|
QDUngetFontFrag( sfnt, glyphMetricPointer );
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EXIT:
|
|
QDUngetFontFrag( sfnt, lastHorizontalMetricsPointer );
|
|
QDUngetFontFrag(sfnt, metrics);
|
|
|
|
/* Make sure a negative styleExtra doesn't result in a negative width
|
|
* Condense style is a good candidate.
|
|
*/
|
|
if (styleExtra < 0) {
|
|
short charCode;
|
|
Fixed* wt = origWidthTable;
|
|
for (charCode = 255; charCode >= 0; --charCode) {
|
|
if (*wt < 0)
|
|
*wt = 0;
|
|
wt++;
|
|
}
|
|
}
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*
|
|
* fs_FillLayoutInfo
|
|
*
|
|
* Return error code like GlyphInfoType.error.
|
|
*/
|
|
#define OVERFLOW_ERR 0x00AA
|
|
int32 fs_FillLayoutInfo( fs_GlyphInputType* inputPtr, fs_GlyphInfoType*, fs_LayoutInfo* info)
|
|
{
|
|
register sfnt_FontHeader* fontHead;
|
|
register sfnt_HorizontalHeader* horiHead;
|
|
int32 error;
|
|
int16 upem;
|
|
register fsg_SplineKey* key = fs_SetUpKey(inputPtr, INITIALIZED | NEWSFNT | NEWTRANS, &error);
|
|
Handle sfnt;
|
|
|
|
if (error) return error;
|
|
SETJUMP(key, error);
|
|
|
|
sfnt = (Handle)key->clientID;
|
|
upem = key->emResolution;
|
|
fontHead = (sfnt_FontHeader*)GetFontTablePtr( sfnt, 0, tag_FontHeader );
|
|
horiHead = (sfnt_HorizontalHeader*)GetFontTablePtr( sfnt, 0, tag_HoriHeader );
|
|
|
|
{
|
|
Fixed xScale = FixMul( key->metricScalar, key->currentTMatrix.transform[0][0]);
|
|
|
|
info->widMax = ShortMulDiv( xScale, horiHead->advanceWidthMax, upem );
|
|
info->lOverHMax = - ROUND(ShortMulDiv( xScale, horiHead->minLeftSideBearing, upem ));
|
|
info->rOverHMax = - ROUND(ShortMulDiv( xScale, horiHead->minRightSideBearing, upem ));
|
|
}
|
|
{
|
|
Fixed yScale = FixMul( key->metricScalar, key->currentTMatrix.transform[1][1]);
|
|
|
|
info->ascent = ROUND(ShortMulDiv( yScale, horiHead->yAscender, upem ));
|
|
info->descent = ROUND(ShortMulDiv( yScale, horiHead->yDescender, upem ));
|
|
info->leading = ROUND(ShortMulDiv( yScale, horiHead->yLineGap, upem ));
|
|
info->yMax = ROUND(ShortMulDiv( yScale, fontHead->yMax, upem )) + YMAX_SLOP;
|
|
info->yMin = ROUND(ShortMulDiv( yScale, fontHead->yMin, upem )) - YMIN_SLOP;
|
|
}
|
|
|
|
if ( info->lOverHMax < 0 ) info->lOverHMax = 0;
|
|
if ( info->rOverHMax < 0 ) info->rOverHMax = 0;
|
|
|
|
QDUngetFontFrag(sfnt, horiHead);
|
|
QDUngetFontFrag(sfnt, fontHead);
|
|
if (info->yMax - info->yMin < 0) return OVERFLOW_ERR;
|
|
|
|
return NO_ERR;
|
|
}
|
|
|
|
/*
|
|
* Extra routines for Chazzvetica <3><4>
|
|
*/
|
|
pascal short fs_LowestPPEM(Handle fontHandle)
|
|
{
|
|
sfnt_FontHeader* fontHead = GetFontTablePtr( fontHandle, 0, tag_FontHeader);
|
|
short lowest = fontHead->lowestRecPPEM;
|
|
QDUngetFontFrag(fontHandle, fontHead);
|
|
return lowest;
|
|
}
|
|
|