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