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.
5044 lines
147 KiB
5044 lines
147 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fdfon.c
|
|
*
|
|
* basic file claim/load/unload font file functions
|
|
*
|
|
* Created: 08-Nov-1991 10:09:24
|
|
* Author: Bodin Dresevic [BodinD]
|
|
*
|
|
* Copyright (c) 1990 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
#include "fd.h"
|
|
#include <stdlib.h>
|
|
#include <winerror.h>
|
|
|
|
#define NOEMCHARSETS 16
|
|
void vFillIFICharsets(FONTFILE *pff, IFIMETRICS *pifi, BYTE *aCharSets, BYTE *pjView, BYTE * pjOS2);
|
|
|
|
// CMI_2219_PRESENT set if 2219 is supported in a font
|
|
// CMI_B7_ABSENT set if b7 is NOT supported in a font
|
|
|
|
#define CMI_2219_PRESENT 1
|
|
#define CMI_B7_ABSENT 2
|
|
|
|
typedef struct _CMAPINFO // cmi
|
|
{
|
|
FLONG fl; // flags, see above
|
|
ULONG i_b7; // index for [b7,b7] wcrun in FD_GLYPHSET if b7 is NOT supported
|
|
ULONG i_2219; // cmap index for 2219 if 2219 IS supported
|
|
ULONG cRuns; // number of runs in a font, excluding the last run
|
|
// if equal to [ffff,ffff]
|
|
uint16 ui16SpecID; // for keep encoding ID
|
|
WcharToIndex *pWCharToIndex;
|
|
ULONG cGlyphs; // total number of glyphs in a font
|
|
} CMAPINFO;
|
|
|
|
|
|
BOOL IsCurrentCodePageDBCS()
|
|
{
|
|
USHORT AnsiCodePage, OemCodePage;
|
|
|
|
EngGetCurrentCodePage(&OemCodePage,&AnsiCodePage);
|
|
|
|
return(AnsiCodePage == 932 || AnsiCodePage == 949 ||
|
|
AnsiCodePage == 1361 || AnsiCodePage == 936 || AnsiCodePage == 950 );
|
|
}
|
|
|
|
|
|
#ifdef WIN31_ORIGINAL_CODE
|
|
;******************************************************************************
|
|
;************************ C O P Y I F I N A M E *************************
|
|
;******************************************************************************
|
|
|
|
cProc CopyIfiName, <FAR, PUBLIC>, <es, si, di>
|
|
parmD lpszUnicode
|
|
parmD lpszAnsi
|
|
parmW cwUnicode
|
|
cBegin
|
|
lfs si, lpszUnicode ; fs:si --> ptr to Unicode str
|
|
les di, lpszAnsi ; es:di --> ptr to DBCS str
|
|
CINCopyLoop:
|
|
lodsw fs:[si] ; load a Unicode
|
|
or ah, ah
|
|
jz @f
|
|
mov es:[di], ah ; store higher byte
|
|
inc di
|
|
@@: stosb ; store lower byte
|
|
or ax, ax ; end of string?
|
|
jnz CINCopyLoop ; no. keep copying
|
|
|
|
mov ax, di ; return number of bytes copyed
|
|
sub ax, lpszAnsi.off
|
|
cEnd
|
|
#endif // WIN31_ORIGINAL_CODE
|
|
|
|
STATIC
|
|
ULONG CopyDBCSIFIName(
|
|
CHAR *AnsiName,
|
|
ULONG BufferLength,
|
|
LPCSTR OriginalName,
|
|
ULONG OriginalLength)
|
|
{
|
|
ULONG AnsiLength = 0;
|
|
WORD *Buffer = (WORD *)OriginalName;
|
|
WORD WordChar;
|
|
|
|
for( ;OriginalLength; OriginalLength-=2 )
|
|
{
|
|
WordChar = *Buffer;
|
|
|
|
if( WordChar & 0x00FF )
|
|
{
|
|
if( BufferLength >= (AnsiLength+2) )
|
|
{
|
|
*AnsiName++ = (CHAR)((WordChar & 0x00FF));
|
|
*AnsiName++ = (CHAR)((WordChar & 0xFF00) >> 8);
|
|
AnsiLength += 2;
|
|
} else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( BufferLength >= (AnsiLength+1) )
|
|
{
|
|
*AnsiName++ = (CHAR)((WordChar & 0xFF00) >> 8);
|
|
AnsiLength++;
|
|
} else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
Buffer++;
|
|
}
|
|
|
|
return (AnsiLength);
|
|
}
|
|
|
|
STATIC UINT GetCodePageFromSpecId( uint16 ui16SpecId )
|
|
{
|
|
USHORT AnsiCodePage, OemCodePage;
|
|
UINT iCodePage;
|
|
|
|
EngGetCurrentCodePage(&OemCodePage,&AnsiCodePage);
|
|
|
|
iCodePage = AnsiCodePage;
|
|
|
|
switch( ui16SpecId )
|
|
{
|
|
case BE_SPEC_ID_SHIFTJIS :
|
|
iCodePage = 932;
|
|
break;
|
|
|
|
case BE_SPEC_ID_GB :
|
|
iCodePage = 936;
|
|
break;
|
|
|
|
case BE_SPEC_ID_BIG5 :
|
|
iCodePage = 950;
|
|
break;
|
|
|
|
case BE_SPEC_ID_WANSUNG :
|
|
iCodePage = 949;
|
|
break;
|
|
|
|
default :
|
|
WARNING("TTFD!:Unknown SPECIFIC ID\n");
|
|
break;
|
|
}
|
|
|
|
return( iCodePage );
|
|
}
|
|
|
|
STATIC BOOL bVerifyMsftHighByteTable
|
|
(
|
|
sfnt_mappingTable * pmap,
|
|
ULONG * pgset,
|
|
CMAPINFO * pcmi,
|
|
uint16 ui16SpecID
|
|
);
|
|
|
|
STATIC ULONG cjComputeGLYPHSET_HIGH_BYTE
|
|
(
|
|
sfnt_mappingTable *pmap,
|
|
ULONG **ppgset,
|
|
CMAPINFO *pcmi
|
|
);
|
|
|
|
STATIC BOOL bVerifyMsftTableGeneral
|
|
(
|
|
sfnt_mappingTable * pmap,
|
|
ULONG * pgset,
|
|
CMAPINFO * pcmi,
|
|
uint16 ui16SpecID
|
|
);
|
|
|
|
STATIC ULONG cjComputeGLYPHSET_MSFT_GENERAL
|
|
(
|
|
sfnt_mappingTable *pmap,
|
|
ULONG **ppgset,
|
|
CMAPINFO *pcmi
|
|
);
|
|
|
|
STATIC BOOL bContainGlyphSet
|
|
(
|
|
WCHAR wc,
|
|
PFD_GLYPHSET pgset
|
|
);
|
|
|
|
|
|
STATIC uint16 ui16BeLangId(ULONG ulPlatId, ULONG ulLangId)
|
|
{
|
|
ulLangId = CV_LANG_ID(ulPlatId,ulLangId);
|
|
return BE_UINT16(&ulLangId);
|
|
}
|
|
|
|
|
|
STATIC FSHORT fsSelectionTTFD(BYTE *pjView, TABLE_POINTERS *ptp)
|
|
{
|
|
PBYTE pjOS2 = (ptp->ateOpt[IT_OPT_OS2].dp) ?
|
|
pjView + ptp->ateOpt[IT_OPT_OS2].dp :
|
|
NULL ;
|
|
|
|
sfnt_FontHeader * phead = (sfnt_FontHeader *)(pjView + ptp->ateReq[IT_REQ_HEAD].dp);
|
|
|
|
//
|
|
// fsSelection
|
|
//
|
|
ASSERTDD(TT_SEL_ITALIC == FM_SEL_ITALIC , "ITALIC \n");
|
|
ASSERTDD(TT_SEL_UNDERSCORE == FM_SEL_UNDERSCORE , "UNDERSCORE \n");
|
|
ASSERTDD(TT_SEL_NEGATIVE == FM_SEL_NEGATIVE , "NEGATIVE \n");
|
|
ASSERTDD(TT_SEL_OUTLINED == FM_SEL_OUTLINED , "OUTLINED \n");
|
|
ASSERTDD(TT_SEL_STRIKEOUT == FM_SEL_STRIKEOUT , "STRIKEOUT \n");
|
|
ASSERTDD(TT_SEL_BOLD == FM_SEL_BOLD , "BOLD \n");
|
|
|
|
if (pjOS2)
|
|
{
|
|
return((FSHORT)BE_UINT16(pjOS2 + OFF_OS2_usSelection));
|
|
}
|
|
else
|
|
{
|
|
#define BE_MSTYLE_BOLD 0x0100
|
|
#define BE_MSTYLE_ITALIC 0x0200
|
|
|
|
FSHORT fsSelection = 0;
|
|
|
|
if (phead->macStyle & BE_MSTYLE_BOLD)
|
|
fsSelection |= FM_SEL_BOLD;
|
|
if (phead->macStyle & BE_MSTYLE_ITALIC)
|
|
fsSelection |= FM_SEL_ITALIC;
|
|
|
|
return fsSelection;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
STATIC BOOL bComputeIFISIZE
|
|
(
|
|
BYTE *pjView,
|
|
TABLE_POINTERS *ptp,
|
|
uint16 ui16PlatID,
|
|
uint16 ui16SpecID,
|
|
uint16 ui16LangID,
|
|
PIFISIZE pifisz,
|
|
BOOL *pbType1
|
|
);
|
|
|
|
STATIC BOOL bCvtUnToMac(BYTE *pjView, TABLE_POINTERS *ptp, uint16 ui16PlatformID);
|
|
|
|
STATIC BOOL bVerifyTTF
|
|
(
|
|
ULONG iFile,
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
PBYTE pjOffsetTable,
|
|
ULONG ulLangId,
|
|
PTABLE_POINTERS ptp,
|
|
PIFISIZE pifisz,
|
|
uint16 *pui16PlatID,
|
|
uint16 *pui16SpecID,
|
|
sfnt_mappingTable **ppmap,
|
|
ULONG *pulGsetType,
|
|
ULONG *pul_wcBias,
|
|
CMAPINFO *pcmi,
|
|
BOOL *pbType1,
|
|
FLONG *pflHack
|
|
);
|
|
|
|
STATIC BOOL bGetTablePointers
|
|
(
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
PBYTE pjOffsetTable,
|
|
PTABLE_POINTERS ptp
|
|
);
|
|
|
|
STATIC BOOL bVerifyMsftTable
|
|
(
|
|
sfnt_mappingTable * pmap,
|
|
ULONG * pgset,
|
|
ULONG * pul_wcBias,
|
|
CMAPINFO * pcmi,
|
|
uint16 ui16SpecID
|
|
);
|
|
|
|
|
|
STATIC BOOL bVerifyMacTable(sfnt_mappingTable * pmap);
|
|
|
|
|
|
STATIC BOOL bComputeIDs
|
|
(
|
|
BYTE * pjView,
|
|
TABLE_POINTERS * ptp,
|
|
uint16 * pui16PlatID,
|
|
uint16 * pui16SpecID,
|
|
sfnt_mappingTable ** ppmap,
|
|
ULONG * pulGsetType,
|
|
ULONG * pul_wcBias,
|
|
CMAPINFO * pcmi
|
|
);
|
|
|
|
|
|
STATIC VOID vFill_IFIMETRICS
|
|
(
|
|
PFONTFILE pff,
|
|
PIFIMETRICS pifi,
|
|
PIFISIZE pifisz
|
|
);
|
|
|
|
BYTE jIFIMetricsToGdiFamily (PIFIMETRICS pifi);
|
|
|
|
|
|
BOOL
|
|
ttfdUnloadFontFileTTC (
|
|
HFF hff
|
|
)
|
|
{
|
|
ULONG i;
|
|
BOOL bRet = TRUE;
|
|
#if DBG
|
|
ULONG ulTrueTypeResource = PTTC(hff)->ulTrueTypeResource;
|
|
#endif
|
|
|
|
// free hff for this ttc file.
|
|
|
|
for( i = 0; i < PTTC(hff)->ulNumEntry; i++ )
|
|
{
|
|
if(PTTC(hff)->ahffEntry[i].iFace == 1)
|
|
{
|
|
if( !ttfdUnloadFontFile(PTTC(hff)->ahffEntry[i].hff) )
|
|
{
|
|
WARNING("TTFD!ttfdUnloadFontFileTTC(): ttfdUnloadFontFile fail\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
#if DBG
|
|
ulTrueTypeResource--;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
ASSERTDD(ulTrueTypeResource == 0L,
|
|
"TTFD!ttfdUnloadFontFileTTC(): ulTrueTypeResource != 0\n");
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* ttfdUnloadFontFile
|
|
*
|
|
*
|
|
* Effects: done with using this tt font file. Release all system resources
|
|
* associated with this font file
|
|
*
|
|
*
|
|
* History:
|
|
* 08-Nov-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
ttfdUnloadFontFile (
|
|
HFF hff
|
|
)
|
|
{
|
|
if (hff == HFF_INVALID)
|
|
return(FALSE);
|
|
|
|
// check the reference count, if not 0 (font file is still
|
|
// selected into a font context) we have a problem
|
|
|
|
ASSERTDD(PFF(hff)->cRef == 0L, "ttfdUnloadFontFile: cRef\n");
|
|
|
|
// no need to unmap the file at this point
|
|
// it has been unmapped when cRef went down to zero
|
|
|
|
// assert that pff->pkp does not point to the allocated mem
|
|
|
|
ASSERTDD(!PFF(hff)->pkp, "UnloadFontFile, pkp not null\n");
|
|
|
|
// free memory associated with this FONTFILE object
|
|
|
|
vFreeFF(hff);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bVerifyTTF
|
|
*
|
|
*
|
|
* Effects: verifies that a ttf file contains consistent tt information
|
|
*
|
|
* History:
|
|
* 08-Nov-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC BOOL
|
|
bVerifyTTF (
|
|
ULONG iFile,
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
PBYTE pjOffsetTable,
|
|
ULONG ulLangId,
|
|
PTABLE_POINTERS ptp,
|
|
PIFISIZE pifisz,
|
|
uint16 *pui16PlatID,
|
|
uint16 *pui16SpecID,
|
|
sfnt_mappingTable **ppmap,
|
|
ULONG *pulGsetType,
|
|
ULONG *pul_wcBias,
|
|
CMAPINFO *pcmi,
|
|
BOOL *pbType1,
|
|
FLONG *pflHack
|
|
)
|
|
{
|
|
sfnt_FontHeader *phead;
|
|
*pflHack = 0;
|
|
|
|
// if attempted a bm *.fon file this will fail, so do not print
|
|
// warning, but if passes this, and then fails, something is wrong
|
|
|
|
if (!bGetTablePointers(pvView,cjView,pjOffsetTable,ptp))
|
|
return (FALSE);
|
|
|
|
phead = (sfnt_FontHeader *)((BYTE *)pvView + ptp->ateReq[IT_REQ_HEAD].dp);
|
|
|
|
#define SFNT_MAGIC 0x5F0F3CF5
|
|
|
|
if (BE_UINT32((BYTE*)phead + SFNT_FONTHEADER_MAGICNUMBER) != SFNT_MAGIC)
|
|
RET_FALSE("TTFD: bVerifyTTF: SFNT_MAGIC \n");
|
|
|
|
if (!bComputeIDs(pvView,
|
|
ptp,
|
|
pui16PlatID,
|
|
pui16SpecID,
|
|
ppmap,
|
|
pulGsetType,
|
|
pul_wcBias,
|
|
pcmi)
|
|
)
|
|
RET_FALSE("TTFD!_bVerifyTTF, bComputeIDs failed\n");
|
|
|
|
if
|
|
(
|
|
!bComputeIFISIZE (
|
|
pvView,
|
|
ptp,
|
|
*pui16PlatID,
|
|
*pui16SpecID,
|
|
ui16BeLangId(*pui16PlatID,ulLangId),
|
|
pifisz, // return results here
|
|
pbType1
|
|
)
|
|
)
|
|
{
|
|
RET_FALSE("TTFD!_bVerifyTTF, bComputeIFISIZE failed\n");
|
|
}
|
|
|
|
// BEGIN Perpetua-Hack
|
|
//
|
|
// If we recognize the unique name to be one of the infamous
|
|
// Perpetua fonts we set some bits.
|
|
//
|
|
// cjUnique pjUnique
|
|
//
|
|
// 60 "Monotype: Perpetua Bold: 1994"
|
|
// 66 "Monotype: Perpetua Regular: 1994"
|
|
|
|
if (*pui16PlatID == BE_PLAT_ID_MS)
|
|
{
|
|
if (pifisz)
|
|
{
|
|
if (pifisz->pjUniqueName)
|
|
{
|
|
char *pszU;
|
|
|
|
switch (pifisz->cjUniqueName)
|
|
{
|
|
case 60:
|
|
pszU = "Monotype: Perpetua Bold: 1994";
|
|
// set bit in anticipation of match
|
|
*pflHack |= FF_PERPETUA_BOLD;
|
|
break;
|
|
case 66:
|
|
pszU = "Monotype: Perpetua Regular: 1994";
|
|
// set bit in anticipation of match
|
|
*pflHack |= FF_PERPETUA_REGULAR;
|
|
break;
|
|
default:
|
|
pszU = 0;
|
|
}
|
|
if (pszU)
|
|
{
|
|
char *psz, *pszF;
|
|
|
|
// adjust starting byte to point at least significant
|
|
// byte of big endian 16-bit character.
|
|
|
|
pszF = (char*) (pifisz->pjUniqueName) + 1;
|
|
for ( psz = pszU ; *psz && (*psz == *pszF) ; psz++ )
|
|
{
|
|
pszF += sizeof(WCHAR);
|
|
}
|
|
if (*psz)
|
|
{
|
|
// string didn't match, clear the bits
|
|
*pflHack = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// END Perpetua-Hack
|
|
|
|
// all checks passed
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* PBYTE pjGetPointer(LONG clientID, LONG dp, LONG cjData)
|
|
*
|
|
* this function is required by scaler. It is very simple
|
|
* Returns a pointer to the position in a ttf file which is at
|
|
* offset dp from the top of the file:
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 08-Nov-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
//!!! clientID should be uint32, just a set of bits
|
|
//!!! I hate to have this function defined like this [bodind]
|
|
|
|
voidPtr FS_CALLBACK_PROTO
|
|
pvGetPointerCallback(
|
|
long clientID,
|
|
long dp,
|
|
long cjData
|
|
)
|
|
{
|
|
cjData;
|
|
|
|
#ifdef FE_SB
|
|
// clientID is FONTFILE structure...
|
|
|
|
if(dp)
|
|
return(voidPtr)((PBYTE)(PFF(clientID)->pvView) + dp);
|
|
else
|
|
return(voidPtr)((PBYTE)(PFF(clientID)->pvView) +
|
|
(PFF(clientID)->ulTableOffset));
|
|
#else
|
|
// clientID is just the pointer to the top of the font file
|
|
|
|
return (voidPtr)((PBYTE)clientID + dp);
|
|
#endif // FE_SB
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* void vReleasePointer(voidPtr pv)
|
|
*
|
|
*
|
|
* required by scaler, the type of this function is ReleaseSFNTFunc
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* 08-Nov-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FS_CALLBACK_PROTO
|
|
vReleasePointerCallback(
|
|
voidPtr pv
|
|
)
|
|
{
|
|
pv;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* PBYTE pjTable
|
|
*
|
|
* Given a table tag, get a pointer and a size for the table
|
|
*
|
|
* History:
|
|
* 11-Nov-1993 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
#ifdef FE_SB
|
|
PBYTE pjTable(ULONG ulTag, PFONTFILE pff, ULONG *pcjTable)
|
|
#else
|
|
PBYTE pjTable(ULONG ulTag, PVOID pvView, ULONG cjView, ULONG *pcjTable)
|
|
#endif
|
|
{
|
|
INT cTables;
|
|
sfnt_OffsetTable *pofft;
|
|
register sfnt_DirectoryEntry *pdire, *pdireEnd;
|
|
|
|
// offset table is at the very top of the file,
|
|
|
|
#ifdef FE_SB
|
|
pofft = (sfnt_OffsetTable *) ((PBYTE) (pff->pvView) + pff->ulTableOffset);
|
|
#else
|
|
pofft = (sfnt_OffsetTable *) pvView;
|
|
#endif
|
|
cTables = (INT) SWAPW(pofft->numOffsets);
|
|
|
|
//!!! here we do linear search, but perhaps we could optimize and do binary
|
|
//!!! search since tags are ordered in ascending order
|
|
|
|
pdireEnd = &pofft->table[cTables];
|
|
|
|
for
|
|
(
|
|
pdire = &pofft->table[0];
|
|
pdire < pdireEnd;
|
|
((PBYTE)pdire) += SIZE_DIR_ENTRY
|
|
)
|
|
{
|
|
|
|
if (ulTag == pdire->tag)
|
|
{
|
|
ULONG ulOffset = (ULONG)SWAPL(pdire->offset);
|
|
ULONG ulLength = (ULONG)SWAPL(pdire->length);
|
|
|
|
// check if the ends of all tables are within the scope of the
|
|
// tt file. If this is is not the case trying to access the field in the
|
|
// table may result in an access violation, as is the case with the
|
|
// spurious FONT.TTF that had the beginning of the cmap table below the
|
|
// end of file, which was resulting in the system crash reported by beta
|
|
// testers. [bodind]
|
|
|
|
if
|
|
(
|
|
!ulLength ||
|
|
#ifdef FE_SB
|
|
((ulOffset + ulLength) > pff->cjView)
|
|
#else
|
|
((ulOffset + ulLength) > cjView)
|
|
#endif
|
|
)
|
|
{
|
|
RETURN("TTFD: pjTable: table offset/length \n", NULL);
|
|
}
|
|
else // we found it
|
|
{
|
|
*pcjTable = ulLength;
|
|
#ifdef FE_SB
|
|
return ((PBYTE)(pff->pvView) + ulOffset);
|
|
#else
|
|
return ((PBYTE)pvView + ulOffset);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
// if we are here, we did not find it.
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* bGetTablePointers - cache the pointers to all the tt tables in a tt file
|
|
*
|
|
* IF a table is not present in the file, the corresponding pointer is
|
|
* set to NULL
|
|
*
|
|
*
|
|
* // tag_CharToIndexMap // 'cmap' 0
|
|
* // tag_GlyphData // 'glyf' 1
|
|
* // tag_FontHeader // 'head' 2
|
|
* // tag_HoriHeader // 'hhea' 3
|
|
* // tag_HorizontalMetrics // 'hmtx' 4
|
|
* // tag_IndexToLoc // 'loca' 5
|
|
* // tag_MaxProfile // 'maxp' 6
|
|
* // tag_NamingTable // 'name' 7
|
|
* // tag_Postscript // 'post' 9
|
|
* // tag_OS_2 // 'OS/2' 10
|
|
*
|
|
* // optional
|
|
*
|
|
* // tag_ControlValue // 'cvt ' 11
|
|
* // tag_FontProgram // 'fpgm' 12
|
|
* // tag_HoriDeviceMetrics // 'hdmx' 13
|
|
* // tag_Kerning // 'kern' 14
|
|
* // tag_LSTH // 'LTSH' 15
|
|
* // tag_PreProgram // 'prep' 16
|
|
* // tag_GlyphDirectory // 'gdir' 17
|
|
* // tag_Editor0 // 'edt0' 18
|
|
* // tag_Editor1 // 'edt1' 19
|
|
* // tag_Encryption // 'cryp' 20
|
|
*
|
|
*
|
|
* returns false if all of required pointers are not present
|
|
*
|
|
* History:
|
|
* 05-Dec-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
BOOL bGetTablePointers (
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
PBYTE pjOffsetTable,
|
|
PTABLE_POINTERS ptp
|
|
)
|
|
{
|
|
INT iTable;
|
|
INT cTables;
|
|
sfnt_OffsetTable *pofft;
|
|
register sfnt_DirectoryEntry *pdire, *pdireEnd;
|
|
ULONG ulTag;
|
|
BOOL bRequiredTable;
|
|
|
|
// offset table is at the very top of the file,
|
|
|
|
#ifdef FE_SB
|
|
pofft = (sfnt_OffsetTable *)pjOffsetTable;
|
|
#else
|
|
pjOffsetTable; // to avoid compiler warnings
|
|
pofft = (sfnt_OffsetTable *)pvView;
|
|
#endif
|
|
|
|
// check version number, if wrong exit before doing
|
|
// anything else. This line rejects bm FON files
|
|
// if they are attempted to be loaed as TTF files
|
|
// Version #'s are in big endian.
|
|
|
|
#define BE_VER1 0x00000100
|
|
#define BE_VER2 0x00000200
|
|
|
|
if ((pofft->version != BE_VER1) && (pofft->version != BE_VER2))
|
|
return (FALSE); // *.fon files fail this check, make this an early out
|
|
|
|
// clean up the pointers
|
|
|
|
RtlZeroMemory((VOID *)ptp, sizeof(TABLE_POINTERS));
|
|
|
|
cTables = (INT) SWAPW(pofft->numOffsets);
|
|
ASSERTDD(cTables <= MAX_TABLES, "cTables\n");
|
|
|
|
pdireEnd = &pofft->table[cTables];
|
|
|
|
for
|
|
(
|
|
pdire = &pofft->table[0];
|
|
pdire < pdireEnd;
|
|
((PBYTE)pdire) += SIZE_DIR_ENTRY
|
|
)
|
|
{
|
|
ULONG ulOffset = (ULONG)SWAPL(pdire->offset);
|
|
ULONG ulLength = (ULONG)SWAPL(pdire->length);
|
|
|
|
ulTag = (ULONG)SWAPL(pdire->tag);
|
|
|
|
// check if the ends of all tables are within the scope of the
|
|
// tt file. If this is is not the case trying to access the field in the
|
|
// table may result in an access violation, as is the case with the
|
|
// spurious FONT.TTF that had the beginning of the cmap table below the
|
|
// end of file, which was resulting in the system crash reported by beta
|
|
// testers. [bodind]
|
|
|
|
if ((ulOffset + ulLength) > cjView)
|
|
RET_FALSE("TTFD: bGetTablePointers : table offset/length \n");
|
|
|
|
if (bGetTagIndex(ulTag, &iTable, &bRequiredTable))
|
|
{
|
|
if (bRequiredTable)
|
|
{
|
|
ptp->ateReq[iTable].dp = ulOffset;
|
|
ptp->ateReq[iTable].cj = ulLength;
|
|
}
|
|
else // optional table
|
|
{
|
|
ptp->ateOpt[iTable].dp = ulOffset;
|
|
ptp->ateOpt[iTable].cj = ulLength;
|
|
|
|
// here we are fixing a possible bug in in the tt file.
|
|
// In lucida sans font they claim that pj != 0 with cj == 0 for
|
|
// vdmx table. Attempting to use this vdmx table was
|
|
// resulting in an access violation in bSearchVdmxTable
|
|
|
|
if (ptp->ateOpt[iTable].cj == 0)
|
|
ptp->ateOpt[iTable].dp = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// now check that all required tables are present
|
|
|
|
for (iTable = 0; iTable < C_REQ_TABLES; iTable++)
|
|
{
|
|
if ((ptp->ateReq[iTable].dp == 0) || (ptp->ateReq[iTable].cj == 0))
|
|
RET_FALSE("TTFD!_required table absent\n");
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bGetTagIndex
|
|
*
|
|
* Determines whether the table is required or optional, assiciates the index
|
|
* into TABLE_POINTERS with the tag
|
|
*
|
|
* returns FALSE if ulTag is not one of the recognized tags
|
|
*
|
|
* History:
|
|
* 09-Feb-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bGetTagIndex (
|
|
ULONG ulTag, // tag
|
|
INT *piTable, // index into a table
|
|
BOOL *pbRequired // requred or optional table
|
|
)
|
|
{
|
|
*pbRequired = FALSE; // default set for optional tables, change the
|
|
// value if required table
|
|
|
|
switch (ulTag)
|
|
{
|
|
// reqired tables:
|
|
|
|
case tag_CharToIndexMap:
|
|
*piTable = IT_REQ_CMAP;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_GlyphData:
|
|
*piTable = IT_REQ_GLYPH;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_FontHeader:
|
|
*piTable = IT_REQ_HEAD;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_HoriHeader:
|
|
*piTable = IT_REQ_HHEAD;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_HorizontalMetrics:
|
|
*piTable = IT_REQ_HMTX;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_IndexToLoc:
|
|
*piTable = IT_REQ_LOCA;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_MaxProfile:
|
|
*piTable = IT_REQ_MAXP;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
case tag_NamingTable:
|
|
*piTable = IT_REQ_NAME;
|
|
*pbRequired = TRUE;
|
|
return (TRUE);
|
|
|
|
// optional tables
|
|
|
|
case tag_OS_2:
|
|
*piTable = IT_OPT_OS2;
|
|
return (TRUE);
|
|
case tag_HoriDeviceMetrics:
|
|
*piTable = IT_OPT_HDMX;
|
|
return (TRUE);
|
|
case tag_Vdmx:
|
|
*piTable = IT_OPT_VDMX;
|
|
return (TRUE);
|
|
case tag_Kerning:
|
|
*piTable = IT_OPT_KERN;
|
|
return (TRUE);
|
|
case tag_LinearThreshold:
|
|
*piTable = IT_OPT_LSTH;
|
|
return (TRUE);
|
|
case tag_Postscript:
|
|
*piTable = IT_OPT_POST;
|
|
return (TRUE);
|
|
case tag_GridfitAndScanProc:
|
|
*piTable = IT_OPT_GASP;
|
|
return (TRUE);
|
|
case tag_mort:
|
|
*piTable = IT_OPT_MORT;
|
|
return (TRUE);
|
|
case tag_GSUB:
|
|
*piTable = IT_OPT_GSUB;
|
|
return (TRUE);
|
|
default:
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC BOOL bComputeIFISIZE
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 10-Dec-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
// this function is particularly likely to break on MIPS, since
|
|
// NamingTable structure is three SHORTS so that
|
|
|
|
#define BE_NAME_ID_COPYRIGHT 0x0000
|
|
#define BE_NAME_ID_FAMILY 0x0100
|
|
#define BE_NAME_ID_SUBFAMILY 0x0200
|
|
#define BE_NAME_ID_UNIQNAME 0x0300
|
|
#define BE_NAME_ID_FULLNAME 0x0400
|
|
#define BE_NAME_ID_VERSION 0x0500
|
|
#define BE_NAME_ID_PSCRIPT 0x0600
|
|
#define BE_NAME_ID_TRADEMARK 0x0700
|
|
|
|
STATIC CHAR pszType1[] = "Converter: Windows Type 1 Installer";
|
|
|
|
// big endian unicode version of the above string
|
|
|
|
STATIC CHAR awszType1[] = {
|
|
0,'C',
|
|
0,'o',
|
|
0,'n',
|
|
0,'v',
|
|
0,'e',
|
|
0,'r',
|
|
0,'t',
|
|
0,'e',
|
|
0,'r',
|
|
0,':',
|
|
0,' ',
|
|
0,'W',
|
|
0,'i',
|
|
0,'n',
|
|
0,'d',
|
|
0,'o',
|
|
0,'w',
|
|
0,'s',
|
|
0,' ',
|
|
0,'T',
|
|
0,'y',
|
|
0,'p',
|
|
0,'e',
|
|
0,' ',
|
|
0,'1',
|
|
0,' ',
|
|
0,'I',
|
|
0,'n',
|
|
0,'s',
|
|
0,'t',
|
|
0,'a',
|
|
0,'l',
|
|
0,'l',
|
|
0,'e',
|
|
0,'r',
|
|
0, 0
|
|
};
|
|
|
|
|
|
|
|
STATIC BOOL bComputeIFISIZE
|
|
(
|
|
BYTE *pjView,
|
|
TABLE_POINTERS *ptp,
|
|
uint16 ui16PlatID,
|
|
uint16 ui16SpecID,
|
|
uint16 ui16LangID,
|
|
PIFISIZE pifisz,
|
|
BOOL *pbType1
|
|
)
|
|
{
|
|
|
|
sfnt_OS2 * pOS2;
|
|
sfnt_NamingTable *pname = (sfnt_NamingTable *)(pjView + ptp->ateReq[IT_REQ_NAME].dp);
|
|
BYTE *pjStorage;
|
|
|
|
sfnt_NameRecord * pnrecInit, *pnrec, *pnrecEnd;
|
|
|
|
BOOL bMatchLangId, bFoundAllNames;
|
|
INT iNameLoop;
|
|
|
|
// pointers to name records for the four strings we are interested in:
|
|
|
|
sfnt_NameRecord * pnrecFamily = (sfnt_NameRecord *)NULL;
|
|
sfnt_NameRecord * pnrecSubFamily = (sfnt_NameRecord *)NULL;
|
|
sfnt_NameRecord * pnrecUnique = (sfnt_NameRecord *)NULL;
|
|
sfnt_NameRecord * pnrecFull = (sfnt_NameRecord *)NULL;
|
|
sfnt_NameRecord * pnrecVersion = (sfnt_NameRecord *)NULL;
|
|
|
|
// get out if this is not one of the platID's we know what to do with
|
|
|
|
if ((ui16PlatID != BE_PLAT_ID_MS) && (ui16PlatID != BE_PLAT_ID_MAC))
|
|
RET_FALSE("ttfd!_ do not know how to handle this plat id\n");
|
|
|
|
// first clean the output structure:
|
|
|
|
memset((PVOID)pifisz, 0, sizeof(IFISIZE));
|
|
|
|
// first name record is layed just below the naming table
|
|
|
|
pnrecInit = (sfnt_NameRecord *)((PBYTE)pname + SIZE_NAMING_TABLE);
|
|
pnrecEnd = &pnrecInit[BE_UINT16(&pname->count)];
|
|
|
|
// in the first iteration of the loop we want to match lang id to our
|
|
// favorite lang id. If we find all 4 strings in that language we are
|
|
// done. If we do not find all 4 string with matching lang id we will try to
|
|
// language only, but not sublanguage. For instance if Canadian French
|
|
// is requested, but the file only contains "French" French names, we will
|
|
// return the names in French French. If that does not work either
|
|
// we shall go over name records again and try to find
|
|
// the strings in English. If that does not work either we
|
|
// shall resort to total desperation and just pick any language.
|
|
// therefore we may go up to 4 times through the NAME_LOOP
|
|
|
|
bFoundAllNames = FALSE;
|
|
|
|
// find the name record with the desired ID's
|
|
// NAME_LOOP:
|
|
|
|
for (iNameLoop = 0; (iNameLoop < 4) && !bFoundAllNames; iNameLoop++)
|
|
{
|
|
for
|
|
(
|
|
pnrec = pnrecInit;
|
|
(pnrec < pnrecEnd) && !(bFoundAllNames && (pnrecVersion != NULL));
|
|
pnrec++
|
|
)
|
|
{
|
|
switch (iNameLoop)
|
|
{
|
|
case 0:
|
|
// match BOTH language and sublanguage
|
|
|
|
bMatchLangId = (pnrec->languageID == ui16LangID);
|
|
break;
|
|
|
|
case 1:
|
|
// match language but not sublanguage
|
|
|
|
bMatchLangId = ((pnrec->languageID & 0xff00) == (ui16LangID & 0xff00));
|
|
break;
|
|
|
|
case 2:
|
|
// try to find english names if desired language is not available
|
|
|
|
bMatchLangId = ((pnrec->languageID & 0xff00) == 0x0900);
|
|
break;
|
|
|
|
case 3:
|
|
// do not care to match language at all, just give us something
|
|
|
|
bMatchLangId = TRUE;
|
|
break;
|
|
|
|
default:
|
|
RIP("ttfd! must not have more than 3 loop iterations\n");
|
|
break;
|
|
}
|
|
|
|
if
|
|
(
|
|
(pnrec->platformID == ui16PlatID) &&
|
|
(pnrec->specificID == ui16SpecID) &&
|
|
bMatchLangId
|
|
)
|
|
{
|
|
switch (pnrec->nameID)
|
|
{
|
|
case BE_NAME_ID_FAMILY:
|
|
|
|
if (!pnrecFamily) // if we did not find it before
|
|
pnrecFamily = pnrec;
|
|
break;
|
|
|
|
case BE_NAME_ID_SUBFAMILY:
|
|
|
|
if (!pnrecSubFamily) // if we did not find it before
|
|
pnrecSubFamily = pnrec;
|
|
break;
|
|
|
|
case BE_NAME_ID_UNIQNAME:
|
|
|
|
if (!pnrecUnique) // if we did not find it before
|
|
pnrecUnique = pnrec;
|
|
break;
|
|
|
|
case BE_NAME_ID_FULLNAME:
|
|
|
|
if (!pnrecFull) // if we did not find it before
|
|
pnrecFull = pnrec;
|
|
break;
|
|
|
|
case BE_NAME_ID_VERSION :
|
|
|
|
if (!pnrecVersion) // if we did not find it before
|
|
pnrecVersion = pnrec;
|
|
break;
|
|
|
|
case BE_NAME_ID_COPYRIGHT:
|
|
case BE_NAME_ID_PSCRIPT :
|
|
case BE_NAME_ID_TRADEMARK:
|
|
break;
|
|
|
|
default:
|
|
RIP("ttfd!bogus name ID\n");
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
bFoundAllNames = (
|
|
(pnrecFamily != NULL) &&
|
|
(pnrecSubFamily != NULL) &&
|
|
(pnrecUnique != NULL) &&
|
|
(pnrecFull != NULL)
|
|
);
|
|
}
|
|
|
|
|
|
} // end of iNameLoop
|
|
|
|
if (!bFoundAllNames)
|
|
{
|
|
// we have gone through the all 3 iterations of the NAME loop
|
|
// and still have not found all the names. We have singled out
|
|
// pnrecVersion because it is not required for the font to be
|
|
// loaded, we only need it to check if this a ttf converted from t1
|
|
|
|
RETURN("ttfd!can not find all name strings in a file\n", FALSE);
|
|
}
|
|
|
|
// get the pointer to the beginning of the storage area for strings
|
|
|
|
pjStorage = (PBYTE)pname + BE_UINT16(&pname->stringOffset);
|
|
|
|
if (ui16PlatID == BE_PLAT_ID_MS)
|
|
{
|
|
// offsets in the records are relative to the beginning of the storage
|
|
|
|
pifisz->cjFamilyName = BE_UINT16(&pnrecFamily->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjFamilyName = pjStorage +
|
|
BE_UINT16(&pnrecFamily->offset);
|
|
|
|
pifisz->cjSubfamilyName = BE_UINT16(&pnrecSubFamily->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjSubfamilyName = pjStorage +
|
|
BE_UINT16(&pnrecSubFamily->offset);
|
|
|
|
pifisz->cjUniqueName = BE_UINT16(&pnrecUnique->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjUniqueName = pjStorage +
|
|
BE_UINT16(&pnrecUnique->offset);
|
|
|
|
pifisz->cjFullName = BE_UINT16(&pnrecFull->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjFullName = pjStorage +
|
|
BE_UINT16(&pnrecFull->offset);
|
|
}
|
|
else // mac id
|
|
{
|
|
// offsets in the records are relative to the beginning of the storage
|
|
|
|
pifisz->cjFamilyName = sizeof(WCHAR) * BE_UINT16(&pnrecFamily->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjFamilyName = pjStorage +
|
|
BE_UINT16(&pnrecFamily->offset);
|
|
|
|
pifisz->cjSubfamilyName = sizeof(WCHAR) * BE_UINT16(&pnrecSubFamily->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjSubfamilyName = pjStorage +
|
|
BE_UINT16(&pnrecSubFamily->offset);
|
|
|
|
pifisz->cjUniqueName = sizeof(WCHAR) * BE_UINT16(&pnrecUnique->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjUniqueName = pjStorage +
|
|
BE_UINT16(&pnrecUnique->offset);
|
|
|
|
pifisz->cjFullName = sizeof(WCHAR) * BE_UINT16(&pnrecFull->length) +
|
|
sizeof(WCHAR); // for terminating zero
|
|
pifisz->pjFullName = pjStorage +
|
|
BE_UINT16(&pnrecFull->offset);
|
|
}
|
|
|
|
// check out if this is a converted Type 1 font:
|
|
|
|
*pbType1 = FALSE; // default
|
|
|
|
if (pnrecVersion)
|
|
{
|
|
ULONG ulLen;
|
|
BYTE *pjVersion = pjStorage + BE_UINT16(&pnrecVersion->offset);
|
|
|
|
if (ui16PlatID == BE_PLAT_ID_MS)
|
|
{
|
|
ulLen = BE_UINT16(&pnrecVersion->length);
|
|
if (ulLen > sizeof(awszType1))
|
|
ulLen = sizeof(awszType1);
|
|
ulLen -= sizeof(WCHAR); // minus terminating zero
|
|
|
|
*pbType1 = !memcmp(pjVersion, awszType1, ulLen);
|
|
}
|
|
else // mac id
|
|
{
|
|
ulLen = BE_UINT16(&pnrecVersion->length); // minus term. zero
|
|
if (ulLen > sizeof(pszType1))
|
|
ulLen = sizeof(pszType1);
|
|
ulLen -= 1; // minus terminating zero
|
|
|
|
*pbType1 = !strncmp(pjVersion, pszType1, ulLen);
|
|
}
|
|
}
|
|
|
|
// lay the strings below the ifimetrics
|
|
// but insert IFIEXTRA below ifimetrics itself and before strings
|
|
|
|
pifisz->cjIFI = sizeof(IFIMETRICS) +
|
|
offsetof(IFIEXTRA, aulReserved[0]) +
|
|
pifisz->cjFamilyName +
|
|
pifisz->cjSubfamilyName +
|
|
pifisz->cjUniqueName +
|
|
pifisz->cjFullName ;
|
|
|
|
pifisz->cjIFI = DWORD_ALIGN(pifisz->cjIFI);
|
|
|
|
// we may need to add a '@' to facename and family name in case this
|
|
// font has a vertical face name
|
|
|
|
pifisz->cjIFI += sizeof(WCHAR) * 2;
|
|
|
|
{
|
|
ULONG cSims = 0;
|
|
|
|
switch (fsSelectionTTFD(pjView,ptp) & (FM_SEL_BOLD | FM_SEL_ITALIC))
|
|
{
|
|
case 0:
|
|
cSims = 3;
|
|
break;
|
|
|
|
case FM_SEL_BOLD:
|
|
case FM_SEL_ITALIC:
|
|
cSims = 1;
|
|
break;
|
|
|
|
case (FM_SEL_ITALIC | FM_SEL_BOLD):
|
|
cSims = 0;
|
|
break;
|
|
|
|
default:
|
|
RIP("TTFD!tampering with flags\n");
|
|
break;
|
|
}
|
|
|
|
if (cSims)
|
|
{
|
|
pifisz->dpSims = pifisz->cjIFI;
|
|
pifisz->cjIFI += (DWORD_ALIGN(sizeof(FONTSIM)) + cSims * DWORD_ALIGN(sizeof(FONTDIFF)));
|
|
}
|
|
else
|
|
{
|
|
pifisz->dpSims = 0;
|
|
}
|
|
}
|
|
|
|
// add charset info:
|
|
|
|
pifisz->dpCharSets = pifisz->cjIFI;
|
|
pifisz->cjIFI += DWORD_ALIGN(NOEMCHARSETS);
|
|
|
|
// finally check if FONTSIGNATURE info is needed
|
|
|
|
pOS2 = (sfnt_OS2 *)((ptp->ateOpt[IT_OPT_OS2].dp) ?
|
|
pjView + ptp->ateOpt[IT_OPT_OS2].dp :
|
|
NULL) ;
|
|
|
|
if (pOS2 && pOS2->Version)
|
|
{
|
|
// 1.0 or higher is TT open
|
|
|
|
pifisz->dpFontSig = pifisz->cjIFI;
|
|
pifisz->cjIFI += sizeof(FONTSIGNATURE); // 6 dwords, no need to add dword align
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC BOOL bComputeIDs
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 13-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC BOOL
|
|
bComputeIDs (
|
|
BYTE * pjView,
|
|
TABLE_POINTERS *ptp,
|
|
uint16 *pui16PlatID,
|
|
uint16 *pui16SpecID,
|
|
sfnt_mappingTable **ppmap,
|
|
ULONG *pulGsetType,
|
|
ULONG *pul_wcBias,
|
|
CMAPINFO *pcmi
|
|
)
|
|
{
|
|
|
|
sfnt_char2IndexDirectory * pcmap =
|
|
(sfnt_char2IndexDirectory *)(pjView + ptp->ateReq[IT_REQ_CMAP].dp);
|
|
|
|
sfnt_platformEntry * pplat = &pcmap->platform[0];
|
|
sfnt_platformEntry * pplatEnd = pplat + BE_UINT16(&pcmap->numTables);
|
|
sfnt_platformEntry * pplatMac = (sfnt_platformEntry *)NULL;
|
|
|
|
*ppmap = (sfnt_mappingTable *)NULL;
|
|
*pul_wcBias = 0;
|
|
|
|
if (pcmap->version != 0) // no need to swap bytes, 0 == be 0
|
|
RET_FALSE("TTFD!_bComputeIDs: version number\n");
|
|
if (BE_UINT16(&(pcmap->numTables)) > 30)
|
|
{
|
|
RET_FALSE("Number of cmap tables greater than 30 -- probably a bad font\n");
|
|
}
|
|
|
|
// find the first sfnt_platformEntry with platformID == PLAT_ID_MS,
|
|
// if there was no MS mapping table, go for the mac one
|
|
|
|
for (; pplat < pplatEnd; pplat++)
|
|
{
|
|
if (pplat->platformID == BE_PLAT_ID_MS)
|
|
{
|
|
BOOL bRet;
|
|
*pui16PlatID = BE_PLAT_ID_MS;
|
|
*pui16SpecID = pplat->specificID;
|
|
*ppmap = (sfnt_mappingTable *)
|
|
((PBYTE)pcmap + SWAPL(pplat->offset));
|
|
|
|
switch((*ppmap)->format)
|
|
{
|
|
case BE_FORMAT_MSFT_UNICODE :
|
|
|
|
switch(pplat->specificID)
|
|
{
|
|
case BE_SPEC_ID_SHIFTJIS :
|
|
case BE_SPEC_ID_GB :
|
|
case BE_SPEC_ID_BIG5 :
|
|
case BE_SPEC_ID_WANSUNG :
|
|
|
|
bRet = bVerifyMsftTableGeneral(*ppmap,pulGsetType,pcmi,
|
|
pplat->specificID);
|
|
break;
|
|
|
|
case BE_SPEC_ID_UGL :
|
|
default :
|
|
|
|
bRet = bVerifyMsftTable(*ppmap,pulGsetType,pul_wcBias,pcmi,
|
|
pplat->specificID);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case BE_FORMAT_HIGH_BYTE :
|
|
|
|
bRet = bVerifyMsftHighByteTable(*ppmap,
|
|
pulGsetType,pcmi,pplat->specificID);
|
|
break;
|
|
|
|
default :
|
|
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
if(!bRet)
|
|
{
|
|
*ppmap = (sfnt_mappingTable *)NULL;
|
|
RET_FALSE("TTFD!_bComputeIDs: bVerifyMsftTable failed \n");
|
|
}
|
|
|
|
// keep specific ID in CMAPINFO
|
|
|
|
pcmi->ui16SpecID = pplat->specificID;
|
|
|
|
|
|
if
|
|
(
|
|
(pplat->specificID == BE_SPEC_ID_UNDEFINED) ||
|
|
(*pul_wcBias) // we are really using f0?? range to put in a symbol font
|
|
)
|
|
{
|
|
// correct the value of the glyph set, we cheat here
|
|
|
|
*pulGsetType = GSET_TYPE_SYMBOL;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
if ((pplat->platformID == BE_PLAT_ID_MAC) &&
|
|
(pplat->specificID == BE_SPEC_ID_UNDEFINED))
|
|
{
|
|
pplatMac = pplat;
|
|
}
|
|
}
|
|
|
|
if (pplatMac != (sfnt_platformEntry *)NULL)
|
|
{
|
|
*pui16PlatID = BE_PLAT_ID_MAC;
|
|
*pui16SpecID = BE_SPEC_ID_UNDEFINED;
|
|
*ppmap = (sfnt_mappingTable *)
|
|
((PBYTE)pcmap + SWAPL(pplatMac->offset));
|
|
|
|
if (!bVerifyMacTable(*ppmap))
|
|
{
|
|
*ppmap = (sfnt_mappingTable *)NULL;
|
|
RET_FALSE("TTFD!_bComputeIDs: bVerifyMacTable failed \n");
|
|
}
|
|
|
|
//!!! lang issues, what if not roman but thai mac char set ??? [bodind]
|
|
|
|
// see if it is necessary to convert unicode to mac code points, or we
|
|
// shall cheat in case of symbol char set for win31 compatiblity
|
|
|
|
if (bCvtUnToMac(pjView, ptp, *pui16PlatID))
|
|
{
|
|
*pulGsetType = GSET_TYPE_MAC_ROMAN;
|
|
}
|
|
else
|
|
{
|
|
*pulGsetType = GSET_TYPE_PSEUDO_WIN;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
RET_FALSE("TTFD!_bComputeIDs: unknown platID\n");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC VOID vComputeGLYPHSET_MSFT_UNICODE
|
|
*
|
|
* computes the glyphset structure for the cmap table that has
|
|
* format 4 = MSFT_UNICODE
|
|
*
|
|
* History:
|
|
* 22-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC ULONG
|
|
cjComputeGLYPHSET_MSFT_UNICODE (
|
|
sfnt_mappingTable *pmap,
|
|
fs_GlyphInputType *pgin,
|
|
fs_GlyphInfoType *pgout,
|
|
FD_GLYPHSET *pgset,
|
|
CMAPINFO *pcmi
|
|
)
|
|
{
|
|
uint16 * pstartCount;
|
|
uint16 * pendCount;
|
|
uint16 cRuns;
|
|
PWCRUN pwcrun, pwcrunEnd, pwcrunInit, pwcrun_b7;
|
|
HGLYPH *phg, *phgEnd;
|
|
ULONG cjRet;
|
|
FS_ENTRY iRet;
|
|
BOOL bInsert_b7;
|
|
|
|
#if DBG
|
|
ULONG cGlyphsSupported = 0;
|
|
#endif
|
|
|
|
cjRet = SZ_GLYPHSET(pcmi->cRuns,pcmi->cGlyphs);
|
|
|
|
if (!pgset)
|
|
{
|
|
return cjRet;
|
|
}
|
|
|
|
// check if need to insert an extra run for b7 only
|
|
|
|
bInsert_b7 = ((pcmi->fl & (CMI_2219_PRESENT | CMI_B7_ABSENT)) == (CMI_2219_PRESENT | CMI_B7_ABSENT));
|
|
|
|
cRuns = BE_UINT16((PBYTE)pmap + OFF_segCountX2) >> 1;
|
|
|
|
// get the pointer to the beginning of the array of endCount code points
|
|
|
|
pendCount = (uint16 *)((PBYTE)pmap + OFF_endCount);
|
|
|
|
// the final endCode has to be 0xffff;
|
|
// if this is not the case, there is a bug in the tt file or in our code:
|
|
|
|
ASSERTDD(pendCount[cRuns - 1] == 0xFFFF,
|
|
"pendCount[cRuns - 1] != 0xFFFF\n");
|
|
|
|
// Get the pointer to the beginning of the array of startCount code points
|
|
// For resons known only to tt designers, startCount array does not
|
|
// begin immediately after the end of endCount array, i.e. at
|
|
// &pendCount[cRuns]. Instead, they insert an uint16 padding which has to
|
|
// set to zero and the startCount array begins after the padding. This
|
|
// padding in no way helps alignment of the structure
|
|
|
|
// ASSERTDD(pendCount[cRuns] == 0, "TTFD!_padding != 0\n");
|
|
|
|
pstartCount = &pendCount[cRuns + 1];
|
|
|
|
// here we shall check if the last run is just a terminator for the
|
|
// array of runs or a real nontrivial run. If just a terminator, there is no
|
|
// need to report it. This will save some memory in the cache plus
|
|
// pifi->wcLast will represent the last glyph that is truly supported in
|
|
// font:
|
|
|
|
if ((pstartCount[cRuns-1] == 0xffff) && (cRuns > 1))
|
|
cRuns -= 1; // do not report trivial run
|
|
|
|
// real no of runs, including the range for b7: If b7 is already supportred
|
|
// then the same as number of runs reported in a font. If b7 is not supported
|
|
// we will have to add a range [b7,b7] to the glyphset structure for win31
|
|
// compatibility reasons. win31 maps b7 to 2219 and we will have b7 point to 2219
|
|
|
|
if (bInsert_b7) // if b7 not supported in a font but 2219 is
|
|
{
|
|
cRuns++; // add a run with b7 only
|
|
}
|
|
|
|
// by default we will not have to simulate the presence of b7 by adding
|
|
// an extra run containing single glyph
|
|
|
|
pwcrun_b7 = NULL;
|
|
|
|
pwcrunInit = &pgset->awcrun[0];
|
|
phg = (HGLYPH *)((PBYTE)pgset + offsetof(FD_GLYPHSET,awcrun) + cRuns*sizeof(WCRUN));
|
|
|
|
if (bInsert_b7) // if b7 not supported in a font, will have to add it
|
|
{
|
|
pwcrun_b7 = pwcrunInit + pcmi->i_b7;
|
|
}
|
|
|
|
ASSERTDD(pcmi->cRuns == cRuns, "cRuns\n");
|
|
|
|
for
|
|
(
|
|
pwcrun = pwcrunInit, pwcrunEnd = pwcrunInit + cRuns;
|
|
pwcrun < pwcrunEnd;
|
|
pwcrun++, pstartCount++, pendCount++
|
|
)
|
|
{
|
|
WCHAR wcFirst, wcLast, wcCurrent;
|
|
|
|
// check if we need to skip a run and a handle space for b7:
|
|
|
|
if (bInsert_b7 && (pwcrun == pwcrun_b7))
|
|
{
|
|
#if DBG
|
|
cGlyphsSupported += 1; // list b7 as a supported glyph
|
|
#endif
|
|
|
|
pwcrun->wcLow = 0xb7;
|
|
pwcrun->cGlyphs = 1;
|
|
pwcrun->phg = phg; // will be initialized later
|
|
phg++; // skip to the next handle
|
|
pwcrun++; // go to the next run
|
|
if (pwcrun == pwcrunEnd) // check if done
|
|
{
|
|
break; // done
|
|
}
|
|
}
|
|
|
|
wcFirst = (WCHAR)BE_UINT16(pstartCount);
|
|
wcLast = (WCHAR)BE_UINT16(pendCount);
|
|
|
|
pwcrun->cGlyphs = (USHORT)(wcLast - wcFirst + 1);
|
|
|
|
// is this a run which contains b7 ?
|
|
|
|
if ((0xb7 >= wcFirst) && (0xb7 <= wcLast))
|
|
pwcrun_b7 = pwcrun;
|
|
|
|
// add the default glyph at the end of the first run, if possible, i.e.
|
|
// if wcLast < 0xffff for the first run, and if we are not in the collision
|
|
// with the run we have possibly added for b7
|
|
|
|
if ((pwcrun == pwcrunInit) && (wcLast < 0xffff))
|
|
{
|
|
if (!bInsert_b7 || (wcLast != 0xb6))
|
|
pwcrun->cGlyphs += 1;
|
|
}
|
|
|
|
#if DBG
|
|
cGlyphsSupported += pwcrun->cGlyphs;
|
|
#endif
|
|
|
|
pwcrun->wcLow = wcFirst;
|
|
pwcrun->phg = phg;
|
|
wcCurrent = wcFirst;
|
|
|
|
for (phgEnd = phg + pwcrun->cGlyphs;phg < phgEnd; phg++,wcCurrent++)
|
|
{
|
|
pgin->param.newglyph.characterCode = (uint16)wcCurrent;
|
|
pgin->param.newglyph.glyphIndex = 0;
|
|
|
|
// compute the glyph index from the character code:
|
|
|
|
if ((iRet = fs_NewGlyph(pgin, pgout)) != NO_ERR)
|
|
{
|
|
V_FSERROR(iRet);
|
|
RET_FALSE("TTFD!_cjComputeGLYPHSET_MSFT_UNICODE, fs_NewGlyph\n");
|
|
}
|
|
|
|
// return the glyph index corresponding to this hglyph:
|
|
|
|
*phg = (HGLYPH)pgout->glyphIndex;
|
|
}
|
|
}
|
|
|
|
// fix a handle for b7:
|
|
|
|
if (pcmi->fl & CMI_2219_PRESENT)
|
|
{
|
|
PWCRUN pwcrun_2219 = pwcrunInit + pcmi->i_2219;
|
|
|
|
ASSERTDD(pwcrun_b7,"these ptrs must not be 0\n");
|
|
ASSERTDD(0x2219 >= pwcrun_2219->wcLow, "pwcrun_2219->wcLow\n");
|
|
ASSERTDD(0x2219 < (pwcrun_2219->wcLow + pwcrun_2219->cGlyphs),
|
|
"pwcrun_2219->wcHi\n"
|
|
);
|
|
|
|
pwcrun_b7->phg[0xb7 - pwcrun_b7->wcLow] =
|
|
pwcrun_2219->phg[0x2219 - pwcrun_2219->wcLow];
|
|
}
|
|
|
|
ASSERTDD(pcmi->cGlyphs == cGlyphsSupported, "cGlyphsSupported\n");
|
|
|
|
pgset->cjThis = cjRet;
|
|
pgset->flAccel = GS_16BIT_HANDLES;
|
|
pgset->cGlyphsSupported = pcmi->cGlyphs;
|
|
pgset->cRuns = cRuns;
|
|
|
|
return cjRet;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC ULONG cjGsetGeneral
|
|
*
|
|
* computes the size of FD_GLYPHSET structure for the font represented
|
|
* by this mapping Table
|
|
*
|
|
* History:
|
|
* 21-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
//!!! this needs some review [bodind]
|
|
|
|
STATIC ULONG
|
|
cjGsetGeneral(
|
|
sfnt_mappingTable *pmap,
|
|
CMAPINFO *pcmi
|
|
)
|
|
{
|
|
switch(pmap->format)
|
|
{
|
|
case BE_FORMAT_MAC_STANDARD:
|
|
|
|
return 20; // return(ggsetMac->cjThis);
|
|
|
|
case BE_FORMAT_MSFT_UNICODE:
|
|
|
|
switch(pcmi->ui16SpecID)
|
|
{
|
|
case BE_SPEC_ID_SHIFTJIS :
|
|
case BE_SPEC_ID_GB :
|
|
case BE_SPEC_ID_BIG5 :
|
|
case BE_SPEC_ID_WANSUNG :
|
|
return cjComputeGLYPHSET_MSFT_GENERAL (pmap,NULL,pcmi);
|
|
|
|
case BE_SPEC_ID_UGL :
|
|
default :
|
|
|
|
return cjComputeGLYPHSET_MSFT_UNICODE (pmap,NULL,NULL,NULL,pcmi);
|
|
}
|
|
|
|
case BE_FORMAT_TRIMMED:
|
|
|
|
WARNING("TTFD!_cjGsetGeneral: TRIMMED format\n");
|
|
return 0;
|
|
|
|
case BE_FORMAT_HIGH_BYTE:
|
|
|
|
WARNING("TTFD!_cjGsetGeneral: HIGH_BYTE format\n");
|
|
return 0;
|
|
|
|
default:
|
|
|
|
WARNING("TTFD!_cjGsetGeneral: illegal format\n");
|
|
return 0;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC BOOL bVerifyMsftTable
|
|
*
|
|
*
|
|
* Effects: checks whether the table is consistent with what tt
|
|
* spec claims it should be
|
|
*
|
|
*
|
|
* History:
|
|
* 22-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC BOOL
|
|
bVerifyMsftTable (
|
|
sfnt_mappingTable *pmap,
|
|
ULONG *pulGsetType,
|
|
ULONG *pul_wcBias,
|
|
CMAPINFO *pcmi,
|
|
uint16 ui16SpecID
|
|
)
|
|
{
|
|
uint16 * pstartCount, * pstartCountBegin;
|
|
uint16 * pendCount, * pendCountEnd, * pendCountBegin;
|
|
uint16 cRuns;
|
|
uint16 usLo, usHi, usHiPrev;
|
|
BOOL bInsert_b7;
|
|
|
|
if (pmap->format != BE_FORMAT_MSFT_UNICODE)
|
|
RET_FALSE("TTFD!_bVerifyMsftTable, format\n");
|
|
|
|
cRuns = BE_UINT16((PBYTE)pmap + OFF_segCountX2);
|
|
|
|
if (cRuns & 1)
|
|
RET_FALSE("TTFD!_bVerifyMsftTable, segCountX2 is odd\n");
|
|
|
|
cRuns >>= 1;
|
|
|
|
//!!! here one could check whether all other quantities in the
|
|
//!!! preceding endCount when derived from cRuns are the
|
|
//!!! same as in the file [bodind]
|
|
|
|
// get the pointer to the beginning of the array of endCount code points
|
|
|
|
pendCountBegin = pendCount = (uint16 *)((PBYTE)pmap + OFF_endCount);
|
|
|
|
// the final endCode has to be 0xffff;
|
|
// if this is not the case, there is a bug in the tt file or in our code:
|
|
|
|
if (pendCount[cRuns - 1] != 0xFFFF)
|
|
RET_FALSE("TTFD!_bVerifyMsftTable, pendCount[cRuns - 1] != 0xFFFF\n");
|
|
|
|
// Get the pointer to the beginning of the array of startCount code points
|
|
// For resons known only to tt designers, startCount array does not
|
|
// begin immediately after the end of endCount array, i.e. at
|
|
// &pendCount[cRuns]. Instead, they insert an uint16 padding which has to
|
|
// set to zero and the startCount array begins after the padding. This
|
|
// padding in no way helps alignment of the structure nor it is useful
|
|
// for anything else. Moreover, there are fonts which forget to set the
|
|
// padding to zero and are otherwise ok (bodoni), which load under win31
|
|
// so that I have to remove this check:
|
|
|
|
#if 0
|
|
|
|
// used to return false here [bodind]
|
|
|
|
if (pendCount[cRuns] != 0)
|
|
TtfdDbgPrint(
|
|
"TTFD!_bVerifyMsftTable, padding = 0x%x\n",
|
|
pendCount[cRuns]
|
|
);
|
|
|
|
#endif
|
|
|
|
// set the default, change only as needed
|
|
|
|
*pulGsetType = GSET_TYPE_GENERAL;
|
|
|
|
// check whether the runs are well ordered, find out if b7
|
|
// is supported in one of the ranges in a font by checking complimetary ranges
|
|
// of glyphs that are NOT SUPPORTED
|
|
|
|
usHiPrev = 0;
|
|
pendCountEnd = &pendCount[cRuns];
|
|
pstartCountBegin = pstartCount = &pendCount[cRuns + 1];
|
|
|
|
// check if this is a candidate for a symbol font
|
|
// stored in the unicode range 0xf000 - 0xf0ff that has to be
|
|
// mapped to 0x0000-0x00ff range, or maybe if this is a crazy arabic font
|
|
// which has glyphs in the range f200-f2ff.
|
|
// We have seen several fonts broken in the past as a result od touching the
|
|
// next few lines of code that compute wcBias.
|
|
// Here are all of these cases:
|
|
|
|
#if 0
|
|
|
|
originally, in 3.51 the code was as follows:
|
|
|
|
if ((*pul_wcBias & 0xFF00) == 0xF000)
|
|
*pul_wcBias = 0xF000;
|
|
else
|
|
*pul_wcBias = 0;
|
|
This did not work for arabic trad.ttf font:
|
|
|
|
trad.ttf. (arabic) format (3,0), range [f200,f2ff],
|
|
wcBias needs to be f200-20 for compat. It can be computed as follows:
|
|
|
|
< if ((*pul_wcBias & 0xFF00) == 0xF000)
|
|
< *pul_wcBias = 0xF000;
|
|
< else
|
|
< *pul_wcBias = 0;
|
|
---
|
|
> *pul_wcBias = (BE_UINT16(pstartCount)) & 0xFF00;
|
|
|
|
for some reason this did not work, perhaps because of msicons2.ttf,
|
|
had to do fix to a fix
|
|
|
|
< *pul_wcBias = (BE_UINT16(pstartCount)) & 0xFF00;
|
|
---
|
|
> *pul_wcBias = BE_UINT16(pstartCount) - 0x20; // = f200 - 20 = f1e0.
|
|
|
|
This is a pathological case, had to be put in so that this font
|
|
can work the same way as it does under win95
|
|
|
|
msicons2.ttf, format (3,0), ranges are [0001,0004], [0007,0007], etc.
|
|
wcBias needs to be ?
|
|
|
|
|
|
garam4.ttf. This is a regular (3,1) font with one anomaly which is that the
|
|
first range is anomalous [00, 00], the second range is [20,ff] etc.
|
|
wcBias needs to be 0 in this case. so the fix is as follows:
|
|
|
|
< *pul_wcBias = BE_UINT16(pstartCount) - 0x20;
|
|
---
|
|
> *pul_wcBias = BE_UINT16(pstartCount);
|
|
> if (*pul_wcBias & 0xff00) // one of these
|
|
> *pul_wcBias = *pul_wcBias - 0x20; // covers arabic case
|
|
> else
|
|
> *pul_wcBias = 0; // garam4 case
|
|
|
|
this is how we arrive at our present code which seems to be breaking
|
|
fonts obtained by conversion from Type 1 fonts with custom encoding,
|
|
examples being cmr10.ttf (yy font)
|
|
|
|
cmr10.ttf, format (3,0), ranges [f000, f080], etc,
|
|
wcBias needs to be f000 in this case.
|
|
|
|
also
|
|
|
|
gotbx__2.ttf, format (3,0), ranges [f005, f006], [f008,f008], etc,
|
|
wcBias needs to be f000 in this case.
|
|
|
|
|
|
#endif
|
|
|
|
|
|
*pul_wcBias = BE_UINT16(pstartCount);
|
|
|
|
if (ui16SpecID == BE_SPEC_ID_UGL) // ie. specific id = 1, regular case
|
|
{
|
|
if ((*pul_wcBias & 0xff00) == 0xf000)
|
|
{
|
|
*pul_wcBias = 0xf000; // chess figurine fonts hack, they have spec id == 1, force them to symbol font case.
|
|
}
|
|
else // all other normal fonts:
|
|
{
|
|
*pul_wcBias = 0; // garam4.ttf is in this class
|
|
}
|
|
}
|
|
else // specific id = 0; // symbol font case
|
|
{
|
|
// trad.ttf, msicons2.ttf, cmr10.ttf, gotbx__2.ttf
|
|
|
|
|
|
switch (*pul_wcBias & 0xff00)
|
|
{
|
|
case 0xf000:
|
|
|
|
// custom encoding t1 fonts converted to tt (cmr10.ttf, gotbx__2.ttf)
|
|
// and and all other "reasonable" tt symbol fonts.
|
|
// Examples of other "reasonable" symbol fonts are
|
|
// marlett.ttf, symbol.ttf and wingding.ttf where for all these fonts
|
|
// the first range is [f020, ???], so that, either formula would work
|
|
|
|
*pul_wcBias = 0xf000;
|
|
break;
|
|
|
|
case 0: // msicons2.ttf
|
|
|
|
*pul_wcBias = 0;
|
|
break;
|
|
|
|
#ifdef FE_SB
|
|
case 0xe000: // eudc fonts
|
|
*pul_wcBias = 0;
|
|
break;
|
|
#endif
|
|
|
|
case 0xf200: // trad.ttf
|
|
default:
|
|
|
|
*pul_wcBias = *pul_wcBias - 0x20;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// here we shall check if the last run is just a terminator for the
|
|
// array of runs or a real nontrivial run. If just a terminator, there is no
|
|
// need to report it. This will save some memory in the cache plus
|
|
// pifi->wcLast will represent the last glyph that is truly supported in
|
|
// font:
|
|
|
|
if ((pstartCountBegin[cRuns-1] == 0xffff) && (cRuns > 1))
|
|
{
|
|
cRuns -= 1; // do not report trivial run
|
|
pendCountEnd--;
|
|
}
|
|
|
|
// init the cmap info:
|
|
|
|
pcmi->fl = 0;
|
|
pcmi->i_b7 = 0; // index for [b7,b7] wcrun in FD_GLYPHSET if b7 is NOT supported
|
|
pcmi->i_2219 = 0; // cmap index for 2219 if 2219 IS supported
|
|
pcmi->cRuns = cRuns; // number of runs in a font, excluding the last run if equal to [ffff,ffff]
|
|
pcmi->cGlyphs = 0; // total number of glyphs in a font
|
|
|
|
for (
|
|
;
|
|
pendCount < pendCountEnd;
|
|
pstartCount++, pendCount++, usHiPrev = usHi
|
|
)
|
|
{
|
|
usLo = BE_UINT16(pstartCount);
|
|
usHi = BE_UINT16(pendCount);
|
|
|
|
if (usHi < usLo)
|
|
RET_FALSE("TTFD!_bVerifyMsftTable: usHi < usLo\n");
|
|
if (usHiPrev > usLo)
|
|
RET_FALSE("TTFD!_bVerifyMsftTable: usHiPrev > usLo\n");
|
|
|
|
pcmi->cGlyphs += (ULONG)(usHi + 1 - usLo);
|
|
|
|
// check if b7 is in one of the ranges of glyphs that are NOT SUPPORTED
|
|
|
|
if ((0xb7 > usHiPrev) && (0xb7 < usLo))
|
|
{
|
|
// store the index of the run that b7 is going to occupy in FD_GLYPHSET
|
|
// Just in case this index is zero we will store it in the upper word
|
|
// of b7Absent and store 1 in the lower word
|
|
|
|
pcmi->fl |= CMI_B7_ABSENT;
|
|
pcmi->i_b7 = (pstartCount - pstartCountBegin);
|
|
}
|
|
|
|
// check if 2219 is supported in a font, if not then there is
|
|
// no need to make a handle for b7 equal to the handle for 2219.
|
|
// In other words if 0x2219 is not supported in a font, there will be no
|
|
// need to hack FD_GLYPHSET to make hg(b7) == hg(2219) and possibly add a
|
|
// [b7,b7] range if b7 is not already supported in a font:
|
|
|
|
if ((0x2219 >= usLo) && (0x2219 <= usHi))
|
|
{
|
|
pcmi->fl |= CMI_2219_PRESENT;
|
|
pcmi->i_2219 = (pstartCount - pstartCountBegin);
|
|
}
|
|
}
|
|
|
|
// this is what we will do
|
|
|
|
// b7 supported 2219 supported => hg(b7) = hg(2219)
|
|
// b7 not supported 2219 supported => add [b7,b7] range and hg(b7) = hg(2219)
|
|
// b7 supported 2219 not supported => do nothing
|
|
// b7 not supported 2219 not supported => do nothing
|
|
|
|
bInsert_b7 = (pcmi->fl & (CMI_2219_PRESENT | CMI_B7_ABSENT)) == (CMI_2219_PRESENT | CMI_B7_ABSENT);
|
|
|
|
if (bInsert_b7)
|
|
{
|
|
// will have to insert [b7,b7] run, one more run, one more glyph, i_2219
|
|
// has to be incremented because the run for b7 will be inserted before the
|
|
// run which contains 2219
|
|
|
|
pcmi->cRuns++;
|
|
pcmi->cGlyphs++;
|
|
pcmi->i_2219++;
|
|
}
|
|
|
|
// add a default glyph at the end of the first run if not in collision with
|
|
// the run for b7 that we may have possibly inserted and if the first run is
|
|
// not the last run at the same time;
|
|
|
|
if (*pendCountBegin != 0xffff)
|
|
{
|
|
if (!bInsert_b7 || (*pendCountBegin != 0xb600)) // big endian for b6
|
|
pcmi->cGlyphs++;
|
|
}
|
|
|
|
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC BOOL bVerifyMacTable(sfnt_mappingTable * pmap)
|
|
*
|
|
* just checking consistency of the format
|
|
*
|
|
* History:
|
|
* 23-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC BOOL
|
|
bVerifyMacTable(
|
|
sfnt_mappingTable * pmap
|
|
)
|
|
{
|
|
if (pmap->format != BE_FORMAT_MAC_STANDARD)
|
|
RET_FALSE("TTFD!_bVerifyMacTable, format \n");
|
|
|
|
// sfnt_mappingTable is followed by <= 256 byte glyphIdArray
|
|
|
|
if (BE_UINT16(&pmap->length) > DWORD_ALIGN(SIZEOF_SFNT_MAPPINGTABLE + 256))
|
|
RET_FALSE("TTFD!_bVerifyMacTable, length \n");
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bLoadTTF
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 29-Jan-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
//!!! SHOUD BE RETURNING hff
|
|
|
|
#ifdef FE_SB
|
|
|
|
#define OFF_TTC_Sign 0x0000
|
|
#define OFF_TTC_Version 0x0004
|
|
#define OFF_TTC_DirectoryCount 0x0008
|
|
#define OFF_TTC_DirectoryEntry 0x000C
|
|
|
|
|
|
ULONG GetUlong( PVOID pvView, ULONG ulOffset)
|
|
{
|
|
ULONG ulReturn;
|
|
|
|
ulReturn = ( (ULONG)*((PBYTE) pvView + ulOffset +3) |
|
|
(((ULONG)*((PBYTE) pvView + ulOffset +2)) << 8) |
|
|
(((ULONG)*((PBYTE) pvView + ulOffset +1)) << 16) |
|
|
(((ULONG)*((PBYTE) pvView + ulOffset +0)) << 24)
|
|
);
|
|
return ( ulReturn );
|
|
}
|
|
|
|
|
|
BOOL bVerifyTTC (
|
|
PVOID pvView
|
|
)
|
|
{
|
|
// Check TTC ID.
|
|
|
|
#define TTC_ID 0x66637474
|
|
|
|
if(*((PULONG)((BYTE*) pvView + OFF_TTC_Sign)) != TTC_ID)
|
|
return(FALSE);
|
|
|
|
// Check TTC verson.
|
|
|
|
#define TTC_VERSION 0x00000100
|
|
|
|
if(*((PULONG)((BYTE*) pvView + OFF_TTC_Version)) != TTC_VERSION)
|
|
RETURN("TTFD!ttfdLoadFontFileTTC(): wrong TTC version\n", FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL bLoadFontFile (
|
|
ULONG iFile,
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
ULONG ulLangId,
|
|
HFF *phttc
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
FILEVIEW fvwTTC;
|
|
BOOL bTTCFormat;
|
|
PTTC_FONTFILE pttc;
|
|
ULONG cjttc,i,j;
|
|
|
|
HFF hff;
|
|
|
|
*phttc = (HFF)NULL; // Important for clean up in case of exception
|
|
|
|
// Check this is a TrueType collection format or not.
|
|
|
|
#if DBG_MORE
|
|
if(bTTCFormat = bVerifyTTC(pvView))
|
|
WARNING("TTFD:ttfdLoadFontFileTTC(): This is TTC format font\n");
|
|
#else
|
|
bTTCFormat = bVerifyTTC(pvView);
|
|
#endif // DBG_MORE
|
|
|
|
// How mamy TrueType resources in this file if TTC file.
|
|
|
|
if(bTTCFormat)
|
|
{
|
|
ULONG ulTrueTypeResource;
|
|
ULONG ulEntry;
|
|
BOOL bCanBeLoaded = FALSE;
|
|
|
|
// Get Directory count.
|
|
|
|
ulTrueTypeResource = GetUlong(pvView,OFF_TTC_DirectoryCount);
|
|
|
|
// Allocate TTC_FONTFILE structure
|
|
|
|
cjttc = offsetof(TTC_FONTFILE,ahffEntry);
|
|
cjttc += sizeof(TTC_HFF_ENTRY) * ulTrueTypeResource * 2; // *2 for Vertical face
|
|
|
|
pttc = pttcAlloc(cjttc);
|
|
|
|
if(pttc == (HFF)NULL)
|
|
RETURN("TTFD!ttfdLoadFontFileTTC(): pttcAlloc failed\n", FALSE);
|
|
|
|
// fill hff array in TTC_FONTFILE struture
|
|
|
|
ulEntry = 0;
|
|
|
|
for( i = 0; i < ulTrueTypeResource; i++ )
|
|
{
|
|
ULONG ulOffset;
|
|
|
|
// get the starting offset of a TrueType font resource.
|
|
|
|
ulOffset = GetUlong(pvView,(OFF_TTC_DirectoryEntry + (4 * i)));
|
|
|
|
// load font..
|
|
|
|
if( bLoadTTF(iFile,pvView,cjView,ulOffset,ulLangId,&hff))
|
|
{
|
|
bCanBeLoaded = TRUE;
|
|
|
|
// set pointer to TTC_FONTFILE in FONTFILE structure
|
|
|
|
PFF(hff)->pttc = pttc;
|
|
|
|
ASSERTDD(
|
|
PFF(hff)->ulNumFaces <= 2,
|
|
"TTFD!ulNumFaces > 2\n"
|
|
);
|
|
|
|
for( j = 0; j < PFF(hff)->ulNumFaces; j++ )
|
|
{
|
|
pttc->ahffEntry[ulEntry + j].hff = hff;
|
|
pttc->ahffEntry[ulEntry + j].iFace = j+1; // start from 1.
|
|
pttc->ahffEntry[ulEntry + j].ulOffsetTable = ulOffset;
|
|
}
|
|
|
|
ulEntry += PFF(hff)->ulNumFaces;
|
|
}
|
|
}
|
|
|
|
// Is there a font that could be loaded ?
|
|
|
|
if(bCanBeLoaded)
|
|
{
|
|
ASSERTDD(
|
|
(ulTrueTypeResource * 2) >= ulEntry,
|
|
"TTFD!ulTrueTypeResource * 2 < ulEntry\n"
|
|
);
|
|
|
|
pttc->ulTrueTypeResource = ulTrueTypeResource;
|
|
pttc->ulNumEntry = ulEntry;
|
|
pttc->cRef = 0;
|
|
pttc->fl = 0;
|
|
|
|
// everything is o.k.
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("TTFD!No TrueType resource in this TTC file\n");
|
|
vFreeTTC(pttc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Load font file.
|
|
|
|
if(bLoadTTF(iFile,pvView,cjView,0,ulLangId,&hff))
|
|
{
|
|
|
|
// Allocate TTC_FONTFILE structure
|
|
|
|
cjttc = offsetof(TTC_FONTFILE,ahffEntry);
|
|
cjttc += sizeof(TTC_HFF_ENTRY) * (PFF(hff)->ulNumFaces);
|
|
|
|
pttc = pttcAlloc(cjttc);
|
|
|
|
if(pttc != (HFF)NULL)
|
|
{
|
|
// set pointer to TTC_FONTFILE in FONTFILE structure
|
|
|
|
PFF(hff)->pttc = pttc;
|
|
|
|
// fill hff array in TTC_FONTFILE struture
|
|
|
|
pttc->ulTrueTypeResource = 1;
|
|
pttc->ulNumEntry = PFF(hff)->ulNumFaces;
|
|
pttc->cRef = 0;
|
|
pttc->fl = 0;
|
|
|
|
// fill up TTC_FONTFILE structure for each faces.
|
|
|
|
for( i = 0; i < PFF(hff)->ulNumFaces; i++ )
|
|
{
|
|
pttc->ahffEntry[i].hff = hff;
|
|
pttc->ahffEntry[i].iFace = i+1;
|
|
pttc->ahffEntry[i].ulOffsetTable = 0;
|
|
}
|
|
|
|
// now, everything is o.k.
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("TTFD!ttfdLoadFontFileTTC(): pttcAlloc failed\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bRet) *phttc = (HFF)pttc;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
#endif
|
|
|
|
STATIC BOOL
|
|
bLoadTTF (
|
|
ULONG iFile,
|
|
PVOID pvView,
|
|
ULONG cjView,
|
|
ULONG ulTableOffset,
|
|
ULONG ulLangId,
|
|
HFF *phff
|
|
)
|
|
{
|
|
PFONTFILE pff;
|
|
FS_ENTRY iRet;
|
|
TABLE_POINTERS tp;
|
|
IFISIZE ifisz;
|
|
|
|
fs_GlyphInputType gin;
|
|
fs_GlyphInfoType gout;
|
|
|
|
sfnt_FontHeader * phead;
|
|
sfnt_HorizontalHeader *phhea;
|
|
|
|
uint16 ui16PlatID, ui16SpecID;
|
|
sfnt_mappingTable *pmap;
|
|
ULONG ulGsetType;
|
|
ULONG cjff, dpwszTTF;
|
|
ULONG ul_wcBias;
|
|
// BEGIN Perpetua-Hack
|
|
FLONG flPerpetuaHack;
|
|
// END Perpetua-Hack
|
|
|
|
// the size of this structure is sizeof(fs_SplineKey) + STAMPEXTRA.
|
|
// It is because of STAMPEXTRA that we are not just putting the strucuture
|
|
// on the stack such as fs_SplineKey sk; we do not want to overwrite the
|
|
// stack at the bottom when putting a stamp in the STAMPEXTRA field.
|
|
// [bodind]. The other way to obtain the correct alignment would be to use
|
|
// union of fs_SplineKey and the array of bytes of length CJ_0.
|
|
|
|
NATURAL anat0[CJ_0 / sizeof(NATURAL)];
|
|
|
|
CMAPINFO cmi;
|
|
BOOL bType1 = FALSE; // if Type1 conversion
|
|
PBYTE pjOffsetTable = (BYTE*) pvView + ulTableOffset;
|
|
|
|
*phff = HFF_INVALID;
|
|
|
|
if
|
|
(
|
|
!bVerifyTTF(
|
|
iFile,
|
|
pvView,
|
|
cjView,
|
|
pjOffsetTable,
|
|
ulLangId,
|
|
&tp,
|
|
&ifisz,
|
|
&ui16PlatID,
|
|
&ui16SpecID,
|
|
&pmap,
|
|
&ulGsetType,
|
|
&ul_wcBias,
|
|
&cmi,
|
|
&bType1,
|
|
&flPerpetuaHack
|
|
)
|
|
)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
// BEGIN Perpetua-Hack
|
|
if (flPerpetuaHack & FF_PERPETUA_BOLD)
|
|
{
|
|
TTFD_PRINT(2,("Rejecting Perpetua Bold\n"));
|
|
return(FALSE);
|
|
}
|
|
// END Perpetua-Hack
|
|
|
|
cjff = offsetof(FONTFILE,ifi) + ifisz.cjIFI;
|
|
if (ulGsetType == GSET_TYPE_GENERAL) // allocate at the bottom
|
|
{
|
|
cjff += cjGsetGeneral(pmap,&cmi);
|
|
}
|
|
|
|
// at this point cjff is equal to the offset to the full path
|
|
// name of the ttf file
|
|
|
|
dpwszTTF = cjff;
|
|
|
|
|
|
if ((pff = pffAlloc(cjff)) == PFF(NULL))
|
|
{
|
|
RET_FALSE("TTFD!ttfdLoadFontFile(): memory allocation error\n");
|
|
}
|
|
*phff = (HFF)pff;
|
|
|
|
// init fields of pff structure
|
|
// store the ttf file name at the bottom of the strucutre
|
|
|
|
phead = (sfnt_FontHeader *)((BYTE *)pvView + tp.ateReq[IT_REQ_HEAD].dp);
|
|
|
|
// remember which file this is
|
|
|
|
pff->iFile = iFile;
|
|
pff->pvView = pvView;
|
|
pff->cjView = cjView;
|
|
pff->ui16EmHt = BE_UINT16(&phead->unitsPerEm);
|
|
pff->ui16PlatformID = ui16PlatID;
|
|
pff->ui16SpecificID = ui16SpecID;
|
|
|
|
// few new fields for user's private api:
|
|
|
|
phhea = (sfnt_HorizontalHeader *)((BYTE *)pvView + tp.ateReq[IT_REQ_HHEAD].dp);
|
|
|
|
pff->usMinD = 0; // flag that it has not been initialized
|
|
pff->igMinD = USHRT_MAX; // flag that it has not been initialized
|
|
pff->sMinA = BE_INT16(&phhea->minLeftSideBearing);
|
|
pff->sMinC = BE_INT16(&phhea->minRightSideBearing);
|
|
|
|
// so far no exception
|
|
|
|
pff->fl = bType1 ? FF_TYPE_1_CONVERSION : 0;
|
|
// BEGIN Perpetua-Hack
|
|
pff->fl |= flPerpetuaHack;
|
|
// END Perpetua-Hack
|
|
pff->pfcToBeFreed = NULL;
|
|
|
|
// convert Language id to macintosh style if this is mac style file
|
|
// else leave it alone, store it in be format, ready to be compared
|
|
// with the values in the font files
|
|
|
|
pff->ui16LanguageID = ui16BeLangId(ui16PlatID,ulLangId);
|
|
pff->dpMappingTable = (ULONG)((BYTE*)pmap - (BYTE*)pvView);
|
|
|
|
pff->pComputeIndexProc = NULL;
|
|
|
|
switch(pmap->format)
|
|
{
|
|
case 0x0400:
|
|
pff->pComputeIndexProc = sfac_ComputeIndex4;
|
|
break;
|
|
case 0x0200:
|
|
pff->pComputeIndexProc = sfac_ComputeIndex2;
|
|
break;
|
|
case 0x0000:
|
|
pff->pComputeIndexProc = sfac_ComputeIndex0;
|
|
break;
|
|
default:
|
|
RIP("ttfd: do not handle this cmap format\n");
|
|
break;
|
|
}
|
|
|
|
// initialize count of HFC's associated with this HFF
|
|
|
|
pff->cRef = 0L;
|
|
|
|
// cache pointers to ttf tables and ifi metrics size info
|
|
|
|
pff->tp = tp;
|
|
|
|
// The kerning pair array is allocated and filled lazily. So set to NULL
|
|
// for now.
|
|
|
|
pff->pkp = (FD_KERNINGPAIR *) NULL;
|
|
|
|
// used for TTC fonts
|
|
|
|
pff->ulTableOffset = ulTableOffset;
|
|
|
|
// Notice that this information is totaly independent
|
|
// of the font file in question, seems to be right according to fsglue.h
|
|
// and compfont code
|
|
|
|
if ((iRet = fs_OpenFonts(&gin, &gout)) != NO_ERR)
|
|
{
|
|
V_FSERROR(iRet);
|
|
vFreeFF(*phff);
|
|
*phff = (HFF)NULL;
|
|
return (FALSE);
|
|
}
|
|
|
|
ASSERTDD(NATURAL_ALIGN(gout.memorySizes[0]) == CJ_0, "mem size 0\n");
|
|
ASSERTDD(gout.memorySizes[1] == 0, "mem size 1\n");
|
|
|
|
|
|
#if DBG
|
|
if (gout.memorySizes[2] != 0)
|
|
TtfdDbgPrint("TTFD!_mem size 2 = 0x%lx \n", gout.memorySizes[2]);
|
|
#endif
|
|
|
|
gin.memoryBases[0] = (char *)anat0;
|
|
gin.memoryBases[1] = NULL;
|
|
gin.memoryBases[2] = NULL;
|
|
|
|
// initialize the font scaler, notice no fields of gin are initialized [BodinD]
|
|
|
|
if ((iRet = fs_Initialize(&gin, &gout)) != NO_ERR)
|
|
{
|
|
// clean up and return:
|
|
|
|
V_FSERROR(iRet);
|
|
vFreeFF(*phff);
|
|
*phff = (HFF)NULL;
|
|
RET_FALSE("TTFD!_ttfdLoadFontFile(): fs_Initialize \n");
|
|
}
|
|
|
|
// initialize info needed by NewSfnt function
|
|
|
|
gin.sfntDirectory = (int32 *)pff->pvView; // pointer to the top of the view of
|
|
// the ttf file
|
|
|
|
#ifdef FE_SB
|
|
gin.clientID = (int32)pff; // pointer to the top of the view of the ttf file
|
|
#else
|
|
gin.clientID = (int32)pff->pvView;
|
|
#endif
|
|
|
|
gin.GetSfntFragmentPtr = pvGetPointerCallback;
|
|
gin.ReleaseSfntFrag = vReleasePointerCallback;
|
|
|
|
gin.param.newsfnt.platformID = BE_UINT16(&pff->ui16PlatformID);
|
|
gin.param.newsfnt.specificID = BE_UINT16(&pff->ui16SpecificID);
|
|
|
|
if ((iRet = fs_NewSfnt(&gin, &gout)) != NO_ERR)
|
|
{
|
|
// clean up and exit
|
|
|
|
V_FSERROR(iRet);
|
|
vFreeFF(*phff);
|
|
*phff = (HFF)NULL;
|
|
RET_FALSE("TTFD!_ttfdLoadFontFile(): fs_NewSfnt \n");
|
|
}
|
|
|
|
pff->pj034 = (PBYTE)NULL;
|
|
pff->pfcLast = (FONTCONTEXT *)NULL;
|
|
|
|
pff->cj3 = NATURAL_ALIGN(gout.memorySizes[3]);
|
|
pff->cj4 = NATURAL_ALIGN(gout.memorySizes[4]);
|
|
|
|
// By default the number of faces is 1L. The vert facename code may change this.
|
|
|
|
pff->ulNumFaces = 1L;
|
|
|
|
|
|
// compute the gset or set a pointer to one of the precomputed gsets
|
|
|
|
pff->iGlyphSet = ulGsetType;
|
|
|
|
switch (pff->iGlyphSet)
|
|
{
|
|
case GSET_TYPE_GENERAL:
|
|
#ifdef DBG_GLYPHSET
|
|
WARNING("GSET_TYPE_GENERAL\n");
|
|
#endif
|
|
|
|
pff->pgset = (FD_GLYPHSET *)((PBYTE)pff + offsetof(FONTFILE,ifi) + ifisz.cjIFI);
|
|
if (!cjComputeGLYPHSET_MSFT_UNICODE(
|
|
pmap,
|
|
&gin,
|
|
&gout,
|
|
pff->pgset,
|
|
&cmi
|
|
)
|
|
)
|
|
{
|
|
// clean up and exit
|
|
|
|
vFreeFF(*phff);
|
|
*phff = (HFF)NULL;
|
|
RET_FALSE("ttfdLoadFontFile(): cjComputeGLYPHSET_MSFT_UNICODE failed\n");
|
|
}
|
|
break;
|
|
|
|
case GSET_TYPE_GENERAL_NOT_UNICODE:
|
|
#ifdef DBG_GLYPHSET
|
|
WARNING("GSET_TYPE_GENERAL_NOT_UNICODE\n");
|
|
#endif
|
|
|
|
// Create GlyphSet
|
|
|
|
cjComputeGLYPHSET_MSFT_GENERAL(
|
|
pmap,
|
|
(ULONG **)&(pff->pgset), // == (FD_GLYPHSET **)
|
|
&cmi
|
|
);
|
|
|
|
pff->pWCharToIndex = cmi.pWCharToIndex;
|
|
break;
|
|
|
|
case GSET_TYPE_HIGH_BYTE:
|
|
#ifdef DBG_GLYPHSET
|
|
WARNING("GSET_TYPE_HIGH_BYTE\n");
|
|
#endif
|
|
|
|
// Create GlyphSet
|
|
|
|
cjComputeGLYPHSET_HIGH_BYTE(
|
|
pmap,
|
|
(ULONG **)&(pff->pgset), // == (FD_GLYPHSET **)
|
|
&cmi
|
|
);
|
|
pff->pWCharToIndex = cmi.pWCharToIndex;
|
|
break;
|
|
|
|
|
|
case GSET_TYPE_MAC_ROMAN:
|
|
#ifdef DBG_GLYPHSET
|
|
WARNING("GSET_TYPE_MAC_ROMAN\n");
|
|
#endif
|
|
|
|
pff->pgset = &gumcr.gset;
|
|
break;
|
|
|
|
case GSET_TYPE_PSEUDO_WIN:
|
|
|
|
// we are cheating, report windows code page even though it is
|
|
// a mac font
|
|
|
|
pff->pgset = gpgsetCurrentCP;
|
|
break;
|
|
|
|
case GSET_TYPE_SYMBOL:
|
|
|
|
// we are cheating, report windows code page even though it is
|
|
// a symbol font where symbols live somewhere high in unicode
|
|
|
|
pff->pgset = gpgsetSymbolCP;
|
|
pff->wcBiasFirst = ul_wcBias;
|
|
|
|
break;
|
|
|
|
default:
|
|
RIP("TTFD!_ulGsetType\n");
|
|
pff->pgset = (PFD_GLYPHSET)NULL;
|
|
break;
|
|
}
|
|
|
|
// if we failed to create the glyphset bail out now
|
|
|
|
if(pff->pgset == NULL)
|
|
{
|
|
// clean up and exit
|
|
|
|
vFreeFF(*phff);
|
|
*phff = (HFF)NULL;
|
|
RET_FALSE("ttfdLoadFontFile(): failed to create glyphset or invalid glyphset\n");
|
|
}
|
|
|
|
// finally compute the ifimetrics for this font, this assumes that gset has
|
|
// also been computed
|
|
|
|
vFill_IFIMETRICS(pff,&pff->ifi,&ifisz);
|
|
|
|
// if this is a far east vertical font we may create a vertical face
|
|
|
|
#ifdef FE_SB
|
|
if ( (IS_ANY_DBCS_CHARSET( pff->ifi.jWinCharSet ) ) &&
|
|
(pff->ifi.panose.bProportion == PAN_PROP_MONOSPACED) &&
|
|
(bCheckVerticalTable( pff ) ) )
|
|
{
|
|
PIFIMETRICS pifiv;
|
|
|
|
ASSERTDD( pff->hgSearchVerticalGlyph != NULL ,
|
|
"pff->hgSearchVerticalGlyph == NULL for vertical font\n");
|
|
|
|
pifiv = (PIFIMETRICS)PV_ALLOC( ifisz.cjIFI );
|
|
|
|
if ( pifiv != NULL )
|
|
{
|
|
PWCHAR pwchSrc, pwchDst;
|
|
|
|
// RtlMoveMemory(...);
|
|
vFill_IFIMETRICS(pff, pifiv, &ifisz);
|
|
|
|
//
|
|
// modify facename so that it has '@' at the beginning of facename.
|
|
//
|
|
pwchSrc = (PWCHAR)((PBYTE)pifiv + pifiv->dpwszFaceName);
|
|
pwchDst = (PWCHAR)((PBYTE)&(pff->ifi) + pff->ifi.dpwszFaceName);
|
|
|
|
*pwchSrc++ = L'@';
|
|
while ( *pwchDst )
|
|
{
|
|
*pwchSrc++ = *pwchDst++;
|
|
}
|
|
*pwchSrc = L'\0';
|
|
|
|
//
|
|
// modify familyname so that it has '@' at the beginning of familyname
|
|
//
|
|
pwchSrc = (PWCHAR)((PBYTE)pifiv + pifiv->dpwszFamilyName);
|
|
pwchDst = (PWCHAR)((PBYTE)&(pff->ifi) + pff->ifi.dpwszFamilyName);
|
|
|
|
*pwchSrc++ = L'@';
|
|
while ( *pwchDst )
|
|
{
|
|
*pwchSrc++ = *pwchDst++;
|
|
}
|
|
*pwchSrc = L'\0';
|
|
|
|
//
|
|
// save a pointer to the vertical ifimetrics.
|
|
// now we have two faces( normal, @face ) for the fontfile.
|
|
//
|
|
pff->pifi_vertical = pifiv;
|
|
pff->ulNumFaces = 2L;
|
|
}
|
|
else
|
|
{
|
|
WARNING("TTFD!bLoadTTF: insufficient mermory - give up to add @face\n");
|
|
}
|
|
}
|
|
#endif
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* STATIC BOOL bCvtUnToMac
|
|
*
|
|
* the following piece of code is stolen from JeanP and
|
|
* he claims that this piece of code is lousy and checks whether
|
|
* we the font is a SYMBOL font in which case unicode to mac conversion
|
|
* should be disabled, according to JeanP (??? who understands this???)
|
|
* This piece of code actually applies to symbol.ttf [bodind]
|
|
*
|
|
*
|
|
* History:
|
|
* 24-Mar-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
STATIC BOOL
|
|
bCvtUnToMac(
|
|
BYTE *pjView,
|
|
TABLE_POINTERS *ptp,
|
|
uint16 ui16PlatformID
|
|
)
|
|
{
|
|
// Find out if we have a Mac font and if the Mac charset translation is needed
|
|
|
|
BOOL bUnToMac = (ui16PlatformID == BE_PLAT_ID_MAC);
|
|
|
|
if (bUnToMac) // change your mind if needed
|
|
{
|
|
sfnt_PostScriptInfo *ppost;
|
|
|
|
ppost = (ptp->ateOpt[IT_OPT_POST].dp) ?
|
|
(sfnt_PostScriptInfo *)(pjView + ptp->ateOpt[IT_OPT_POST].dp):
|
|
NULL;
|
|
|
|
if
|
|
(
|
|
ppost &&
|
|
(BE_UINT32((BYTE*)ppost + POSTSCRIPTNAMEINDICES_VERSION) == 0x00020000)
|
|
)
|
|
{
|
|
INT i, cGlyphs;
|
|
|
|
cGlyphs = (INT)BE_UINT16(&ppost->numberGlyphs);
|
|
|
|
for (i = 0; i < cGlyphs; i++)
|
|
{
|
|
uint16 iNameIndex = ppost->postScriptNameIndices.glyphNameIndex[i];
|
|
if ((int8)(iNameIndex & 0xff) && ((int8)(iNameIndex >> 8) > 1))
|
|
break;
|
|
}
|
|
|
|
if (i < cGlyphs)
|
|
bUnToMac = FALSE;
|
|
}
|
|
}
|
|
return bUnToMac;
|
|
}
|
|
|
|
|
|
// Weight (must convert from IFIMETRICS weight to Windows LOGFONT.lfWeight).
|
|
|
|
// !!! [Windows 3.1 compatibility]
|
|
// Because of some fonts shipped with WinWord, if usWeightClass is 10
|
|
// or above, then usWeightClass == lfWeight. All other cases, use
|
|
// the conversion table.
|
|
|
|
// pan wt -> Win weight converter:
|
|
|
|
STATIC USHORT ausIFIMetrics2WinWeight[10] = {
|
|
0, 100, 200, 300, 350, 400, 600, 700, 800, 900
|
|
};
|
|
|
|
STATIC BYTE
|
|
ajPanoseFamily[16] = {
|
|
FF_DONTCARE // 0 (Any)
|
|
,FF_DONTCARE // 1 (No Fit)
|
|
,FF_ROMAN // 2 (Cove)
|
|
,FF_ROMAN // 3 (Obtuse Cove)
|
|
,FF_ROMAN // 4 (Square Cove)
|
|
,FF_ROMAN // 5 (Obtuse Square Cove)
|
|
,FF_ROMAN // 6 (Square)
|
|
,FF_ROMAN // 7 (Thin)
|
|
,FF_ROMAN // 8 (Bone)
|
|
,FF_ROMAN // 9 (Exaggerated)
|
|
,FF_ROMAN // 10 (Triangle)
|
|
,FF_SWISS // 11 (Normal Sans)
|
|
,FF_SWISS // 12 (Obtuse Sans)
|
|
,FF_SWISS // 13 (Perp Sans)
|
|
,FF_SWISS // 14 (Flared)
|
|
,FF_SWISS // 15 (Rounded)
|
|
};
|
|
|
|
|
|
static BYTE
|
|
ajPanoseFamilyForJapanese[16] = {
|
|
FF_DONTCARE // 0 (Any)
|
|
,FF_DONTCARE // 1 (No Fit)
|
|
,FF_ROMAN // 2 (Cove)
|
|
,FF_ROMAN // 3 (Obtuse Cove)
|
|
,FF_ROMAN // 4 (Square Cove)
|
|
,FF_ROMAN // 5 (Obtuse Square Cove)
|
|
,FF_ROMAN // 6 (Square)
|
|
,FF_ROMAN // 7 (Thin)
|
|
,FF_ROMAN // 8 (Bone)
|
|
,FF_ROMAN // 9 (Exaggerated)
|
|
,FF_ROMAN // 10 (Triangle)
|
|
,FF_MODERN // 11 (Normal Sans)
|
|
,FF_MODERN // 12 (Obtuse Sans)
|
|
,FF_MODERN // 13 (Perp Sans)
|
|
,FF_MODERN // 14 (Flared)
|
|
,FF_MODERN // 15 (Rounded)
|
|
};
|
|
|
|
|
|
// Unfortunately, NT-J 3.51 and Windows 95-J ship with buggy versions of
|
|
// msmincho.ttc msgothic.ttc. These fonts have the FS_CHINESESIMP bit set
|
|
// instead of FS_JAPANESE. As a result the code which computes the charset
|
|
// based on font signatures will be incorrect for these fonts. To remedy
|
|
// this we will check the face name of the font to see if is ms gothic or
|
|
// of ms mincho and if so will ignore the font signature when computing charset.
|
|
// Since want these fonts to work on both English and Japanese versions of NT
|
|
// we will check for both the Japanese and English versions of the names.
|
|
// [gerritv] 2-1-96
|
|
|
|
WCHAR *MinchoOrGothicFaces[] =
|
|
{
|
|
L"MS MINCHO",
|
|
L"MS PMINCHO",
|
|
L"MS GOTHIC",
|
|
L"MS PGOTHIC",
|
|
L"\xff2d\xff33\x20\xff30\x30b4\x30b7\x30c3\x30af", // MS PGOTHIC
|
|
L"\xff2d\xff33\x20\xff30\x660e\x671d", // MS PMINCHO
|
|
L"\xff2d\xff33\x20\x30b4\x30b7\x30c3\x30af", // MS GOTHIC
|
|
L"\xff2d\xff33\x20\x660e\x671d" // MS MINCHO
|
|
};
|
|
|
|
|
|
BOOL IsMsMinchoOrMsGothic(PWCHAR pwc)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < sizeof(MinchoOrGothicFaces) / sizeof(WCHAR*); i++)
|
|
{
|
|
if(!_wcsicmp(pwc,MinchoOrGothicFaces[i]))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* vFill_IFIMETRICS
|
|
*
|
|
* Effects: Looks into the font file and fills IFIMETRICS
|
|
*
|
|
* History:
|
|
* Mon 09-Mar-1992 10:51:56 by Kirk Olynyk [kirko]
|
|
* Added Kerning Pair support.
|
|
* 18-Nov-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
STATIC VOID
|
|
vFill_IFIMETRICS(
|
|
PFONTFILE pff,
|
|
PIFIMETRICS pifi,
|
|
PIFISIZE pifisz
|
|
)
|
|
{
|
|
BYTE *pjView = (BYTE*)pff->pvView;
|
|
PTABLE_POINTERS ptp = &pff->tp;
|
|
BYTE jWinCharset;
|
|
IFIEXTRA *pifiex;
|
|
|
|
// ptrs to various tables of tt files
|
|
|
|
PBYTE pjNameTable = pjView + ptp->ateReq[IT_REQ_NAME].dp;
|
|
sfnt_FontHeader *phead =
|
|
(sfnt_FontHeader *)(pjView + ptp->ateReq[IT_REQ_HEAD].dp);
|
|
|
|
sfnt_maxProfileTable * pmaxp =
|
|
(sfnt_maxProfileTable *)(pjView + ptp->ateReq[IT_REQ_MAXP].dp);
|
|
|
|
sfnt_HorizontalHeader *phhea =
|
|
(sfnt_HorizontalHeader *)(pjView + ptp->ateReq[IT_REQ_HHEAD].dp);
|
|
|
|
sfnt_PostScriptInfo *ppost = (sfnt_PostScriptInfo *) (
|
|
(ptp->ateOpt[IT_OPT_POST].dp) ?
|
|
pjView + ptp->ateOpt[IT_OPT_POST].dp :
|
|
NULL
|
|
);
|
|
|
|
PBYTE pjOS2 = (ptp->ateOpt[IT_OPT_OS2].dp) ?
|
|
pjView + ptp->ateOpt[IT_OPT_OS2].dp :
|
|
NULL ;
|
|
|
|
pifi->cjThis = pifisz->cjIFI;
|
|
pifi->cjIfiExtra = offsetof(IFIEXTRA, aulReserved[0]);
|
|
|
|
// lay pifiextra below ifimetrics
|
|
|
|
pifiex = (IFIEXTRA *)(pifi + 1);
|
|
pifiex->ulIdentifier = 0;
|
|
|
|
// enter the number of distinct font indicies
|
|
// the question here is what we do with symbol fonts where we lie
|
|
// about how many glyphs there really are in the font:
|
|
|
|
|
|
// this code parallels vCharacterCode:
|
|
// That is if hglyph == glyphindex we will report this number to the engine
|
|
// else we will set it to zero to indicate that it should not be used.
|
|
|
|
if (pff->iGlyphSet == GSET_TYPE_GENERAL ||
|
|
pff->iGlyphSet == GSET_TYPE_GENERAL_NOT_UNICODE ||
|
|
pff->iGlyphSet == GSET_TYPE_HIGH_BYTE)
|
|
{
|
|
pifiex->cig = BE_UINT16(&pmaxp->numGlyphs);
|
|
}
|
|
else
|
|
{
|
|
pifiex->cig = 0;
|
|
}
|
|
|
|
// get name strings info
|
|
|
|
//
|
|
// For the 3.1 compatibility, GRE returns FamilyName rather than
|
|
// Facename for GetTextFace. We make a room for '@' in both
|
|
// familyname and facename.
|
|
//
|
|
|
|
pifi->dpwszFamilyName = sizeof(IFIMETRICS) + offsetof(IFIEXTRA, aulReserved[0]);
|
|
pifi->dpwszUniqueName = pifi->dpwszFamilyName + pifisz->cjFamilyName + sizeof(WCHAR);
|
|
pifi->dpwszFaceName = pifi->dpwszUniqueName + pifisz->cjUniqueName;
|
|
pifi->dpwszStyleName = pifi->dpwszFaceName + pifisz->cjFullName + sizeof(WCHAR);
|
|
|
|
// copy the strings to their new location. Here we assume that the
|
|
// sufficient memory has been allocated
|
|
|
|
if (pff->ui16PlatformID == BE_PLAT_ID_MS)
|
|
{
|
|
|
|
if (pff->ui16SpecificID == BE_SPEC_ID_BIG5 ||
|
|
pff->ui16SpecificID == BE_SPEC_ID_WANSUNG ||
|
|
pff->ui16SpecificID == BE_SPEC_ID_GB)
|
|
{
|
|
CHAR chConvertArea[128];
|
|
UINT iCodePage = GetCodePageFromSpecId(pff->ui16SpecificID);
|
|
|
|
//
|
|
// Convert MBCS string to Unicode..
|
|
//
|
|
// Do for FamilyName....
|
|
//
|
|
RtlZeroMemory(chConvertArea,sizeof(chConvertArea));
|
|
|
|
CopyDBCSIFIName(chConvertArea,
|
|
sizeof(chConvertArea),
|
|
(LPCSTR)pifisz->pjFamilyName,
|
|
pifisz->cjFamilyName-sizeof(WCHAR)); // -sizeof(WCHAR) for
|
|
// real length
|
|
|
|
if(EngMultiByteToWideChar(iCodePage,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFamilyName),
|
|
pifisz->cjFamilyName,
|
|
chConvertArea,
|
|
strlen(chConvertArea)+1) == -1)
|
|
{
|
|
|
|
WARNING("TTFD!vFill_IFIMETRICS() MBCS to Unicode conversion failed\n");
|
|
goto CopyUnicodeString;
|
|
}
|
|
|
|
//
|
|
// Do for FullName....
|
|
//
|
|
|
|
RtlZeroMemory(chConvertArea,sizeof(chConvertArea));
|
|
CopyDBCSIFIName(chConvertArea,
|
|
sizeof(chConvertArea),
|
|
(LPCSTR)pifisz->pjFullName,
|
|
pifisz->cjFullName-sizeof(WCHAR)); // -sizeof(WCHAR) for
|
|
// real length
|
|
|
|
if(EngMultiByteToWideChar(iCodePage,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFaceName),
|
|
pifisz->cjFullName,
|
|
chConvertArea,
|
|
strlen(chConvertArea)+1) == -1)
|
|
{
|
|
WARNING("TTFD!vFill_IFIMETRICS() MBCS to Unicode conversion failed\n");
|
|
goto CopyUnicodeString;
|
|
}
|
|
|
|
//
|
|
// Do for UniqueName....
|
|
//
|
|
|
|
RtlZeroMemory(chConvertArea,sizeof(chConvertArea));
|
|
CopyDBCSIFIName(chConvertArea,sizeof(chConvertArea),
|
|
(LPCSTR)pifisz->pjUniqueName,
|
|
pifisz->cjUniqueName-sizeof(WCHAR)); // -sizeof(WCHAR) for
|
|
// real length
|
|
|
|
if(EngMultiByteToWideChar(iCodePage,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszUniqueName),
|
|
pifisz->cjUniqueName,
|
|
chConvertArea,
|
|
strlen(chConvertArea)+1) == -1)
|
|
{
|
|
WARNING("TTFD!vFill_IFIMETRICS() MBCS to Unicode conversion failed\n");
|
|
goto CopyUnicodeString;
|
|
}
|
|
|
|
if(pff->ui16SpecificID == BE_SPEC_ID_WANSUNG ||
|
|
pff->ui16SpecificID == BE_SPEC_ID_BIG5 )
|
|
{
|
|
// MingLi.TTF's bug, Style use Unicode encoding, not BIG5 encodingi, GB??
|
|
|
|
vCpyBeToLeUnicodeString
|
|
(
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszStyleName),
|
|
(LPWSTR)pifisz->pjSubfamilyName,
|
|
pifisz->cjSubfamilyName / 2
|
|
);
|
|
}
|
|
else
|
|
{
|
|
UINT iRet;
|
|
|
|
iRet = EngMultiByteToWideChar(iCodePage,
|
|
(LPWSTR)((PBYTE)pifi+pifi->dpwszStyleName),
|
|
pifisz->cjSubfamilyName,
|
|
(LPSTR)pifisz->pjSubfamilyName,
|
|
pifisz->cjSubfamilyName);
|
|
|
|
if( iRet == -1 )
|
|
{
|
|
WARNING("TTFD!vFill_IFIMETRICS() MBCS to Unicode failed\n");
|
|
goto CopyUnicodeString;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CopyUnicodeString:
|
|
|
|
vCpyBeToLeUnicodeString
|
|
(
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFamilyName),
|
|
(LPWSTR)pifisz->pjFamilyName,
|
|
pifisz->cjFamilyName / 2);
|
|
|
|
vCpyBeToLeUnicodeString
|
|
(
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFaceName),
|
|
(LPWSTR)pifisz->pjFullName,
|
|
pifisz->cjFullName / 2
|
|
);
|
|
|
|
vCpyBeToLeUnicodeString
|
|
(
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszUniqueName),
|
|
(LPWSTR)pifisz->pjUniqueName,
|
|
pifisz->cjUniqueName / 2
|
|
);
|
|
|
|
vCpyBeToLeUnicodeString
|
|
(
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszStyleName),
|
|
(LPWSTR)pifisz->pjSubfamilyName,
|
|
pifisz->cjSubfamilyName / 2
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTDD(pff->ui16PlatformID == BE_PLAT_ID_MAC,
|
|
"bFillIFIMETRICS: not mac id \n");
|
|
|
|
vCpyMacToLeUnicodeString
|
|
(
|
|
pff->ui16LanguageID,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFamilyName),
|
|
pifisz->pjFamilyName,
|
|
pifisz->cjFamilyName / 2
|
|
);
|
|
|
|
vCpyMacToLeUnicodeString
|
|
(
|
|
pff->ui16LanguageID,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszFaceName),
|
|
pifisz->pjFullName,
|
|
pifisz->cjFullName / 2
|
|
);
|
|
|
|
vCpyMacToLeUnicodeString
|
|
(
|
|
pff->ui16LanguageID,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszUniqueName),
|
|
pifisz->pjUniqueName,
|
|
pifisz->cjUniqueName / 2
|
|
);
|
|
|
|
vCpyMacToLeUnicodeString
|
|
(
|
|
pff->ui16LanguageID,
|
|
(LPWSTR)((PBYTE)pifi + pifi->dpwszStyleName),
|
|
pifisz->pjSubfamilyName,
|
|
pifisz->cjSubfamilyName / 2
|
|
);
|
|
}
|
|
|
|
//
|
|
// flInfo
|
|
//
|
|
pifi->flInfo = (
|
|
FM_INFO_TECH_TRUETYPE |
|
|
FM_INFO_ARB_XFORMS |
|
|
FM_INFO_RETURNS_OUTLINES |
|
|
FM_INFO_RETURNS_BITMAPS |
|
|
FM_INFO_1BPP | // monochrome
|
|
FM_INFO_4BPP | // anti-aliased too
|
|
FM_INFO_RIGHT_HANDED
|
|
);
|
|
|
|
if (ppost && BE_UINT32((BYTE*)ppost + POSTSCRIPTNAMEINDICES_ISFIXEDPITCH))
|
|
{
|
|
ULONG cHMTX;
|
|
int16 aw,xMin,xMax;
|
|
sfnt_HorizontalMetrics *phmtx;
|
|
|
|
pifi->flInfo |= FM_INFO_OPTICALLY_FIXED_PITCH;
|
|
|
|
// CHECK IF THE FONT HAS NONNEGATIVE A AND C SPACES
|
|
|
|
xMin = (int16) BE_UINT16(&phead->xMin);
|
|
xMax = (int16) BE_UINT16(&phead->xMax);
|
|
|
|
phmtx = (sfnt_HorizontalMetrics *)(pjView + ptp->ateReq[IT_REQ_HMTX ].dp);
|
|
cHMTX = (ULONG) BE_UINT16(&phhea->numberOf_LongHorMetrics);
|
|
aw = (int16)BE_UINT16(&phmtx[cHMTX-1].advanceWidth);
|
|
|
|
if ((xMin >= 0) && (xMax <= aw))
|
|
{
|
|
|
|
// TtfdDbgPrint("%ws\n:",(PBYTE)pifi + pifi->dpwszUniqueName);
|
|
// TtfdDbgPrint("xMin = %d, xMax = %d, aw = %d\n", xMin, xMax, aw);
|
|
|
|
pifi->flInfo |= FM_INFO_NONNEGATIVE_AC;
|
|
}
|
|
}
|
|
|
|
pifi->dpCharSets = 0; // for now
|
|
|
|
pifi->lEmbedId = 0; // not used, stored in pff.
|
|
|
|
// fsSelection
|
|
|
|
pifi->fsSelection = fsSelectionTTFD(pjView, ptp);
|
|
|
|
// some of the old windows fonts contain the char set in the upper byte of
|
|
// the fsSelection field of the os2 table.
|
|
|
|
jWinCharset = (BYTE)(pifi->fsSelection >> 8);
|
|
|
|
// fsType
|
|
|
|
pifi->fsType = (pjOS2) ? (BE_UINT16(pjOS2 + OFF_OS2_fsType)) & TT_FSDEF_MASK : 0;
|
|
|
|
// em height
|
|
|
|
pifi->fwdUnitsPerEm = (FWORD) BE_INT16(&phead->unitsPerEm);
|
|
pifi->fwdLowestPPEm = BE_UINT16(&phead->lowestRecPPEM);
|
|
|
|
// ascender, descender, linegap
|
|
|
|
pifi->fwdMacAscender = (FWORD) BE_INT16(&phhea->yAscender);
|
|
pifi->fwdMacDescender = (FWORD) BE_INT16(&phhea->yDescender);
|
|
pifi->fwdMacLineGap = (FWORD) BE_INT16(&phhea->yLineGap);
|
|
|
|
if (pjOS2)
|
|
{
|
|
pifi->fwdWinAscender = (FWORD) BE_INT16(pjOS2 + OFF_OS2_usWinAscent);
|
|
pifi->fwdWinDescender = (FWORD) BE_INT16(pjOS2 + OFF_OS2_usWinDescent);
|
|
pifi->fwdTypoAscender = (FWORD) BE_INT16(pjOS2 + OFF_OS2_sTypoAscender);
|
|
pifi->fwdTypoDescender = (FWORD) BE_INT16(pjOS2 + OFF_OS2_sTypoDescender);
|
|
pifi->fwdTypoLineGap = (FWORD) BE_INT16(pjOS2 + OFF_OS2_sTypoLineGap);
|
|
}
|
|
else
|
|
{
|
|
pifi->fwdWinAscender = pifi->fwdMacAscender;
|
|
pifi->fwdWinDescender = -(pifi->fwdMacDescender);
|
|
pifi->fwdTypoAscender = pifi->fwdMacAscender;
|
|
pifi->fwdTypoDescender = pifi->fwdMacDescender;
|
|
pifi->fwdTypoLineGap = pifi->fwdMacLineGap;
|
|
}
|
|
|
|
// font box
|
|
|
|
pifi->rclFontBox.left = (LONG)((FWORD)BE_INT16(&phead->xMin));
|
|
pifi->rclFontBox.top = (LONG)((FWORD)BE_INT16(&phead->yMax));
|
|
pifi->rclFontBox.right = (LONG)((FWORD)BE_INT16(&phead->xMax));
|
|
pifi->rclFontBox.bottom = (LONG)((FWORD)BE_INT16(&phead->yMin));
|
|
|
|
// fwdMaxCharInc -- really the maximum character width
|
|
//
|
|
// [Windows 3.1 compatibility]
|
|
// Note: Win3.1 calculates max char width to be equal to the width of the
|
|
// bounding box (Font Box). This is actually wrong since the bounding box
|
|
// may pick up its left and right max extents from different glyphs,
|
|
// resulting in a bounding box that is wider than any single glyph. But
|
|
// this is the way Windows 3.1 does it, so that's the way we'll do it.
|
|
|
|
// pifi->fwdMaxCharInc = (FWORD) BE_INT16(&phhea->advanceWidthMax);
|
|
|
|
pifi->fwdMaxCharInc = (FWORD) (pifi->rclFontBox.right - pifi->rclFontBox.left);
|
|
|
|
// fwdAveCharWidth
|
|
|
|
if (pjOS2)
|
|
{
|
|
pifi->fwdAveCharWidth = (FWORD)BE_INT16(pjOS2 + OFF_OS2_xAvgCharWidth);
|
|
|
|
// This is here for Win 3.1 compatibility since some apps expect non-
|
|
// zero widths and Win 3.1 does the same in this case.
|
|
|
|
if( pifi->fwdAveCharWidth == 0 )
|
|
pifi->fwdAveCharWidth = (FWORD)(pifi->fwdMaxCharInc / 2);
|
|
}
|
|
else
|
|
{
|
|
pifi->fwdAveCharWidth = (FWORD)((pifi->fwdMaxCharInc * 2) / 3);
|
|
}
|
|
|
|
// !!! New code needed [kirko]
|
|
// The following is done for Win 3.1 compatibility
|
|
// reasons. The correct thing to do would be to look for the
|
|
// existence of the 'PCLT'Z table and retieve the XHeight and CapHeight
|
|
// fields, otherwise use the default Win 3.1 behavior.
|
|
|
|
pifi->fwdCapHeight = pifi->fwdUnitsPerEm/2;
|
|
pifi->fwdXHeight = pifi->fwdUnitsPerEm/4;
|
|
|
|
// Underscore, Subscript, Superscript, Strikeout
|
|
|
|
if (ppost)
|
|
{
|
|
pifi->fwdUnderscoreSize = (FWORD)BE_INT16(&ppost->underlineThickness);
|
|
pifi->fwdUnderscorePosition = (FWORD)BE_INT16(&ppost->underlinePosition);
|
|
}
|
|
else
|
|
{
|
|
// must provide reasonable defaults, when there is no ppost table,
|
|
// win 31 sets these quantities to zero. This does not sound reasonable.
|
|
// I will supply the (relative) values the same as for arial font. [bodind]
|
|
|
|
pifi->fwdUnderscoreSize = (pifi->fwdUnitsPerEm + 7)/14;
|
|
pifi->fwdUnderscorePosition = -((pifi->fwdUnitsPerEm + 5)/10);
|
|
}
|
|
|
|
if (pjOS2)
|
|
{
|
|
pifi->fwdSubscriptXSize = BE_INT16(pjOS2 + OFF_OS2_ySubscriptXSize );
|
|
pifi->fwdSubscriptYSize = BE_INT16(pjOS2 + OFF_OS2_ySubscriptYSize );
|
|
pifi->fwdSubscriptXOffset = BE_INT16(pjOS2 + OFF_OS2_ySubscriptXOffset );
|
|
pifi->fwdSubscriptYOffset = BE_INT16(pjOS2 + OFF_OS2_ySubscriptYOffset );
|
|
pifi->fwdSuperscriptXSize = BE_INT16(pjOS2 + OFF_OS2_ySuperScriptXSize );
|
|
pifi->fwdSuperscriptYSize = BE_INT16(pjOS2 + OFF_OS2_ySuperScriptYSize );
|
|
pifi->fwdSuperscriptXOffset = BE_INT16(pjOS2 + OFF_OS2_ySuperScriptXOffset);
|
|
pifi->fwdSuperscriptYOffset = BE_INT16(pjOS2 + OFF_OS2_ySuperScriptYOffset);
|
|
pifi->fwdStrikeoutSize = BE_INT16(pjOS2 + OFF_OS2_yStrikeOutSize );
|
|
pifi->fwdStrikeoutPosition = BE_INT16(pjOS2 + OFF_OS2_yStrikeOutPosition);
|
|
}
|
|
else
|
|
{
|
|
pifi->fwdSubscriptXSize = 0;
|
|
pifi->fwdSubscriptYSize = 0;
|
|
pifi->fwdSubscriptXOffset = 0;
|
|
pifi->fwdSubscriptYOffset = 0;
|
|
pifi->fwdSuperscriptXSize = 0;
|
|
pifi->fwdSuperscriptYSize = 0;
|
|
pifi->fwdSuperscriptXOffset = 0;
|
|
pifi->fwdSuperscriptYOffset = 0;
|
|
pifi->fwdStrikeoutSize = pifi->fwdUnderscoreSize;
|
|
pifi->fwdStrikeoutPosition = (FWORD)(pifi->fwdMacAscender / 3) ;
|
|
}
|
|
|
|
|
|
//
|
|
// panose
|
|
//
|
|
pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
|
|
if (pjOS2)
|
|
{
|
|
pifi->usWinWeight = BE_INT16(pjOS2 + OFF_OS2_usWeightClass);
|
|
|
|
// now comes a hack from win31. Here is the comment from fonteng2.asm:
|
|
|
|
// MAXPMWEIGHT equ ($ - pPM2WinWeight)/2 - 1
|
|
|
|
//; Because winword shipped early TT fonts, - only index usWeightClass
|
|
//; if between 0 and 9. If above 9 then treat as a normal Windows lfWeight.
|
|
//
|
|
// cmp bx,MAXPMWEIGHT
|
|
// ja @f ;jmp if weight is ok as is
|
|
// shl bx, 1 ;make it an offset into table of WORDs
|
|
// mov bx, cs:[bx].pPM2WinWeight
|
|
//@@: xchg ax, bx
|
|
// stosw ;store font weight
|
|
|
|
// we emulate this in NT:
|
|
|
|
#define MAXPMWEIGHT ( sizeof(ausIFIMetrics2WinWeight) / sizeof(ausIFIMetrics2WinWeight[0]) )
|
|
|
|
if (pifi->usWinWeight < MAXPMWEIGHT)
|
|
pifi->usWinWeight = ausIFIMetrics2WinWeight[pifi->usWinWeight];
|
|
|
|
RtlCopyMemory((PVOID)&pifi->panose,
|
|
(PVOID)(pjOS2 + OFF_OS2_Panose), sizeof(PANOSE));
|
|
}
|
|
else // os2 table is not present
|
|
{
|
|
pifi->panose.bFamilyType = PAN_FAMILY_TEXT_DISPLAY;
|
|
pifi->panose.bSerifStyle = PAN_ANY;
|
|
pifi->panose.bWeight = (BYTE)
|
|
((phead->macStyle & BE_MSTYLE_BOLD) ?
|
|
PAN_WEIGHT_BOLD :
|
|
PAN_WEIGHT_BOOK
|
|
);
|
|
pifi->panose.bProportion = (BYTE)
|
|
((pifi->flInfo & FM_INFO_OPTICALLY_FIXED_PITCH) ?
|
|
PAN_PROP_MONOSPACED :
|
|
PAN_ANY
|
|
);
|
|
pifi->panose.bContrast = PAN_ANY;
|
|
pifi->panose.bStrokeVariation = PAN_ANY;
|
|
pifi->panose.bArmStyle = PAN_ANY;
|
|
pifi->panose.bLetterform = PAN_ANY;
|
|
pifi->panose.bMidline = PAN_ANY;
|
|
pifi->panose.bXHeight = PAN_ANY;
|
|
|
|
// have to fake it up, cause we can not read it from the os2 table
|
|
// really important to go through this table for compatibility reasons [bodind]
|
|
|
|
pifi->usWinWeight =
|
|
ausIFIMetrics2WinWeight[pifi->panose.bWeight];
|
|
}
|
|
|
|
//
|
|
// first, last, break, defalut
|
|
//
|
|
|
|
#define LAST_CHAR 255
|
|
#define SPACE_CHAR 32
|
|
|
|
// Assume character bias is zero.
|
|
|
|
pifi->lCharBias = 0;
|
|
|
|
if (!(pff->fl & FF_TYPE_1_CONVERSION))
|
|
{
|
|
|
|
// Ignore the font signature if this is an ms mincho or ms gothic
|
|
// type face since Win 95-J and Win NT 3.51J shipped these fonts
|
|
// with buggy font signatures. I've also require that the font
|
|
// signature be non-zero to enter this case. The reason for
|
|
// this is that I when I try to load a 3.5 korean font such as
|
|
// gulim.ttf, it appears that it has a zero font signature which
|
|
// will cause us to mark it as ANSI.
|
|
|
|
if (pjOS2 && *((uint16*)(pjOS2+SFNT_OS2_VERSION)) &&
|
|
!IsMsMinchoOrMsGothic((LPWSTR)((PBYTE)pifi + pifi->dpwszFaceName)) &&
|
|
((DWORD)BE_UINT32(pjOS2+OFF_OS2_ulCodePageRange1)))
|
|
{
|
|
DWORD fontSig;
|
|
|
|
fontSig = (DWORD)BE_UINT32(pjOS2+OFF_OS2_ulCodePageRange1);
|
|
|
|
// We only supports ANSI/SHIFTJIS/BIG5/WANSANG/GB2312 charset for
|
|
// FarEast version.
|
|
//
|
|
// [NOTE:]
|
|
//
|
|
// We will have TRUE world wide support in NT 4.0 with TranslateCharsetInfo()
|
|
//
|
|
|
|
if (fontSig & FS_JISJAPAN)
|
|
{
|
|
pifi->jWinCharSet = SHIFTJIS_CHARSET;
|
|
pff->uiFontCodePage = 932;
|
|
}
|
|
else if (fontSig & FS_CHINESETRAD)
|
|
{
|
|
pifi->jWinCharSet = CHINESEBIG5_CHARSET;
|
|
pff->uiFontCodePage = 950;
|
|
}
|
|
else if (fontSig & FS_CHINESESIMP)
|
|
{
|
|
pifi->jWinCharSet = GB2312_CHARSET;
|
|
pff->uiFontCodePage = 936;
|
|
}
|
|
else if (fontSig & FS_WANSUNG)
|
|
{
|
|
pifi->jWinCharSet = HANGEUL_CHARSET;
|
|
pff->uiFontCodePage = 949;
|
|
}
|
|
else
|
|
{
|
|
pifi->jWinCharSet = jWinCharset;
|
|
|
|
// Added this next line of garbage for Win 3.1 compatability sake.
|
|
// The WatchTower Library depends on for the charset to be set properly
|
|
// on a set of fonts that comes with it. [gerritv] 3-6-95
|
|
|
|
if (!jWinCharset && (pifi->panose.bFamilyType==PAN_FAMILY_PICTORIAL))
|
|
pifi->jWinCharSet = SYMBOL_CHARSET;
|
|
|
|
// caution: note that jWinCharSet as computed from the upper byte
|
|
// of the fsSelection field in os2 table may be different than ANSI_CHARSET,
|
|
// jet we shall set uiFontCodePage to be 1252. It turns out that this does
|
|
// matter, it is only important that this value is correct if it corresponds to
|
|
// a DBCS code page, else it will not even get used, therefore it is safe not to
|
|
// bother to compute it correctly in this case and instead just set it to
|
|
// some SBCS value, such as 1252. [bodind]
|
|
|
|
pff->uiFontCodePage = 1252;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Determine character set.
|
|
//
|
|
if(bContainGlyphSet( U_HALFWIDTH_KATAKANA_LETTER_A , pff->pgset ) &&
|
|
bContainGlyphSet( U_HALFWIDTH_KATAKANA_LETTER_I , pff->pgset ) &&
|
|
bContainGlyphSet( U_HALFWIDTH_KATAKANA_LETTER_U , pff->pgset ) &&
|
|
bContainGlyphSet( U_HALFWIDTH_KATAKANA_LETTER_E , pff->pgset ) &&
|
|
bContainGlyphSet( U_HALFWIDTH_KATAKANA_LETTER_O , pff->pgset )
|
|
)
|
|
{
|
|
pifi->jWinCharSet = SHIFTJIS_CHARSET;
|
|
pff->uiFontCodePage = 932;
|
|
}
|
|
else if( bContainGlyphSet( U_FULLWIDTH_HAN_IDEOGRAPHIC_61D4 , pff->pgset ) &&
|
|
bContainGlyphSet( U_FULLWIDTH_HAN_IDEOGRAPHIC_9EE2 , pff->pgset )
|
|
)
|
|
{
|
|
pifi->jWinCharSet = GB2312_CHARSET;
|
|
pff->uiFontCodePage = 936;
|
|
}
|
|
else if( bContainGlyphSet( U_FULLWIDTH_HAN_IDEOGRAPHIC_9F98 , pff->pgset ) &&
|
|
bContainGlyphSet( U_FULLWIDTH_HAN_IDEOGRAPHIC_9F79 , pff->pgset )
|
|
)
|
|
{
|
|
pifi->jWinCharSet = CHINESEBIG5_CHARSET;
|
|
pff->uiFontCodePage = 950;
|
|
}
|
|
else if( bContainGlyphSet( U_FULLWIDTH_HANGUL_LETTER_GA , pff->pgset ) &&
|
|
bContainGlyphSet( U_FULLWIDTH_HANGUL_LETTER_HA , pff->pgset )
|
|
)
|
|
{
|
|
pifi->jWinCharSet = HANGEUL_CHARSET;
|
|
pff->uiFontCodePage = 949;
|
|
}
|
|
else if(bContainGlyphSet( U_PRIVATE_USER_AREA_E000 , pff->pgset ) &&
|
|
IsCurrentCodePageDBCS())
|
|
{
|
|
USHORT AnsiCodePage, OemCodePage;
|
|
CHARSETINFO csi;
|
|
|
|
EngGetCurrentCodePage(&OemCodePage,&AnsiCodePage);
|
|
|
|
// !!! I claim that what we really want to do is
|
|
// return the proper DBCS charset (based on the current code page)
|
|
// if there are characters in the EUDC range. If the current
|
|
// code page is not a DBCS code page then we shouldn't be here
|
|
// and should fall through to the old behavior. Hence I've added
|
|
// a check above making sure the current code page is a DBCS
|
|
// code page in order to get here. The old code didn't have
|
|
// this check and had the following functionality instead of
|
|
// my switch statement.
|
|
// GreTranslateCharSetInfo from the engine I will implement that
|
|
// functionality here [gerritv]
|
|
//
|
|
//if( GreTranslateCharsetInfo((DWORD *)GetACP(),&csi,TCI_SRCCODEPAGE) )
|
|
// pifi->jWinCharSet = csi.ciCharset;
|
|
//else
|
|
// pifi->jWinCharSet = ANSI_CHARSET;
|
|
//
|
|
|
|
switch(AnsiCodePage)
|
|
{
|
|
case 932:
|
|
pifi->jWinCharSet = SHIFTJIS_CHARSET;
|
|
break;
|
|
case 949:
|
|
pifi->jWinCharSet = HANGEUL_CHARSET;
|
|
break;
|
|
case 1361:
|
|
pifi->jWinCharSet = JOHAB_CHARSET;
|
|
break;
|
|
case 936:
|
|
pifi->jWinCharSet = GB2312_CHARSET;
|
|
break;
|
|
case 950:
|
|
pifi->jWinCharSet = CHINESEBIG5_CHARSET;
|
|
break;
|
|
default:
|
|
ASSERTDD(FALSE, "shouldn't be here if non DBCS code page\n");
|
|
}
|
|
|
|
pff->uiFontCodePage = AnsiCodePage;
|
|
}
|
|
else
|
|
{
|
|
pifi->jWinCharSet = jWinCharset;
|
|
|
|
// Added this next line of garbage for Win 3.1 compatability sake.
|
|
// The WatchTower Library depends on for the charset to be set properly
|
|
// on a set of fonts that comes with it. [gerritv] 3-6-95
|
|
|
|
if (!jWinCharset && (pifi->panose.bFamilyType==PAN_FAMILY_PICTORIAL))
|
|
pifi->jWinCharSet = SYMBOL_CHARSET;
|
|
|
|
// caution: note that jWinCharSet as computed from the upper byte
|
|
// of the fsSelection field in os2 table may be different than ANSI_CHARSET,
|
|
// jet we shall set uiFontCodePage to be 1252. It turns out that this does
|
|
// matter, it is only important that this value is correct if it corresponds to
|
|
// a DBCS code page, else it will not even get used, therefore it is safe not to
|
|
// bother to compute it correctly in this case and instead just set it to
|
|
// some SBCS value, such as 1252. [bodind]
|
|
|
|
pff->uiFontCodePage = 1252;
|
|
}
|
|
}
|
|
|
|
if (pff->ui16PlatformID == BE_PLAT_ID_MS && (pjOS2))
|
|
{
|
|
// win 31 compatibility behavior, ask kirko about the origin
|
|
|
|
USHORT usF, usL;
|
|
|
|
usF = BE_UINT16(pjOS2 + OFF_OS2_usFirstChar);
|
|
usL = BE_UINT16(pjOS2 + OFF_OS2_usLastChar);
|
|
|
|
if (usL > LAST_CHAR)
|
|
{
|
|
if (usF > LAST_CHAR)
|
|
{
|
|
pifi->lCharBias = (LONG) (usF - (USHORT) SPACE_CHAR);
|
|
|
|
pifi->jWinCharSet = SYMBOL_CHARSET;
|
|
pifi->chFirstChar = SPACE_CHAR;
|
|
pifi->chLastChar = (BYTE)min(LAST_CHAR, usL - usF + SPACE_CHAR);
|
|
}
|
|
else
|
|
{
|
|
pifi->chFirstChar = (BYTE) usF;
|
|
pifi->chLastChar = LAST_CHAR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pifi->chFirstChar = (BYTE) usF;
|
|
pifi->chLastChar = (BYTE) usL;
|
|
}
|
|
pifi->chFirstChar -= 2;
|
|
|
|
//
|
|
// In SHIFTJIS TrueType font, We use 0xa5 ( U+ff65 ) character
|
|
// as a SBCS default character accoring to Microsoft Standard
|
|
// character set specification ( SHIFTJIS version )
|
|
// font file's default char ( 0x1f ) is a DBCS(Full Width)
|
|
// defalt character.
|
|
// in NT, we won't use DBCS default character
|
|
//
|
|
|
|
if( pifi->jWinCharSet == SHIFTJIS_CHARSET )
|
|
{
|
|
pifi->chDefaultChar = 0xa5;
|
|
pifi->chBreakChar = pifi->chFirstChar + 2;
|
|
}
|
|
else if ( pifi->jWinCharSet == CHINESEBIG5_CHARSET ||
|
|
pifi->jWinCharSet == GB2312_CHARSET )
|
|
{
|
|
pifi->chDefaultChar = 0x3f; // Space
|
|
pifi->chBreakChar = pifi->chFirstChar + 2;
|
|
}
|
|
else
|
|
{
|
|
pifi->chDefaultChar = pifi->chFirstChar + 1;
|
|
pifi->chBreakChar = pifi->chDefaultChar + 1;
|
|
}
|
|
|
|
//!!! little bit dangerous, what if 32 and 31 do not exhist in the font?
|
|
//!!! we must not lie to the engine, these two have to exhist in
|
|
//!!! some of the runs reported to the engine [bodind]
|
|
|
|
// Pls refer above comment
|
|
if( pifi->jWinCharSet == SHIFTJIS_CHARSET )
|
|
{
|
|
pifi->wcDefaultChar = (WCHAR) 0xff65;
|
|
pifi->wcBreakChar = (WCHAR) pifi->chBreakChar;
|
|
}
|
|
else if( pifi->jWinCharSet == CHINESEBIG5_CHARSET ||
|
|
pifi->jWinCharSet == GB2312_CHARSET )
|
|
{
|
|
pifi->wcDefaultChar = (WCHAR) 0x25a1;
|
|
pifi->wcBreakChar = (WCHAR) pifi->chBreakChar;
|
|
}
|
|
else
|
|
{
|
|
pifi->wcDefaultChar = (WCHAR) pifi->chDefaultChar;
|
|
pifi->wcBreakChar = (WCHAR) pifi->chBreakChar ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// win 31 compatibility behavior
|
|
|
|
pifi->chFirstChar = SPACE_CHAR - 2;
|
|
pifi->chLastChar = LAST_CHAR;
|
|
|
|
//
|
|
// In SHIFTJIS TrueType font, We use 0xa5 ( U+ff65 ) character
|
|
// as a SBCS default character according to Microsoft Standard
|
|
// character set specification ( SHIFTJIS version )
|
|
// font file's default char ( 0x1f ) is a DBCS defalt character.
|
|
// in NT, we won't use DBCS default character.
|
|
//
|
|
|
|
if( pifi->jWinCharSet == SHIFTJIS_CHARSET )
|
|
{
|
|
pifi->chDefaultChar = 0xa5;
|
|
pifi->chBreakChar = SPACE_CHAR;
|
|
}
|
|
else if (pifi->jWinCharSet == CHINESEBIG5_CHARSET ||
|
|
pifi->jWinCharSet == GB2312_CHARSET )
|
|
{
|
|
pifi->chDefaultChar = 0x20; // Space
|
|
pifi->chBreakChar = SPACE_CHAR;
|
|
}
|
|
else
|
|
{
|
|
pifi->chBreakChar = SPACE_CHAR;
|
|
pifi->chDefaultChar = SPACE_CHAR - 1;
|
|
}
|
|
|
|
//!!! little bit dangerous, what if 32 and 31 do not exhist in the font?
|
|
//!!! we must not lie to the engine, these two have to exhist in
|
|
//!!! some of the runs reported to the engine [bodind]
|
|
|
|
if( pifi->jWinCharSet == SHIFTJIS_CHARSET )
|
|
{
|
|
pifi->wcBreakChar = SPACE_CHAR;
|
|
pifi->wcDefaultChar = (WCHAR) 0xff65;
|
|
}
|
|
else if( pifi->jWinCharSet == CHINESEBIG5_CHARSET ||
|
|
pifi->jWinCharSet == GB2312_CHARSET )
|
|
{
|
|
pifi->wcBreakChar = SPACE_CHAR;
|
|
pifi->wcDefaultChar = (WCHAR) 0x25a1;
|
|
}
|
|
else
|
|
{
|
|
pifi->wcBreakChar = SPACE_CHAR;
|
|
pifi->wcDefaultChar = SPACE_CHAR - 1;
|
|
}
|
|
}
|
|
}
|
|
else // t1 conversion, have to be compatible with ps driver:
|
|
{
|
|
pifi->chFirstChar = ((BYTE *)phhea)[SFNT_HORIZONTALHEADER_RESERVED0];
|
|
pifi->chLastChar = ((BYTE *)phhea)[SFNT_HORIZONTALHEADER_RESERVED1];
|
|
pifi->chDefaultChar = 149;
|
|
pifi->chBreakChar = ((BYTE *)phhea)[SFNT_HORIZONTALHEADER_RESERVED3] + pifi->chFirstChar;
|
|
|
|
// charset has the highest weight. This will ensure that the charset of the
|
|
// tt font is the same as charset of the original type 1 font, ensuring the
|
|
// correct mapping. That is we will always get the tt conversion for the
|
|
// screen and the corresponding t1 original on the printer.
|
|
// The CharSet value got stored to hhead straight from .pfm file
|
|
|
|
pifi->jWinCharSet = ((BYTE *)phhea)[SFNT_HORIZONTALHEADER_RESERVED4];
|
|
|
|
// this is win31 hack. to understand look at pslib\pfmtontm.c
|
|
|
|
#define NO_TRANSLATE_CHARSET 200 /* djm 12/20/87 */ // WIN31 HACK
|
|
|
|
if (pifi->jWinCharSet == NO_TRANSLATE_CHARSET)
|
|
pifi->jWinCharSet = ANSI_CHARSET;
|
|
|
|
// adobe has handed out zapfdingbats with ansi charset in the pfm file.
|
|
// ps resident version of zapfdingbats has charset = symbol.
|
|
// For this reason only we override the value we have just written with
|
|
// symbol charset. (In wow16 they force charset for zapfdingbats to SYMBOL)
|
|
|
|
if
|
|
(
|
|
(!_wcsicmp((PWSTR)((BYTE*)pifi + pifi->dpwszFamilyName),L"ZapfDingbats") ||
|
|
!_wcsicmp((PWSTR)((BYTE*)pifi + pifi->dpwszFamilyName),L"Symbol"))
|
|
&& (pifi->jWinCharSet == ANSI_CHARSET)
|
|
)
|
|
{
|
|
pifi->jWinCharSet = SYMBOL_CHARSET;
|
|
}
|
|
}
|
|
|
|
// this is always done in the same fashion, regardless of the glyph set type
|
|
|
|
{
|
|
WCRUN *pwcRunLast = &pff->pgset->awcrun[pff->pgset->cRuns - 1];
|
|
pifi->wcFirstChar = pff->pgset->awcrun[0].wcLow;
|
|
pifi->wcLastChar = pwcRunLast->wcLow + pwcRunLast->cGlyphs - 1;
|
|
}
|
|
|
|
|
|
//!!! one should look into directional hints here, this is good for now
|
|
|
|
pifi->ptlBaseline.x = 1;
|
|
pifi->ptlBaseline.y = 0;
|
|
pifi->ptlAspect.x = 1;
|
|
pifi->ptlAspect.y = 1;
|
|
|
|
// this is what win 31 is doing, so we will do the same thing [bodind]
|
|
|
|
pifi->ptlCaret.x = (LONG)BE_INT16(&phhea->horizontalCaretSlopeDenominator);
|
|
pifi->ptlCaret.y = (LONG)BE_INT16(&phhea->horizontalCaretSlopeNumerator);
|
|
|
|
// We have to use one of the reserved fields to return the italic angle.
|
|
|
|
if (ppost)
|
|
{
|
|
// The italic angle is stored in the POST table as a 16.16 fixed point
|
|
// number. We want the angle expressed in tenths of a degree. What we
|
|
// can do here is multiply the entire 16.16 number by 10. The most
|
|
// significant 16-bits of the result is the angle in tenths of a degree.
|
|
//
|
|
// In the conversion below, we don't care whether the right shift is
|
|
// arithmetic or logical because we are only interested in the lower
|
|
// 16-bits of the result. When the 16-bit result is cast back to LONG,
|
|
// the sign is restored.
|
|
|
|
int16 iTmp;
|
|
|
|
iTmp = (int16) ((BE_INT32((BYTE*)ppost + POSTSCRIPTNAMEINDICES_ITALICANGLE) * 10) >> 16);
|
|
pifi->lItalicAngle = (LONG) iTmp;
|
|
}
|
|
else
|
|
pifi->lItalicAngle = 0;
|
|
|
|
//
|
|
// vendor id
|
|
//
|
|
if (pjOS2)
|
|
{
|
|
char *pchSrc = (char*)(pjOS2 + OFF_OS2_achVendID);
|
|
|
|
pifi->achVendId[0] = *(pchSrc );
|
|
pifi->achVendId[1] = *(pchSrc + 1);
|
|
pifi->achVendId[2] = *(pchSrc + 2);
|
|
pifi->achVendId[3] = *(pchSrc + 3);
|
|
}
|
|
else
|
|
{
|
|
pifi->achVendId[0] = 'U';
|
|
pifi->achVendId[1] = 'n';
|
|
pifi->achVendId[2] = 'k';
|
|
pifi->achVendId[3] = 'n';
|
|
}
|
|
|
|
//
|
|
// kerning pairs
|
|
//
|
|
{
|
|
PBYTE pj = (ptp->ateOpt[IT_OPT_KERN].dp) ?
|
|
(pjView + ptp->ateOpt[IT_OPT_KERN].dp):
|
|
NULL;
|
|
|
|
if (!pj)
|
|
{
|
|
pifi->cKerningPairs = 0;
|
|
}
|
|
else
|
|
{
|
|
PBYTE pjEndOfView = pjView + pff->cjView;
|
|
|
|
ULONG cTables = BE_UINT16(pj+KERN_OFFSETOF_TABLE_NTABLES);
|
|
pj += KERN_SIZEOF_TABLE_HEADER;
|
|
|
|
while (cTables)
|
|
{
|
|
//
|
|
// Windows will only recognize KERN_WINDOWS_FORMAT
|
|
//
|
|
|
|
// make sure this doesn't put us past the file view
|
|
// KERN_OFFSETOF_SUBTABLE_FORMAT > KERN_OFFSETOF_SUBTABLE_LENGTH so
|
|
// one check here will cover both cases below where we derefence pj
|
|
|
|
if(pj+KERN_OFFSETOF_SUBTABLE_FORMAT >= pjEndOfView ||
|
|
pj+KERN_OFFSETOF_SUBTABLE_FORMAT < pjView )
|
|
{
|
|
WARNING("vFill_IFIMETRICS font has bad kerning table\n");
|
|
cTables = 0;
|
|
break;
|
|
}
|
|
|
|
if ((*(pj+KERN_OFFSETOF_SUBTABLE_FORMAT)) == KERN_WINDOWS_FORMAT)
|
|
{
|
|
break;
|
|
}
|
|
pj += BE_UINT16(pj+KERN_OFFSETOF_SUBTABLE_LENGTH);
|
|
cTables -= 1;
|
|
}
|
|
pifi->cKerningPairs = (SHORT) (cTables ? BE_UINT16(pj+KERN_OFFSETOF_SUBTABLE_NPAIRS) : 0);
|
|
}
|
|
}
|
|
|
|
|
|
// jWinPitchAndFamily
|
|
|
|
#ifdef THIS_IS_WIN31_SOURCE_CODE
|
|
|
|
; record family type
|
|
|
|
mov ah, pIfiMetrics.ifmPanose.bFamilyKind
|
|
or ah,ah
|
|
jz @F
|
|
.errnz 0 - PANOSE_FK_ANY
|
|
dec ah
|
|
jz @F
|
|
.errnz 1 - PANOSE_FK_NOFIT
|
|
dec ah
|
|
jz @F
|
|
.errnz 2 - PANOSE_FK_TEXT
|
|
mov al, FF_SCRIPT
|
|
dec ah
|
|
jz MFDSetFamily
|
|
.errnz 3 - PANOSE_FK_SCRIPT
|
|
mov al, FF_DECORATIVE
|
|
dec ah
|
|
jz MFDSetFamily
|
|
.errnz 4 - PANOSE_FK_DECORATIVE
|
|
.errnz 5 - PANOSE_FK_PICTORIAL
|
|
@@:
|
|
mov al, FF_MODERN
|
|
cmp pIfiMetrics.ifmPanose.bProportion, PANOSE_FIXED_PITCH
|
|
jz MFDSetFamily
|
|
mov al, pIfiMetrics.ifmPanose.bSerifStyle
|
|
sub ah, ah
|
|
mov si, ax
|
|
add si, MiscSegOFFSET pPansoseSerifXlate
|
|
mov al, cs:[si] ;get serif style
|
|
MFDSetFamily:
|
|
cmp pIfiMetrics.ifmPanose.bProportion, PANOSE_FIXED_PITCH
|
|
je @f
|
|
; test pIfiMetrics.fsType, IFIMETRICS_FIXED
|
|
; jnz @F
|
|
inc al ;hack: var pitch: 1, fixed pitch: 0
|
|
.errnz VARIABLE_PITCH-FIXED_PITCH-1
|
|
@@:
|
|
or al, PF_ENGINE_TYPE SHL PANDFTYPESHIFT ;mark font as engine
|
|
stosb ;copy pitch and font family info
|
|
.errnz efbPitchAndFamily-efbPixHeight-2
|
|
|
|
#endif // end of win31 source code,
|
|
|
|
if(pifi->jWinCharSet == SHIFTJIS_CHARSET)
|
|
{
|
|
//
|
|
// Following Code is Win3.1J compatibility
|
|
//
|
|
// ajPanoseFamilyForJapanese is defined as following
|
|
//
|
|
// static BYTE
|
|
// ajPanoseFamilyForJapanese[16] = {
|
|
// FF_DONTCARE // 0 (Any)
|
|
// ,FF_DONTCARE // 1 (No Fit)
|
|
// ,FF_ROMAN // 2 (Cove)
|
|
// ,FF_ROMAN // 3 (Obtuse Cove)
|
|
// ,FF_ROMAN // 4 (Square Cove)
|
|
// ,FF_ROMAN // 5 (Obtuse Square Cove)
|
|
// ,FF_ROMAN // 6 (Square)
|
|
// ,FF_ROMAN // 7 (Thin)
|
|
// ,FF_ROMAN // 8 (Bone)
|
|
// ,FF_ROMAN // 9 (Exaggerated)
|
|
// ,FF_ROMAN // 10 (Triangle)
|
|
// ,FF_MODERN // 11 (Normal Sans)
|
|
// ,FF_MODERN // 12 (Obtuse Sans)
|
|
// ,FF_MODERN // 13 (Perp Sans)
|
|
// ,FF_MODERN // 14 (Flared)
|
|
// ,FF_MODERN // 15 (Rounded)
|
|
// };
|
|
//
|
|
// Win3.1J determine the font is fixed pitch or not by
|
|
// Proportion in PANOSE. if Proportion is PAN_PROP_MONOSPACED (9)
|
|
// Win3.1J treat the font as fixed pitch font
|
|
//
|
|
// In detail, Please refer to following document
|
|
//
|
|
// GDI TrueType Extension for Far East version Rev 1.02
|
|
// Author : Shusuke Uehara [ ShusukeU ]
|
|
//
|
|
// 30.Aug.1993 -By- Hideyuki Nagase [ hideyukn ]
|
|
//
|
|
|
|
if(pifi->panose.bFamilyType == PAN_FAMILY_SCRIPT)
|
|
{
|
|
pifi->jWinPitchAndFamily = FF_SCRIPT;
|
|
}
|
|
else
|
|
{
|
|
if (pifi->panose.bSerifStyle >= sizeof(ajPanoseFamilyForJapanese))
|
|
{
|
|
pifi->jWinPitchAndFamily = ajPanoseFamily[0];
|
|
}
|
|
else
|
|
{
|
|
pifi->jWinPitchAndFamily =
|
|
ajPanoseFamilyForJapanese[pifi->panose.bSerifStyle];
|
|
}
|
|
}
|
|
|
|
if(pifi->panose.bProportion == PAN_PROP_MONOSPACED)
|
|
{
|
|
pifi->flInfo |= (FM_INFO_OPTICALLY_FIXED_PITCH | FM_INFO_DBCS_FIXED_PITCH);
|
|
}
|
|
|
|
// Defining the pitch
|
|
// set the lower 4 bits according to the LOGFONT convention
|
|
//
|
|
pifi->jWinPitchAndFamily |= (pifi->flInfo & FM_INFO_OPTICALLY_FIXED_PITCH) ?
|
|
FIXED_PITCH : VARIABLE_PITCH;
|
|
}
|
|
else
|
|
{
|
|
|
|
// verified that the translation to c is correct [bodind]
|
|
// Set the family type in the upper nibble
|
|
|
|
switch (pifi->panose.bFamilyType)
|
|
{
|
|
case PAN_FAMILY_DECORATIVE:
|
|
|
|
pifi->jWinPitchAndFamily = FF_DECORATIVE;
|
|
break;
|
|
|
|
case PAN_FAMILY_SCRIPT:
|
|
|
|
pifi->jWinPitchAndFamily = FF_SCRIPT;
|
|
break;
|
|
|
|
default:
|
|
|
|
if (pifi->panose.bProportion == PAN_PROP_MONOSPACED)
|
|
{
|
|
pifi->jWinPitchAndFamily = FF_MODERN;
|
|
}
|
|
else
|
|
{
|
|
if (pifi->panose.bSerifStyle >= sizeof(ajPanoseFamily))
|
|
{
|
|
pifi->jWinPitchAndFamily = ajPanoseFamily[0];
|
|
}
|
|
else
|
|
{
|
|
pifi->jWinPitchAndFamily = ajPanoseFamily[pifi->panose.bSerifStyle];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Defining the pitch
|
|
// set the lower 4 bits according to the LOGFONT convention
|
|
|
|
pifi->jWinPitchAndFamily |= (pifi->flInfo & FM_INFO_OPTICALLY_FIXED_PITCH) ?
|
|
FIXED_PITCH : VARIABLE_PITCH;
|
|
}
|
|
|
|
// simulation information:
|
|
|
|
if (pifi->dpFontSim = pifisz->dpSims)
|
|
{
|
|
FONTDIFF FontDiff;
|
|
FONTSIM * pfsim = (FONTSIM *)((BYTE *)pifi + pifi->dpFontSim);
|
|
FONTDIFF *pfdiffBold = NULL;
|
|
FONTDIFF *pfdiffItalic = NULL;
|
|
FONTDIFF *pfdiffBoldItalic = NULL;
|
|
|
|
switch (pifi->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD))
|
|
{
|
|
case 0:
|
|
// all 3 simulations are present
|
|
|
|
pfsim->dpBold = DWORD_ALIGN(sizeof(FONTSIM));
|
|
pfsim->dpItalic = pfsim->dpBold + DWORD_ALIGN(sizeof(FONTDIFF));
|
|
pfsim->dpBoldItalic = pfsim->dpItalic + DWORD_ALIGN(sizeof(FONTDIFF));
|
|
|
|
pfdiffBold = (FONTDIFF *)((BYTE*)pfsim + pfsim->dpBold);
|
|
pfdiffItalic = (FONTDIFF *)((BYTE*)pfsim + pfsim->dpItalic);
|
|
pfdiffBoldItalic = (FONTDIFF *)((BYTE*)pfsim + pfsim->dpBoldItalic);
|
|
|
|
break;
|
|
|
|
case FM_SEL_ITALIC:
|
|
case FM_SEL_BOLD:
|
|
|
|
// only bold italic variation is present:
|
|
|
|
pfsim->dpBold = 0;
|
|
pfsim->dpItalic = 0;
|
|
|
|
pfsim->dpBold = 0;
|
|
pfsim->dpItalic = 0;
|
|
|
|
pfsim->dpBoldItalic = DWORD_ALIGN(sizeof(FONTSIM));
|
|
pfdiffBoldItalic = (FONTDIFF *)((BYTE*)pfsim + pfsim->dpBoldItalic);
|
|
|
|
break;
|
|
|
|
case (FM_SEL_ITALIC | FM_SEL_BOLD):
|
|
RIP("ttfd!another case when flags have been messed up\n");
|
|
break;
|
|
}
|
|
|
|
// template reflecting a base font:
|
|
// (note that the FM_SEL_REGULAR bit is masked off because none of
|
|
// the simulations generated will want this flag turned on).
|
|
|
|
FontDiff.jReserved1 = 0;
|
|
FontDiff.jReserved2 = 0;
|
|
FontDiff.jReserved3 = 0;
|
|
FontDiff.bWeight = pifi->panose.bWeight;
|
|
FontDiff.usWinWeight = pifi->usWinWeight;
|
|
FontDiff.fsSelection = pifi->fsSelection & ~FM_SEL_REGULAR;
|
|
FontDiff.fwdAveCharWidth = pifi->fwdAveCharWidth;
|
|
FontDiff.fwdMaxCharInc = pifi->fwdMaxCharInc;
|
|
FontDiff.ptlCaret = pifi->ptlCaret;
|
|
|
|
//
|
|
// Create FONTDIFFs from the base font template
|
|
//
|
|
if (pfdiffBold)
|
|
{
|
|
*pfdiffBold = FontDiff;
|
|
pfdiffBoldItalic->bWeight = PAN_WEIGHT_BOLD;
|
|
pfdiffBold->fsSelection |= FM_SEL_BOLD;
|
|
pfdiffBold->usWinWeight = FW_BOLD;
|
|
|
|
// really only true if ntod transform is unity
|
|
|
|
pfdiffBold->fwdAveCharWidth += 1;
|
|
pfdiffBold->fwdMaxCharInc += 1;
|
|
}
|
|
|
|
if (pfdiffItalic)
|
|
{
|
|
*pfdiffItalic = FontDiff;
|
|
pfdiffItalic->fsSelection |= FM_SEL_ITALIC;
|
|
|
|
pfdiffItalic->ptlCaret.x = CARET_X;
|
|
pfdiffItalic->ptlCaret.y = CARET_Y;
|
|
}
|
|
|
|
if (pfdiffBoldItalic)
|
|
{
|
|
*pfdiffBoldItalic = FontDiff;
|
|
pfdiffBoldItalic->bWeight = PAN_WEIGHT_BOLD;
|
|
pfdiffBoldItalic->fsSelection |= (FM_SEL_BOLD | FM_SEL_ITALIC);
|
|
pfdiffBoldItalic->usWinWeight = FW_BOLD;
|
|
|
|
pfdiffBoldItalic->ptlCaret.x = CARET_X;
|
|
pfdiffBoldItalic->ptlCaret.y = CARET_Y;
|
|
|
|
pfdiffBoldItalic->fwdAveCharWidth += 1;
|
|
pfdiffBoldItalic->fwdMaxCharInc += 1;
|
|
}
|
|
|
|
}
|
|
|
|
// offset to charesets
|
|
|
|
pifi->dpCharSets = pifisz->dpCharSets;
|
|
vFillIFICharsets(pff,
|
|
pifi,
|
|
(BYTE *)pifi + pifi->dpCharSets,
|
|
pjView,
|
|
pjOS2);
|
|
|
|
// check if there is font signiture info
|
|
|
|
pifiex->dpFontSig = pifisz->dpFontSig;
|
|
|
|
// fill in the font signature, for now, non-trivial only for tt fonts
|
|
// The following if is equivalent to
|
|
// if (pjOS2 && ((sfnt_OS2 *)pjOS2)->Version)
|
|
|
|
if (pifiex->dpFontSig)
|
|
{
|
|
// 1.0 or higher is TT open
|
|
|
|
FONTSIGNATURE *pfsig = (FONTSIGNATURE *)((BYTE *)pifi + pifiex->dpFontSig);
|
|
|
|
pfsig->fsUsb[0] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCharRange[0]);
|
|
pfsig->fsUsb[1] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCharRange[1]);
|
|
pfsig->fsUsb[2] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCharRange[2]);
|
|
pfsig->fsUsb[3] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCharRange[3]);
|
|
pfsig->fsCsb[0] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCodePageRange[0]);
|
|
pfsig->fsCsb[1] = SWAPL(((sfnt_OS2 *)pjOS2)->ulCodePageRange[1]);
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* BOOL bVerifyMsftHighByteTable
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
STATIC BOOL bVerifyMsftHighByteTable
|
|
(
|
|
sfnt_mappingTable * pmap,
|
|
ULONG * pgset,
|
|
CMAPINFO * pcmi,
|
|
uint16 ui16SpecID
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER( pmap );
|
|
|
|
// Now, we only support SHIFTJIS encoding
|
|
|
|
if( ui16SpecID != BE_SPEC_ID_SHIFTJIS &&
|
|
ui16SpecID != BE_SPEC_ID_GB &&
|
|
ui16SpecID != BE_SPEC_ID_BIG5 &&
|
|
ui16SpecID != BE_SPEC_ID_WANSUNG
|
|
) return( FALSE );
|
|
|
|
// Init stuff
|
|
|
|
*pgset = GSET_TYPE_HIGH_BYTE;
|
|
|
|
pcmi->fl = 0;
|
|
pcmi->i_b7 = 0;
|
|
pcmi->i_2219 = 0;
|
|
pcmi->cRuns = 0;
|
|
pcmi->cGlyphs = 0;
|
|
pcmi->pWCharToIndex = NULL;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* BOOL bVerifyMsftTableGeneral
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
STATIC BOOL bVerifyMsftTableGeneral
|
|
(
|
|
sfnt_mappingTable * pmap,
|
|
ULONG * pgset,
|
|
CMAPINFO * pcmi,
|
|
uint16 ui16SpecID
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER( pmap );
|
|
|
|
// Now, we only support SHIFTJIS encoding
|
|
|
|
if( ui16SpecID != BE_SPEC_ID_SHIFTJIS &&
|
|
ui16SpecID != BE_SPEC_ID_GB &&
|
|
ui16SpecID != BE_SPEC_ID_BIG5 &&
|
|
ui16SpecID != BE_SPEC_ID_WANSUNG
|
|
) return( FALSE );
|
|
|
|
// Init stuff
|
|
|
|
*pgset = GSET_TYPE_GENERAL_NOT_UNICODE;
|
|
|
|
pcmi->fl = 0;
|
|
pcmi->i_b7 = 0;
|
|
pcmi->i_2219 = 0;
|
|
pcmi->cRuns = 0;
|
|
pcmi->cGlyphs = 0;
|
|
pcmi->pWCharToIndex = NULL;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* ULONG CreateGlyphSetFromMITable
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
STATIC ULONG CreateGlyphSetFromMITable
|
|
(
|
|
CMAPINFO *pcmi,
|
|
MbcsToIndex *MITable,
|
|
USHORT MICount,
|
|
ULONG **ppgset
|
|
)
|
|
{
|
|
USHORT ii;
|
|
INT iCodePage;
|
|
WcharToIndex *WITable;
|
|
ULONG cRuns;
|
|
ULONG cGlyphsSupported;
|
|
ULONG cjThis;
|
|
BOOL bInRun = FALSE;
|
|
FD_GLYPHSET *pgset;
|
|
WcharToIndex *WINow;
|
|
PWCRUN pwcrun;
|
|
HGLYPH *phg;
|
|
|
|
|
|
// Alloc WcharToIndex table
|
|
|
|
WITable = PV_ALLOC( sizeof(WcharToIndex) * 0xFFFF );
|
|
RtlZeroMemory( WITable , sizeof(WcharToIndex) * 0xFFFF );
|
|
|
|
if( WITable == NULL )
|
|
{
|
|
WARNING("TTFD!CreateGlyphSetFromMITable() PV_ALLOC() fail\n");
|
|
*ppgset = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
// Set CodePage
|
|
|
|
iCodePage = GetCodePageFromSpecId( pcmi->ui16SpecID );
|
|
|
|
// Fill up WcharToIndex table
|
|
|
|
for( ii = 0 ; ii < MICount ; ii++ )
|
|
{
|
|
WCHAR wChar[2];
|
|
int iRet;
|
|
|
|
// Convert Mbcs to Wide char
|
|
|
|
iRet = EngMultiByteToWideChar(iCodePage ,
|
|
wChar,
|
|
2 * sizeof(WCHAR),
|
|
MITable[ii].MbcsChar,
|
|
2);
|
|
|
|
if( iRet == -1 )
|
|
{
|
|
WARNING("TTFD!MultiByteToWideChar fail\n");
|
|
V_FREE(WITable);
|
|
*ppgset = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
if( !WITable[wChar[0]].bValid )
|
|
{
|
|
WITable[wChar[0]].bValid = TRUE;
|
|
WITable[wChar[0]].wChar = wChar[0];
|
|
WITable[wChar[0]].hGlyph = MITable[ii].hGlyph;
|
|
}
|
|
}
|
|
|
|
// Dump WITable
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
for( ii = 0 ; ii < 0xFFFF ; ii++ )
|
|
{
|
|
if(WITable[ii].bValid)
|
|
{
|
|
TtfdDbgPrint("WideChar - %x : hGlyph - %x \n",
|
|
WITable[ii].wChar , WITable[ii].hGlyph );
|
|
}
|
|
}
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Compute cRuns and cGlyphsSupported
|
|
|
|
cRuns = 0;
|
|
cGlyphsSupported = 0;
|
|
|
|
for( ii = 0 ; ii < 0xFFFF ; ii++ )
|
|
{
|
|
if( !WITable[ii].bValid )
|
|
{
|
|
if( bInRun )
|
|
{
|
|
bInRun = FALSE;
|
|
cRuns++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bInRun = TRUE;
|
|
cGlyphsSupported++;
|
|
}
|
|
}
|
|
if( bInRun )
|
|
cRuns++;
|
|
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("cRuns - %x , cGlyphsSupported - %x\n",cRuns,cGlyphsSupported);
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Compute needed size for FD_GLYPHSET
|
|
|
|
cjThis = sizeof ( FD_GLYPHSET ) + (cRuns - 1) * sizeof ( WCRUN )
|
|
+ cGlyphsSupported * sizeof( HGLYPH );
|
|
|
|
if( ppgset == NULL ) return( cjThis );
|
|
|
|
// Alloc FD_GLYPHSET table
|
|
|
|
pgset = PV_ALLOC( cjThis );
|
|
RtlZeroMemory( pgset , cjThis );
|
|
|
|
if( pgset == NULL )
|
|
{
|
|
WARNING("TTFD!cjComputeGLYPHSET_HIGH_BYTE() PV_ALLOC() fail\n");
|
|
V_FREE(WITable);
|
|
*ppgset = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
pgset->cjThis = cjThis;
|
|
pgset->flAccel = 0;
|
|
pgset->cRuns = cRuns;
|
|
pgset->cGlyphsSupported = cGlyphsSupported;
|
|
|
|
// Fill UP FD_GLYPHSET
|
|
|
|
|
|
pwcrun = &(pgset->awcrun[0]);
|
|
phg = (HGLYPH *)((PBYTE)pgset + sizeof( FD_GLYPHSET ) + (cRuns - 1) *
|
|
sizeof(WCRUN));
|
|
|
|
WINow = &WITable[0];
|
|
|
|
for( ii = 0 ; ii < cRuns ; ii++ )
|
|
{
|
|
while( !WINow->bValid ) WINow++;
|
|
|
|
pwcrun->wcLow = WINow->wChar;
|
|
pwcrun->cGlyphs = 0;
|
|
pwcrun->phg = phg;
|
|
while( WINow->bValid )
|
|
{
|
|
pwcrun->cGlyphs++;
|
|
*phg++ = WINow->hGlyph;
|
|
WINow++;
|
|
}
|
|
pwcrun++;
|
|
}
|
|
|
|
pcmi->pWCharToIndex = WITable;
|
|
|
|
*ppgset = (ULONG *)pgset;
|
|
|
|
return( cjThis );
|
|
}
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* ULONG cjComputeGLYPHSET_HIGH_BYTE
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
typedef struct _subHeader
|
|
{
|
|
uint16 firstCode;
|
|
uint16 entryCount;
|
|
int16 idDelta;
|
|
uint16 idRangeOffset;
|
|
} subHeader;
|
|
|
|
STATIC ULONG cjComputeGLYPHSET_HIGH_BYTE
|
|
(
|
|
sfnt_mappingTable *pmap,
|
|
ULONG **ppgset,
|
|
CMAPINFO *pcmi
|
|
)
|
|
{
|
|
uint16 *pui16SubHeaderKeys = (uint16 *)((PBYTE)pmap + 6);
|
|
subHeader *pSubHeaderArray = (subHeader *)(pui16SubHeaderKeys + 256);
|
|
|
|
UINT cjChar = 0;
|
|
USHORT ii , jj;
|
|
|
|
MbcsToIndex *MITable;
|
|
USHORT MICount;
|
|
|
|
ULONG cjGlyphSet;
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("pui16SubHeaderKeys - %x\n",pui16SubHeaderKeys);
|
|
TtfdDbgPrint("pSubHeaderArray - %x\n",pSubHeaderArray);
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Compute how many chars in this cmap ?
|
|
|
|
// for single-byte char
|
|
|
|
cjChar = (BE_UINT16(&(((subHeader *)((PBYTE)pSubHeaderArray))->entryCount)));
|
|
|
|
// for double-byte char
|
|
|
|
for( ii = 0 ; ii < 256 ; ii ++ )
|
|
{
|
|
jj = BE_UINT16( &pui16SubHeaderKeys[ii] );
|
|
if( jj != 0 )
|
|
cjChar +=
|
|
(BE_UINT16(&(((subHeader *)((PBYTE)pSubHeaderArray + jj))->entryCount)));
|
|
}
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("cjChar - %x\n",cjChar);
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Alloc memory for MbcsToIndex table
|
|
|
|
MITable = PV_ALLOC( sizeof(MbcsToIndex) * cjChar );
|
|
|
|
if( MITable == NULL )
|
|
{
|
|
WARNING("TTFD!cjComputeGLYPHSET_HIGH_BYTE() PV_ALLOC() fail\n");
|
|
*ppgset = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
// Fill up MbcsToIndex table
|
|
|
|
MICount = 0;
|
|
|
|
// Process single-byte char
|
|
|
|
for( ii = 0 ; ii < 256 ; ii ++ )
|
|
{
|
|
USHORT entryCount, firstCode, idDelta, idRangeOffset;
|
|
subHeader *CurrentSubHeader;
|
|
uint16 *pui16GlyphArray;
|
|
HGLYPH hGlyph;
|
|
|
|
jj = BE_UINT16( &pui16SubHeaderKeys[ii] );
|
|
|
|
if( jj != 0 ) continue;
|
|
|
|
CurrentSubHeader = pSubHeaderArray;
|
|
|
|
firstCode = BE_UINT16(&(CurrentSubHeader->firstCode));
|
|
entryCount = BE_UINT16(&(CurrentSubHeader->entryCount));
|
|
idDelta = BE_UINT16(&(CurrentSubHeader->idDelta));
|
|
idRangeOffset = BE_UINT16(&(CurrentSubHeader->idRangeOffset));
|
|
|
|
pui16GlyphArray = (uint16 *)((PBYTE)&(CurrentSubHeader->idRangeOffset) +
|
|
idRangeOffset);
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("\n");
|
|
TtfdDbgPrint("firstCode - %x , entryCount - %x\n",firstCode,entryCount);
|
|
TtfdDbgPrint("idDelta - %x , idROffset - %x\n",idDelta,idRangeOffset);
|
|
TtfdDbgPrint("GlyphArray - %x\n",pui16GlyphArray);
|
|
TtfdDbgPrint("\n");
|
|
#endif // DBG_GLYPHSET
|
|
|
|
ASSERTDD( idDelta == 0 , "TTFD!cjComputeGLYPHSET_HIGH_BYTE:entryCount != 0\n" );
|
|
|
|
hGlyph = (HGLYPH)BE_UINT16(&pui16GlyphArray[ii-firstCode]);
|
|
|
|
if( hGlyph == 0 ) continue;
|
|
|
|
MITable[MICount].MbcsChar[0] = (UCHAR) ii;
|
|
MITable[MICount].MbcsChar[1] = (UCHAR) NULL;
|
|
MITable[MICount].hGlyph = hGlyph;
|
|
MICount++;
|
|
}
|
|
|
|
// Process double-byte char
|
|
|
|
for( ii = 0 ; ii < 256 ; ii ++ )
|
|
{
|
|
USHORT entryCount, firstCode, idDelta, idRangeOffset;
|
|
subHeader *CurrentSubHeader;
|
|
uint16 *pui16GlyphArray;
|
|
|
|
jj = BE_UINT16( &pui16SubHeaderKeys[ii] );
|
|
|
|
if( jj == 0 ) continue;
|
|
|
|
CurrentSubHeader = (subHeader *)((PBYTE)pSubHeaderArray + jj);
|
|
|
|
firstCode = BE_UINT16(&(CurrentSubHeader->firstCode));
|
|
entryCount = BE_UINT16(&(CurrentSubHeader->entryCount));
|
|
idDelta = BE_UINT16(&(CurrentSubHeader->idDelta));
|
|
idRangeOffset = BE_UINT16(&(CurrentSubHeader->idRangeOffset));
|
|
|
|
pui16GlyphArray = (uint16 *)((PBYTE)&(CurrentSubHeader->idRangeOffset) +
|
|
idRangeOffset);
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("\n");
|
|
TtfdDbgPrint("firstCode - %x , entryCount - %x\n",firstCode,entryCount);
|
|
TtfdDbgPrint("idDelta - %x , idROffset - %x\n",idDelta,idRangeOffset);
|
|
TtfdDbgPrint("GlyphArray - %x\n",pui16GlyphArray);
|
|
TtfdDbgPrint("\n");
|
|
#endif // DBG_GLYPHSET
|
|
|
|
for( jj = firstCode ; jj < firstCode + entryCount ; jj++ )
|
|
{
|
|
HGLYPH hGlyph;
|
|
|
|
hGlyph = (HGLYPH)(BE_UINT16(&pui16GlyphArray[jj-firstCode]));
|
|
|
|
if( hGlyph == 0 ) continue;
|
|
|
|
MITable[MICount].MbcsChar[0] = (UCHAR) ii;
|
|
MITable[MICount].MbcsChar[1] = (UCHAR) jj;
|
|
MITable[MICount].MbcsChar[2] = (UCHAR) NULL;
|
|
MITable[MICount].hGlyph = hGlyph + idDelta;
|
|
MICount++;
|
|
}
|
|
}
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
// Dump MITable
|
|
// for( ii = 0 ; ii < MICount ; ii++ )
|
|
for( ii = 0 ; ii < 10 ; ii++ )
|
|
{
|
|
TtfdDbgPrint("MbcsChar - %2x%2x : hGlyph - %x \n"
|
|
,MITable[ii].MbcsChar[0],
|
|
MITable[ii].MbcsChar[1] , MITable[ii].hGlyph );
|
|
}
|
|
#endif // DBG_GLYPHSET
|
|
|
|
cjGlyphSet = CreateGlyphSetFromMITable( pcmi, MITable, MICount, ppgset );
|
|
|
|
V_FREE( MITable );
|
|
|
|
return( cjGlyphSet );
|
|
}
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* ULONG cjComputeGLYPHSET_MSFT_GENERAL
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
STATIC ULONG cjComputeGLYPHSET_MSFT_GENERAL
|
|
(
|
|
sfnt_mappingTable *pmap,
|
|
ULONG **ppgset,
|
|
CMAPINFO *pcmi
|
|
)
|
|
{
|
|
USHORT cSegments;
|
|
uint16 *pendCountKeep , *pstartCountKeep , *pendCount , *pstartCount;
|
|
uint16 *pidDelta, *pRangeOffset, *pGlyphArray;
|
|
|
|
USHORT cChars;
|
|
|
|
USHORT ii;
|
|
|
|
MbcsToIndex *MITable;
|
|
USHORT MICount;
|
|
|
|
ULONG cjGlyphSet;
|
|
|
|
cSegments = BE_UINT16((PBYTE)pmap + OFF_segCountX2) / 2;
|
|
pendCountKeep = pendCount = (uint16 *)((PBYTE)pmap + OFF_endCount);
|
|
pstartCountKeep = pstartCount = (uint16 *)(pendCount + (cSegments + 1));
|
|
pidDelta = (uint16 *) pstartCount + (cSegments * 1);
|
|
pRangeOffset = (uint16 *) pstartCount + (cSegments * 2);
|
|
pGlyphArray = (uint16 *) pstartCount + (cSegments * 3);
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("cSegments - %x\n",cSegments );
|
|
TtfdDbgPrint("pstart - %x\n",pstartCount );
|
|
TtfdDbgPrint("pGlyphArray - %x\n",pGlyphArray );
|
|
TtfdDbgBreakPoint();
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Compute how many chars in this table
|
|
|
|
cChars = 0;
|
|
|
|
for( ii = 0 ; ii < cSegments - 1 ; ii ++ , pendCount ++ , pstartCount ++ )
|
|
cChars += (BE_UINT16(pendCount) - BE_UINT16(pstartCount) + 1);
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("cChars - %x\n",cChars);
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Alloc memory for MbcsToIndex table
|
|
|
|
MITable = PV_ALLOC( sizeof(MbcsToIndex) * cChars );
|
|
|
|
if( MITable == NULL )
|
|
{
|
|
WARNING("TTFD!cjComputeGLYPHSET_MSFT_GENERAL() PV_ALLOC() fail\n");
|
|
*ppgset = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
// Fill up MbcsToIndex table
|
|
|
|
pendCount = pendCountKeep;
|
|
pstartCount = pstartCountKeep;
|
|
|
|
MICount = 0;
|
|
|
|
for( ii = 0 ; ii < cSegments - 1 ; ii ++ , pendCount ++ , pstartCount ++ )
|
|
{
|
|
USHORT usStart , usEnd;
|
|
USHORT jj;
|
|
|
|
usStart = BE_UINT16(pstartCount);
|
|
usEnd = BE_UINT16(pendCount);
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("usStart - %x\n",usStart);
|
|
TtfdDbgPrint("usEnd - %x\n",usEnd);
|
|
#endif // DBG_GLYPHSET
|
|
|
|
// Check order
|
|
|
|
if( usStart > usEnd ) WARNING("TTFD!usStart > usEnd\n");
|
|
|
|
for( jj = usStart ; jj <= usEnd ; jj ++ )
|
|
{
|
|
*(ULONG *)(MITable[MICount].MbcsChar) = (LONG)0;
|
|
|
|
if( usStart > 0xFF )
|
|
*(USHORT *)(MITable[MICount].MbcsChar) = ((jj >> 8) | (jj << 8));
|
|
else
|
|
*(USHORT *)(MITable[MICount].MbcsChar) = jj;
|
|
|
|
if( pRangeOffset[ii] == 0 )
|
|
MITable[MICount].hGlyph = (USHORT)(jj + BE_UINT16(pidDelta + ii));
|
|
else
|
|
MITable[MICount].hGlyph =
|
|
(USHORT)(BE_UINT16((USHORT *)&pRangeOffset[ii] +
|
|
BE_UINT16(&pRangeOffset[ii])/2+(jj-usStart)) +
|
|
BE_UINT16( pidDelta + ii ));
|
|
MICount++;
|
|
}
|
|
}
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
TtfdDbgPrint("MICount - %x\n",MICount);
|
|
#endif
|
|
|
|
ASSERTDD( cChars == MICount , "cChars != MICount - 1\n" );
|
|
|
|
#ifdef DBG_GLYPHSET
|
|
// Dump MITable
|
|
for( ii = 0 ; ii < MICount ; ii++ )
|
|
{
|
|
TtfdDbgPrint("MbcsChar - %2x%2x : hGlyph - %x \n"
|
|
,MITable[ii].MbcsChar[0] ,
|
|
MITable[ii].MbcsChar[1] ,
|
|
MITable[ii].hGlyph );
|
|
}
|
|
#endif // DBG_GLYPHSET
|
|
|
|
cjGlyphSet = CreateGlyphSetFromMITable( pcmi, MITable, MICount, ppgset );
|
|
|
|
V_FREE( MITable );
|
|
|
|
return( cjGlyphSet );
|
|
}
|
|
|
|
/*************************************************************************\
|
|
*
|
|
* BOOL bContainGlyphSet()
|
|
*
|
|
* History:
|
|
* 11-Oct-1993 -By- Hideyuki Nagase [HideyukN]
|
|
* Wrote it.
|
|
*
|
|
**************************************************************************/
|
|
|
|
STATIC BOOL bContainGlyphSet
|
|
(
|
|
WCHAR wc,
|
|
PFD_GLYPHSET pgs
|
|
)
|
|
{
|
|
WCRUN *pwcRun = pgs->awcrun;
|
|
|
|
// binary search over awcrun, looking for correct run, if any
|
|
|
|
WCRUN *pwcRunLow = pgs->awcrun;
|
|
WCRUN *pwcRunHi = pgs->awcrun + (pgs->cRuns - 1);
|
|
|
|
while ( 1 )
|
|
{
|
|
int nwc;
|
|
|
|
// if run exists, it is in [pwcRunLow, pwcRunHi]
|
|
|
|
pwcRun = pwcRunLow + (pwcRunHi-pwcRunLow)/2;
|
|
nwc = wc - pwcRun->wcLow;
|
|
|
|
if ( nwc < 0)
|
|
{
|
|
// if correct run exists, it is in [pwcRunLow, pwcRun)
|
|
pwcRunHi = pwcRun - 1;
|
|
|
|
}
|
|
else if ( nwc >= (int)pwcRun->cGlyphs)
|
|
{
|
|
// if correct run exists, it is in (pwcRun, pwcHi]
|
|
pwcRunLow = pwcRun + 1;
|
|
}
|
|
else
|
|
{
|
|
// pwcRun is correct run
|
|
if ( pwcRun->phg != NULL )
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
if ( pwcRunLow > pwcRunHi )
|
|
{
|
|
// wc is not in any run
|
|
return FALSE;
|
|
}
|
|
} // while
|
|
}
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
//***************** F I L L I F I C H A R S E T S *********************
|
|
//*****************************************************************************
|
|
//
|
|
// Now determine how many charsets are supported in the TTF file. If
|
|
// the family isn't pictorial, then I assume it is at least an WANSI
|
|
// font. Then I see if a Unicode 0x2206 (Mac Increment char) is present
|
|
// in the font, if it is then I assume the MAC_CHARSET is supported.
|
|
// Finally, I check if Unicode 0x2592 (IBM medium shade char) is in
|
|
// the font, if so then I assume the OEM_CHARSET is supported.
|
|
//
|
|
// If the family is pictorial, then assume only the SYMBOL_CHARSET is
|
|
// supported.
|
|
//
|
|
// Wed 25-Jan-1995 -by- Bodin Dresevic [BodinD]
|
|
// update: stolen from win95 code
|
|
//*****************************************************************************
|
|
|
|
|
|
extern DWORD fs[]; // charset/fs table
|
|
extern UINT nCharsets;
|
|
extern UINT charsets[];
|
|
|
|
// these are in descending order in the font signature. there are no holes
|
|
// as defined in the spec. we go backwards so that 437 will be found first
|
|
// (usa/english)
|
|
|
|
UINT oemPages[] = {437, 850, 708, 737, 775, 852, 855, 857,
|
|
860, 861, 862, 863, 864, 865, 866, 869};
|
|
|
|
#define FEOEM_CHARSET 254
|
|
|
|
void vFillIFICharsets(
|
|
FONTFILE *pff,
|
|
IFIMETRICS *pifi,
|
|
BYTE *aCharSets,
|
|
BYTE *pjView,
|
|
BYTE * pjOS2)
|
|
{
|
|
int iCS = 0;
|
|
DWORD fsig;
|
|
UINT i;
|
|
DWORD fsigOEM;
|
|
BYTE cs;
|
|
uint8 *pCmap = pjView + pff->dpMappingTable + sizeof(sfnt_mappingTable);
|
|
uint16 giFirstChar = pjOS2 ? BE_UINT16(pjOS2+OFF_OS2_usFirstChar) : 0;
|
|
|
|
// This routine is to be replaced by a routine that searches the registry
|
|
// for the names of fonts that have bogus os2 table signatures:
|
|
|
|
|
|
BOOL bDBCSFont = IS_ANY_DBCS_CHARSET(pifi->jWinCharSet);
|
|
|
|
// Far East versions of Windows 95 ignore the charset array for far east
|
|
// fonts. Instead they jam the charset of the font, the value 254
|
|
// (which the call FEOEM_CHARSET), and DEFAULT_CHARSET into the array.
|
|
// The following code comes from t2api.asm
|
|
//
|
|
// ifdef DBCS ;DBCS T2 output
|
|
//;----------------- Set charset and family for DBCS font -------------------
|
|
//
|
|
// test bptr fEmbed, FEM_WIN31 ; Want new format?
|
|
// .errnz (FEM_WIN31 and 0FF00h) ;
|
|
// jnz @f ; No,
|
|
// sub di, MAXCHARSETS
|
|
//@@:
|
|
// Save <es, bx>
|
|
// cCall GetCharSetFromLanguage, <lhFontFile>
|
|
// or ax, ax <-- this will be zero if non-far east font
|
|
// jz @f
|
|
//
|
|
// test bptr fEmbed, FEM_WIN31 ; Want new format?
|
|
// .errnz (FEM_WIN31 and 0FF00h) ;
|
|
// jnz MFDOldCharSetOnly ; No, skip charset array
|
|
//
|
|
// and eax, 0ffh
|
|
// or eax, (FEOEM_CHARSET shl 8) + (DEFAULT_CHARSET shl 16)
|
|
// mov dwptr es:[di], eax
|
|
//MFDOldCharSetOnly:
|
|
// mov es:[di-efbaCharSets-1].efbCharSet, al
|
|
//
|
|
// For WIN 95-J compatibility sake I will do the same here [gerritv]
|
|
// If you remove this code in the future be sure to put a check in here
|
|
// to handle the buggy msmincho and msgothic fonts that have FS_CHINESESIMP
|
|
// instead of FS_JAPANESE in the signature. [gerritv]
|
|
//
|
|
|
|
if(bDBCSFont && IsMsMinchoOrMsGothic((LPWSTR)((PBYTE)pifi + pifi->dpwszFaceName)))
|
|
{
|
|
aCharSets[iCS++] = pifi->jWinCharSet;
|
|
}
|
|
else if (pjOS2 && *((uint16*)(pjOS2+SFNT_OS2_VERSION)))
|
|
{
|
|
// font signature
|
|
|
|
fsig = (DWORD)BE_UINT32(pjOS2+OFF_OS2_ulCodePageRange1);
|
|
|
|
for (i=0; i<nCharsets; i++)
|
|
if (fsig & fs[i])
|
|
aCharSets[iCS++] = (BYTE)charsets[i];
|
|
|
|
// fill in special bits
|
|
|
|
if (fsig & 0X80000000) // FS_SYMBOL = 0X80000000
|
|
aCharSets[iCS++] = SYMBOL_CHARSET;
|
|
|
|
// get the codepage value if any.
|
|
|
|
fsig = (DWORD)BE_UINT32(pjOS2+OFF_OS2_ulCodePageRange2);
|
|
if (fsig)
|
|
{
|
|
USHORT OemCodePage, AnsiCodePage;
|
|
|
|
EngGetCurrentCodePage(&OemCodePage,&AnsiCodePage);
|
|
|
|
fsigOEM = 0x80000000L;
|
|
for (i=0; i<NOEMCHARSETS; i++)
|
|
{
|
|
if ((UINT) OemCodePage == oemPages[i])
|
|
{
|
|
if (fsigOEM & fsig)
|
|
aCharSets[iCS++] = OEM_CHARSET;
|
|
break;
|
|
}
|
|
fsigOEM >>= 1; // move to next OEM page
|
|
}
|
|
}
|
|
}
|
|
else if ((pifi->panose.bFamilyType != PAN_FAMILY_PICTORIAL ) && (giFirstChar < 256))
|
|
{
|
|
if (pCmap)
|
|
{
|
|
if( pifi->fsSelection & 0xff00 )
|
|
{
|
|
// backward compatability. If a value exists here then this is a
|
|
// Win 3.1 foreign font.
|
|
|
|
cs = (BYTE)((pifi->fsSelection >> 8) & 0xff) ;
|
|
switch (cs)
|
|
{
|
|
case 0xB2:
|
|
case 0xB3:
|
|
case 0xB4:
|
|
#ifdef WINDOWS_ME
|
|
aCharSets[iCS++] = 0xB2;
|
|
aCharSets[iCS++] = 1; // end of charsets
|
|
aCharSets[iCS++] = 0x00; // WRONG unicode locations
|
|
aCharSets[iCS++] = cs; // in the font!
|
|
cs = 1;
|
|
#else
|
|
cs = SYMBOL_CHARSET;
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
aCharSets[iCS++] = cs;
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
// ANSI_FIX
|
|
// ANSI_FIX
|
|
//
|
|
// for now, we always assume an ANSI charset if we are not sure.
|
|
//
|
|
// This will have to change later. The non-ANSI markets have fonts
|
|
// which have no ANSI so this would be wrong.
|
|
//
|
|
if (pff->pComputeIndexProc( pCmap, 0xd0, NULL ))
|
|
// ANSI_FIX
|
|
// ANSI_FIX
|
|
#endif
|
|
aCharSets[iCS++] = ANSI_CHARSET; // 0
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x2206, NULL ))
|
|
aCharSets[iCS++] = 0x4d; // MAC_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x03cb, NULL ))
|
|
aCharSets[iCS++] = 0xA1 ; // GREEK_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x0130, NULL ))
|
|
aCharSets[iCS++] = 0xA2 ; // TURKISH_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x05d0, NULL ))
|
|
aCharSets[iCS++] = 0xB1 ; // TURKISH_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x0451, NULL ))
|
|
aCharSets[iCS++] = 0xcc ; // RUSSIAN_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x0148, NULL ))
|
|
aCharSets[iCS++] = 0xee; // EE_CHARSET
|
|
|
|
if (pff->pComputeIndexProc( pCmap, 0x2592, NULL ))
|
|
aCharSets[iCS++] = OEM_CHARSET; // ff
|
|
}
|
|
}
|
|
}
|
|
#if defined(WINDOWS_ME)
|
|
else if( (pifi->giFirstChar >= 0xf000) && (pifi->fsSelection & 0xff00))
|
|
{
|
|
// its a 3.1 oldstyle font. For some reason best known to
|
|
// themselves they decided to put all the fonts in the symbol area and
|
|
// to ignore unicode.
|
|
//
|
|
// HACK! As we know that GDI16 never looks beyond the DEFAULT_CHARSET
|
|
// flag we shove at the end, and we know that there are 14 spare locations
|
|
// in the array, we will use these to store the symbol location where
|
|
// the font is loaded from. This is a hardcoded value taken from
|
|
// win3.1/Heb/ara/far
|
|
//
|
|
// this isn't the cleanest way to do this, but this affects nothing else
|
|
// in the system so there is no core affected code and it's fast for the
|
|
// LPK. (This is good cause then Chico apps aren't dragged down by bogus
|
|
// 3.1 stuff).
|
|
|
|
switch ((BYTE)((pifi->fsSelection >> 8) & 0xff))
|
|
{
|
|
case 0xB1 :
|
|
case 0xB5 :
|
|
aCharSets[iCS++] = 0xB1;
|
|
aCharSets[iCS++] = 1;
|
|
aCharSets[iCS++] = 0x00;
|
|
aCharSets[iCS++] = 0xf0;
|
|
break;
|
|
|
|
case 0xB2 :
|
|
case 0xB3 :
|
|
case 0xB4 :
|
|
aCharSets[iCS++] = 0xB2 ;
|
|
aCharSets[iCS++] = 1;
|
|
aCharSets[iCS++] = 0x00;
|
|
if ((BYTE)((pifi->fsSelection >> 8) & 0xff) == 0xB3)
|
|
aCharSets[iCS++] = 0xf2;
|
|
else
|
|
aCharSets[iCS++] = 0xf1;
|
|
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
aCharSets[iCS++] = SYMBOL_CHARSET;
|
|
}
|
|
|
|
if (bDBCSFont && (iCS < 16))
|
|
{
|
|
aCharSets[iCS++] = FEOEM_CHARSET;
|
|
}
|
|
|
|
// Terminate with all DEFAULT_...
|
|
|
|
while ( iCS < 16 )
|
|
aCharSets[iCS++] = DEFAULT_CHARSET;
|
|
|
|
|
|
#ifdef DEBUG
|
|
if( aCharSets[0] == DEFAULT_CHARSET )
|
|
{
|
|
eprintf( "FillIFICharSets: no charsets detected in %s, forcing ANSI!\n", pff->szFileName );
|
|
aCharSets[0] = ANSI_CHARSET;
|
|
}
|
|
#endif
|
|
|
|
}
|