/******************************Module*Header*******************************\ * Module Name: dcobj.cxx * * * * Non inline methods for DC user object. These are in a separate module * * to save other modules from having to do more includes. * * * * Created: 09-Aug-1989 13:57:58 * * Author: Donald Sidoroff [donalds] * * * * Copyright (c) 1989-1999 Microsoft Corporation * \**************************************************************************/ #include "precomp.hxx" extern RECTL rclEmpty; /******************************Public*Routine******************************\ * * VOID XDCOBJ::vSetDefaultFont(BOOL bDisplay) * * * Effects: called from bCleanDC and CreateDC * * History: * 21-Mar-1996 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/ VOID XDCOBJ::vSetDefaultFont(BOOL bDisplay) { // If display PDEV, then select System stock font. HLFONT hlfntNew; if (bDisplay) { ulDirty(ulDirty() | DISPLAY_DC ); hlfntNew = STOCKOBJ_SYSFONT; } else { hlfntNew = STOCKOBJ_DEFAULTDEVFONT; } // this can not fail with the stock fonts, also increments ref count PLFONT plfnt = (PLFONT)HmgShareCheckLock((HOBJ)hlfntNew, LFONT_TYPE); ASSERTGDI(plfnt, "vSetDefaultFont: plfnt == NULL\n"); pdc->hlfntNew(hlfntNew); pdc->plfntNew(plfnt); } /******************************Member*Function*****************************\ * DCSAVE::bDelete() * * Attempt to delete the DC. * * History: * Sat 19-Aug-1989 00:32:58 -by- Charles Whitmer [chuckwh] * Wrote it. \**************************************************************************/ BOOL XDCOBJ::bDeleteDC(BOOL bProcessCleanup) { PFFLIST *pPFFList; BOOL bIsPrivate; RFONTOBJ rfDeadMeat(pdc->prfnt()); // deletion constructor, see rfntobj.cxx // Nuke the brushes (unreference count to brush realization) peboFill()->vNuke(); peboLine()->vNuke(); peboText()->vNuke(); peboBackground()->vNuke(); // remove any colortransform in this DC. vCleanupColorTransform(bProcessCleanup); // remove any remote fonts if(pPFFList = pdc->pPFFList) { while( pPFFList ) { PFFLIST *pTmp; pTmp = pPFFList; pPFFList = pPFFList->pNext; GreAcquireSemaphoreEx(ghsemPublicPFT, SEMORDER_PUBLICPFT, NULL); // this list is also used for local printing with embed fonts bIsPrivate = (pTmp->pPFF->pPFT == gpPFTPrivate) ? TRUE : FALSE; PUBLIC_PFTOBJ pfto(pTmp->pPFF->pPFT); //pPFFList != NULL only if the PFFs have been added to the DC for remote printing. // bUnloadWorkhorse should release the ghsemPublicPFT if (!pfto.bUnloadWorkhorse( pTmp->pPFF, 0, ghsemPublicPFT, bIsPrivate ? FR_PRINT_EMB_FONT : FR_NOT_ENUM)) { WARNING("XDCOBJ::bDelete unable to delete remote font.\n"); } VFREEMEM( pTmp ); } } // remove this from handle manager. HmgFree((HOBJ)pdc->hGet()); pdc = (PDC) NULL; // Prevents ~DCOBJ from doing anything. return(TRUE); } /******************************Data*Structure******************************\ * dclevelDefault * * Defines the default DC image for use by DCMEMOBJ. * * History: * Thu 09-Aug-1990 20:54:02 -by- Charles Whitmer [chuckwh] * Wrote the nearly bare bones version. We'll build it back up with the * DC structure as we add components. \**************************************************************************/ DC_ATTR DcAttrDefault = { {0}, // PVOID pvLDC; (ULONG)DIRTY_CHARSET, // ULONG ulDirty_; (HBRUSH)0, // HBRUSH hbrush (HPEN)0, // HPEN hpen (COLORREF)0x00ffffff, // COLORREF crBackgroundClr; (COLORREF)0x00ffffff, // ULONG ulBackgroundClr; (COLORREF)0, // COLORREF crForegroundClr; (COLORREF)0, // ULONG ulForegroundClr; (COLORREF)0x00ffffff, // COLORREF crDCBrushClr; (COLORREF)0x00ffffff, // ULONG ulDCBrushClr; (COLORREF)0, // COLORREF crDCPenClr; (COLORREF)0, // ULONG ulDCPenClr; (ULONG)0, // ULONG iCS_CP; GM_COMPATIBLE, // ULONG iGraphicsMode; R2_COPYPEN, // BYTE jROP2; OPAQUE, // BYTE jBkMode; ALTERNATE, // BYTE jFillMode; BLACKONWHITE, // BYTE jStretchBltMode; {0}, // POINTL ptlCurrent {0}, // POINTL ptfxCurrent OPAQUE, // LONG lBkMode; ALTERNATE, // ULONG lFillMode; BLACKONWHITE, // LONG lStretchBltMode; 0, // FLONG flFontMapper; // DC_ICM_OFF, // LONG lIcmMode; (HANDLE)0, // HANDLE hcmXform; (HCOLORSPACE)0, // HCOLORSPACE hColorSpace; (DWORD)0, // DWORD dwDIBColorSpace; (COLORREF)CLR_INVALID, // COLORREF IcmBrushColor; (COLORREF)CLR_INVALID, // COLORREF IcmPenColor; {0}, // PVOID pvICM; // TA_LEFT|TA_TOP|TA_NOUPDATECP, // FLONG flTextAlign; TA_LEFT|TA_TOP|TA_NOUPDATECP, // LONG lTextAlign; (LONG)0, // LONG lTextExtra; (LONG)ABSOLUTE, // LONG lRelAbs; (LONG)0, // LONG lBreakExtra; (LONG)0, // LONG cBreak; (HLFONT)0, // HLFONT hlfntNew; { // MATRIX mxWorldToDevice EFLOAT_16, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_16, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_LTOFX }, { // MATRIX mxDeviceToWorld EFLOAT_1Over16, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_1Over16, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_FXTOL }, { // MATRIX mxWorldToPage EFLOAT_1, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_1, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_LTOL }, EFLOAT_16, // EFLOAT efM11PtoD EFLOAT_16, // EFLOAT efM22PtoD EFLOAT_0, // EFLOAT efDxPtoD EFLOAT_0, // EFLOAT efDyPtoD MM_TEXT, // ULONG iMapMode; 0, // DWORD dwLayout; 0, // LONG lWindowOrgx; {0,0}, // POINTL ptlWindowOrg; {1,1}, // SIZEL szlWindowExt; {0,0}, // POINTL ptlViewPortOrg; {1,1}, // SIZEL szlViewPortExt; WORLD_TO_PAGE_IDENTITY | // flXform PAGE_TO_DEVICE_SCALE_IDENTITY | PAGE_TO_DEVICE_IDENTITY, {0,0}, // SIZEL szlVirtualDevicePixel; {0,0}, // SIZEL szlVirtualDeviceMm; {0,0}, // POINTL ptlBrushOrigin; {0} // RECTREGION VisRectRegion; }; DCLEVEL dclevelDefault = { 0, // HPAL hpal; 0, // PPALETTE ppal; 0, // PVOID pColorSpace; DC_ICM_OFF, // ULONG lIcmMode; 1, // LONG lSaveDepth; 0, // LONG lSaveDepthStartDoc; (HDC) 0, // HDC hdcSave; {0,0}, // POINTL ptlKmBrushOrigin; (PBRUSH)NULL, // PBRUSH pbrFill; (PBRUSH)NULL, // PBRUSH pbrLine; (PLFONT)NULL, // PLFONT plfntNew_; HPATH_INVALID, // HPATH hpath; 0, // FLONG flPath; { // LINEATTRS laPath; 0, // FLONG fl; 0, // ULONG iJoin; 0, // ULONG iEndCap; {IEEE_0_0F}, // FLOAT_LONG elWidth; IEEE_10_0F, // FLOAT eMiterLimit; 0, // ULONG cstyle; (PFLOAT_LONG) NULL, // PFLOAT_LONG pstyle; {IEEE_0_0F} // FLOAT_LONG elStyleState; }, NULL, // HRGN prgnClip; NULL, // HRGN prgnMeta; { // COLORADJUSTMENT ca sizeof(COLORADJUSTMENT), // WORD caSize CA_DEFAULT, // WORD caFlags ILLUMINANT_DEFAULT, // WORD caIlluminantIndex HT_DEF_RGB_GAMMA, // WORD caRedPowerGamma HT_DEF_RGB_GAMMA, // WORD caGreenPowerGamma HT_DEF_RGB_GAMMA, // WORD caBluePowerGamma REFERENCE_BLACK_DEFAULT, // WORD caReferenceBlack REFERENCE_WHITE_DEFAULT, // WORD caReferenceWhite CONTRAST_ADJ_DEFAULT, // SHORT caContrast BRIGHTNESS_ADJ_DEFAULT, // SHORT caBrightness COLORFULNESS_ADJ_DEFAULT, // SHORT caColorfulness REDGREENTINT_ADJ_DEFAULT, // SHORT caRedGreenTint }, 0, // FLONG flFontState; {0,0}, // UNIVERSAL_FONT_ID ufi; {{0,0},{0,0},{0,0},{0,0}}, // UNIVERSAL_FON_ID aQuickLinks[QUICK_UFI_LINKS] 0, // PUNIVERSAL_FONT_ID pufi 0, // UINT uNumLinkedFonts 0, // BOOL bTurnOffLinking 0, // FLONG flFlags; 0, // FLONG flbrush; { // MATRIX mxWorldToDevice EFLOAT_16, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_16, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_LTOFX }, { // MATRIX mxDeviceToWorld EFLOAT_1Over16, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_1Over16, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_FXTOL }, { // MATRIX mxWorldToPage EFLOAT_1, // EFLOAT efM11 EFLOAT_0, // EFLOAT efM12 EFLOAT_0, // EFLOAT efM21 EFLOAT_1, // EFLOAT efM22 EFLOAT_0, // EFLOAT efDx EFLOAT_0, // EFLOAT efDy 0, // FIX fxDx 0, // FIX fxDy XFORM_SCALE | // FLONG flAccel XFORM_UNITY | XFORM_NO_TRANSLATION | XFORM_FORMAT_LTOL }, EFLOAT_16, // EFLOAT efM11PtoD EFLOAT_16, // EFLOAT efM22PtoD EFLOAT_0, // EFLOAT efDxPtoD EFLOAT_0, // EFLOAT efDyPtoD EFLOAT_0, // EFLOAT efM11_TWIPS EFLOAT_0, // EFLOAT efM22_TWIPS EFLOAT_0, // efPr11 EFLOAT_0, // efPr22 0, // SURFACE *pSurface; {0,0}, // SIZEL sizl; }; /******************************Public*Routine******************************\ * BOOL DCOBJ::bCleanDC () * * Restores the DCLEVEL to the same as when DC was created via CreateDC (i.e, * resets it back to dclevelDefault). Also used to clean the DC before * deletion. * * Returns: * TRUE if successful, FALSE if an error occurs. * * History: * 21-May-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ BOOL XDCOBJ::bCleanDC () { // Set TRUE if cleaning the DC invalidates the prfnt with respect to // the DC's transform. BOOL bFontXformDirty; // Sync the brush SYNC_DRAWING_ATTRS(pdc); // If the current map mode is MM_TEXT and the current prfnt is NOT dirty // with respect to the transform, then after we scrub the DC clean, the // pfrnt is still clean with respect to transform. Otherwise, the font // is dirty with respect to transform. if ((ulMapMode() == MM_TEXT) && !this->pdc->bXFormChange()) bFontXformDirty = FALSE; else bFontXformDirty = TRUE; // Restore DC to lowest level. if (1 < lSaveDepth()) GreRestoreDC(hdc(), 1); // Restore the palette. if (ppal() != ppalDefault) GreSelectPalette(hdc(), (HPALETTE)dclevelDefault.hpal, TRUE); if (dctp() == DCTYPE_MEMORY) { // Restore the bitmap if necessary. hbmSelectBitmap(hdc(), STOCKOBJ_BITMAP, TRUE); // Watch out that DirectDraw sometimes marks DCTYPE_MEMORY // surfaces as being 'full-screen'. Consequently, we have // to reset that here. // // (Note that we don't reset the flag for DCTYPE_DIRECT // surfaces, because that flag is automatically updated by // PDEVOBJ::bDisabled() for all DCTYPE_DIRECT surfaces when // the mode changes.) bInFullScreen(FALSE); } // Reset pixel format. ipfdDevMax(-1); // If any regions exist, delete them. if (pdc->dclevel.prgnClip != NULL) { RGNOBJ ro1(pdc->dclevel.prgnClip); // Note: GreRestoreDC(1) should guarantee regions' reference // counts are 1 ASSERTGDI (ro1.cGet_cRefs() == 1, "DCOBJ::bCleanDC(): bad ref count, deleting prgnClip\n"); ro1.bDeleteRGNOBJ(); pdc->dclevel.prgnClip = NULL; } if (pdc->dclevel.prgnMeta != NULL) { RGNOBJ ro2(pdc->dclevel.prgnMeta); // Note: GreRestoreDC(1) should guarantee regions' reference // counts are 1 ASSERTGDI (ro2.cGet_cRefs() == 1, "DCOBJ::bCleanDC(): bad ref count, deleting prgnMeta\n"); ro2.bDeleteRGNOBJ(); pdc->dclevel.prgnMeta = NULL; } // delete the path if (pdc->dclevel.hpath != HPATH_INVALID) { XEPATHOBJ epath(pdc->dclevel.hpath); ASSERTGDI(epath.bValid(), "Invalid DC path"); epath.vDelete(); } // Undo the locks from when the fill and line brushes were selected. // (Un-reference-count the brushes.) DEC_SHARE_REF_CNT_LAZY0(pdc->dclevel.pbrFill); DEC_SHARE_REF_CNT_LAZY0(pdc->dclevel.pbrLine); // make sure to delete the old logfont object if it is marked for deletion DEC_SHARE_REF_CNT_LAZY_DEL_LOGFONT(pdc->plfntNew()); // decrement ref count for the colorspace selected in DC. DEC_SHARE_REF_CNT_LAZY_DEL_COLORSPACE(pdc->dclevel.pColorSpace); // Make sure everything else is set to default. // // Preserve 'pSurface' and 'sizl' in the DCLEVEL -- it may asynchronously // be updated by dynamic mode changing. RtlCopyMemory(&pdc->dclevel, &dclevelDefault, offsetof(DCLEVEL, pSurface)); RtlCopyMemory(pdc->pDCAttr, &DcAttrDefault, sizeof(DC_ATTR)); // Mark brush, charset, color space and color transform as dirty. ulDirtyAdd(DIRTY_BRUSHES|DIRTY_CHARSET|DIRTY_COLORSPACE|DIRTY_COLORTRANSFORM); // Lock the fill and line brushes we just selected in. // (Reference-count the brushes.) // These locks can't fail. INC_SHARE_REF_CNT(pdc->dclevel.pbrFill); INC_SHARE_REF_CNT(pdc->dclevel.pbrLine); // Clean up the font stuff. (This must be done after copying the default // dclevel). { PDEVOBJ pdo(hdev()); // If display PDEV, then select System stock font. vSetDefaultFont(pdo.bDisplayPDEV()); // if primary display dc, set the DC_PRIMARY_DISPLAY flag on if (hdev() == UserGetHDEV()) { ulDirtyAdd(DC_PRIMARY_DISPLAY); } // OK, set the dclevel's font xfrom dirty flag from the value computed // BEFORE the GreRestoreDC. this->pdc->vXformChange(bFontXformDirty); } // Lock color space we just selected in. INC_SHARE_REF_CNT(pdc->dclevel.pColorSpace); RFONTOBJ rfoDead(pdc->prfnt()); // special constructor deactivates pdc->prfnt(0); // this RFONT // free up linked UFIs if not allocated pointing to fast buffer if(pdc->dclevel.pufi && (pdc->dclevel.pufi != pdc->dclevel.aQuickLinks)) { VFREEMEM(pdc->dclevel.pufi); pdc->dclevel.pufi = NULL; } // Set the filling origin to whatever the DC origin is. pdc->ptlFillOrigin(pdc->eptlOrigin().x,pdc->eptlOrigin().y); // Assume Rao has been made dirty by the above work. pdc->vReleaseRao(); return(TRUE); } /******************************Member*Function*****************************\ * XDCOBJ::bSetLinkedUFIs( PFF *ppff ); * * Add the list of linked UFIs to tDC * * History: * Mon 15-Dec-1996 -by- Gerrit van Wingerden [gerritv] * Wrote it. \**************************************************************************/ BOOL XDCOBJ::bSetLinkedUFIs(PUNIVERSAL_FONT_ID pufis, UINT uNumUFIs) { pdc->dclevel.bTurnOffLinking = (uNumUFIs) ? FALSE : TRUE; // If pufi hasn't been initialized or it is too small, reinitialize it. if(!pdc->dclevel.pufi || (uNumUFIs > pdc->dclevel.uNumLinkedFonts)) { if(pdc->dclevel.pufi && (pdc->dclevel.pufi != pdc->dclevel.aQuickLinks)) { VFREEMEM(pdc->dclevel.pufi); pdc->dclevel.pufi = NULL; } if(uNumUFIs <= QUICK_UFI_LINKS) { pdc->dclevel.pufi = pdc->dclevel.aQuickLinks; } else { if(!(pdc->dclevel.pufi = (PUNIVERSAL_FONT_ID) PALLOCMEM(sizeof(UNIVERSAL_FONT_ID) * uNumUFIs,'ddaG'))) { WARNING("GDI: XDCOBJ::bSetLinkedUFIs of of memory\n"); pdc->dclevel.uNumLinkedFonts = 0; return(FALSE); } } pdc->dclevel.uNumLinkedFonts = uNumUFIs; } memcpy(pdc->dclevel.pufi, pufis, sizeof(UNIVERSAL_FONT_ID) * uNumUFIs); return(TRUE); } /******************************Member*Function*****************************\ * XDCOBJ::bAddRemoteFont( PFF *ppff ); * * Add the PFF of a remote font to this DC. * * History: * Mon 06-Feb-1995 -by- Gerrit van Wingerden [gerritv] * Wrote it. \**************************************************************************/ BOOL XDCOBJ::bAddRemoteFont( PFF *ppff ) { BOOL bRet = FALSE; PFFLIST *pPFFList; pPFFList = (PFFLIST*) PALLOCMEM( sizeof(PFFLIST),'ddaG' ); if( pPFFList == NULL ) { WARNING("XDCOBJ::bAddRemoteFont unable to allocate memory\n"); } else { pPFFList->pNext = pdc->pPFFList; pdc->pPFFList = pPFFList; pPFFList->pPFF = ppff; bRet = TRUE; } return(bRet); } /****************************Member*Function*****************************\ * XDCOBJ::bRemoveMergeFont(UNIVERSAL_FONT_ID ufi); * * Remove a merged font from the public font table and pPFFList in the dc. * * History: * Jan-27-1997 Xudong Wu [tessiew] * Wrote it. \************************************************************************/ BOOL XDCOBJ::bRemoveMergeFont(UNIVERSAL_FONT_ID ufi) { GDIFunctionID(XDCOBJ::bRemoveMergeFont); PFFLIST *pPFFCur, *pPFFPrev; BOOL bRet = FALSE; pPFFPrev = pPFFCur = pdc->pPFFList; while(pPFFCur && !bRet) { PFFOBJ pffo(pPFFCur->pPFF); if (pffo.ulCheckSum() == ufi.CheckSum) { UINT iFont; // check whether the Index field also match for (iFont = 0; iFont < pffo.cFonts(); iFont++ ) { ASSERTGDI(pffo.ppfe(iFont), "Invalid ppfe\n"); if (pffo.ppfe(iFont)->ufi.Index == ufi.Index) { bRet = TRUE; break; } } } if (!bRet) { pPFFPrev = pPFFCur; pPFFCur = pPFFCur->pNext; } } if (bRet) { GreAcquireSemaphoreEx(ghsemPublicPFT, SEMORDER_PUBLICPFT, NULL); PUBLIC_PFTOBJ pfto; // bUnloadWorkhorse should release gpsemPublicePFT if (!(bRet = pfto.bUnloadWorkhorse(pPFFCur->pPFF, 0, ghsemPublicPFT, FR_NOT_ENUM))) { WARNING("Unable to delete the font.\n"); } else { if (pPFFCur == pdc->pPFFList) { pdc->pPFFList = pPFFCur->pNext; } else { pPFFPrev->pNext = pPFFCur->pNext; } VFREEMEM(pPFFCur); } } return bRet; } /******************************Member*Function*****************************\ * DCMEMOBJ::DCMEMOBJ() * * Allocates RAM for a new DC. Fills the RAM with default values. * * History: * * Fri 07-Dec-1990 -by- Patrick Haluptzok [patrickh] * Adding palette support * * Thu 09-Aug-1990 17:29:25 -by- Charles Whitmer [chuckwh] * Changed a little for NT DDI. * * Fri 01-Sep-1989 04:36:19 -by- Charles Whitmer [chuckwh] * Wrote it. \**************************************************************************/ DCMEMOBJ::DCMEMOBJ( ULONG iType, BOOL bAltType) { pdc = (PDC) NULL; bKeep = FALSE; // // Check the type. // ASSERTGDI((iType == DCTYPE_INFO) || (iType == DCTYPE_MEMORY) || (iType == DCTYPE_DIRECT), "Invalid DC type"); // // Allocate the DC 0 initialized // PDC pdcTemp = pdc = (PDC)HmgAlloc(sizeof(DC), DC_TYPE, HMGR_ALLOC_LOCK); if (pdcTemp != (PDC)NULL) { // // if this is an alternate DC (may need special attention on the client side // due to printing or metafiling) set the type to LO_ALTDC_TYPE from LO_TYPE // if (bAltType) { HmgModifyHandleType((HOBJ)MODIFY_HMGR_TYPE(pdcTemp->hGet(),LO_ALTDC_TYPE)); } pdcTemp->dcattr = DcAttrDefault; pdcTemp->pDCAttr = &pdcTemp->dcattr; pdcTemp->dclevel = dclevelDefault; // // Lock the fill and line brushes we just selected in as part of the // default DC. // (Reference-count the brushes.) // These locks can't fail. // INC_SHARE_REF_CNT(pdc->dclevel.pbrFill); INC_SHARE_REF_CNT(pdc->dclevel.pbrLine); INC_SHARE_REF_CNT(pdc->dclevel.pColorSpace); pdcTemp->dctp((DCTYPE) iType); pdcTemp->fs(0); ASSERTGDI(pdcTemp->hpal() == STOCKOBJ_PAL, "Bad initial hpal for DCMEMOBJ"); ASSERTGDI(pdcTemp->hdcNext() == (HDC) 0, "ERROR this is baddfd343dc"); ASSERTGDI(pdcTemp->hdcPrev() == (HDC) 0, "ERROR this is e43-99crok4"); pdcTemp->ptlFillOrigin(0,0); ulDirty(DIRTY_BRUSHES|DIRTY_CHARSET|DIRTY_COLORSPACE|DIRTY_COLORTRANSFORM); // // Update the pointer to the COLORADJUSTMENT structure for // the 4 EBRUSHOBJ. // COLORADJUSTMENT *pca = pColorAdjustment(); pdcTemp->peboFill()->pColorAdjustment(pca); pdcTemp->peboLine()->pColorAdjustment(pca); pdcTemp->peboText()->pColorAdjustment(pca); pdcTemp->peboBackground()->pColorAdjustment(pca); pdcTemp->prfnt(PRFNTNULL); pdcTemp->hlfntCur(HLFONT_INVALID); pdcTemp->flSimulationFlags(0); ulCopyCount((ULONG)-1); ipfdDevMax(-1); // also reset in bCleanDC pdcTemp->prgnVis(NULL); pdcTemp->vPFFListSet(NULL); pdcTemp->vCXFListSet(NULL); } } /******************************Member*Function*****************************\ * DCMEMOBJ::DCMEMOBJ(&dcobjs) * * Create a new DC and copy in the DC passed to us. This is used by * SaveDC. * * History: * 06-Jan-1990 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ DCMEMOBJ::DCMEMOBJ(DCOBJ& dco) { // // Assume failure. // bKeep = FALSE; // // Allocate the DC, // pdc = (PDC)HmgAlloc(sizeof(DC), DC_TYPE, HMGR_ALLOC_LOCK); if (pdc != (PDC)NULL) { pdc->fs(0); pdc->prgnVis(NULL); pdc->ppdev(dco.pdc->ppdev()); // // shared attrs point to self // pdc->pDCAttr = &pdc->dcattr; dco.pdc->vCopyTo(*this); } } /******************************Member*Function*****************************\ * DCSAVE::vCopyTo * * Carbon copy the DCOBJ * * History: * 24-Apr-1991 -by- Donald Sidoroff [donalds] * Moved it out-of-line. \**************************************************************************/ VOID DC::vCopyTo(XDCOBJ& dco) { // // The dynamic mode changing code needs to be able to dynamically update // some fields in the DCLEVEL, and consequently needs to be able to track // all DCLEVELs. So this routine should be used carefully and under // the appropriate lock to ensure that the dynamic mode change code does // not fall over. We do both because one or the other might not have // set DC_SYNCHRONIZE. // vAssertDynaLock(TRUE); dco.pdc->vAssertDynaLock(TRUE); // // copy dc level and dcattr // *dco.pdc->pDCAttr = *pDCAttr; dco.pdc->dclevel = dclevel; if (dclevel.pufi == dclevel.aQuickLinks) { dco.pdc->dclevel.pufi = dco.pdc->dclevel.aQuickLinks; } else if (dclevel.pufi) { if(dco.pdc->dclevel.pufi = (PUNIVERSAL_FONT_ID) PALLOCMEM(sizeof(UNIVERSAL_FONT_ID) * dclevel.uNumLinkedFonts,'ddaG')) { memcpy(dco.pdc->dclevel.pufi, dclevel.pufi, sizeof(UNIVERSAL_FONT_ID) * dclevel.uNumLinkedFonts); } else { WARNING("GDI: DC::vCopyTo out of memory\n"); dco.pdc->dclevel.uNumLinkedFonts = 0; } } } /******************************Member*Function*****************************\ * DCMEMOBJ::~DCMEMOBJ() * * Frees a DC unless told to keep it. * * History: * Sat 19-Aug-1989 00:30:53 -by- Charles Whitmer [chuckwh] * Wrote it. \**************************************************************************/ DCMEMOBJ::~DCMEMOBJ() { if (pdc != (PDC) NULL) { if (bKeep) { DEC_EXCLUSIVE_REF_CNT(pdc); } else { if (pdc->pDCAttr != &pdc->dcattr) { RIP("ERROR,~DCMEMOBJ on DC with client attrs\n"); } // // shouldn't free DC with client attrs // HmgFree((HOBJ)pdc->hGet()); } pdc = (PDC) NULL; } } /******************************Member*Function*****************************\ * DC::vUpdate_VisRect * * update user-mode vis region bounding rectangle if dirty * * History: * 2/18/99 LingyunW [Lingyun Wang] * Wrote it. \**************************************************************************/ VOID DC::vUpdate_VisRect(REGION *prgn) { // // update user-mode vis region bounding rectangle if dirty // if ((PENTRY_FROM_POBJ(this)->Flags & HMGR_ENTRY_INVALID_VIS)) { if (prgn) { // // setup user-mode region info // RGNOBJ roVis(prgn); pDCAttr->VisRectRegion.Flags = roVis.iComplexity(); if (roVis.iComplexity() == NULLREGION) { // // set pdcatrr vis rgn to NULLRGN // pDCAttr->VisRectRegion.Rect = rclEmpty; } else { PPOINTL pptlWindow = (PPOINTL)prclWindow(); RECTL rcl; roVis.vGet_rcl(&rcl); // // subtract window offset from user-mode region // rcl.left -= pptlWindow->x; rcl.top -= pptlWindow->y; rcl.right -= pptlWindow->x; rcl.bottom -= pptlWindow->y; pDCAttr->VisRectRegion.Rect = rcl; } // // mark DCATTR VIS region as valid // } else { pDCAttr->VisRectRegion.Rect = rclEmpty; } PENTRY_FROM_POBJ(this)->Flags &= ~HMGR_ENTRY_INVALID_VIS; } } /******************************Public*Routine******************************\ * DCREGION::bSetDefaultRegion(x, y) * * Set the default region and erclWindow for bitmaps and surfaces * * History: * 11-Dec-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/ BOOL DC::bSetDefaultRegion() { // Release the old RaoRgn vReleaseRao(); // Get the extents SIZEL sizl; vGet_sizlWindow(&sizl); // Get a rectangle matching the device extents ERECTL ercl(0, 0, sizl.cx, sizl.cy); // // Bug #310012: Under multimon, the rectangle isn't necessarily // based at 0,0. See dcrgn.cxx. // ERECTL erclSurface = ercl; PDEVOBJ pdo(hdev()); ASSERTGDI(pdo.bValid(), "Invalid pdev\n"); { DEVLOCKOBJ dl(pdo); if (pdo.bMetaDriver() && bHasSurface() && pSurface()->bPDEVSurface()) { erclSurface += *pdo.pptlOrigin(); } } // If a VisRgn exists, initialize it, else create a new one if ((prgnVis() != (REGION *) NULL) && (prgnVis() != prgnDefault)) { RGNOBJ ro(prgnVis()); ro.vSet((RECTL *) &erclSurface); } else { RGNMEMOBJ rmoRect; if (!rmoRect.bValid()) { prgnVis(prgnDefault); return(FALSE); } // Set the region to the rectangle rmoRect.vSet((RECTL *) &erclSurface); // Make it long lived prgnVis(rmoRect.prgnGet()); } prgnVis()->vStamp(); eptlOrigin((EPOINTL*) &ercl); // // Note that we don't use erclSurface to set erclWindow. // erclWindow's value is a complete hack, and User won't fix it. // Their code requires that the top left point of erclWindow is equal // to the DC origin. On top of that, they overload the DC origin: e.g. in a // monitor-specific DC for an 800x600 monitor // based at (1024,0), erclWindow is (-1024, 0, -224, 600). Go figure. // erclWindow(&ercl); erclClip(&erclSurface); // Whenever DC origin changes, it affects ptlFillOrigin. Since the origin // was set to zero, we can just copy the brush origin in as the fill origin. // set by user using a DC not owned by the current process ptlFillOrigin(&dcattr.ptlBrushOrigin); return(TRUE); } /******************************Public*Routine******************************\ * BOOL DCPATH::bOldPenNominal(exo, lPenWidth) * * Decides if the old-style (created with CreatePen) pen is a nominal * width pen or a wide line, depending on the current transform. * * History: * 27-Jan-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #define FX_THREE_HALVES (LTOFX(1) + (LTOFX(1) >> 1)) #define FX_THREE_HALVES_SQUARED (FX_THREE_HALVES * FX_THREE_HALVES) BOOL DC::bOldPenNominal( EXFORMOBJ& exo, // Current world-to-device transform LONG lPenWidth) // Pen's width { BOOL bRet = FALSE; if (!(pDCAttr->flXform & WORLD_TRANSFORM_SET)) { // If no world transform set, use the same criteria as does Win3 (namely, // the pen is nominal if the transformed x-value is less than 1.5) EVECTORL evtl(lPenWidth, 0); if (exo.bXform(&evtl, (PVECTORFX) &evtl, 1)) if (ABS(evtl.x) < FX_THREE_HALVES) bRet = TRUE; } else { // A world transform has been set. VECTORL avtl[2]; avtl[0].x = lPenWidth; avtl[0].y = 0; avtl[1].x = 0; avtl[1].y = lPenWidth; // We want to be consistent under rotation when using the // intellectually challenged CreatePen pens, so we go to the trouble // of ensuring that the transformed axes of the pen lie within // a circle of radius 1.5: if (exo.bXform(avtl, (PVECTORFX) avtl, 2)) { // We can kick out most pens with this simple test: if ((MAX(ABS(avtl[0].x), ABS(avtl[0].y)) < FX_THREE_HALVES) && (MAX(ABS(avtl[1].x), ABS(avtl[1].y)) < FX_THREE_HALVES)) // We now know it's safe to compute the square of the // Euclidean lengths in 32-bits without overflow: if (((avtl[0].x * avtl[0].x + avtl[0].y * avtl[0].y) < FX_THREE_HALVES_SQUARED) && ((avtl[1].x * avtl[1].x + avtl[1].y * avtl[1].y) < FX_THREE_HALVES_SQUARED)) bRet = TRUE; } } return(bRet); } /******************************Public*Routine******************************\ * VOID DC::vRealizeLineAttrs(exo) * * Initializes the given LINEATTRS structure. Uses fields from the DC * and the current brush. * * This function will be called as a result of a change in current pen, * or a change in current transform. As a result, we reset the style * state. * * History: * 23-Sep-1992 -by- Donald Sidoroff [donalds] * Added failure case * * 27-Jan-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ VOID DC::vRealizeLineAttrs(EXFORMOBJ& exo) { PPEN ppen = (PPEN) dclevel.pbrLine; LINEATTRS *pla = &dclevel.laPath; // Remember that we've realized the LINEATTRS for this pen: if (ppen->bIsOldStylePen()) { // A pen of width zero is always nominal, regardless of the transform: if ((exo.bIdentity() && ppen->lWidthPen() <= 1) || (ppen->lWidthPen() == 0) || bOldPenNominal(exo, ppen->lWidthPen())) { pla->elWidth.l = 1; // Nominal width line if (ppen->pstyle() != (PFLOAT_LONG) NULL) { pla->cstyle = ppen->cstyle(); // Size of style array pla->pstyle = ppen->pstyle(); pla->fl = LA_STYLED; // Cosmetic, styled } else { pla->cstyle = 0; pla->pstyle = (PFLOAT_LONG) NULL; pla->fl = 0; // Cosmetic, no style } pla->elStyleState.l = 0; // Reset style state } else { pla->fl = LA_GEOMETRIC; // Geometric pla->elWidth.e = ppen->l_eWidthPen(); // Need float value of width pla->cstyle = 0; pla->pstyle = (PFLOAT_LONG) NULL; // Old wide pens are un-styled pla->elStyleState.e = IEEE_0_0F; } } else { // New-style ExtCreatePen pen: if (ppen->bIsCosmetic()) { pla->fl = ppen->bIsAlternate() ? LA_ALTERNATE : 0; pla->elWidth.l = ppen->lWidthPen(); pla->elStyleState.l = 0; } else { pla->fl = LA_GEOMETRIC; pla->elWidth.e = ppen->l_eWidthPen(); pla->elStyleState.e = IEEE_0_0F; } pla->cstyle = ppen->cstyle(); pla->pstyle = ppen->pstyle(); if (pla->pstyle != NULL) { pla->fl |= LA_STYLED; } } pla->iJoin = ppen->iJoin(); pla->iEndCap = ppen->iEndCap(); } /******************************Public*Routine******************************\ * VOID DCOBJ::vAccumulate(ercl) * * Accumulate bounds * * History: * 08-Dec-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID XDCOBJ::vAccumulate(ERECTL& ercl) { if (bAccum()) { erclBounds() |= ercl; } if (bAccumApp()) { erclBoundsApp() |= ercl; } } /******************************Member*Function*****************************\ * DC::bMakeInfoDC * * This routine is used to take a printer DC and temporarily make it a * Metafile DC for spooled printing. This way it can be associated with * an enhanced metafile. During this period, it should look and act just * like an info DC. * * bSet determines if it should be set into the INFO DC state or restored * to the Direct state. * * History: * 06-Jan-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ BOOL DC::bMakeInfoDC( BOOL bSet) { BOOL bRet = FALSE; if (!bDisplay()) { if (bSet) { if (!bTempInfoDC() && (dctp() == DCTYPE_DIRECT)) { vSetTempInfoDC(); dctp(DCTYPE_INFO); vSavePsurfInfo(); // now that this is an info dc, we want it to be the size of // the entire surface PDEVOBJ pdo(hdev()); if ((pdo.sizl().cx != sizl().cx) || (pdo.sizl().cy != sizl().cy)) { sizl(pdo.sizl()); bSetDefaultRegion(); } bRet = TRUE; } else { WARNING("GreMakeInfoDC(TRUE) - already infoDC\n"); } } else { if (bTempInfoDC() && (dctp() == DCTYPE_INFO)) { vClearTempInfoDC(); dctp(DCTYPE_DIRECT); vRestorePsurfInfo(); // back to an direct DC. It needs to be reset to the size of // the surface. (band) if (bHasSurface()) { if ((pSurface()->sizl().cx != sizl().cx) || (pSurface()->sizl().cy != sizl().cy)) { sizl(pSurface()->sizl()); bSetDefaultRegion(); } } bRet = TRUE; } else { WARNING("GreMakeInfoDC(FALSE) - not infoDC\n"); } } } else { WARNING("GreMakeInfoDC - on display dc\n"); } return(bRet); } /******************************Member*Function*****************************\ * DC::vAssertDynaLock() * * This routine verifies that appropriate locks are held before accessing * DC fields that may otherwise be changed asynchronously by the dynamic * mode-change code. * * History: * 06-Feb-1996 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/ #if DBG VOID DC::vAssertDynaLock(BOOL bDcLevelField) { // // One of the following conditions is enough to allow the thread // to safely access fields that may be modified by the dyanmic // mode changing: // // 1. It's an info DC, or a DC with the default bitmap selected in -- // these will not change modes; // 2. It's a DCLEVEL specific field and a DIB is selected in that // doesn't require DevLock locking; // 3. Direct DC's that aren't the display, such as printers -- // these will not dynamically change modes; // 4. That the DEVLOCK is held; // 5. That the Palette semaphore is held; // 6. That the Handle Manager semaphore is held; // 7. That the USER semaphore is held. // #if !defined(_GDIPLUS_) ASSERTGDI(!bHasSurface() || ((bDcLevelField) && !(fs() & DC_SYNCHRONIZEACCESS)) || ((dctp() == DCTYPE_DIRECT) && !bDisplay()) || (GreIsSemaphoreOwnedByCurrentThread(hsemDcDevLock_)) || (GreIsSemaphoreSharedByCurrentThread(ghsemShareDevLock)) || (GreIsSemaphoreOwnedByCurrentThread(ghsemPalette)) || (GreIsSemaphoreOwnedByCurrentThread(ghsemHmgr)) || UserIsUserCritSecIn(), "A dynamic mode change lock must be held to access this field"); #endif } #endif