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.
 
 
 
 
 
 

2276 lines
66 KiB

/*********************************************************************************
* misceudc.cxx
*
* This file contains EUDC specific methods for various GRE object. I am moving
* them to a separate file to make it easier to modify them after checkin freezes.
* Once FE_SB ifdefs are removed we will probably want to move these object back
* to the appropriate xxxobj.cxx files.
*
* 5-1-96 Gerrit van Wingerden [gerritv]
*
* Copyright (c) 1996-1999 Microsoft Corporation
********************************************************************************/
#include "precomp.hxx"
extern HSEMAPHORE ghsemEUDC2;
LONG lNormAngle(LONG lAngle);
/******************************Public*Routine******************************\
* GLYPHDATA *RFONTOBJ::pgdGetEudcMetrics()
*
* 9-29-1993 Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
GLYPHDATA *RFONTOBJ::pgdGetEudcMetrics(WCHAR wc, RFONTOBJ* prfoBase)
{
if (prfnt->wcgp == NULL)
{
if (!bAllocateCache(prfoBase))
{
return(NULL);
}
}
if (prfnt->wcgp->cRuns == 0)
{
WARNING("EUDC -- pgdGetEudcMetrics - empty glyphset\n");
return pgdDefault();
}
GPRUN *pwcRun = prfnt->wcgp->agpRun; // initialize with guess for loop below
GLYPHDATA *wpgd;
// Find the correct run, if any.
// Try the current run first.
UINT swc = (UINT)wc - pwcRun->wcLow;
if ( swc >= pwcRun->cGlyphs )
{
pwcRun = gprunFindRun(wc);
swc = (UINT)wc - pwcRun->wcLow;
if ( swc < pwcRun->cGlyphs )
{
wpgd = pwcRun->apgd[swc];
}
else
{
return(NULL);
}
}
else
{
// Look up entry in current run
// This path should go in line
wpgd = pwcRun->apgd[swc];
}
// check to make sure in cache, insert if needed
if ( wpgd == NULL )
{
// This path should go out of line
if ( !bInsertMetrics(&pwcRun->apgd[swc], wc) )
{
// when insert fails trying to get just metrics, it is a hard
// failure. Get out of here!
WARNING("EUDC -- bGetGlyphMetrics - bInsertMetrics failed\n");
return(NULL);
}
wpgd = pwcRun->apgd[swc];
}
return wpgd;
}
/******************************Public*Routine******************************\
* GLYPHDATA *RFONTOBJ::pgdGetEudcMetricsPlus()
*
*
* 9-29-1993 Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
GLYPHDATA *RFONTOBJ::pgdGetEudcMetricsPlus
(
WCHAR wc,
RFONTOBJ* prfoBase
)
{
if (prfnt->wcgp == NULL)
{
if (!bAllocateCache(prfoBase))
{
return(NULL);
}
}
if (prfnt->wcgp->cRuns == 0)
{
WARNING("EUDC -- pgdGetEudcMetricsPlus - empty glyphset\n");
return pgdDefault();
}
GPRUN *pwcRun = prfnt->wcgp->agpRun; // initialize with guess for loop below
GLYPHDATA *wpgd;
// Find the correct run, if any.
// Try the current run first.
UINT swc = (UINT)wc - pwcRun->wcLow;
if ( swc >= pwcRun->cGlyphs )
{
pwcRun = gprunFindRun(wc);
swc = (UINT)wc - pwcRun->wcLow;
if ( swc < pwcRun->cGlyphs )
{
wpgd = pwcRun->apgd[swc];
}
else
{
return(NULL);
}
}
else
{
// Look up entry in current run
// This path should go in line
wpgd = pwcRun->apgd[swc];
}
// check to make sure in cache, insert if needed
if ( wpgd == NULL )
{
// This path should go out of line
if ( !bInsertMetricsPlus(&pwcRun->apgd[swc], wc) )
{
// when insert fails trying to get just metrics, it is a hard
// failure. Get out of here!
WARNING("EUDC -- bGetGlyphMetricsPlus - bInsertMetrics failed\n");
return(NULL);
}
wpgd = pwcRun->apgd[swc];
}
// Don't bother inserting glyphs since we are going to force the driver to
// enum anyway.
return wpgd;
}
/******************************Public*Routine******************************\
* RFONTOBJ::bCheckEudcFontCaps
*
* History:
* 9-Nov-93 -by- Hideyuki Nagase
* Wrote it.
\**************************************************************************/
BOOL RFONTOBJ::bCheckEudcFontCaps
(
IFIOBJ &ifioEudc
)
{
// Check FontLink configuration.
if( ulFontLinkControl & FLINK_DISABLE_LINK_BY_FONTTYPE )
{
// Fontlink for Device font is disabled ?
if( bDeviceFont() )
{
if( ulFontLinkControl & FLINK_DISABLE_DEVFONT )
{
return(FALSE);
}
}
else
{
// Fontlink for TrueType font is disabled ?
if( (ulFontLinkControl & FLINK_DISABLE_TTFONT) &&
(prfnt->flInfo & FM_INFO_TECH_TRUETYPE ) )
{
return( FALSE );
}
// Fontlink for Vector font is disabled ?
if( (ulFontLinkControl & FLINK_DISABLE_VECTORFONT) &&
(prfnt->flInfo & FM_INFO_TECH_STROKE ) )
{
return( FALSE );
}
// Fontlink for Bitmap font is disabled ?
if( (ulFontLinkControl & FLINK_DISABLE_BITMAPFONT) &&
(prfnt->flInfo & FM_INFO_TECH_BITMAP ) )
{
return( FALSE );
}
}
}
BOOL bRotIs90Degree;
// Can EUDC font do arbitarary tramsforms ?
if( ifioEudc.bArbXforms() )
return( TRUE );
// Can its Orientation degree be divided by 900 ?
bRotIs90Degree = (prfnt->ulOrientation % 900) == 0;
// if the Orientation is 0, 90, 270, 360... and the EUDC font can be
// rotated by 90 degrees, we accept this link.
if( ifioEudc.b90DegreeRotations() && bRotIs90Degree )
return( TRUE );
// if not, we reject this link.
return( FALSE );
}
/******************************Public*Routine******************************\
* IsSingularEudcGlyph
*
* History:
*
* 25-Jul-95 -by- Hideyuki Nagase
* Wrote it.
\**************************************************************************/
BOOL IsSingularEudcGlyph
(
GLYPHDATA *wpgd, BOOL bSimulatedBold
)
{
//
// Determine this is really registerd EUDC glyph or not.
//
// [NT 3.51 code for reference]
//
// if( wpgd->rclInk.left == 0 &&
// wpgd->rclInk.top == 0 &&
// (wpgd->rclInk.right == 0 || wpgd->rclInk.right == 1) &&
// (wpgd->rclInk.bottom == 0 || wpgd->rclInk.bottom == 1)
// )
// return( TRUE );
//
// This glyph does not have advance width, it might be non-registered
// character, then return TRUE to let replace this with EUDC default
// character.
//
// dchinn 5/12/99: The code used to use the bSimulatedBold flag.
// If bSimulatedBold were TRUE and if fxD == 0x10, then we return TRUE.
// That code is no longer needed because ClaudeBe made a change elsewhere
// to leave fxD as 0x00 when doing bold simulation. So, the test below
// is correct whether or not bSimulatedBold is TRUE.
if( wpgd->fxD == 0 ) return( TRUE );
//
// Otherwise, use this glyph.
//
return( FALSE );
}
BOOL RFONTOBJ::bInitSystemTT(XDCOBJ &dco)
{
UINT iPfeOffset = (prfnt->bVertical ? PFE_VERTICAL : PFE_NORMAL);
RFONTOBJ rfo;
EUDCLOGFONT SystemTTLogfont;
ComputeEUDCLogfont(&SystemTTLogfont, dco);
PFE *ppfeSystem = (gappfeSystemDBCS[iPfeOffset] == NULL) ?
gappfeSystemDBCS[PFE_NORMAL] : gappfeSystemDBCS[iPfeOffset];
rfo.vInit(dco,ppfeSystem,&SystemTTLogfont,FALSE );
if( rfo.bValid() )
{
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"vInitSystemTT() -- linking system DBCS font");
prfnt->prfntSystemTT = rfo.prfntFont();
}
return(prfnt->prfntSystemTT != NULL);
}
GLYPHDATA *RFONTOBJ::FindLinkedGlyphDataPlus
(
XDCOBJ *pdco,
ESTROBJ *pto,
WCHAR wc,
COUNT index,
COUNT c,
BOOL *pbAccel,
BOOL bSystemTTSearch,
BOOL bGetBits
)
{
GLYPHDATA *wpgd;
LONG *plPartition = pto ? pto->plPartitionGet() : NULL;
// don't setup system EUDC font if there are remote links
if(!pdco->uNumberOfLinkedUFIs() && bSystemTTSearch && bIsSystemTTGlyph(wc))
{
if(!prfnt->prfntSystemTT)
{
WARNING("Error initializing TT system font 2\n");
return(pgdDefault());
}
if(pto && !(pto->bSystemPartitionInit()))
{
// this call can't fail for the SystemTT case
pto->bPartitionInit(c,0,FALSE);
}
// mark the glyph as coming from a SystemTT font
RFONTTMPOBJ rfo;
rfo.vInit(prfnt->prfntSystemTT);
if(rfo.bValid() &&
(wpgd = bGetBits ? rfo.pgdGetEudcMetricsPlus(wc, this) : rfo.pgdGetEudcMetrics(wc, this)))
{
if (pto)
{
ASSERTGDI(pto->bSystemPartitionInit(),
"FindLinkedGlyphDataPlus: FontLink partition no initialized\n");
pto->vTTSysGlyphsInc();
plPartition[index] = EUDCTYPE_SYSTEM_TT_FONT;
// turn off accelerator since we're going to mess with the driver
*pbAccel = FALSE;
}
return(wpgd);
}
else
{
return(pgdDefault());
}
}
// next search through all the EUDC fonts in order to see if the glyph is one of them
for( UINT uiFont = 0;
uiFont < prfnt->uiNumLinks;
uiFont ++ )
{
RFONTTMPOBJ rfo;
rfo.vInit( prfnt->paprfntFaceName[uiFont] );
if(rfo.bValid())
{
if( (wpgd = bGetBits ? rfo.pgdGetEudcMetricsPlus(wc, this)
: rfo.pgdGetEudcMetrics(wc, this)) != NULL )
{
if( !IsSingularEudcGlyph(wpgd, rfo.pfo()->flFontType & FO_SIM_BOLD) )
{
if (pto)
{
plPartition[index] = EUDCTYPE_FACENAME + uiFont;
pto->vFaceNameInc(uiFont);
// turn off accelerator since we're going to mess with the driver
*pbAccel = FALSE;
}
return( wpgd );
}
}
}
}
// see if the glyph is in the DEFAULT EUDC font
if( prfnt->prfntDefEUDC != NULL )
{
RFONTTMPOBJ rfo( prfnt->prfntDefEUDC );
if (rfo.bValid())
{
wpgd = bGetBits ? rfo.pgdGetEudcMetricsPlus(wc, this)
: rfo.pgdGetEudcMetrics(wc, this);
if( wpgd != NULL )
{
if( !IsSingularEudcGlyph(wpgd, rfo.pfo()->flFontType & FO_SIM_BOLD) )
{
if (pto)
{
// mark this character as an EUDC character
plPartition[index] = EUDCTYPE_DEFAULT;
// increment count of Sys EUDC glyphs
pto->vDefGlyphsInc();
// turn off accelerator since we're going to mess with the driver
*pbAccel = FALSE;
}
return( wpgd );
}
}
}
}
// see if the glyph is in the SYSTEM-WIDE EUDC font
if( prfnt->prfntSysEUDC != NULL )
{
RFONTTMPOBJ rfo( prfnt->prfntSysEUDC );
if (rfo.bValid())
{
wpgd = bGetBits ? rfo.pgdGetEudcMetricsPlus(wc, this)
: rfo.pgdGetEudcMetrics(wc, this);
if( wpgd != NULL )
{
if( !IsSingularEudcGlyph(wpgd, rfo.pfo()->flFontType & FO_SIM_BOLD))
{
if (pto)
{
// mark this character as an EUDC characte and indicate that there
// are EUDC glyphs in the font
plPartition[index] = EUDCTYPE_SYSTEM_WIDE;
pto->vSysGlyphsInc();
// turn off accelerator since we're going to mess with the driver
*pbAccel = FALSE;
}
return( wpgd );
}
}
}
}
return( NULL );
}
/******************************Public*Routine******************************\
* RFONTOBJ::wpgdGetLinkMetricsPlus
*
* If GetGlyphMetricsPlus encounters a default character call off to this
* routine to try and get it from the EUDC and face name linked fonts.
*
* History:
*
* 19-Jan-95 -by- Hideyuki Nagase
* Rewrote it.
*
* 14-Jul-93 -by- Gerrit van Wingerden
* Wrote it.
\**************************************************************************/
GLYPHDATA *RFONTOBJ::wpgdGetLinkMetricsPlus
(
XDCOBJ *pdco,
ESTROBJ *pto,
WCHAR *pwc,
WCHAR *pwcInit,
COUNT c,
BOOL *pbAccel,
BOOL bGetBits
)
{
GLYPHDATA *wpgd;
WCHAR *pwcCurrent = pwc;
WCHAR *pwcEnd = pwcInit + c;
// bLinkingTurnedOff forces linking to be turned off. It will be TRUE
// when we are printing an EMF file that originated on a machine that
// had no fontlinking turned on
if(pdco == NULL ||
pdco->bLinkingTurnedOff() ||
(!gbAnyLinkedFonts && !IS_SYSTEM_EUDC_PRESENT() && (pdco->uNumberOfLinkedUFIs() == 0)))
{
return(pgdDefault());
}
for (; (pwcCurrent < pwcEnd && (*pwcCurrent >= 0x80) && (*pwcCurrent <= 0x9F) ); pwcCurrent+=1)
{
}
if (pwcCurrent == pwcEnd)
{
// all the characters are in the range 0x80 to 0x9F
// we don't want to look through font linking for characters in that range
// this is a performance issue to avoid calling font linking code on English system with
// far east language pack installed
// client side caching is requesting through iGetPublicWidthTable() the width for ANSI codes
// 0x00 to 0xFF, those code are converted to Unicode. Some code in the range 0x80->0x9F
// are not converted and stay in that range causing the linked fonts to be loaded to look for those characters
// Unicode in that range belong to the C1 controls, it doesn't make sense to look for them through
// font linking, see Windows bug 157772.
return(pgdDefault());
}
// always initialize the System TT to avoid a deadlock situation
if (!pdco->uNumberOfLinkedUFIs() && prfnt->bIsSystemFont)
{
if((!prfnt->prfntSystemTT) && !bInitSystemTT(*pdco))
{
WARNING("Error initializing TT system font 4\n");
}
else
{
GreAcquireSemaphore(prfnt->hsemEUDC);
if(!(prfnt->flEUDCState & TT_SYSTEM_INITIALIZED))
{
INCREMENTEUDCCOUNT;
RFONTTMPOBJ rfo(prfnt->prfntSystemTT);
rfo.vGetCache();
prfnt->flEUDCState |= TT_SYSTEM_INITIALIZED;
}
GreReleaseSemaphore(prfnt->hsemEUDC);
}
}
// if this is an SBCS system font and the glyph exists in the DBCS TT system front
// grab it from there
if(!pdco->uNumberOfLinkedUFIs() && bIsSystemTTGlyph(*pwc))
{
if(!prfnt->prfntSystemTT)
{
WARNING("Invalid prfntSystemTT\n");
return(pgdDefault());
}
if(pto && !(pto->bSystemPartitionInit()))
{
// this call can't fail for the SystemTT case
pto->bPartitionInit(c,0,FALSE);
}
// mark the glyph as coming from a SystemTT font
RFONTTMPOBJ rfo;
rfo.vInit(prfnt->prfntSystemTT);
if(rfo.bValid() &&
(wpgd = (bGetBits ? rfo.pgdGetEudcMetricsPlus(*pwc, this)
: rfo.pgdGetEudcMetrics(*pwc, this))))
{
if (pto)
{
ASSERTGDI(pto->bSystemPartitionInit(),
"wpgdGetLinkMetricsPlus: FontLink partition no initialized\n");
LONG *plPartition = pto->plPartitionGet();
pto->vTTSysGlyphsInc();
plPartition[pwc-pwcInit] = EUDCTYPE_SYSTEM_TT_FONT;
// turn off accelerator since we're going to mess with the driver
*pbAccel = FALSE;
}
return(wpgd);
}
else
{
return(pgdDefault());
}
}
// if the codepoint is not in any linked font or the EUDC information is
// being changed just return the default character
if(!pdco->uNumberOfLinkedUFIs() &&!bIsLinkedGlyph( *pwc ))
{
return( pgdDefault() );
}
// initialize EUDC fonts if we haven't done so already
{
GreAcquireSemaphore(prfnt->hsemEUDC);
if( !( prfnt->flEUDCState & EUDC_INITIALIZED ) )
{
// this value will be decremented in RFONTOBJ::dtHelper()
INCREMENTEUDCCOUNT;
FLINKMESSAGE2(DEBUG_FONTLINK_RFONT,
"wpgdGetLinkMetricsPlus():No request to change EUDC data %d\n", gcEUDCCount);
vInitEUDC( *pdco );
// lock the font cache semaphores for any EUDC rfonts linked to this font
if( prfnt->prfntSysEUDC != NULL )
{
// lock the SystemEUDC RFONT cache
RFONTTMPOBJ rfo( prfnt->prfntSysEUDC );
rfo.vGetCache();
}
if( prfnt->prfntDefEUDC != NULL )
{
RFONTTMPOBJ rfo( prfnt->prfntDefEUDC );
rfo.vGetCache();
}
for( UINT ii = 0; ii < prfnt->uiNumLinks; ii++ )
{
if( prfnt->paprfntFaceName[ii] != NULL )
{
RFONTTMPOBJ rfo( prfnt->paprfntFaceName[ii] );
rfo.vGetCache();
}
}
prfnt->flEUDCState |= EUDC_INITIALIZED;
}
GreReleaseSemaphore(prfnt->hsemEUDC);
}
if (pto && !(pto->bPartitionInit()) )
{
// Sets up partitioning pointers and glyph counts in the ESTROBJ.
if( !(pto->bPartitionInit(c,prfnt->uiNumLinks,TRUE)) )
{
return( pgdDefault() );
}
}
// Find linked font GLYPHDATA
wpgd = FindLinkedGlyphDataPlus(
pdco,pto,*pwc,(COUNT)(pwc-pwcInit),c,pbAccel,FALSE, bGetBits);
if( wpgd == NULL )
{
// load EudcDefault Char GlyphData from "Base font".
wpgd = bGetBits ?
pgdGetEudcMetricsPlus(EudcDefaultChar, NULL) :
pgdGetEudcMetrics(EudcDefaultChar, NULL);
if( wpgd != NULL )
{
return( wpgd );
}
// load EudcDefault Char GlyphData from "Linked font".
wpgd = FindLinkedGlyphDataPlus(pdco,pto,EudcDefaultChar,(COUNT)(pwc-pwcInit),c,pbAccel,TRUE, bGetBits);
if( wpgd != NULL )
{
return( wpgd );
}
// Otherwise return default char of base font.
return( pgdDefault() );
}
return( wpgd );
}
/******************************Public*Routine******************************\
* RFONTOBJ::dtHelper()
*
* Thu 12-Jan-1995 15:00:00 -by- Hideyuki Nagase [hideyukn]
* Rewrote it.
**************************************************************************/
VOID RFONTOBJ::dtHelper(BOOL bReleaseEUDC2)
{
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,"Calling dtHelper()\n");
GreAcquireSemaphore(prfnt->hsemEUDC);
// if SystemTT RFONTOBJ was used release it
if((prfnt->flEUDCState & TT_SYSTEM_INITIALIZED) &&
!(prfnt->flEUDCState & EUDC_NO_CACHE))
{
if (prfnt->prfntSystemTT)
{
RFONTTMPOBJ rfo(prfnt->prfntSystemTT);
rfo.vReleaseCache();
DECREMENTEUDCCOUNT;
}
}
// if EUDC was initizlized for this RFONTOBJ, clean up its.
if( prfnt->flEUDCState & EUDC_INITIALIZED )
{
if(!(prfnt->flEUDCState & EUDC_NO_CACHE))
{
for( INT ii = prfnt->uiNumLinks - 1; ii >= 0; ii-- )
{
if( prfnt->paprfntFaceName[ii] != NULL )
{
RFONTTMPOBJ rfo( prfnt->paprfntFaceName[ii] );
rfo.vReleaseCache();
}
}
if( prfnt->prfntDefEUDC != NULL )
{
RFONTTMPOBJ rfo( prfnt->prfntDefEUDC );
rfo.vReleaseCache();
}
if( prfnt->prfntSysEUDC != NULL )
{
RFONTTMPOBJ rfo( prfnt->prfntSysEUDC );
rfo.vReleaseCache();
}
}
if (bReleaseEUDC2)
{
ASSERTGDI(gcEUDCCount > 0, "gcEUDCCount <= 0\n");
DECREMENTEUDCCOUNT;
}
}
prfnt->flEUDCState &= ~(EUDC_INITIALIZED|TT_SYSTEM_INITIALIZED|EUDC_NO_CACHE);
GreReleaseSemaphore(prfnt->hsemEUDC);
}
/******************************************************************************
* void RFONTOBJ::ComputeEUDCLogfont(EUDCLOGFONT*)
*
* This function computes an EUDCLOGFONT from a base font.
*
*****************************************************************************/
void RFONTOBJ::ComputeEUDCLogfont(EUDCLOGFONT *pEudcLogfont, XDCOBJ& dco)
{
PDEVOBJ pdo(dco.hdev());
LFONTOBJ lfo(dco.pdc->hlfntCur(), &pdo);
PFEOBJ pfeo(prfnt->ppfe);
RFONTTMPOBJ rfoT(prfnt);
DCOBJ dcoT(dco.hdc());
IFIOBJR ifio(pfeo.pifi(),rfoT,dcoT);
BOOL bFixedPitch = FALSE;
if (!lfo.bValid())
return;
pEudcLogfont->fsSelection = ifio.fsSelection();
pEudcLogfont->flBaseFontType = pfo()->flFontType;
pEudcLogfont->lBaseHeight = lfo.lHeight();
pEudcLogfont->lBaseWidth = lfo.lWidth();
pEudcLogfont->lEscapement = lfo.lEscapement();
pEudcLogfont->ulOrientation = lfo.ulOrientation();
LONG lInternalLeading = 0;
if(ifio.bFixedPitch())
bFixedPitch = TRUE;
// We have to try to scale linked font as exactly same size as base font.
if( !(pEudcLogfont->bContinuousScaling = ifio.bContinuousScaling()) )
{
if (dco.pdc->bWorldToDeviceIdentity())
{
// We only need to get the AveCharWidth for FIX_PITCH
if (bFixedPitch)
pEudcLogfont->lBaseWidth = ifio.fwdAveCharWidth();
// these are special case hacks to get better linking with Ms San Serif
// we force a bitmap for size 8 and 10 and also use ascent based
// mapping for all other size.
//
// Old comment:
// for NT 5.0 make this more general
// and make it configurable in the registry.
//
if(!_wcsicmp(ifio.pwszFaceName(), L"Ms Sans Serif"))
{
if(fxMaxExtent() > LTOFX(12) && fxMaxExtent() < LTOFX(17))
{
pEudcLogfont->lBaseHeight = 12;
}
else
{
pEudcLogfont->lBaseHeight =
LONG_FLOOR_OF_FIX(fxMaxAscent() + FIX_HALF);
}
}
else
if(ulFontLinkControl & FLINK_SCALE_EUDC_BY_HEIGHT)
{
pEudcLogfont->lBaseHeight = LONG_FLOOR_OF_FIX(fxMaxExtent() + FIX_HALF);
}
else
{
pEudcLogfont->lBaseHeight = LONG_FLOOR_OF_FIX(fxMaxAscent() + FIX_HALF);
}
}
else
{
if (bFixedPitch)
pEudcLogfont->lBaseWidth = lCvt(efDtoWBase_31(),((LONG) ifio.fwdAveCharWidth()) << 4);
if (ulFontLinkControl & FLINK_SCALE_EUDC_BY_HEIGHT)
{
pEudcLogfont->lBaseHeight = lCvt(efDtoWAscent_31(),(LONG) fxMaxExtent());
}
else
{
pEudcLogfont->lBaseHeight = lCvt(efDtoWAscent_31(),(LONG) fxMaxAscent());
}
}
// Multiply raster interger scaling value.
// (Only for Width, Height was already scaled value.)
if (bFixedPitch)
pEudcLogfont->lBaseWidth *= prfnt->ptlSim.x;
FLINKMESSAGE(DEBUG_FONTLINK_DUMP,"GDISRV:BaseFont is RASTER font\n");
}
else
{
LONG lBaseHeight;
if (dco.pdc->bWorldToDeviceIdentity())
{
lBaseHeight = LONG_FLOOR_OF_FIX(fxMaxExtent() + FIX_HALF);
}
else
{
lBaseHeight = lCvt(efDtoWAscent_31(),(LONG) fxMaxExtent());
}
if (lNonLinearIntLeading() == MINLONG)
{
// Rather than scaling the notional internal leading, try
// to get closer to HINTED internal leading by computing it
// as the difference between the HINTED height and UNHINTED
// EmHeight.
lInternalLeading = lBaseHeight - lCvt(efNtoWScaleAscender(),ifio.fwdUnitsPerEm());
if (bFixedPitch)
pEudcLogfont->lBaseWidth = lCvt(efNtoWScaleBaseline(), ifio.tmAveCharWidth());
}
else
{
// But if the font provider has given us a hinted internal leading,
// just use it.
lInternalLeading =
lCvt(efDtoWAscent_31(),lNonLinearIntLeading());
if (bFixedPitch)
pEudcLogfont->lBaseWidth = lCvt(efDtoWBase_31(), lNonLinearAvgCharWidth());
}
// Check we should eliminate the internal leading for EUDC size.
if( lInternalLeading < 0 )
pEudcLogfont->lBaseHeight = lBaseHeight + lInternalLeading;
else
pEudcLogfont->lBaseHeight = lBaseHeight - lInternalLeading;
if ((pEudcLogfont->lBaseHeight <= 13))
{
if (pEudcLogfont->lBaseHeight == 11 && lBaseHeight >= 12)
pEudcLogfont->lBaseHeight = 12;
else if (pEudcLogfont->lBaseHeight == 13 && lBaseHeight >= 15)
pEudcLogfont->lBaseHeight = 15;
}
}
// if the base font is Raster font. we need to adjust escapement/orientation.
// because they can not generate arbitaraty rotated glyphs.
if(!(ifio.bArbXforms()))
{
if( ifio.b90DegreeRotations() )
{
// font provider can support per 90 degree rotations.
if( pEudcLogfont->ulOrientation )
{
ULONG ulTemp;
ulTemp = lNormAngle(pEudcLogfont->ulOrientation);
pEudcLogfont->ulOrientation =
(ulTemp / ORIENTATION_90_DEG) * ORIENTATION_90_DEG;
if( (dco.pdc->bYisUp()) && (ulTemp % ORIENTATION_90_DEG))
pEudcLogfont->ulOrientation =
lNormAngle(pEudcLogfont->ulOrientation + ORIENTATION_90_DEG);
}
if( pEudcLogfont->lEscapement )
{
LONG lTemp;
lTemp = lNormAngle(pEudcLogfont->lEscapement);
pEudcLogfont->lEscapement =
(lTemp / ORIENTATION_90_DEG) * ORIENTATION_90_DEG;
if( (dco.pdc->bYisUp()) && (lTemp % ORIENTATION_90_DEG))
pEudcLogfont->lEscapement =
lNormAngle(pEudcLogfont->lEscapement + ORIENTATION_90_DEG);
}
}
else
{
// font provider can generate only horizontal glyph
pEudcLogfont->ulOrientation = 0L;
pEudcLogfont->lEscapement = 0L;
}
}
#if DBG
if(gflEUDCDebug & DEBUG_FONTLINK_DUMP)
{
DbgPrint(" Base font face name %ws \n", ifio.pwszFaceName());
DbgPrint("GDISRV:lBaseWidth = %d\n",pEudcLogfont->lBaseWidth);
DbgPrint("GDISRV:lBaseHeight = %d\n",pEudcLogfont->lBaseHeight);
DbgPrint("GDISRV:lInternalL = %d\n",lInternalLeading);
DbgPrint("GDISRV:lEscapement = %d\n",pEudcLogfont->lEscapement);
DbgPrint("GDISRV:lOrientation = %d\n",pEudcLogfont->ulOrientation);
}
#endif
}
/******************************************************************************
* PFE *ppfeFromUFI(PUNIVERSAL_FONT_ID pufi)
*
* Given a UFI, returns a corresponding PFE. This function assume the caller
* has grabed the ghsemPublicPFT semaphore.
*
*****************************************************************************/
PFE *ppfeFromUFI(PUNIVERSAL_FONT_ID pufi)
{
PUBLIC_PFTOBJ pfto;
FHOBJ fho(&pfto.pPFT->pfhUFI);
HASHBUCKET *pbkt;
PFE *ppfeRet = NULL;
pbkt = fho.pbktSearch( NULL, (UINT*)NULL, pufi );
if( pbkt != NULL )
{
PFELINK *ppfel;
for (ppfel = pbkt->ppfelEnumHead ; ppfel; ppfel = ppfel->ppfelNext)
{
PFEOBJ pfeo (ppfel->ppfe);
// if the UFI's match and (in the case of a remote font) the process
// that created the remote font is the same as the current one then
// we've got a match
if(UFI_SAME_FACE(pfeo.pUFI(),pufi) && pfeo.SameProccess())
{
if( pfeo.bDead() )
{
WARNING("MAPPER::bFoundForcedMatch mapped to dead PFE\n");
}
else
{
ppfeRet = ppfel->ppfe;
break;
}
}
}
#if DBG
if (!ppfel)
{
WARNING1("ppfeFromUFI couldn't map to PFE\n");
}
#endif
}
else
{
WARNING("ppfeFromUFI pbkt is NULL\n");
}
return ppfeRet;
}
void RFONTOBJ::vInitEUDCRemote(XDCOBJ& dco)
{
#if DBG
DbgPrint("calling remote vinit\n");
#endif // DBG
if((prfnt->paprfntFaceName != NULL) &&
(prfnt->paprfntFaceName[0] != NULL))
{
// If there is at least one facename link then the remote links must be initialized.
// The set of links for a particular RFONT will never change during a print
// job and the RFONT can only be used for this print-job (PDEV). Thus we
// don't have to check a time stamp or anything else to determine if the links
// have changed and can simply return.
return;
}
// remote UFIs get treated as facename links so first initialize the facename array
if(prfnt->paprfntFaceName == (PRFONT *)NULL)
{
if(dco.uNumberOfLinkedUFIs() > QUICK_FACE_NAME_LINKS)
{
if(!(prfnt->paprfntFaceName =
(PRFONT *)PALLOCMEM(dco.uNumberOfLinkedUFIs() * sizeof(PRFONT),'flnk')))
{
WARNING("vInitEUDCRemote: out of memory\n");
return;
}
}
else
{
prfnt->paprfntFaceName = prfnt->aprfntQuickBuff;
}
}
prfnt->uiNumLinks = 0;
// Lock and Validate the LFONTOBJ user object.
UINT u;
PFEOBJ pfeo(prfnt->ppfe);
PDEVOBJ pdo(dco.hdev());
LFONTOBJ lfo(dco.pdc->hlfntCur(), &pdo);
RFONTTMPOBJ rfoT(prfnt);
DCOBJ dcoT(dco.hdc());
IFIOBJR ifio(pfeo.pifi(),rfoT,dcoT);
// Fill up LogFont for EUDC.
EUDCLOGFONT EudcLogFont;
ComputeEUDCLogfont(&EudcLogFont, dco);
for(u = 0; u < dco.uNumberOfLinkedUFIs(); u++)
{
{
// this set of brackets is to make sure the ppfref descructor gets called
PFE *ppfe;
PFFREFOBJ pffref;
RFONTOBJ rfo;
#if DBG
DbgPrint("Trying to get pfe %d\n", u);
#endif // DBG
{
SEMOBJ so(ghsemPublicPFT);
if(ppfe = ppfeFromUFI(&dco.pufiLinkedFonts()[u]))
{
PFEOBJ pfeo1(ppfe);
pffref.vInitRef(pfeo1.pPFF());
#if DBG
DbgPrint("Found it\n");
#endif // DBG
}
}
if(ppfe)
{
rfo.vInit(dco, ppfe, &EudcLogFont, FALSE);
if(rfo.bValid())
{
#if DBG
DbgPrint("Got a valid RFONT ENTRY\n");
#endif // DBG
prfnt->paprfntFaceName[prfnt->uiNumLinks++] =
rfo.prfntFont();
}
}
}
}
#if DBG
DbgPrint("done: font has %d remote links\n", prfnt->uiNumLinks);
#endif // DBG
}
/******************************Public*Routine******************************\
* RFONTOBJ::vInitEUDC( XDCOBJ )
*
* This routine is called during text out when the first character that isn't
* in the base font is encountered. vInitEUDC will then realize any EUDC RFONTS
* (if they haven't already been realized on previous text outs) so that they
* can possibly be used if the character(s) are in the EUDC fonts.
*
* Thu 12-Jan-1995 15:00:00 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
VOID RFONTOBJ::vInitEUDC( XDCOBJ& dco )
{
if(dco.uNumberOfLinkedUFIs())
{
vInitEUDCRemote(dco);
return;
}
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"Calling vInitEUDC()\n");
// If we have already initialized System EUDC font, and NOT have
// any FaceName Linked font, we have nothing to do in this function.
PFEOBJ pfeo(prfnt->ppfe);
// In most cases, we have the system EUDC font, at least.
// If the system eudc was initizlied, we might short-cut the eudc realization.
if((prfnt->prfntSysEUDC != NULL) || (!IS_SYSTEM_EUDC_PRESENT()))
{
// if default eudc scheme is disabled or is already initizlied. we can
// short-cut the realization.
if((!bFinallyInitializeFontAssocDefault && !gbSystemDBCSFontEnabled) ||
(prfnt->prfntDefEUDC != NULL) )
{
// if there is no facename eudc for this font or, is already initizlied
// we can return here...
if((pfeo.pGetLinkedFontEntry() == NULL) ||
((prfnt->paprfntFaceName != NULL) &&
(pfeo.pGetLinkedFontEntry() != NULL) &&
(prfnt->bFilledEudcArray == TRUE) &&
(prfnt->ulTimeStamp == pfeo.ulGetLinkTimeStamp())))
{
return;
}
}
}
// Lock and Validate the LFONTOBJ user object.
PDEVOBJ pdo(dco.hdev());
LFONTOBJ lfo(dco.pdc->hlfntCur(), &pdo);
RFONTTMPOBJ rfoT(prfnt);
DCOBJ dcoT(dco.hdc());
IFIOBJR ifio(pfeo.pifi(),rfoT,dcoT);
// Fill up LogFont for EUDC.
EUDCLOGFONT EudcLogFont;
ComputeEUDCLogfont(&EudcLogFont, dco);
// first handle the system EUDC font
UINT iPfeOffset = (prfnt->bVertical ? PFE_VERTICAL : PFE_NORMAL);
if((prfnt->prfntSysEUDC == NULL) &&
(gappfeSysEUDC[iPfeOffset] != NULL))
{
RFONTOBJ rfo;
PFEOBJ pfeoEudc(gappfeSysEUDC[iPfeOffset]);
IFIOBJ ifioEudc(pfeoEudc.pifi());
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"Connecting System wide EUDC font....\n");
// check Eudc font capacity
if(!bCheckEudcFontCaps(ifioEudc))
{
// font capacity is not match we won't use system eudc.
prfnt->prfntSysEUDC = (RFONT *)NULL;
}
else
{
rfo.vInit( dco,
gappfeSysEUDC[iPfeOffset],
&EudcLogFont,
FALSE ); // prfnt->cache.bSmallMetrics );
if( rfo.bValid() )
{
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"vInitEUDC() -- linking System EUDC\n");
prfnt->prfntSysEUDC = rfo.prfntFont();
}
}
}
// next handle default links
if(bFinallyInitializeFontAssocDefault && (prfnt->prfntDefEUDC == NULL))
{
BYTE jWinCharSet = (ifio.lfCharSet());
BYTE jFamily = (ifio.lfPitchAndFamily() & 0xF0);
UINT iIndex = (jFamily >> 4);
BOOL bEnableDefaultLink = FALSE;
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"Connecting Default EUDC font....\n");
// Check default font association is disabled for this charset or not.
switch (jWinCharSet)
{
case ANSI_CHARSET:
case OEM_CHARSET:
case SYMBOL_CHARSET:
//
// following code is equal to
//
// if ((Char == ANSI_CHARSET && fFontAssocStatus & ANSI_ASSOC) ||
// (Char == OEM_CHARSET && fFontAssocStatus & OEM_ASSOC) ||
// (Char == SYMBOL_CHARSET && fFontAssocStatus & SYMBOL_ASSOC) )
//
if( ((jWinCharSet + 2) & 0xf) & fFontAssocStatus )
{
bEnableDefaultLink = TRUE;
}
else
bEnableDefaultLink = FALSE;
break;
default:
bEnableDefaultLink = FALSE;
break;
}
if( bEnableDefaultLink )
{
// Check the value is valid or not.
if( iIndex < NUMBER_OF_FONTASSOC_DEFAULT )
{
ASSERTGDI( (FontAssocDefaultTable[iIndex].DefaultFontType == jFamily),
"GDISRV:FONTASSOC DEFAULT:Family index is wrong\n");
// if the registry data for specified family's default is ivalid
// use default.....
if( !FontAssocDefaultTable[iIndex].ValidRegData )
{
iIndex = (NUMBER_OF_FONTASSOC_DEFAULT-1);
}
}
else
{
// iIndex is out of range, use default one....
WARNING("GDISRV:FontAssoc:Family is strange, use default\n");
iIndex = (NUMBER_OF_FONTASSOC_DEFAULT-1);
}
// If vertical font is selected for base font, but the vertical font for
// default EUDC is not available, but normal font is provided, use normal
// font.
if((iPfeOffset == PFE_VERTICAL) &&
(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] ==
PPFENULL) &&
(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] != PPFENULL))
{
iPfeOffset = PFE_NORMAL;
}
RFONTOBJ rfo;
PFEOBJ pfeoEudc(FontAssocDefaultTable[iIndex].DefaultFontPFEs[iPfeOffset]);
// Check the PFE in default table is valid or not.
if( pfeoEudc.bValid() )
{
IFIOBJ ifioEudc(pfeoEudc.pifi());
if( !bCheckEudcFontCaps(ifioEudc) )
{
prfnt->prfntDefEUDC = (RFONT *)NULL;
}
else
{
rfo.vInit( dco,
FontAssocDefaultTable[iIndex].DefaultFontPFEs[iPfeOffset],
&EudcLogFont,
FALSE ); // prfnt->cache.bSmallMetrics );
if( rfo.bValid() )
{
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"vInitEUDC() -- linking default EUDC\n");
prfnt->prfntDefEUDC = rfo.prfntFont();
}
}
}
}
else
{
// FontAssociation is disabled for this charset.
prfnt->prfntDefEUDC = (RFONT *)NULL;
}
}
else
{
prfnt->prfntDefEUDC = NULL;
}
// next handle all the face name links
if(pfeo.pGetLinkedFontEntry() != NULL)
{
BOOL bNeedToBeFilled = !(prfnt->bFilledEudcArray);
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,"Connecting Face name EUDC font....\n");
//
// if this RFONT has linked RFONT array and its linked font information
// is dated, just update it here..
//
if((prfnt->paprfntFaceName != NULL) &&
(prfnt->ulTimeStamp != pfeo.ulGetLinkTimeStamp()))
{
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,
"vInitEUDC():This RFONT is dated, now updating...\n");
//
// Inactivating old linked RFONT.
//
// if Eudc font that is linked to this RFONT was removed, the removed
// RFONT entry contains NULL, and its Eudc RFONT is already killed during
// EudcUnloadLinkW() function. then we should inactivate all Eudc RFONT that
// is still Active (Not Killed)..
//
for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
{
//
// Check Eudc RFONT is still active..
//
if( prfnt->paprfntFaceName[ii] != NULL )
{
RFONTTMPOBJ rfoTmp( prfnt->paprfntFaceName[ii] );
#if DBG
if( gflEUDCDebug & DEBUG_FONTLINK_RFONT )
{
DbgPrint("vInitEUDC() deactivating linked font %x\n",
prfnt->paprfntFaceName[ii]);
}
#endif
rfoTmp.bMakeInactiveHelper((PRFONT *)NULL);
prfnt->paprfntFaceName[ii] = NULL;
}
}
//
// Free this Array if it was allocated..
//
if( prfnt->paprfntFaceName != prfnt->aprfntQuickBuff )
VFREEMEM( prfnt->paprfntFaceName );
//
// Invalidate the pointer.
//
prfnt->paprfntFaceName = (PRFONT *)NULL;
prfnt->uiNumLinks = 0;
}
if( prfnt->paprfntFaceName == (PRFONT *)NULL )
{
if(pfeo.pGetLinkedFontEntry()->uiNumLinks > QUICK_FACE_NAME_LINKS)
{
prfnt->paprfntFaceName =
(PRFONT *)PALLOCMEM(pfeo.pGetLinkedFontEntry()->uiNumLinks *
sizeof(PRFONT),'flnk');
}
else
{
prfnt->paprfntFaceName = prfnt->aprfntQuickBuff;
}
bNeedToBeFilled = TRUE;
}
if( bNeedToBeFilled )
{
PLIST_ENTRY p = pfeo.pGetLinkedFontList()->Flink;
UINT uiRfont = 0;
while( p != pfeo.pGetLinkedFontList() )
{
#if DBG
if( gflEUDCDebug & DEBUG_FONTLINK_RFONT )
{
DbgPrint("vInitEUDC() -- linking FaceName %d\n", uiRfont);
}
#endif
PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
//
// Check this linked font have Vertical facename or not,
// if it doesn't have, use normal facename...
//
UINT iPfeOffsetLocal;
if( ppfeData->appfe[iPfeOffset] == NULL )
iPfeOffsetLocal = PFE_NORMAL;
else
iPfeOffsetLocal = iPfeOffset;
PFEOBJ pfeoEudc(ppfeData->appfe[iPfeOffsetLocal]);
IFIOBJ ifioEudc(pfeoEudc.pifi());
if( bCheckEudcFontCaps(ifioEudc) )
{
RFONTOBJ rfo;
rfo.vInit( dco,
ppfeData->appfe[iPfeOffsetLocal],
&EudcLogFont,
FALSE ); // prfnt->cache.bSmallMetrics );
if( rfo.bValid() )
{
ASSERTGDI(uiRfont < pfeo.pGetLinkedFontEntry()->uiNumLinks ,
"uiRfont >= pfeo.uiNumLinks\n");
prfnt->paprfntFaceName[uiRfont] = rfo.prfntFont();
//
// Increase real linked font number.
//
uiRfont++;
}
}
p = p->Flink;
}
prfnt->uiNumLinks = uiRfont;
prfnt->ulTimeStamp = pfeo.ulGetLinkTimeStamp();
prfnt->bFilledEudcArray = TRUE;
}
}
else
{
// if this PFE has no eudc link list..
// the pointer to linked RFONT array should be NULL.
ASSERTGDI(prfnt->paprfntFaceName == NULL,
"vInitEUDC():The font has not linked font, but has its Array\n");
}
#if DBG
if(gflEUDCDebug & DEBUG_FONTLINK_DUMP) lfo.vDump();
#endif
}
/******************************Public*Routine******************************\
* RFONTOBJ::vInit (DCOBJ, PFE*, LONG, FIX)
*
* This is a special constructor used for EUDC fonts. Rather than use the
* LOGFONT currently selected into the DC to map to a PFE, it is passed in
* a PFE. If lBaseWidth of lBaseHeight is non-zero vInit will try to realize a
* font with width and height as close as possible to those lBaseWidth/Height.
*
* Tue 24-Oct-1995 12:00:00 -by- Hideyuki Nagase [hideyukn]
* Rewrote it.
*
* Thu 23-Feb-1995 10:00:00 -by- Hideyuki Nagase [hideyukn]
* SmallMetrics support.
*
* Fri 25-Mar-1993 10:00:00 -by- Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
VOID RFONTOBJ::vInit(
XDCOBJ &dco,
PFE *ppfeEUDCFont,
EUDCLOGFONT *pEudcLogFont,
BOOL bSmallMetrics
)
{
SEMOBJ sem(ghsemEUDC2);
BOOL bNeedPaths = dco.pdc->bActive() ? TRUE : FALSE;
FLINKMESSAGE(DEBUG_FONTLINK_RFONT,"gdisrv!vInit():Initializing EUDC font.\n");
ASSERTGDI(bSmallMetrics == FALSE,"gdisrv!bSmallMetrics is 1 for EUDC font\n");
BOOL bRet = FALSE;
// Get PDEV user object (need for bFindRFONT).
// This must be done before the ghsemPublicPFT is locked down.
PDEVOBJ pdo(dco.hdev());
ASSERTGDI(pdo.bValid(), "gdisrv!RFONTOBJ(dco): bad pdev in dc\n");
// Lock and Validate the LFONTOBJ user object.
LFONTOBJ lfo(dco.pdc->hlfntCur(), &pdo);
if (!lfo.bValid())
{
WARNING("gdisrv!RFONTOBJ(dco): bad LFONT handle\n");
prfnt = PRFNTNULL; // mark RFONTOBJ invalid
return;
}
// Now we're ready to track down this RFONT we want...
// Compute the Notional to Device transform for this realization.
PFEOBJ pfeo(ppfeEUDCFont);
IFIOBJ ifio(pfeo.pifi());
ASSERTGDI(pfeo.bValid(), "gdisrv!RFONTOBJ(dco): bad ppfe from mapping\n");
// Set bold and italic simulation flags if neccesary
FLONG flSim = 0;
// if base font is originally italialized or simulated, we
// also generate italic font.
if ( (pEudcLogFont->flBaseFontType & FO_SIM_ITALIC) ||
(pEudcLogFont->fsSelection & FM_SEL_ITALIC) )
{
flSim |= lfo.flEudcFontItalicSimFlags(ifio.bNonSimItalic(),
ifio.bSimItalic());
}
// If the basefont is BMP font then we only embolden the linked font for Display
// If the basefont is scalable then we embolden linked font at any device.
if ( (pdo.bDisplayPDEV() || pEudcLogFont->bContinuousScaling) &&
((pEudcLogFont->fsSelection & FM_SEL_BOLD) ||
(pEudcLogFont->flBaseFontType & FO_SIM_BOLD)))
{
flSim |= lfo.flEudcFontBoldSimFlags((USHORT)ifio.lfWeight());
}
//
//
// We won't set bold simulation flag to font driver.
// This is for following situation.
// if the base font is FIXED_PITCH font, and enbolden, then
// we need to scale EUDC font as same width of based font.
// but font enbolden simulation is depend on the font driver, we
// might not get exact same witdh of scaled eudc font.
//
//
// this is needed only by ttfd to support win31 hack: VDMX XFORM QUANTIZING
// NOTE: in the case that the requested height is 0 we will pick a default
// value which represent the character height and not the cell height for
// Win 3.1 compatibility. Thus I have he changed this check to be <= 0
// from just < 0. [gerritv]
//
if (ifio.bTrueType() && (lfo.plfw()->lfHeight <= 0))
flSim |= FO_EM_HEIGHT;
// Now we need to check if the base font is going to be antialiased,
// if so we also want to antialias the linked font, if it is capable of it
if ((pEudcLogFont->flBaseFontType & FO_GRAY16) && (pfeo.pifi()->flInfo & FM_INFO_4BPP))
{
flSim |= (pEudcLogFont->flBaseFontType & (FO_GRAY16 | FO_CLEARTYPE_X));
}
// Hack the width of the logfont to get same width of eudc font as base font.
LONG lWidthSave = lfo.lWidth( pEudcLogFont->lBaseWidth );
LONG lHeightSave = lfo.lHeight( pEudcLogFont->lBaseHeight );
ULONG ulOrientationSave = lfo.ulOrientation( pEudcLogFont->ulOrientation );
ULONG lEscapementSave = lfo.lEscapement( pEudcLogFont->lEscapement );
FD_XFORM fdx; // realize with this notional to device xform
POINTL ptlSim; // for bitmap scaling simulations
if (!ifio.bContinuousScaling())
{
WARNING("EUDC font could not be ContinuousScaling\n");
prfnt = PRFNTNULL; // mark RFONTOBJ invalid
return;
}
else
{
ptlSim.x = 1; ptlSim.y = 1; // this will be not used for scalable font...
}
bRet = pfeo.bSetFontXform(dco, lfo.plfw(), &fdx,
0,
flSim,
(POINTL* const) &ptlSim,
ifio,
TRUE // font is linked
);
// if bSetFontXform() was fail, return here....
if( !bRet )
{
lfo.lWidth( lWidthSave );
lfo.lHeight( lHeightSave );
lfo.ulOrientation( ulOrientationSave );
lfo.lEscapement( lEscapementSave );
WARNING("gdisrv!RFONTOBJ(dco): failed to compute font transform\n");
prfnt = PRFNTNULL; // mark RFONTOBJ invalid
return;
}
// Tell PFF about this new reference, and then release the global sem.
// Note that vInitRef() must be called while holding the semaphore.
PFFREFOBJ pffref;
{
SEMOBJ so(ghsemPublicPFT);
pffref.vInitRef(pfeo.pPFF());
}
// go find the font
EXFORMOBJ xoWtoD(dco.pdc->mxWorldToDevice());
ASSERTGDI(xoWtoD.bValid(), "gdisrv!RFONTOBJ(dco) - \n");
// Attempt to find an RFONT in the lists cached off the PDEV. Its transform,
// simulation state, style, etc. all must match.
if ( bFindRFONT(&fdx,
flSim,
0, // lfo.pelfw()->elfStyleSize,
pdo,
&xoWtoD,
ppfeEUDCFont,
bNeedPaths,
dco.pdc->iGraphicsMode(),
bSmallMetrics,
RFONT_TYPE_UNICODE // must be unicode for EUDC
) )
{
FLINKMESSAGE2(DEBUG_FONTLINK_RFONT,"EUDC RFONT is %x\n",prfnt);
// now restore the old width
lfo.lWidth( lWidthSave );
lfo.lHeight( lHeightSave );
lfo.ulOrientation( ulOrientationSave );
lfo.lEscapement( lEscapementSave );
// Grab cache semaphore.
vGetCache();
dco.pdc->vXformChange(FALSE);
return;
}
// If we get here, we couldn't find an appropriate font realization.
// Now, we are going to create one just for us to use.
bRet = bRealizeFont(&dco,
&pdo,
lfo.pelfw(),
ppfeEUDCFont,
&fdx,
(POINTL* const) &ptlSim,
flSim,
0, // lfo.pelfw()->elfStyleSize,
bNeedPaths,
bSmallMetrics,
RFONT_TYPE_UNICODE
);
// now restore the old width
lfo.lWidth( lWidthSave );
lfo.lHeight( lHeightSave );
lfo.ulOrientation( ulOrientationSave );
lfo.lEscapement( lEscapementSave );
if( !bRet )
{
WARNING("gdisrv!RFONTOBJ(dco): realization failed, RFONTOBJ invalidated\n");
prfnt = PRFNTNULL; // mark RFONTOBJ invalid
return;
}
ASSERTGDI(bValid(), "gdisrv!RFONTOBJ(dco): invalid hrfnt from realization\n");
// We created a new RFONT, we better hold the PFF reference!
pffref.vKeepIt();
// Finally, grab the cache semaphore.
vGetCache();
dco.pdc->vXformChange(FALSE);
FLINKMESSAGE2(DEBUG_FONTLINK_RFONT,"EUDC RFONT is %x\n",prfnt);
return;
}
/******************************Public*Routine******************************\
* BOOL RFONTOBJ::bIsLinkedGlyph (WCHAR wc)
*
* Does a quick check to see if a character is in either the system EUDC
* font or a font that has been linked to this RFONT.
*
* Tue 17-Jan-1995 14:00:00 -by- Hideyuki Nagase [hideyukn]
* Rewrote it.
*
* Wed 11-Aug-1993 10:00:00 -by- Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
#define IS_PRIVATE_EUDC_AREA(wc) \
(((wc) >= 0xE000) && ((wc) <= 0xF8FF))
BOOL RFONTOBJ::bIsLinkedGlyph( WCHAR wc )
{
GreAcquireSemaphore( ghsemEUDC1 );
// we don't release ghsemEUDC1 mutex here, we have to guard the current eudc
// link data. All of the API that change eudc data, try to hold this
// mutex, if we hold it, nobody can process the request...
//
// if another thread will change eudc link between this thread is in after
// release the mutex (end of this function) and before we increment gcEUDCCount
// in vInitEUDC(). In the case, this function might return TRUE for non-linked
// char or return FALSE for linked char, but we don't need to worry about this.
// because following line in wpgdGetLinkMetricsPlus() will returns NULL and
// we will return default char. the cost is only time..
BOOL bRet = FALSE;
// EudcDefaultChar should be displayed for 'Private User Area', when there is no
// font are linked. (font's default character should not be came up).
if( IS_PRIVATE_EUDC_AREA(wc) )
{
bRet = TRUE;
}
if( (bRet == FALSE) && IS_SYSTEM_EUDC_PRESENT() && IS_IN_SYSTEM_EUDC(wc) )
{
bRet = TRUE;
}
if( (bRet == FALSE) && bFinallyInitializeFontAssocDefault )
{
//
// THIS CODEPATH SHOULD BE OPTIMIZED....
//
// UNDER_CONSTRUCTION.
//
UINT iPfeOffset = (prfnt->bVertical ? PFE_VERTICAL : PFE_NORMAL);
PFEOBJ pfeo(prfnt->ppfe);
IFIOBJ ifio(pfeo.pifi());
BYTE jFamily = (ifio.lfPitchAndFamily() & 0xF0);
UINT iIndex = (jFamily >> 4);
//
// Check the value is valid or not.
//
if( iIndex < NUMBER_OF_FONTASSOC_DEFAULT )
{
ASSERTGDI( (FontAssocDefaultTable[iIndex].DefaultFontType == jFamily),
"GDISRV:FONTASSOC DEFAULT:Family index is wrong\n");
//
// if the registry data for specified family's default is ivalid
// use default.....
//
if( !FontAssocDefaultTable[iIndex].ValidRegData )
{
iIndex = (NUMBER_OF_FONTASSOC_DEFAULT-1);
}
}
else
{
//
// iIndex is out of range, use default..
//
WARNING("GDISRV:FontAssoc:Family is strange, use default\n");
iIndex = (NUMBER_OF_FONTASSOC_DEFAULT-1);
}
//
// If vertical font is selected for base font, but the vertical font for
// default EUDC is not available, but normal font is provided, use normal
// font.
//
if( (iPfeOffset == PFE_VERTICAL) &&
(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] == PPFENULL) &&
(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] != PPFENULL))
{
iPfeOffset = PFE_NORMAL;
}
PFEOBJ pfeoEudc(FontAssocDefaultTable[iIndex].DefaultFontPFEs[iPfeOffset]);
//
// Check the PFE in default table is valid or not.
//
if( pfeoEudc.bValid() )
{
if( IS_IN_FACENAME_LINK( pfeoEudc.pql(), wc ))
{
bRet = TRUE;
}
}
}
else
if(gbSystemDBCSFontEnabled)
{
PFEOBJ pfeo(prfnt->ppfe);
if(pfeo.bSBCSSystemFont())
{
// we assume that the set of glyphs is the same for the vertical and
// non vertical PFE's so for simplicity always use the normal pfe.
PFEOBJ pfeSystemDBCSFont(gappfeSystemDBCS[PFE_NORMAL]);
ASSERTGDI(pfeSystemDBCSFont.bValid(),
"bIsLinkedGlyph: invalid SystemDBCSFont pfe\n");
if(IS_IN_FACENAME_LINK(pfeSystemDBCSFont.pql(),wc))
{
bRet = TRUE;
}
}
}
// Walk through FaceName link list if we haven't found it yet.
if( bRet == FALSE )
{
//
// Is this a FaceName EUDC character ?
//
UINT iPfeOffset = (prfnt->bVertical ? PFE_VERTICAL : PFE_NORMAL);
PFEOBJ pfeo(prfnt->ppfe);
PLIST_ENTRY p = pfeo.pGetLinkedFontList()->Flink;
//
// Scan the linked font list for this base font.
//
while( p != pfeo.pGetLinkedFontList() )
{
PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
//
// Check this linked font have Vertical facename or not,
// if it doesn't have, use normal facename...
//
UINT iPfeOffsetLocal;
if( ppfeData->appfe[iPfeOffset] == NULL )
iPfeOffsetLocal = PFE_NORMAL;
else
iPfeOffsetLocal = iPfeOffset;
PFEOBJ pfeoEudc(ppfeData->appfe[iPfeOffsetLocal]);
ASSERTGDI( pfeoEudc.pql() != NULL ,
"bIsLinkedGlyph() pfeoEudc.pql() == NULL\n" );
if(IS_IN_FACENAME_LINK( pfeoEudc.pql(), wc ))
{
bRet = TRUE;
break;
}
p = p->Flink;
}
}
GreReleaseSemaphore( ghsemEUDC1 );
return(bRet);
}
/******************************Public*Routine******************************\
* BOOL STROBJ_bEnumLinked (pstro,pc,ppgpos)
*
* The glyph enumerator.
*
* History:
* Tue 28-Sep-1993 11:37:00 -by- Gerrit van Wingerden
* Converted to a special helper function to handle linked fonts.
*
* Tue 17-Mar-1992 10:35:05 -by- Charles Whitmer [chuckwh]
* Simplified it and gave it the quick exit. Also let drivers call here
* direct.
*
* 02-Oct-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL STROBJ_bEnumLinked(ESTROBJ *peso, ULONG *pc,PGLYPHPOS *ppgpos)
{
// Quick exit.
if( peso->cgposCopied == 0 )
{
for( peso->plNext = peso->plPartition, peso->pgpNext = peso->pgpos;
*(peso->plNext) != peso->lCurrentFont;
(peso->pgpNext)++, (peso->plNext)++ );
{
}
}
else
{
if( peso->cgposCopied == peso->cGlyphs )
{
// no more glyphs so just return
*pc = 0;
return(FALSE);
}
else
{
// find next glyph
for( (peso->plNext)++, (peso->pgpNext)++;
*(peso->plNext) != (peso->lCurrentFont);
(peso->pgpNext)++, (peso->plNext)++ );
{
}
}
}
if (peso->prfo == NULL) // check for journaling
{
WARNING("ESTROBJ::bEnum(), bitmap font, prfo == NULL\n");
*pc = 0;
return(FALSE);
}
if( peso->prfo->cGetGlyphData(1,peso->pgpNext) == 0 )
{
WARNING("couldn't get glyph for some reason\n");
*pc = 0;
return(FALSE);
}
peso->cgposCopied += 1; // update enumeration state
*pc = 1;
*ppgpos = peso->pgpNext;
return(peso->cgposCopied < peso->cGlyphs); // TRUE => more to come.
}
/******************************Public*Routine******************************\
* VOID ESTROBJ fxBaseLineAdjust( _fxBaseLineAdjust )
*
* History:
* 24-Dec-1993 -by- Hideyuki Nagase
* Wrote it.
\**************************************************************************/
VOID ESTROBJ::ptlBaseLineAdjustSet( POINTL& _ptlBaseLineAdjust )
{
INT ii;
UINT uFound;
ptlBaseLineAdjust = _ptlBaseLineAdjust;
if( !(ptlBaseLineAdjust.x || ptlBaseLineAdjust.y) )
return;
for( ii = 0,uFound = 0 ; uFound < cGlyphs ; ii++ )
{
if( plPartition[ii] == lCurrentFont )
{
pgpos[ii].ptl.x += ptlBaseLineAdjust.x;
pgpos[ii].ptl.y += ptlBaseLineAdjust.y;
uFound++;
}
}
}
/******************************Public*Routine******************************\
* BOOL ESTROBJ bPartitionInit( c, uiNumLinks )
*
* History:
* 29-Nov-1995 -by- Hideyuki Nagase
* Add initialize for FaceNameGlyphs array.
*
* 29-Sep-1993 -by- Gerrit van Wingerden
* Wrote it.
\**************************************************************************/
BOOL ESTROBJ::bPartitionInit(COUNT c, UINT uiNumLinks, BOOL bEudcInit)
{
// Always initialize at least for the SystemTTEUDC Font. We can't initialize
// the EUDC specific stuff until we've called RFONTOBJ::vInitEUDC, something
// we won't do when just outputing System DBCS glyphs
// the first thing we should do is clear the SO_ZERO_BEARINGS and
// SO_CHAR_INC_EQUAL_BM_BASE flags in the TEXOBJ since this will turn
// off potentially fatal optimizations in the H3 case.
flAccel &= ~(SO_CHAR_INC_EQUAL_BM_BASE|SO_ZERO_BEARINGS);
if(!(flTO & TO_SYS_PARTITION))
{
plPartition = (LONG*) &pgpos[c];
pwcPartition = (WCHAR*) &plPartition[c];
RtlZeroMemory((VOID*)plPartition, c * sizeof(LONG));
pacFaceNameGlyphs = NULL;
cSysGlyphs = 0;
cDefGlyphs = 0;
cTTSysGlyphs = 0;
flTO |= TO_SYS_PARTITION;
}
if(bEudcInit)
{
if( uiNumLinks >= QUICK_FACE_NAME_LINKS )
{
pacFaceNameGlyphs = (ULONG *) PALLOCMEM(uiNumLinks * sizeof(UINT),'flnk');
if (pacFaceNameGlyphs == (ULONG *) NULL)
{
// if we fail allocate memory, we just cancel eudc output.
return (FALSE);
}
flTO |= TO_ALLOC_FACENAME;
}
else
{
pacFaceNameGlyphs = acFaceNameGlyphs;
RtlZeroMemory((VOID*) pacFaceNameGlyphs, uiNumLinks * sizeof(UINT));
}
flTO |= TO_PARTITION_INIT;
}
return (TRUE);
}
/****************************************************************************
* RFONTOBJ::GetLinkedFontUFIs
*
* This routine returns the UFI's for the font(s) that are linked to this
* RFONT. If pufi is NULL, simply returns the number of UFI's linked to
* this RFONT.
*
*****************************************************************************/
INT RFONTOBJ::GetLinkedFontUFIs(XDCOBJ& dco, PUNIVERSAL_FONT_ID pufi, INT NumUFIs)
{
UINT u;
INT UFICount = 0;
// check pui
if (NumUFIs && pufi == NULL)
{
WARNING("RFONTOBJ::GetLinkedFontUFIs() pufi == NULL but NumUFIs != 0\n");
return (0);
}
// initialize system TT font if applicable
if(prfnt->bIsSystemFont)
{
if((!prfnt->prfntSystemTT) && !bInitSystemTT(dco))
{
WARNING("Error initializing TT system font 5\n");
return(0);
}
prfnt->flEUDCState |= EUDC_NO_CACHE;
}
// initialize EUDC fonts if we haven't done so already
{
GreAcquireSemaphore(prfnt->hsemEUDC);
if( !( prfnt->flEUDCState & EUDC_INITIALIZED ) )
{
// this value will be decremented in RFONTOBJ::dtHelper()
INCREMENTEUDCCOUNT;
vInitEUDC(dco);
prfnt->flEUDCState |= (EUDC_INITIALIZED | EUDC_NO_CACHE);
}
GreReleaseSemaphore(prfnt->hsemEUDC);
}
if(prfnt->prfntSystemTT)
{
if(UFICount++ < NumUFIs)
{
RFONTTMPOBJ rfo(prfnt->prfntSystemTT);
rfo.vUFI(pufi);
pufi++;
}
}
for(u = 0; u < prfnt->uiNumLinks; u++)
{
ASSERTGDI(prfnt->paprfntFaceName[u],"GDI:uGetLinkedFonts: null facename font\n");
if(UFICount++ < NumUFIs)
{
RFONTTMPOBJ rfo(prfnt->paprfntFaceName[u]);
rfo.vUFI(pufi);
pufi++;
}
}
if(prfnt->prfntDefEUDC)
{
if(UFICount++ < NumUFIs)
{
RFONTTMPOBJ rfo(prfnt->prfntDefEUDC);
rfo.vUFI(pufi);
pufi++;
}
}
if(prfnt->prfntSysEUDC)
{
if(UFICount++ < NumUFIs)
{
RFONTTMPOBJ rfo(prfnt->prfntSysEUDC);
rfo.vUFI(pufi);
pufi++;
}
}
return(UFICount);
}