BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, // FIXME: don't use floating point! double EndArc, ARCTYPE arctype) { PDC_ATTR pdcattr; PBRUSH pbrush; int Start = (int)ceil(StartArc); int End = (int)ceil(EndArc); BOOL Chord = (arctype == GdiTypeChord), ret; pdcattr = dc->pdcattr; pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush); if (!pbrush) { DPRINT1("FillArc Fail\n"); EngSetLastError(ERROR_INTERNAL_ERROR); return FALSE; } // Sort out alignment here. ret = app_fill_arc(dc, rect( XLeft, YLeft, Width, Height), (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start, (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End, pbrush, Chord); BRUSH_ShareUnlockBrush(pbrush); return ret; }
BOOL FASTCALL IntGdiPolyPatBlt( HDC hDC, DWORD dwRop, PPATRECT pRects, INT cRects, ULONG Reserved) { INT i; PBRUSH pbrush; PDC pdc; EBRUSHOBJ eboFill; pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (pdc->dctype == DC_TYPE_INFO) { DC_UnlockDc(pdc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } for (i = 0; i < cRects; i++) { pbrush = BRUSH_ShareLockBrush(pRects->hBrush); /* Check if we could lock the brush */ if (pbrush != NULL) { /* Initialize a brush object */ EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc); IntPatBlt( pdc, pRects->r.left, pRects->r.top, pRects->r.right, pRects->r.bottom, dwRop, &eboFill); /* Cleanup the brush object and unlock the brush */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); } pRects++; } DC_UnlockDc(pdc); return TRUE; }
BOOL APIENTRY NtGdiPatBlt( HDC hDC, INT XLeft, INT YLeft, INT Width, INT Height, DWORD ROP) { PBRUSH pbrush; DC *dc; PDC_ATTR pdcattr; BOOL ret; BOOL UsesSource = ROP_USES_SOURCE(ROP); if (UsesSource) { /* In this case we call on GdiMaskBlt */ return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0); } dc = DC_LockDc(hDC); if (dc == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); DPRINT1("NtGdiPatBlt on info DC!\n"); /* Yes, Windows really returns TRUE in this case */ return TRUE; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush); if (pbrush == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); DC_UnlockDc(dc); return FALSE; } ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush); BRUSH_ShareUnlockBrush(pbrush); DC_UnlockDc(dc); return ret; }
INIT_FUNCTION NTSTATUS NTAPI InitDcImpl() { psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]); if (!psurfDefaultBitmap) return STATUS_UNSUCCESSFUL; pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]); if (!pbrDefaultBrush) return STATUS_UNSUCCESSFUL; return STATUS_SUCCESS; }
BOOL FASTCALL IntGdiPolyPatBlt( HDC hDC, DWORD dwRop, PPATRECT pRects, INT cRects, ULONG Reserved) { INT i; PBRUSH pbrush; PDC pdc; pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (pdc->dctype == DC_TYPE_INFO) { DC_UnlockDc(pdc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } for (i = 0; i < cRects; i++) { pbrush = BRUSH_ShareLockBrush(pRects->hBrush); if(pbrush != NULL) { IntPatBlt( pdc, pRects->r.left, pRects->r.top, pRects->r.right, pRects->r.bottom, dwRop, pbrush); BRUSH_ShareUnlockBrush(pbrush); } pRects++; } DC_UnlockDc(pdc); return TRUE; }
VOID NTAPI DC_vSetOwner(PDC pdc, ULONG ulOwner) { if (pdc->rosdc.hClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner); } if (pdc->rosdc.hGCClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner); } if (pdc->dclevel.hPath) { GreSetObjectOwner(pdc->dclevel.hPath, ulOwner); } /* Dereference current brush and pen */ BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); /* Select the default fill and line brush */ pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; pdc->dcattr.hpen = StockObjects[BLACK_PEN]; pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); /* Mark them as dirty */ pdc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE; /* Allocate or free DC attribute */ if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE) { if (pdc->pdcattr != &pdc->dcattr) DC_vFreeDcAttr(pdc); } else if (ulOwner == GDI_OBJ_HMGR_POWNED) { if (pdc->pdcattr == &pdc->dcattr) DC_bAllocDcAttr(pdc); } /* Set the DC's ownership */ GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner); }
VOID FASTCALL DC_vUpdateFillBrush(PDC pdc) { PDC_ATTR pdcattr = pdc->pdcattr; PBRUSH pbrFill; /* Check if the brush handle has changed */ if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr) { /* Try to lock the new brush */ pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); if (pbrFill) { /* Unlock old brush, set new brush */ BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); pdc->dclevel.pbrFill = pbrFill; /* Mark eboFill as dirty */ pdcattr->ulDirty_ |= DIRTY_FILL; } else { /* Invalid brush handle, restore old one */ pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr; } } /* Check if the EBRUSHOBJ needs update */ if (pdcattr->ulDirty_ & DIRTY_FILL) { /* Update eboFill */ EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc); } /* Check for DC brush */ if (pdcattr->hbrush == StockObjects[DC_BRUSH]) { /* ROS HACK, should use surf xlate */ /* Update the eboFill's solid color */ EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, pdcattr->crPenClr); } /* Clear flags */ pdcattr->ulDirty_ &= ~(DIRTY_FILL | DC_BRUSH_DIRTY); }
BOOL FASTCALL IntRoundRect( PDC dc, int Left, int Top, int Right, int Bottom, int xCurveDiameter, int yCurveDiameter) { PDC_ATTR pdcattr; PBRUSH pbrLine, pbrFill; RECTL RectBounds; LONG PenWidth, PenOrigWidth; BOOL ret = TRUE; // Default to success BRUSH brushTemp; ASSERT ( dc ); // Caller's responsibility to set this up if ( PATH_IsPathOpen(dc->dclevel) ) return PATH_RoundRect ( dc, Left, Top, Right, Bottom, xCurveDiameter, yCurveDiameter ); if ((Left == Right) || (Top == Bottom)) return TRUE; xCurveDiameter = max(abs( xCurveDiameter ), 1); yCurveDiameter = max(abs( yCurveDiameter ), 1); if (Right < Left) { INT tmp = Right; Right = Left; Left = tmp; } if (Bottom < Top) { INT tmp = Bottom; Bottom = Top; Top = tmp; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); pbrLine = PEN_ShareLockPen(pdcattr->hpen); if (!pbrLine) { /* Nothing to do, as we don't have a bitmap */ EngSetLastError(ERROR_INTERNAL_ERROR); return FALSE; } PenOrigWidth = PenWidth = pbrLine->ptPenWidth.x; if (pbrLine->ulPenStyle == PS_NULL) PenWidth = 0; if (pbrLine->ulPenStyle == PS_INSIDEFRAME) { if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2; if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2; Left += PenWidth / 2; Right -= (PenWidth - 1) / 2; Top += PenWidth / 2; Bottom -= (PenWidth - 1) / 2; } if (!PenWidth) PenWidth = 1; pbrLine->ptPenWidth.x = PenWidth; RectBounds.left = Left; RectBounds.top = Top; RectBounds.right = Right; RectBounds.bottom = Bottom; IntLPtoDP(dc, (LPPOINT)&RectBounds, 2); RectBounds.left += dc->ptlDCOrig.x; RectBounds.top += dc->ptlDCOrig.y; RectBounds.right += dc->ptlDCOrig.x; RectBounds.bottom += dc->ptlDCOrig.y; pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); if (!pbrFill) { DPRINT1("FillRound Fail\n"); EngSetLastError(ERROR_INTERNAL_ERROR); ret = FALSE; } else { DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds); RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp)); brushTemp.ptOrigin.x += RectBounds.left - Left; brushTemp.ptOrigin.y += RectBounds.top - Top; ret = IntFillRoundRect( dc, RectBounds.left, RectBounds.top, RectBounds.right, RectBounds.bottom, xCurveDiameter, yCurveDiameter, &brushTemp); BRUSH_ShareUnlockBrush(pbrFill); if (ret) { ret = IntDrawRoundRect( dc, RectBounds.left, RectBounds.top, RectBounds.right, RectBounds.bottom, xCurveDiameter, yCurveDiameter, pbrLine); } DC_vFinishBlit(dc, NULL); } pbrLine->ptPenWidth.x = PenOrigWidth; PEN_ShareUnlockPen(pbrLine); return ret; }
BOOL APIENTRY NtGdiEllipse( HDC hDC, int Left, int Top, int Right, int Bottom) { PDC dc; PDC_ATTR pdcattr; RECTL RectBounds; PBRUSH pbrush; BOOL ret = TRUE; LONG PenWidth, PenOrigWidth; LONG RadiusX, RadiusY, CenterX, CenterY; PBRUSH pFillBrushObj; BRUSH tmpFillBrushObj; if ((Left == Right) || (Top == Bottom)) return TRUE; dc = DC_LockDc(hDC); if (dc == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (PATH_IsPathOpen(dc->dclevel)) { ret = PATH_Ellipse(dc, Left, Top, Right, Bottom); DC_UnlockDc(dc); return ret; } if (Right < Left) { INT tmp = Right; Right = Left; Left = tmp; } if (Bottom < Top) { INT tmp = Bottom; Bottom = Top; Top = tmp; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); pbrush = PEN_ShareLockPen(pdcattr->hpen); if (!pbrush) { DPRINT1("Ellipse Fail 1\n"); DC_UnlockDc(dc); EngSetLastError(ERROR_INTERNAL_ERROR); return FALSE; } PenOrigWidth = PenWidth = pbrush->ptPenWidth.x; if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0; if (pbrush->ulPenStyle == PS_INSIDEFRAME) { if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2; if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2; Left += PenWidth / 2; Right -= (PenWidth - 1) / 2; Top += PenWidth / 2; Bottom -= (PenWidth - 1) / 2; } if (!PenWidth) PenWidth = 1; pbrush->ptPenWidth.x = PenWidth; RectBounds.left = Left; RectBounds.right = Right; RectBounds.top = Top; RectBounds.bottom = Bottom; IntLPtoDP(dc, (LPPOINT)&RectBounds, 2); RectBounds.left += dc->ptlDCOrig.x; RectBounds.right += dc->ptlDCOrig.x; RectBounds.top += dc->ptlDCOrig.y; RectBounds.bottom += dc->ptlDCOrig.y; // Setup for dynamic width and height. RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2); CenterX = (RectBounds.right + RectBounds.left) / 2; CenterY = (RectBounds.bottom + RectBounds.top) / 2; DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n", RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom); DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n", CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2); pFillBrushObj = BRUSH_ShareLockBrush(pdcattr->hbrush); if (NULL == pFillBrushObj) { DPRINT1("FillEllipse Fail\n"); EngSetLastError(ERROR_INTERNAL_ERROR); ret = FALSE; } else { RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj)); //tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left; //tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top; tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x; tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y; DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds); ret = IntFillEllipse( dc, CenterX - RadiusX, CenterY - RadiusY, RadiusX*2, // Width RadiusY*2, // Height &tmpFillBrushObj); BRUSH_ShareUnlockBrush(pFillBrushObj); if (ret) { ret = IntDrawEllipse( dc, CenterX - RadiusX, CenterY - RadiusY, RadiusX*2, // Width RadiusY*2, // Height pbrush); } DC_vFinishBlit(dc, NULL); } pbrush->ptPenWidth.x = PenOrigWidth; PEN_ShareUnlockPen(pbrush); DC_UnlockDc(dc); DPRINT("Ellipse Exit.\n"); return ret; }
VOID NTAPI DC_vInitDc( PDC pdc, DCTYPE dctype, PPDEVOBJ ppdev) { /* Setup some basic fields */ pdc->dctype = dctype; pdc->ppdev = ppdev; pdc->dhpdev = ppdev->dhpdev; pdc->hsem = ppdev->hsemDevLock; pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps; pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2; pdc->fs = DC_DIRTY_RAO; /* Setup dc attribute */ pdc->pdcattr = &pdc->dcattr; pdc->dcattr.pvLDC = NULL; pdc->dcattr.ulDirty_ = DIRTY_DEFAULT; if (ppdev == gppdevPrimary) pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY; /* Setup the DC size */ if (dctype == DCTYPE_MEMORY) { /* Memory DCs have a 1 x 1 bitmap by default */ pdc->dclevel.sizl.cx = 1; pdc->dclevel.sizl.cy = 1; } else { /* Other DC's are as big as the related PDEV */ pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes; pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes; } /* Setup Window rect based on DC size */ pdc->erclWindow.left = 0; pdc->erclWindow.top = 0; pdc->erclWindow.right = pdc->dclevel.sizl.cx; pdc->erclWindow.bottom = pdc->dclevel.sizl.cy; if (dctype == DCTYPE_DIRECT) { /* Direct DCs get the surface from the PDEV */ pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev); pdc->erclBounds.left = 0x7fffffff; pdc->erclBounds.top = 0x7fffffff; pdc->erclBounds.right = 0x80000000; pdc->erclBounds.bottom = 0x80000000; pdc->erclBoundsApp.left = 0xffffffff; pdc->erclBoundsApp.top = 0xfffffffc; pdc->erclBoundsApp.right = 0x00007ffc; // FIXME pdc->erclBoundsApp.bottom = 0x00000333; // FIXME pdc->erclClip = pdc->erclBounds; pdc->co = gxcoTrivial; pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY; } else { /* Non-direct DCs don't have a surface by default */ pdc->dclevel.pSurface = NULL; pdc->erclBounds.left = 0; pdc->erclBounds.top = 0; pdc->erclBounds.right = 0; pdc->erclBounds.bottom = 0; pdc->erclBoundsApp = pdc->erclBounds; pdc->erclClip = pdc->erclWindow; pdc->co = gxcoTrivial; } //pdc->dcattr.VisRectRegion: /* Setup coordinate transformation data */ pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault; pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault; pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault; pdc->dclevel.efM11PtoD = gef16; pdc->dclevel.efM22PtoD = gef16; pdc->dclevel.efDxPtoD = gef0; pdc->dclevel.efDyPtoD = gef0; pdc->dclevel.efM11_TWIPS = gef0; pdc->dclevel.efM22_TWIPS = gef0; pdc->dclevel.efPr11 = gef0; pdc->dclevel.efPr22 = gef0; pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice; pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld; pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage; pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD; pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD; pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD; pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD; pdc->dcattr.iMapMode = MM_TEXT; pdc->dcattr.dwLayout = 0; pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY | PAGE_TO_DEVICE_IDENTITY | WORLD_TO_PAGE_IDENTITY; /* Setup more coordinates */ pdc->ptlDCOrig.x = 0; pdc->ptlDCOrig.y = 0; pdc->dcattr.lWindowOrgx = 0; pdc->dcattr.ptlWindowOrg.x = 0; pdc->dcattr.ptlWindowOrg.y = 0; pdc->dcattr.szlWindowExt.cx = 1; pdc->dcattr.szlWindowExt.cy = 1; pdc->dcattr.ptlViewportOrg.x = 0; pdc->dcattr.ptlViewportOrg.y = 0; pdc->dcattr.szlViewportExt.cx = 1; pdc->dcattr.szlViewportExt.cy = 1; pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes; pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes; pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize; pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize; pdc->dcattr.szlVirtualDeviceSize.cx = 0; pdc->dcattr.szlVirtualDeviceSize.cy = 0; /* Setup regions */ pdc->prgnAPI = NULL; pdc->prgnRao = NULL; pdc->dclevel.prgnClip = NULL; pdc->dclevel.prgnMeta = NULL; /* Allocate a Vis region */ pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy); ASSERT(pdc->prgnVis); /* Initialize Clip object */ IntEngInitClipObj(&pdc->co); /* Setup palette */ pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE]; pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal); /* Setup path */ pdc->dclevel.hPath = NULL; pdc->dclevel.flPath = 0; // pdc->dclevel.lapath: /* Setup colors */ pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.crForegroundClr = RGB(0, 0, 0); pdc->dcattr.ulForegroundClr = RGB(0, 0, 0); pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff); pdc->dcattr.crPenClr = RGB(0, 0, 0); pdc->dcattr.ulPenClr = RGB(0, 0, 0); /* Select the default fill and line brush */ pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; pdc->dcattr.hpen = StockObjects[BLACK_PEN]; pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); pdc->dclevel.ptlBrushOrigin.x = 0; pdc->dclevel.ptlBrushOrigin.y = 0; pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin; /* Initialize EBRUSHOBJs */ EBRUSHOBJ_vInitFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc); EBRUSHOBJ_vInitFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc); EBRUSHOBJ_vInitFromDC(&pdc->eboText, pbrDefaultBrush, pdc); EBRUSHOBJ_vInitFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc); /* Setup fill data */ pdc->dcattr.jROP2 = R2_COPYPEN; pdc->dcattr.jBkMode = 2; pdc->dcattr.lBkMode = 2; pdc->dcattr.jFillMode = ALTERNATE; pdc->dcattr.lFillMode = 1; pdc->dcattr.jStretchBltMode = 1; pdc->dcattr.lStretchBltMode = 1; pdc->ptlFillOrigin.x = 0; pdc->ptlFillOrigin.y = 0; /* Setup drawing position */ pdc->dcattr.ptlCurrent.x = 0; pdc->dcattr.ptlCurrent.y = 0; pdc->dcattr.ptfxCurrent.x = 0; pdc->dcattr.ptfxCurrent.y = 0; /* Setup ICM data */ pdc->dclevel.lIcmMode = 0; pdc->dcattr.lIcmMode = 0; pdc->dcattr.hcmXform = NULL; pdc->dcattr.flIcmFlags = 0; pdc->dcattr.IcmBrushColor = CLR_INVALID; pdc->dcattr.IcmPenColor = CLR_INVALID; pdc->dcattr.pvLIcm = NULL; pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f pdc->dclevel.pColorSpace = NULL; // FIXME pdc->pClrxFormLnk = NULL; // pdc->dclevel.ca = /* Setup font data */ pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8 pdc->pPFFList = NULL; pdc->flSimulationFlags = 0; pdc->lEscapement = 0; pdc->prfnt = NULL; pdc->dcattr.flFontMapper = 0; pdc->dcattr.flTextAlign = 0; pdc->dcattr.lTextAlign = 0; pdc->dcattr.lTextExtra = 0; pdc->dcattr.lRelAbs = 1; pdc->dcattr.lBreakExtra = 0; pdc->dcattr.cBreak = 0; pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT]; pdc->dclevel.plfnt = LFONT_ShareLockFont(pdc->dcattr.hlfntNew); /* Other stuff */ pdc->hdcNext = NULL; pdc->hdcPrev = NULL; pdc->ipfdDevMax = 0; pdc->ulCopyCount = -1; pdc->ptlDoBanding.x = 0; pdc->ptlDoBanding.y = 0; pdc->dclevel.lSaveDepth = 1; pdc->dclevel.hdcSave = NULL; pdc->dcattr.iGraphicsMode = GM_COMPATIBLE; pdc->dcattr.iCS_CP = 0; pdc->pSurfInfo = NULL; if (defaultDCstate == NULL) { defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC); ASSERT(defaultDCstate); RtlZeroMemory(defaultDCstate, sizeof(DC)); defaultDCstate->pdcattr = &defaultDCstate->dcattr; DC_vCopyState(pdc, defaultDCstate, TRUE); } }
/* Mostly inspired from wine code. * We use low level functions because: * - at this point, the icon bitmap could have a different bit depth than the DC, * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap. * This happens after a mode setting change. * - it avoids massive GDI objects locking when only the destination surface needs it. * - It makes (small) performance gains. */ BOOL UserDrawIconEx( HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL; PDC pdc = NULL; BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor, hbmAlpha; BOOL bOffScreen; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; /* Stupid case */ if((diFlags & DI_NORMAL) == 0) { ERR("DrawIconEx called without mask or color bitmap to draw.\n"); return FALSE; } if (pIcon->CURSORF_flags & CURSORF_ACON) { ACON* pAcon = (ACON*)pIcon; if(istepIfAniCur >= pAcon->cicur) { ERR("NtUserDrawIconEx: istepIfAniCur too big!\n"); return FALSE; } pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]]; } hbmMask = pIcon->hbmMask; hbmColor = pIcon->hbmColor; hbmAlpha = pIcon->hbmAlpha; /* * Get our objects. * Shared locks are enough, we are only reading those bitmaps */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if(psurfMask == NULL) { ERR("Unable to lock the mask surface.\n"); return FALSE; } /* Color bitmap is not mandatory */ if(hbmColor == NULL) { /* But then the mask bitmap must have the information in it's bottom half */ ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy); psurfColor = NULL; } else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL) { ERR("Unable to lock the color bitmap.\n"); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } pdc = DC_LockDc(hDc); if(!pdc) { ERR("Could not lock the destination DC.\n"); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Prepare the underlying surface */ DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; if(psurfDest == NULL) { /* Empty DC */ DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy); /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) cxWidth = is_icon(pIcon) ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->cx; } /* Fix height parameter, if needed */ if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) cyHeight = is_icon(pIcon) ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->cy; } /* Should we render off-screen? */ bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); if (bOffScreen) { /* Yes: Allocate and paint the offscreen surface */ EBRUSHOBJ eboFill; PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw); TRACE("Performing off-screen rendering.\n"); if(!pbrush) { ERR("Failed to get brush object.\n"); goto Cleanup; } #if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat, 0, 0, NULL); if(!psurfOffScreen) { ERR("Failed to allocate the off-screen surface.\n"); BRUSH_ShareUnlockBrush(pbrush); goto Cleanup; } /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL); RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight); Ret = IntEngBitBlt(&psurfOffScreen->SurfObj, NULL, NULL, NULL, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } /* We now have our destination surface */ psurfDest = psurfOffScreen; #else pdcClipObj = pdc->rosdc.CombinedClip; /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL); Ret = IntEngBitBlt(&psurfDest->SurfObj, NULL, NULL, pdcClipObj, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } #endif } else { /* We directly draw to the DC */ TRACE("Performing on screen rendering.\n"); pdcClipObj = pdc->rosdc.CombinedClip; // psurfOffScreen = NULL; } /* Now do the rendering */ if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; PSURFACE psurf = NULL; psurf = SURFACE_ShareLockSurface(hbmAlpha); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); goto NoAlpha; } /* Initialize color translation object */ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0); /* Now do it */ Ret = IntEngAlphaBlend(&psurfDest->SurfObj, &psurf->SurfObj, pdcClipObj, &exlo.xlo, &rcDest, &rcSrc, &blendobj); EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurf); if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } NoAlpha: if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to mask the bitmap data.\n"); goto Cleanup; } } if(diFlags & DI_IMAGE) { if (psurfColor) { DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ; EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfColor->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } else { /* Mask bitmap holds the information in its bottom half */ DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY; RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy); EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } } done: #if 0 /* We're done. Was it a double buffered draw ? */ if(bOffScreen) { /* Yes. Draw it back to our DC */ POINTL ptSrc = {0, 0}; /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; /* Color translation */ EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); /* Blt it! */ Ret = IntEngBitBlt(&psurfDest->SurfObj, &psurfOffScreen->SurfObj, NULL, pdcClipObj, &exlo.xlo, &rcDest, &ptSrc, NULL, NULL, NULL, ROP4_SRCCOPY); EXLATEOBJ_vCleanup(&exlo); } #endif Cleanup: if(pdc) { DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); } #if 0 /* Delete off screen rendering surface */ if(psurfOffScreen) GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); #endif /* Unlock other surfaces */ SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return Ret; }