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.
520 lines
19 KiB
520 lines
19 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: lfntobj.cxx
|
|
*
|
|
* Non-inline methods for logical font objects.
|
|
*
|
|
* Created: 30-Oct-1990 09:32:48
|
|
* Author: Gilman Wong [gilmanw]
|
|
*
|
|
* Copyright (c) 1990-1999 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
#include "winsta.h"
|
|
|
|
extern PW32PROCESS gpidSpool;
|
|
|
|
extern "C" USHORT gProtocolType;
|
|
#define IsRemoteConnection() (gProtocolType != PROTOCOL_CONSOLE)
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSetLFONTOwner
|
|
*
|
|
* Set the owner of the LFONT
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
GreSetLFONTOwner(
|
|
HLFONT hlfnt,
|
|
W32PID lPid)
|
|
{
|
|
if (lPid == OBJECT_OWNER_CURRENT)
|
|
{
|
|
lPid = W32GetCurrentPID();
|
|
}
|
|
|
|
return(HmgSetOwner((HOBJ)hlfnt, lPid, LFONT_TYPE));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* LFONTOBJ::LFONTOBJ (HLFONT hlfnt, PDEVOBJ * ppdo)
|
|
*
|
|
* Constructor for a logical font user object.
|
|
*
|
|
* This constructor is a little trickier than most because the handle coming
|
|
* in may reference one of the "aliased" stock fonts. These stock fonts, rather
|
|
* than representing a single "wish list" of attributes, represent a set of
|
|
* such lists. Which member of the set is being referenced is determined by
|
|
* the calling application's default display or PDEV (i.e., we ask the PDEV
|
|
* for the real HLFONT handle).
|
|
*
|
|
* The strategy is the constructor locks the handle passed in and checks the
|
|
* type. If its not an aliased LFONT, then we're done. If it is an aliased
|
|
* font, the aliased HLFONT handle is released and a PDEVOBJ is queried for
|
|
* the appropriate HFLONT handle to lock.
|
|
*
|
|
* History:
|
|
* Thu 23-Sep-1993 -by- Patrick Haluptzok [patrickh]
|
|
* SSS
|
|
*
|
|
* 30-Oct-1990 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
LFONTOBJ::LFONTOBJ (HLFONT hlfnt, PDEVOBJ* ppdo)
|
|
{
|
|
plfnt = (PLFONT) HmgShareLock((HOBJ)hlfnt, LFONT_TYPE);
|
|
|
|
//
|
|
// Check for aliased LFONT.
|
|
//
|
|
|
|
if ((plfnt != NULL) && (plfnt->fl & LF_FLAG_ALIASED))
|
|
{
|
|
HDEV hDev = UserGetHDEV();
|
|
|
|
//
|
|
// This is an aliased font. Save type.
|
|
//
|
|
|
|
LFTYPE lftSave = plfnt->lft;
|
|
|
|
// Release the aliased LFONT.
|
|
|
|
DEC_SHARE_REF_CNT_LAZY_DEL_LOGFONT(plfnt);
|
|
|
|
plfnt = NULL;
|
|
|
|
PDEVOBJ pdo(hDev);
|
|
|
|
if (!ppdo)
|
|
{
|
|
ppdo = &pdo;
|
|
}
|
|
|
|
if (ppdo->bValid())
|
|
{
|
|
//
|
|
// Grab appropriate HLFONT from the PDEV.
|
|
//
|
|
|
|
switch (lftSave)
|
|
{
|
|
|
|
case LF_TYPE_DEVICE_DEFAULT:
|
|
hlfnt = ppdo->hlfntDefault();
|
|
break;
|
|
|
|
case LF_TYPE_ANSI_FIXED:
|
|
hlfnt = ppdo->hlfntAnsiFixed();
|
|
break;
|
|
|
|
case LF_TYPE_ANSI_VARIABLE:
|
|
hlfnt = ppdo->hlfntAnsiVariable();
|
|
break;
|
|
|
|
default:
|
|
RIP("LFONTOBJ has invalid type for aliased font");
|
|
}
|
|
|
|
plfnt = (PLFONT) HmgShareLock((HOBJ)hlfnt, LFONT_TYPE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* LFONTOBJ::ppfeMapFont
|
|
*
|
|
* Note:
|
|
* RFONTOBJ constructor, which is the only function (so far) to call
|
|
* this, grabs the ghsemPublicPFT semaphore prior to calling this to
|
|
* make PFT tree stable before scanning it during mapping.
|
|
*
|
|
* Returns:
|
|
* Handle to a realized font (HRFONT) that is a close or exact match to
|
|
* this logical font. HRFONT_INVALID returned if an error occurs.
|
|
*
|
|
* History:
|
|
* 24-Sept-1996 -by- Xudong Wu [TessieW]
|
|
* If a suitable pfe found in map cache, we still need to check whether the
|
|
* current process has the right to map the font.
|
|
*
|
|
* 11-Dec-1990 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PFE *LFONTOBJ::ppfeMapFont (
|
|
XDCOBJ& dco,
|
|
FLONG *pflSim,
|
|
POINTL *pptlSim,
|
|
FLONG *pflAboutMatch,
|
|
BOOL bIndexFont
|
|
)
|
|
{
|
|
int i; // index into mapcache array
|
|
MAPCACHE* mapcache = plfnt->mapcache;
|
|
PFE* ppfe = PPFENULL; // return value
|
|
MATRIX& matrix = dco.pdc->mxWorldToDevice();
|
|
HDEV hdev = dco.hdev();
|
|
ULONG iBitmapFormat = 0; // important in anti-aliased case
|
|
FLONG flGray = 0;
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_PPFEMAPFONT)
|
|
{
|
|
KdPrint(("Font Mapping: \"%ws\" hlfnt = %p hdc = %p\n",plfnt->wcCapFacename, hlfnt(),dco.hdc()));
|
|
KdBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
|
|
// If we are in a path bracket, we never look in the map cache (the mapping
|
|
// is also never put in the cache). We'll just run the font mapper. We
|
|
// could cache path bracketed font mappings, but we would have to add a flag
|
|
// or type to the MAPCACHE structure and add an extra comparison inside the
|
|
// mapcache scanning loop. Since we currently consider text in paths to be
|
|
// the exception rather than the rule, we have decided not eat the cost of
|
|
// of the extra compare in the pathological case rather than in the common
|
|
// case.
|
|
|
|
if (!dco.pdc->bActive())
|
|
{
|
|
// If anitaliasing is requested and possible then set FO_GRAY16 in flGray
|
|
|
|
BYTE jQual = plfw()->lfQuality;
|
|
if (dco.bDisplay() || dco.dctp() == DCTYPE_MEMORY)
|
|
{
|
|
if
|
|
(
|
|
((gulFontInformation & FE_AA_ON) && jQual != NONANTIALIASED_QUALITY) ||
|
|
(jQual == ANTIALIASED_QUALITY) || (jQual == CLEARTYPE_QUALITY) || (jQual == CLEARTYPE_NATURAL_QUALITY)
|
|
)
|
|
{
|
|
// WINBUG 152724 07/31/2000 claudebe
|
|
// Terminal server now allow more than 256 colors. Text antialiazing rendered on the server is very slow.
|
|
// We decided for Whistler to turn off text antialiazing under terminal client session.
|
|
// For Blackcomb we will provide the terminal server team with a text antialiazing library that they can use on the // client to generate text antialiazing on the client.
|
|
|
|
if (!IsRemoteConnection() && (dco.pdc->bHasSurface()))
|
|
{
|
|
// Acquire the handle manager lock while we look at the
|
|
// surface to protect against dynamic mode changing.
|
|
|
|
MLOCKFAST mo;
|
|
|
|
switch ( iBitmapFormat = dco.pdc->pSurface()->so.iBitmapFormat )
|
|
{
|
|
case BMF_16BPP:
|
|
case BMF_24BPP:
|
|
case BMF_32BPP:
|
|
|
|
flGray = FO_GRAY16; // request antialiased font
|
|
if ( jQual == CLEARTYPE_NATURAL_QUALITY )
|
|
flGray |= FO_CLEARTYPENATURAL_X | FO_CLEARTYPE_X;
|
|
else if ((jQual == CLEARTYPE_QUALITY) || (gulFontInformation & FE_CT_ON))
|
|
flGray |= FO_CLEARTYPE_X;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Scan the map cache for a suitable mapping.
|
|
// Skip the cache if it is glyph index.
|
|
|
|
if (!bIndexFont)
|
|
{
|
|
for ( i = 0; i < plfnt->cMapsInCache; i += 1)
|
|
{
|
|
// For a mapping to be suitable, the device must match AND
|
|
// the transforms (neglecting translation) must match.
|
|
// There are more restrictions for antialiased text (see below)
|
|
|
|
if ( (hdev == mapcache[i].hdev) &&
|
|
(mapcache[i].efM11 == matrix.efM11) &&
|
|
(mapcache[i].efM12 == matrix.efM12) &&
|
|
(mapcache[i].efM21 == matrix.efM21) &&
|
|
(mapcache[i].efM22 == matrix.efM22)
|
|
)
|
|
{
|
|
// We found it. Check that it's still valid.
|
|
|
|
HPFECOBJ pfecobj(mapcache[i].hpfec);
|
|
PFEOBJ pfeo(pfecobj.GetPFE(mapcache[i].iFont));
|
|
if ( !pfeo.bValid() )
|
|
{
|
|
WARNING1("Invalid ppfe in mapping cache\n");
|
|
}
|
|
else
|
|
{
|
|
// The cached notional to device transform is unchanged.
|
|
// The cached mapping is good if:
|
|
//
|
|
//
|
|
// A. the application is requesting antialiased text and
|
|
// the cached text was also requested to be antialiased
|
|
// Moreover, in the antialiased case, the bitmap format
|
|
// must be the same.
|
|
|
|
// or
|
|
//
|
|
// B. the application is not requesting antialiasing
|
|
// and the cached text was not requested to be antialiased
|
|
|
|
// Need to check whether the current process has the right
|
|
// to mapping the font.
|
|
|
|
if (pfeo.bEmbPvtOk() || (gpidSpool == (PW32PROCESS)W32GetCurrentProcess()))
|
|
{
|
|
if ( flGray ) // requesting antialiased text?
|
|
{ // yes
|
|
if ((mapcache[i].flSim & (FO_GRAY16 | FO_CLEARTYPE_X)) == flGray)
|
|
{ // yes
|
|
if (iBitmapFormat == mapcache[i].iBitmapFormat) // same format?
|
|
{ // yes
|
|
ppfe = pfeo.ppfeGet(); // cached mapping is good
|
|
}
|
|
}
|
|
}
|
|
else if ( !(mapcache[i].flSim & FO_GRAY16) )
|
|
{
|
|
ppfe = pfeo.ppfeGet();
|
|
}
|
|
}
|
|
}
|
|
if ( ppfe ) // cached mapping good?
|
|
{ // yes -- update simulation flags
|
|
*pflSim = mapcache[i].flSim;
|
|
pptlSim->x = mapcache[i].ptlSim.x;
|
|
pptlSim->y = mapcache[i].ptlSim.y;
|
|
*pflAboutMatch = mapcache[i].flAboutMatch;
|
|
break;
|
|
}
|
|
else
|
|
{ // cached mapping is not good
|
|
// Remove the mapping so we don't run into it again.
|
|
|
|
if ( (i+1) < plfnt->cMapsInCache )
|
|
{
|
|
RtlMoveMemory
|
|
(
|
|
(PVOID) &mapcache[i],
|
|
(PVOID) &mapcache[i+1],
|
|
(UINT) (((PBYTE) &mapcache[plfnt->cMapsInCache]) - ((PBYTE) &mapcache[i+1]))
|
|
);
|
|
}
|
|
|
|
plfnt->cMapsInCache -= 1; // correct the map count
|
|
|
|
// current position is no longer a rejected candidate,
|
|
// so go back one index
|
|
|
|
i -= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( !ppfe )
|
|
{
|
|
// Call the font mapper with the Win 3.1 compatible weighting and max
|
|
// penalties. If the LOGFONT is a stock object, transforms are ignored
|
|
// (i.e., the LOGFONT is implied to be in pixel coordinates (MM_TEXT)).
|
|
//
|
|
// The result is stuffed into the map cache if we are not in a
|
|
// path bracket.
|
|
//
|
|
// Note. ppfeGetAMatch() modifies sets FO_SIM_BOLD and FO_SIM_ITALIC
|
|
// in *pflSim as is necessary -- it does not set FO_GRAY16
|
|
// which is set in this routine after this call.
|
|
|
|
ppfe = ppfeGetAMatch(
|
|
dco,
|
|
pelfw(),
|
|
plfnt->wcCapFacename,
|
|
ULONG_MAX-1,
|
|
(plfnt->fl & LF_FLAG_STOCK) ? FM_BIT_PIXEL_COORD : 0,
|
|
pflSim,
|
|
pptlSim,
|
|
pflAboutMatch,
|
|
bIndexFont
|
|
);
|
|
PFEOBJ pfeo(ppfe);
|
|
if ( !pfeo.bValid() )
|
|
{
|
|
RIP("Bad return value from ppfeGetAMatch\n");
|
|
}
|
|
else if (!dco.pdc->bActive())
|
|
{
|
|
ASSERTGDI( !(*pflSim & FO_GRAY16), "ppfeGetAMatch erroneously set FO_GRAY16\n");
|
|
|
|
// If the application is requesting antialiased text and the font is
|
|
// capable then we set the FO_GRAY16 bit in *pflSim. Note that this
|
|
// does not guarantee that the font driver will antialiase the text
|
|
// only that GDI will suggest to the font driver that the font
|
|
// be antialiased.
|
|
|
|
if (flGray && (pfeo.pifi()->flInfo & FM_INFO_4BPP))
|
|
{
|
|
*pflSim |= FO_GRAY16;
|
|
|
|
if
|
|
(
|
|
// (dco.flGraphicsCaps2() & GCAPS2_CLEARTYPE_X) && // commented out only for now
|
|
(dco.bDisplay() || (dco.dctp() == DCTYPE_MEMORY)) &&
|
|
dco.pdc->bHasSurface() &&
|
|
(pfeo.pifi()->flInfo & FM_INFO_TECH_TRUETYPE) && // to be removed if ps fonts start supporting ClearType
|
|
(pelfw()->elfEnumLogfontEx.elfLogFont.lfQuality != ANTIALIASED_QUALITY) &&
|
|
((pelfw()->elfEnumLogfontEx.elfLogFont.lfQuality == CLEARTYPE_QUALITY) ||
|
|
(pelfw()->elfEnumLogfontEx.elfLogFont.lfQuality == CLEARTYPE_NATURAL_QUALITY) ||
|
|
((gulFontInformation & FE_CT_ON) && (gulFontInformation & FE_AA_ON)))
|
|
)
|
|
{
|
|
if(pelfw()->elfEnumLogfontEx.elfLogFont.lfQuality == CLEARTYPE_NATURAL_QUALITY)
|
|
*pflSim |= FO_CLEARTYPENATURAL_X | FO_CLEARTYPE_X;
|
|
else
|
|
*pflSim |= FO_CLEARTYPE_X;
|
|
}
|
|
}
|
|
|
|
// Not in cache, so do the map and put it in the cache
|
|
// if it is not glyph index.
|
|
|
|
if (!bIndexFont)
|
|
{
|
|
// Check to see if we are past the max. number of cached mappings.
|
|
// If the limit is exceeded, flush the cache by resetting the
|
|
// the count.
|
|
|
|
if (i >= MAXCACHEENTRIES)
|
|
{
|
|
i = plfnt->cMapsInCache = 0;
|
|
}
|
|
|
|
// Update cache information for the new mapping.
|
|
|
|
mapcache[i].hpfec = pfeo.hpfecGet();
|
|
mapcache[i].iFont = pfeo.iFont();
|
|
mapcache[i].hdev = hdev;
|
|
mapcache[i].flSim = *pflSim;
|
|
mapcache[i].ptlSim.x = pptlSim->x;
|
|
mapcache[i].ptlSim.y = pptlSim->y;
|
|
mapcache[i].efM11 = matrix.efM11;
|
|
mapcache[i].efM12 = matrix.efM12;
|
|
mapcache[i].efM21 = matrix.efM21;
|
|
mapcache[i].efM22 = matrix.efM22;
|
|
mapcache[i].flAboutMatch = *pflAboutMatch;
|
|
mapcache[i].iBitmapFormat = iBitmapFormat;
|
|
plfnt->cMapsInCache += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if successfull, update the charset and code page info in the dc:
|
|
|
|
if (ppfe)
|
|
{
|
|
// new font mapping may have occurred as a result of w->d xform change,
|
|
// GraphicsMode change. Also when this routine is called from
|
|
// RFONTOBJ::bInit, the new mapping may have occured as a result of
|
|
// asking for pathobj instead of bitmap realization. In other words
|
|
// It is not necessary at this point to have DIRTY_CHARSET bit set,
|
|
// (which only happens when a new logfont is selected in the DC).
|
|
// Any of these factors could cause the change of the font selected
|
|
// in the dc and therefore also of the corresponding CodePage i.e. CharSet.
|
|
|
|
#if 0
|
|
if (!(dco.ulDirty() & DIRTY_CHARSET))
|
|
{
|
|
if (dco.pdc->iCS_CP() != (*pflAboutMatch >> 8))
|
|
{
|
|
DbgPrint("ppfe: 0x%p, iCS_CP: 0x%lx, flAboutMatch: 0x%p\n",
|
|
ppfe, dco.pdc->iCS_CP(), *pflAboutMatch);
|
|
RIP("ppfeMapFont, dco.pdc->iCS_CP is bogus\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef FE_SB
|
|
|
|
// If font association is turned on for this character set then we need
|
|
// to force the code page to ANSI so that ANSI apps can get a the DBCS
|
|
// in the font via ANSI api's. We do this unless the user has set the
|
|
// override bit in the LOGFONT.
|
|
|
|
if(fFontAssocStatus &&
|
|
!(plfw()->lfClipPrecision & CLIP_DFA_DISABLE))
|
|
{
|
|
UINT Charset = (*pflAboutMatch >> 24) & 0xFF;
|
|
|
|
if((Charset == ANSI_CHARSET && fFontAssocStatus & ANSI_ASSOC) ||
|
|
(Charset == OEM_CHARSET && fFontAssocStatus & OEM_ASSOC))
|
|
|
|
// (Charset == OEM_CHARSET && fFontAssocStatus & OEM_ASSOC) ||
|
|
// we might want to keep the codepage as CP_SYMBOL??????
|
|
// (Charset == SYMBOL_CHARSET && fFontAssocStatus & SYMBOL_ASSOC))
|
|
|
|
{
|
|
USHORT AnsiCodePage, OemCodePage;
|
|
RtlGetDefaultCodePage(&AnsiCodePage,&OemCodePage);
|
|
|
|
*pflAboutMatch = (*pflAboutMatch & 0xFF0000FF) | (AnsiCodePage << 8);
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
dco.pdc->iCS_CP(*pflAboutMatch >> 8);
|
|
|
|
// clean the DIRTY_CHARSET bit
|
|
|
|
dco.ulDirtySub(DIRTY_CHARSET);
|
|
}
|
|
|
|
return (ppfe);
|
|
}
|
|
|
|
#if DBG
|
|
/******************************Public*Routine******************************\
|
|
* VOID LFONTOBJ::vDump ()
|
|
*
|
|
* Debugging code.
|
|
*
|
|
* History:
|
|
* 25-Feb-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID LFONTOBJ::vDump ()
|
|
{
|
|
DbgPrint("\nContents of LFONT, HLFONT = 0x%lx\n", hlfnt());
|
|
|
|
if (hlfnt() == STOCKOBJ_SYSFONT)
|
|
DbgPrint("S Y S T E M F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_SYSFIXEDFONT)
|
|
DbgPrint("S Y S T E M F I X E D F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_OEMFIXEDFONT)
|
|
DbgPrint("O E M F I X E D F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_DEFAULTDEVFONT)
|
|
DbgPrint("D E V I C E D E F A U L T F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_ANSIFIXEDFONT)
|
|
DbgPrint("A N S I F I X E D F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_ANSIVARFONT)
|
|
DbgPrint("A N S I V A R I A B L E F O N T \n");
|
|
if (hlfnt() == STOCKOBJ_DEFAULTGUIFONT)
|
|
DbgPrint("D E F A U L T G U I F O N T \n");
|
|
|
|
DbgPrint("LOGFONT \n");
|
|
DbgPrint(" lfHeight = %d\n", plfnt->elfw.elfLogFont.lfHeight);
|
|
DbgPrint(" lfWidth = %d\n", plfnt->elfw.elfLogFont.lfWidth);
|
|
DbgPrint(" lfFaceName = %ws\n", plfnt->elfw.elfLogFont.lfFaceName);
|
|
DbgPrint("\n");
|
|
}
|
|
#endif
|