Leaked source code of windows server 2003
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

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