|
|
/******************************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; }
|