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

789 lines
20 KiB

/******************************Module*Header*******************************\
* Module Name: fontfile.c *
* *
* "Methods" for operating on FONTCONTEXT and FONTFILE objects *
* *
* Created: 18-Nov-1990 15:23:10 *
* Author: Bodin Dresevic [BodinD] *
* *
* Copyright (c) 1993 Microsoft Corporation *
\**************************************************************************/
#include "fd.h"
#include "fdsem.h"
// these are truly globaly defined structures
GLYPHSET_MAC_ROMAN gumcr;
STATIC VOID vInitGlyphset
(
PFD_GLYPHSET pgset,
PWCRANGE pwcrg,
ULONG cwcrg
);
PFD_GLYPHSET gpgsetCurrentCP = NULL; // current code page
PFD_GLYPHSET gpgsetSymbolCP = NULL; // current code page + symbol area
#define C_ANSI_CHAR_MAX 256
HSEMAPHORE ghsemTTFD;
// The driver function table with all function index/address pairs
DRVFN gadrvfnTTFD[] =
{
{ INDEX_DrvEnablePDEV, (PFN) ttfdEnablePDEV, },
{ INDEX_DrvDisablePDEV, (PFN) ttfdDisablePDEV, },
{ INDEX_DrvCompletePDEV, (PFN) ttfdCompletePDEV, },
{ INDEX_DrvQueryFont, (PFN) ttfdQueryFont },
{ INDEX_DrvQueryFontTree, (PFN) ttfdQueryFontTree },
{ INDEX_DrvQueryFontData, (PFN) ttfdSemQueryFontData },
{ INDEX_DrvDestroyFont, (PFN) ttfdSemDestroyFont },
{ INDEX_DrvQueryFontCaps, (PFN) ttfdQueryFontCaps },
{ INDEX_DrvLoadFontFile, (PFN) ttfdSemLoadFontFile },
{ INDEX_DrvUnloadFontFile, (PFN) ttfdSemUnloadFontFile },
{ INDEX_DrvQueryFontFile, (PFN) ttfdQueryFontFile },
{ INDEX_DrvQueryAdvanceWidths, (PFN) ttfdSemQueryAdvanceWidths },
{ INDEX_DrvFree, (PFN) ttfdSemFree },
{ INDEX_DrvQueryTrueTypeTable, (PFN) ttfdSemQueryTrueTypeTable },
{ INDEX_DrvQueryTrueTypeOutline, (PFN) ttfdSemQueryTrueTypeOutline},
{ INDEX_DrvGetTrueTypeFile, (PFN) ttfdGetTrueTypeFile }
};
/******************************Public*Routine******************************\
* ttfdEnableDriver
*
* Enables the driver by retrieving the drivers function table and version.
*
* Sun 25-Apr-1993 -by- Patrick Haluptzok [patrickh]
* Change to be same as DDI Enable.
*
* History:
* 12-Dec-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL ttfdEnableDriver(
ULONG iEngineVersion,
ULONG cj,
PDRVENABLEDATA pded)
{
WCHAR awc[C_ANSI_CHAR_MAX];
BYTE aj[C_ANSI_CHAR_MAX];
INT cRuns;
ULONG cjCurrentCP, cjSymbolCP;
// Engine Version is passed down so future drivers can support previous
// engine versions. A next generation driver can support both the old
// and new engine conventions if told what version of engine it is
// working with. For the first version the driver does nothing with it.
iEngineVersion;
if ((ghsemTTFD = EngCreateSemaphore()) == (HSEMAPHORE) 0)
{
return(FALSE);
}
pded->pdrvfn = gadrvfnTTFD;
pded->c = sizeof(gadrvfnTTFD) / sizeof(DRVFN);
pded->iDriverVersion = DDI_DRIVER_VERSION;
// gpgsetCurrentCP contains the unicode runs for the current ansi code page
// It is going to be used for fonts with PlatformID for Mac, but for which
// we have determined that we are going to cheat and pretend that the code
// page is NOT mac but windows code page. Those are the fonts identified
// by bCvtUnToMac = FALSE
cRuns = cUnicodeRangesSupported(
0, // cp, not supported yet, uses current code page
0, // iFirst,
C_ANSI_CHAR_MAX, // cChar, <--> iLast == 255
awc, // out buffer with sorted array of unicode glyphs
aj // coressponding ansi values
);
// allocate memory for the glyphset corresponding to this code page
cjCurrentCP = SZ_GLYPHSET(cRuns,C_ANSI_CHAR_MAX);
// for symbol fonts we report both the current code page plus
// the range 0xf000-0xf0ff.
cjSymbolCP = SZ_GLYPHSET(cRuns + 1, 2 * C_ANSI_CHAR_MAX);
gpgsetCurrentCP = (FD_GLYPHSET *)PV_ALLOC(cjCurrentCP + cjSymbolCP);
if (gpgsetCurrentCP == NULL)
{
EngDeleteSemaphore(ghsemTTFD);
RETURN("TTFD!_out of mem at init time\n", FD_ERROR);
}
cComputeGlyphSet (
awc, // input buffer with a sorted array of cChar supported WCHAR's
aj,
C_ANSI_CHAR_MAX, // cChar
cRuns, // if nonzero, the same as return value
gpgsetCurrentCP // output buffer to be filled with cRanges runs
);
//!!! add one more char to wcrun[0] for the default glyph!!!
#ifdef DBG_GLYPHSET
{
int i,j;
for (i = 0; i < C_ANSI_CHAR_MAX; i += 16)
{
for (j = 0; j < 16; j++)
TtfdDbgPrint("0x%x,", awc[i+j]);
TtfdDbgPrint("\n");
}
}
vDbgGlyphset(gpgsetCurrentCP);
#endif // DBG_GLYPHSET
// symbol cp is allocated from the same chunck
// of memory as the gpgsetCurrentCP.
gpgsetSymbolCP = (PFD_GLYPHSET)((BYTE*)gpgsetCurrentCP + cjCurrentCP);
// now use gpgsetCurrentCP to manufacture symbol character set:
gpgsetSymbolCP->cjThis = cjSymbolCP;
gpgsetSymbolCP->flAccel = gpgsetCurrentCP->flAccel;
gpgsetSymbolCP->cGlyphsSupported = 2 * C_ANSI_CHAR_MAX;
gpgsetSymbolCP->cRuns = cRuns + 1;
{
INT iRun, ihg;
HGLYPH *phgS, *phgD;
phgD = (HGLYPH *)&gpgsetSymbolCP->awcrun[cRuns+1];
for
(
iRun = 0;
(iRun < cRuns) && (gpgsetCurrentCP->awcrun[iRun].wcLow < 0xf000);
iRun++
)
{
gpgsetSymbolCP->awcrun[iRun].wcLow =
gpgsetCurrentCP->awcrun[iRun].wcLow;
gpgsetSymbolCP->awcrun[iRun].cGlyphs =
gpgsetCurrentCP->awcrun[iRun].cGlyphs;
gpgsetSymbolCP->awcrun[iRun].phg = phgD;
RtlCopyMemory(
phgD,
gpgsetCurrentCP->awcrun[iRun].phg,
sizeof(HGLYPH) * gpgsetCurrentCP->awcrun[iRun].cGlyphs
);
phgD += gpgsetCurrentCP->awcrun[iRun].cGlyphs;
}
// now insert the user defined area:
gpgsetSymbolCP->awcrun[iRun].wcLow = 0xf000;
gpgsetSymbolCP->awcrun[iRun].cGlyphs = C_ANSI_CHAR_MAX;
gpgsetSymbolCP->awcrun[iRun].phg = phgD;
for (ihg = 0; ihg < C_ANSI_CHAR_MAX; ihg++)
*phgD++ = ihg;
// and now add the remaining ranges if any from the current code page:
for ( ; iRun < cRuns; iRun++)
{
gpgsetSymbolCP->awcrun[iRun+1].wcLow =
gpgsetCurrentCP->awcrun[iRun].wcLow;
gpgsetSymbolCP->awcrun[iRun+1].cGlyphs =
gpgsetCurrentCP->awcrun[iRun].cGlyphs;
gpgsetSymbolCP->awcrun[iRun+1].phg = phgD;
RtlCopyMemory(
phgD,
gpgsetCurrentCP->awcrun[iRun].phg,
sizeof(HGLYPH) * gpgsetCurrentCP->awcrun[iRun].cGlyphs
);
phgD += gpgsetCurrentCP->awcrun[iRun].cGlyphs;
}
}
// make sure that we have correctly defined C_RUNS_XXXX
// which is necessary in order to be able to define GLYPHSET unions
// correctly
ASSERTDD(sizeof(gawcrgMacRoman)/sizeof(gawcrgMacRoman[0]) == C_RUNS_MAC_ROMAN,
"C_RUNS_MAC_ROMAN\n");
// init global glyphset structures:
vInitGlyphset(& gumcr.gset, gawcrgMacRoman, C_RUNS_MAC_ROMAN);
return(TRUE);
}
/******************************Public*Routine******************************\
* DHPDEV DrvEnablePDEV
*
* Initializes a bunch of fields for GDI
*
\**************************************************************************/
DHPDEV
ttfdEnablePDEV(
DEVMODEW* pdm,
PWSTR pwszLogAddr,
ULONG cPat,
HSURF* phsurfPatterns,
ULONG cjCaps,
ULONG* pdevcaps,
ULONG cjDevInfo,
DEVINFO* pdi,
HDEV hdev,
PWSTR pwszDeviceName,
HANDLE hDriver)
{
PVOID* ppdev;
//
// Allocate a four byte PDEV for now
// We can grow it if we ever need to put information in it.
//
ppdev = (PVOID*) EngAllocMem(0, sizeof(PVOID), 'dftT');
return ((DHPDEV) ppdev);
}
/******************************Public*Routine******************************\
* DrvDisablePDEV
*
* Release the resources allocated in DrvEnablePDEV. If a surface has been
* enabled DrvDisableSurface will have already been called.
*
\**************************************************************************/
VOID
ttfdDisablePDEV(
DHPDEV dhpdev)
{
EngFreeMem(dhpdev);
}
/******************************Public*Routine******************************\
* VOID DrvCompletePDEV
*
* Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
*
\**************************************************************************/
VOID
ttfdCompletePDEV(
DHPDEV dhpdev,
HDEV hdev)
{
return;
}
/******************************Public*Routine******************************\
*
* VOID vInitGlyphState(PGLYPHSTAT pgstat)
*
* Effects: resets the state of the new glyph
*
* History:
* 22-Nov-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID vInitGlyphState(PGLYPHSTATUS pgstat)
{
pgstat->hgLast = HGLYPH_INVALID;
pgstat->igLast = 0xffffffff;
}
/******************************Public*Routine******************************\
*
* STATIC VOID vInitGlyphset
*
*
* init global glyphset strucutes, given the set of supported ranges
*
* Warnings:
*
* History:
* 24-Jan-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
STATIC VOID vInitGlyphset
(
PFD_GLYPHSET pgset,
PWCRANGE pwcrg,
ULONG cwcrg
)
{
ULONG i;
pgset->cjThis = offsetof(FD_GLYPHSET,awcrun) + cwcrg * sizeof(WCRUN);
pgset->flAccel = GS_UNICODE_HANDLES | GS_16BIT_HANDLES;
pgset->cRuns = cwcrg;
pgset->cGlyphsSupported = 0;
for (i = 0; i < cwcrg; i++)
{
pgset->awcrun[i].wcLow = pwcrg[i].wcLo;
pgset->awcrun[i].cGlyphs = (USHORT)(pwcrg[i].wcHi - pwcrg[i].wcLo + 1);
pgset->awcrun[i].phg = (HGLYPH *)NULL;
pgset->cGlyphsSupported += pgset->awcrun[i].cGlyphs;
}
// will add an extra glyph to awcrun[0] which will be used as default glyph:
pgset->awcrun[0].cGlyphs += 1;
pgset->cGlyphsSupported += 1;
}
#ifdef FE_SB
VOID vMarkFontGone(TTC_FONTFILE *pff, DWORD iExceptionCode)
{
ULONG i;
ASSERTDD(pff, "ttfd!vMarkFontGone, pff\n");
// this font has disappeared, probably net failure or somebody pulled the
// floppy with ttf file out of the floppy drive
if (iExceptionCode == STATUS_IN_PAGE_ERROR) // file disappeared
{
// prevent any further queries about this font:
pff->fl |= FF_EXCEPTION_IN_PAGE_ERROR;
for( i = 0; i < pff->ulNumEntry ; i++ )
{
PFONTFILE pffReal;
// get real pff.
pffReal = PFF(pff->ahffEntry[i].hff);
// if memoryBases 0,3,4 were allocated free the memory,
// for they are not going to be used any more
if (pffReal->pj034)
{
V_FREE(pffReal->pj034);
pffReal->pj034 = NULL;
}
// if memory for font context was allocated and exception occured
// after allocation but before completion of ttfdOpenFontContext,
// we have to free it:
if (pffReal->pfcToBeFreed)
{
V_FREE(pffReal->pfcToBeFreed);
pffReal->pfcToBeFreed = NULL;
}
}
}
if (iExceptionCode == STATUS_ACCESS_VIOLATION)
{
RIP("TTFD!this is probably a buggy ttf file\n");
}
}
#else
VOID vMarkFontGone(FONTFILE *pff, DWORD iExceptionCode)
{
ASSERTDD(pff, "vMarkFontGone, pff\n");
// this font has disappeared, probably net failure or somebody pulled the
// floppy with ttf file out of the floppy drive
if (iExceptionCode == STATUS_IN_PAGE_ERROR) // file disappeared
{
// prevent any further queries about this font:
pff->fl |= FF_EXCEPTION_IN_PAGE_ERROR;
// if memoryBases 0,3,4 were allocated free the memory,
// for they are not going to be used any more
if (pff->pj034)
{
V_FREE(pff->pj034);
pff->pj034 = NULL;
}
// if memory for font context was allocated and exception occured
// after allocation but before completion of ttfdOpenFontContext,
// we have to free it:
if (pff->pfcToBeFreed)
{
V_FREE(pff->pfcToBeFreed);
pff->pfcToBeFreed = NULL;
}
}
if (iExceptionCode == STATUS_ACCESS_VIOLATION)
{
WARNING("TTFD!this is probably a buggy ttf file\n");
}
}
#endif
/**************************************************************************\
*
* These are semaphore grabbing wrapper functions for TT driver entry
* points that need protection.
*
* Mon 29-Mar-1993 -by- Bodin Dresevic [BodinD]
* update: added try/except wrappers
*
* !!! should we also do some unmap file clean up in case of exception?
* !!! what are the resources to be freed in this case?
* !!! I would think,if av files should be unmapped, if in_page exception
* !!! nothing should be done
*
*
\**************************************************************************/
HFF
ttfdSemLoadFontFile (
ULONG cFiles,
ULONG *piFile,
PVOID *ppvView,
ULONG *pcjView,
ULONG ulLangId
)
{
HFF hff = (HFF)NULL;
ULONG iFile;
PVOID pvView;
ULONG cjView;
if (cFiles != 1)
return hff;
iFile = *piFile;
pvView = *ppvView;
cjView = *pcjView;
EngAcquireSemaphore(ghsemTTFD);
try
{
// BUGBUG The client side has to tell us if it is embedded !
BOOL bRet = FALSE;
//BUGBUG
#ifdef FE_SB
bRet = bLoadFontFile(iFile,
pvView,
cjView,
ulLangId,
&hff
);
#else
bRet = bLoadTTF(iFile,
pvView,
cjView,
0, // just set to 0 actually ignored in non FE_SB build
ulLangId,
&hff
);
#endif
if (!bRet)
{
ASSERTDD(hff == (HFF)NULL, "LoadFontFile, hff not null\n");
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in ttfdLoadFontFile\n");
ASSERTDD(GetExceptionCode() == STATUS_IN_PAGE_ERROR,
"ttfdSemLoadFontFile, strange exception code\n");
if (hff)
{
vFreeFF(hff);
hff = (HFF)NULL;
}
}
EngReleaseSemaphore(ghsemTTFD);
return hff;
}
BOOL
ttfdSemUnloadFontFile (
HFF hff
)
{
BOOL bRet;
EngAcquireSemaphore(ghsemTTFD);
try
{
#ifdef FE_SB
bRet = ttfdUnloadFontFileTTC(hff);
#else
bRet = ttfdUnloadFontFile(hff);
#endif
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in ttfdUnloadFontFile\n");
bRet = FALSE;
}
EngReleaseSemaphore(ghsemTTFD);
return bRet;
}
LONG
ttfdSemQueryFontData (
DHPDEV dhpdev,
FONTOBJ *pfo,
ULONG iMode,
HGLYPH hg,
GLYPHDATA *pgd,
PVOID pv,
ULONG cjSize
)
{
LONG lRet;
dhpdev;
EngAcquireSemaphore(ghsemTTFD);
try
{
lRet = ttfdQueryFontData (
pfo,
iMode,
hg,
pgd,
pv,
cjSize
);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in ttfdQueryFontData\n");
#ifdef FE_SB
vMarkFontGone((TTC_FONTFILE *)pfo->iFile, GetExceptionCode());
#else
vMarkFontGone((FONTFILE *)pfo->iFile, GetExceptionCode());
#endif
lRet = FD_ERROR;
}
EngReleaseSemaphore(ghsemTTFD);
return lRet;
}
VOID
ttfdSemFree (
PVOID pv,
ULONG id
)
{
EngAcquireSemaphore(ghsemTTFD);
ttfdFree (
pv,
id
);
EngReleaseSemaphore(ghsemTTFD);
}
VOID
ttfdSemDestroyFont (
FONTOBJ *pfo
)
{
EngAcquireSemaphore(ghsemTTFD);
ttfdDestroyFont (
pfo
);
EngReleaseSemaphore(ghsemTTFD);
}
LONG
ttfdSemQueryTrueTypeOutline (
DHPDEV dhpdev,
FONTOBJ *pfo,
HGLYPH hglyph,
BOOL bMetricsOnly,
GLYPHDATA *pgldt,
ULONG cjBuf,
TTPOLYGONHEADER *ppoly
)
{
LONG lRet;
dhpdev;
EngAcquireSemaphore(ghsemTTFD);
try
{
lRet = ttfdQueryTrueTypeOutline (
pfo,
hglyph,
bMetricsOnly,
pgldt,
cjBuf,
ppoly
);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in ttfdQueryTrueTypeOutline\n");
#ifdef FE_SB
vMarkFontGone((TTC_FONTFILE *)pfo->iFile, GetExceptionCode());
#else
vMarkFontGone((FONTFILE *)pfo->iFile, GetExceptionCode());
#endif
lRet = FD_ERROR;
}
EngReleaseSemaphore(ghsemTTFD);
return lRet;
}
/******************************Public*Routine******************************\
* BOOL ttfdQueryAdvanceWidths
*
* History:
* 29-Jan-1993 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL ttfdSemQueryAdvanceWidths
(
DHPDEV dhpdev,
FONTOBJ *pfo,
ULONG iMode,
HGLYPH *phg,
LONG *plWidths,
ULONG cGlyphs
)
{
BOOL bRet;
dhpdev;
EngAcquireSemaphore(ghsemTTFD);
try
{
bRet = bQueryAdvanceWidths (
pfo,
iMode,
phg,
plWidths,
cGlyphs
);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in bQueryAdvanceWidths\n");
#ifdef FE_SB
vMarkFontGone((TTC_FONTFILE *)pfo->iFile, GetExceptionCode());
#else
vMarkFontGone((FONTFILE *)pfo->iFile, GetExceptionCode());
#endif
bRet = FD_ERROR; // TRI-BOOL according to chuckwh
}
EngReleaseSemaphore(ghsemTTFD);
return bRet;
}
LONG
ttfdSemQueryTrueTypeTable (
HFF hff,
ULONG ulFont, // always 1 for version 1.0 of tt
ULONG ulTag, // tag identifying the tt table
PTRDIFF dpStart, // offset into the table
ULONG cjBuf, // size of the buffer to retrieve the table into
PBYTE pjBuf // ptr to buffer into which to return the data
)
{
LONG lRet;
EngAcquireSemaphore(ghsemTTFD);
try
{
lRet = ttfdQueryTrueTypeTable (
hff,
ulFont, // always 1 for version 1.0 of tt
ulTag, // tag identifying the tt table
dpStart, // offset into the table
cjBuf, // size of the buffer to retrieve the table into
pjBuf // ptr to buffer into which to return the data
);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
WARNING("TTFD!_ exception in ttfdQueryTrueTypeTable\n");
#ifdef FE_SB
vMarkFontGone((TTC_FONTFILE *)hff, GetExceptionCode());
#else
vMarkFontGone((FONTFILE *)hff, GetExceptionCode());
#endif
lRet = FD_ERROR;
}
EngReleaseSemaphore(ghsemTTFD);
return lRet;
}