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