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.
398 lines
11 KiB
398 lines
11 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fdfc.c
|
|
*
|
|
* Various font context functions. Adapted from BodinD's bitmap font driver.
|
|
*
|
|
* Copyright (c) 1990-1995 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "fd.h"
|
|
|
|
#define MIN(A,B) ((A) < (B) ? (A) : (B))
|
|
#define MAX(A,B) ((A) > (B) ? (A) : (B))
|
|
|
|
#if defined(_AMD64_) || defined(_IA64_)
|
|
#define MUL16(ef) {ef *= 16; }
|
|
#define lCvt(ef, l) ((LONG) (ef * l))
|
|
#else
|
|
#define MUL16(ef) {if (ef.lMant != 0) ef.lExp += 4; }
|
|
LONG lCvt(EFLOAT ef,LONG l);
|
|
#endif
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* BOOL bInitXform
|
|
*
|
|
* Initialize the coefficients of the transforms for the given font context.
|
|
* It also transforms and saves various measurements of the font in the
|
|
* context.
|
|
*
|
|
* History:
|
|
* 25-Feb-1992 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL bInitXform(PFONTCONTEXT pfc, XFORMOBJ *pxo)
|
|
{
|
|
// !!! bFloatToFix should be replaced with a compare and a type cast.
|
|
// Dont update the coefficeints in the font context yet since overflows
|
|
// might occur.
|
|
|
|
VECTORFL vtflTmp;
|
|
POINTL ptl;
|
|
XFORML xfm;
|
|
|
|
// Get the transform elements.
|
|
|
|
XFORMOBJ_iGetXform(pxo,&xfm);
|
|
|
|
// Convert elements of the matrix from IEEE float to our EFLOAT.
|
|
|
|
vEToEF(xfm.eM11, &pfc->efM11);
|
|
vEToEF(xfm.eM12, &pfc->efM12);
|
|
vEToEF(xfm.eM21, &pfc->efM21);
|
|
vEToEF(xfm.eM22, &pfc->efM22);
|
|
|
|
// The path we are to construct takes 1/16 pixel per unit. So lets
|
|
// multiply this factor in the transform.
|
|
|
|
MUL16(pfc->efM11)
|
|
MUL16(pfc->efM12)
|
|
MUL16(pfc->efM21)
|
|
MUL16(pfc->efM22)
|
|
|
|
//
|
|
// These are the special cases for which we need to clip bottom and right
|
|
// edges. Below is the lower case letter e all posible 90 rotations and
|
|
// flips.
|
|
//
|
|
//
|
|
// *** *** ** ***** *** *** ***** **
|
|
// * * * * * * * * * * * * * * * * * *
|
|
// ***** ***** * * * * * * ***** ***** * * * * * *
|
|
// * * * * * * * * * * * * * * * * * *
|
|
// *** *** ***** ** *** *** ** *****
|
|
//
|
|
// case 1 case 2 case 6 case 5 case 3 case 4 case 7 case 8
|
|
//
|
|
//
|
|
|
|
|
|
if (bIsZero(pfc->efM12) && bIsZero(pfc->efM21))
|
|
{
|
|
pfc->flags |= FC_SCALE_ONLY;
|
|
if (!bPositive(pfc->efM11))
|
|
pfc->flags |= FC_X_INVERT;
|
|
|
|
if( bPositive(pfc->efM11 ) )
|
|
{
|
|
pfc->flags |= (bPositive(pfc->efM22)) ? FC_ORIENT_1 : FC_ORIENT_2;
|
|
}
|
|
else
|
|
{
|
|
pfc->flags |= (bPositive(pfc->efM22)) ? FC_ORIENT_4 : FC_ORIENT_3;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if( bIsZero(pfc->efM22) && bIsZero(pfc->efM11) )
|
|
{
|
|
|
|
if( bPositive(pfc->efM21 ) )
|
|
{
|
|
pfc->flags |= (bPositive(pfc->efM12)) ? FC_ORIENT_5 : FC_ORIENT_6;
|
|
}
|
|
else
|
|
{
|
|
pfc->flags |= (bPositive(pfc->efM12)) ? FC_ORIENT_7 : FC_ORIENT_8;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Transform the base and the side vectors. Should never overflow.
|
|
|
|
ptl.x = 1;
|
|
ptl.y = 0;
|
|
|
|
bXformUnitVector(&ptl,
|
|
&xfm,
|
|
&pfc->vtflBase,
|
|
&pfc->pteUnitBase,
|
|
(pfc->flags & FC_SIM_EMBOLDEN) ? &pfc->ptqUnitBase : NULL,
|
|
&pfc->efBase);
|
|
|
|
pfc->fxEmbolden = 0;
|
|
|
|
if (pfc->flags & FC_SIM_EMBOLDEN)
|
|
{
|
|
// emboldening shift for vector fonts in not always one with vector fonts
|
|
// It is computed as 1 * efBase. This is win31 compatible way of doing this
|
|
|
|
pfc->fxEmbolden = ((lCvt(pfc->efBase, 1) + 8) & 0xfffffff0);
|
|
if (pfc->fxEmbolden < 24)
|
|
{
|
|
// primitive "hinting", do not let it become zero
|
|
|
|
pfc->fxEmbolden = 16;
|
|
pfc->pfxBaseOffset.x = FXTOL(pfc->ptqUnitBase.x.HighPart + 8);
|
|
pfc->pfxBaseOffset.y = FXTOL(pfc->ptqUnitBase.y.HighPart + 8);
|
|
|
|
// resolve mult of 45 degrees situations:
|
|
|
|
if ((pfc->pfxBaseOffset.x == pfc->pfxBaseOffset.y) ||
|
|
(pfc->pfxBaseOffset.x == -pfc->pfxBaseOffset.y) )
|
|
{
|
|
pfc->pfxBaseOffset.y = 0;
|
|
}
|
|
|
|
pfc->pfxBaseOffset.x = LTOFX(pfc->pfxBaseOffset.x);
|
|
pfc->pfxBaseOffset.y = LTOFX(pfc->pfxBaseOffset.y);
|
|
|
|
ASSERTDD(pfc->pfxBaseOffset.x || pfc->pfxBaseOffset.y, "x zero and y zero\n");
|
|
ASSERTDD((pfc->pfxBaseOffset.x && pfc->pfxBaseOffset.y) == 0, "x * y not zero\n");
|
|
}
|
|
else
|
|
{
|
|
pfc->pfxBaseOffset.x = lCvt(pfc->vtflBase.x, 1);
|
|
pfc->pfxBaseOffset.y = lCvt(pfc->vtflBase.y, 1);
|
|
}
|
|
}
|
|
|
|
// Transform the side vector.
|
|
|
|
ptl.x = 0;
|
|
ptl.y = -1;
|
|
|
|
bXformUnitVector(&ptl, &xfm, &vtflTmp,
|
|
&pfc->pteUnitSide, NULL, &pfc->efSide);
|
|
|
|
pfc->fxInkTop = fxLTimesEf(&pfc->efSide, pfc->pifi->fwdWinAscender);
|
|
pfc->fxInkBottom = -fxLTimesEf(&pfc->efSide, pfc->pifi->fwdWinDescender);
|
|
|
|
pfc->fxItalic = 0;
|
|
if (pfc->flags & FC_SIM_ITALICIZE)
|
|
{
|
|
pfc->fxItalic
|
|
= (fxLTimesEf(
|
|
&pfc->efBase,
|
|
(pfc->pifi->fwdWinAscender + pfc->pifi->fwdWinDescender + 1)/2
|
|
) + 8) & 0xfffffff0 ;
|
|
}
|
|
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* HFC vtfdOpenFontContext
|
|
*
|
|
* Open a font context. Store font transform and other requests for
|
|
* the realization of this font.
|
|
*
|
|
* History:
|
|
* 27-Feb-1992 -by- Wendy Wu [wendywu]
|
|
* Adapted from bmfd.
|
|
\**************************************************************************/
|
|
|
|
HFC vtfdOpenFontContext(FONTOBJ *pfo)
|
|
{
|
|
PFONTFILE pff = (PFONTFILE)pfo->iFile;
|
|
PFONTCONTEXT pfc;
|
|
BYTE *pjView;
|
|
DWORD dwFirstCharOffset;
|
|
|
|
#ifdef DEBUGSIM
|
|
DbgPrint("vtfdOpenFontContext, ulFont = %ld\n", ulFont);
|
|
#endif // DEBUGSIM
|
|
|
|
if (pff == (PFONTFILE) NULL)
|
|
return(HFC_INVALID);
|
|
|
|
// iFace is 1 based:
|
|
|
|
if ((pfo->iFace < 1L) || (pfo->iFace > pff->cFace)) // pfo->iFace values are 1 based
|
|
return(HFC_INVALID);
|
|
|
|
// increase the reference count of the font file, WE DO THIS ONLY WHEN
|
|
// WE ARE SURE that can not fail any more
|
|
|
|
// need to grab a sem for we will be looking into cRef now.
|
|
|
|
if (pff->cRef == 0)
|
|
{
|
|
// need to remap the file into the memory again and update pointers:
|
|
|
|
UINT i;
|
|
|
|
if (!EngMapFontFileFD(pff->iFile,(PULONG*)&pff->pvView, &pff->cjView))
|
|
{
|
|
WARNING("somebody removed the file\n");
|
|
return (HFC_INVALID);
|
|
}
|
|
|
|
for (i = 0; i < pff->cFace; i++)
|
|
{
|
|
pff->afd[i].re.pvResData = (PVOID) (
|
|
(BYTE*)pff->pvView + pff->afd[i].re.dpResData
|
|
);
|
|
}
|
|
}
|
|
|
|
// remember this so that we do not have to read from the file
|
|
// after we allocate the memory for the font context. This simplifies
|
|
// clean up code in case of exception, i.e. disappearing font files.
|
|
|
|
pjView = pff->afd[pfo->iFace-1].re.pvResData;
|
|
dwFirstCharOffset = READ_DWORD(pjView + OFF_BitsOffset);
|
|
|
|
// Allocate memory for the font context.
|
|
|
|
if ((pfc = pfcAlloc()) == (PFONTCONTEXT)NULL)
|
|
{
|
|
if (pff->cRef == 0)
|
|
{
|
|
EngUnmapFontFileFD(pff->iFile);
|
|
}
|
|
return(HFC_INVALID);
|
|
}
|
|
|
|
// we MUST NOT not touch the memory mapped file past this point
|
|
// until the end of the routine. This is important for the
|
|
// proper clean up code in case of exception. [bodind]
|
|
|
|
pfc->pre = &pff->afd[pfo->iFace-1].re;
|
|
pfc->pifi = pff->afd[pfo->iFace-1].pifi;
|
|
|
|
// SET wendywu style flags
|
|
|
|
pfc->flags = 0;
|
|
|
|
if (pfo->flFontType & FO_SIM_BOLD)
|
|
pfc->flags |= FC_SIM_EMBOLDEN;
|
|
|
|
if (pfo->flFontType & FO_SIM_ITALIC)
|
|
pfc->flags |= FC_SIM_ITALICIZE;
|
|
|
|
pfc->dpFirstChar = dwFirstCharOffset;
|
|
|
|
// !!! Vector font file doesn't have the byte filler. Win31 bug?
|
|
|
|
//pfc->ajCharTable = pjView + OFF_jUnused20;
|
|
|
|
// Store the transform matrix.
|
|
|
|
if ( !bInitXform(pfc, FONTOBJ_pxoGetXform(pfo)) )
|
|
{
|
|
WARNING("vtfdOpenFontContext transform out of range\n");
|
|
|
|
if (pff->cRef == 0)
|
|
{
|
|
EngUnmapFontFileFD(pff->iFile);
|
|
}
|
|
vFree(pfc);
|
|
return(HFC_INVALID);
|
|
}
|
|
|
|
// State that the hff passed to this function is the FF selected in
|
|
// this font context.
|
|
|
|
pfc->pff = pff;
|
|
|
|
(pff->cRef)++;
|
|
|
|
return((HFC)pfc);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vtfdDestroyFont
|
|
*
|
|
* Driver can release all resources associated with this font realization
|
|
* (embodied in the FONTOBJ).
|
|
*
|
|
* History:
|
|
* 02-Sep-1992 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vtfdDestroyFont (
|
|
FONTOBJ *pfo
|
|
)
|
|
{
|
|
//
|
|
// For the vector font driver, this is simply closing the font context.
|
|
// We cleverly store the font context handle in the FONTOBJ pvProducer
|
|
// field.
|
|
//
|
|
EngAcquireSemaphore(ghsemVTFD);
|
|
vtfdCloseFontContext((HFC) pfo->pvProducer);
|
|
EngReleaseSemaphore(ghsemVTFD);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL vtfdCloseFontContext
|
|
*
|
|
* Close the font context and update the context link for the associated
|
|
* font file.
|
|
*
|
|
* History:
|
|
* 27-Feb-1992 -by- Wendy Wu [wendywu]
|
|
* Adapted from bmfd.
|
|
\**************************************************************************/
|
|
|
|
BOOL vtfdCloseFontContext(HFC hfc)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (hfc != HFC_INVALID)
|
|
{
|
|
//
|
|
// decrement the reference count for the corresponding FONTFILE
|
|
//
|
|
|
|
if (PFC(hfc)->pff->cRef > 0L)
|
|
{
|
|
(PFC(hfc)->pff->cRef)--;
|
|
|
|
//
|
|
// if this file is going out of use we can close it to save memory
|
|
//
|
|
|
|
if (PFC(hfc)->pff->cRef == 0L)
|
|
{
|
|
// if FF_EXCEPTION_IN_PAGE_ERROR is set
|
|
// and the font type is TYPE_FNT or TYPE_DLL16
|
|
// the font file must have been unmapped in vVtfdMarkFontGone
|
|
|
|
if (!(PFC(hfc)->pff->fl & FF_EXCEPTION_IN_PAGE_ERROR) ||
|
|
!((PFC(hfc)->pff->iType == TYPE_FNT) || (PFC(hfc)->pff->iType == TYPE_DLL16)))
|
|
{
|
|
EngUnmapFontFileFD(PFC(hfc)->pff->iFile);
|
|
}
|
|
PFC(hfc)->pff->fl &= ~FF_EXCEPTION_IN_PAGE_ERROR;
|
|
}
|
|
|
|
//
|
|
// free the memory associated with hfc
|
|
//
|
|
|
|
vFree(PFC(hfc));
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("vtfdCloseFontContext: cRef <= 0\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|