VOID NTAPI IntHideMousePointer( _Inout_ PDEVOBJ *ppdev, _Inout_ SURFOBJ *psoDest) { GDIPOINTER *pgp; POINTL pt; RECTL rclDest; POINTL ptlSave; ASSERT(ppdev); ASSERT(psoDest); pgp = &ppdev->Pointer; if (!pgp->Enabled) { return; } pgp->Enabled = FALSE; if (!pgp->psurfSave) { DPRINT("No SaveSurface!\n"); return; } /* Calculate cursor coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; rclDest.left = max(pt.x, 0); rclDest.top = max(pt.y, 0); rclDest.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx); rclDest.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy); ptlSave.x = rclDest.left - pt.x; ptlSave.y = rclDest.top - pt.y; IntEngBitBlt(psoDest, &pgp->psurfSave->SurfObj, NULL, NULL, NULL, &rclDest, &ptlSave, &ptlSave, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); }
VOID NTAPI IntShowMousePointer( _Inout_ PDEVOBJ *ppdev, _Inout_ SURFOBJ *psoDest) { GDIPOINTER *pgp; POINTL pt; RECTL rclSurf, rclPointer; ASSERT(ppdev); ASSERT(psoDest); pgp = &ppdev->Pointer; if (pgp->Enabled) { return; } pgp->Enabled = TRUE; /* Check if we have any mouse pointer */ if (!pgp->psurfSave) return; /* Calculate pointer coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; /* Calculate the rect on the surface */ rclSurf.left = max(pt.x, 0); rclSurf.top = max(pt.y, 0); rclSurf.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx); rclSurf.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy); /* Calculate the rect in the pointer bitmap */ rclPointer.left = rclSurf.left - pt.x; rclPointer.top = rclSurf.top - pt.y; rclPointer.right = min(pgp->Size.cx, psoDest->sizlBitmap.cx - pt.x); rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y); /* Copy the pixels under the cursor to temporary surface. */ IntEngBitBlt(&pgp->psurfSave->SurfObj, psoDest, NULL, NULL, NULL, &rclPointer, (POINTL*)&rclSurf, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); /* Blt the pointer on the screen. */ if (pgp->psurfColor) { if(!(pgp->flags & SPS_ALPHA)) { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_SRCAND); IntEngBitBlt(psoDest, &pgp->psurfColor->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_SRCINVERT); } else { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; EXLATEOBJ exlo; EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppdev->ppalSurf, 0, 0, 0); IntEngAlphaBlend(psoDest, &pgp->psurfColor->SurfObj, NULL, &exlo.xlo, &rclSurf, &rclPointer, &blendobj); EXLATEOBJ_vCleanup(&exlo); } } else { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); rclPointer.top += pgp->Size.cy; IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } }
BOOL FASTCALL IntPatBlt( PDC pdc, INT XLeft, INT YLeft, INT Width, INT Height, DWORD dwRop, PEBRUSHOBJ pebo) { RECTL DestRect; SURFACE *psurf; POINTL BrushOrigin; BOOL ret; PBRUSH pbrush; ASSERT(pebo); pbrush = pebo->pbrush; ASSERT(pbrush); FIXUP_ROP(dwRop); if (pbrush->flAttrs & BR_IS_NULL) { return TRUE; } if (Width > 0) { DestRect.left = XLeft; DestRect.right = XLeft + Width; } else { DestRect.left = XLeft + Width + 1; DestRect.right = XLeft + 1; } if (Height > 0) { DestRect.top = YLeft; DestRect.bottom = YLeft + Height; } else { DestRect.top = YLeft + Height + 1; DestRect.bottom = YLeft + 1; } IntLPtoDP(pdc, (LPPOINT)&DestRect, 2); DestRect.left += pdc->ptlDCOrig.x; DestRect.top += pdc->ptlDCOrig.y; DestRect.right += pdc->ptlDCOrig.x; DestRect.bottom += pdc->ptlDCOrig.y; #ifdef _USE_DIBLIB_ BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft; #else BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y; #endif DC_vPrepareDCsForBlit(pdc, &DestRect, NULL, NULL); psurf = pdc->dclevel.pSurface; ret = IntEngBitBlt( &psurf->SurfObj, NULL, NULL, &pdc->co.ClipObj, NULL, &DestRect, NULL, NULL, &pebo->BrushObject, &BrushOrigin, ROP_TO_ROP4(dwRop)); DC_vFinishBlit(pdc, NULL); return ret; }
BOOL FASTCALL IntRectangle(PDC dc, int LeftRect, int TopRect, int RightRect, int BottomRect) { SURFACE *psurf = NULL; PBRUSH pbrLine, pbrFill; BOOL ret = FALSE; // Default to failure RECTL DestRect; MIX Mix; PDC_ATTR pdcattr; POINTL BrushOrigin; ASSERT ( dc ); // Caller's responsibility to set this up pdcattr = dc->pdcattr; // Rectangle Path only. if ( PATH_IsPathOpen(dc->dclevel) ) { return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect ); } /* Make sure rectangle is not inverted */ DestRect.left = min(LeftRect, RightRect); DestRect.right = max(LeftRect, RightRect); DestRect.top = min(TopRect, BottomRect); DestRect.bottom = max(TopRect, BottomRect); IntLPtoDP(dc, (LPPOINT)&DestRect, 2); DestRect.left += dc->ptlDCOrig.x; DestRect.right += dc->ptlDCOrig.x; DestRect.top += dc->ptlDCOrig.y; DestRect.bottom += dc->ptlDCOrig.y; /* In GM_COMPATIBLE, don't include bottom and right edges */ if (pdcattr->iGraphicsMode == GM_COMPATIBLE) { DestRect.right--; DestRect.bottom--; } DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect); if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); pbrFill = dc->dclevel.pbrFill; pbrLine = dc->dclevel.pbrLine; if (!pbrLine) { ret = FALSE; goto cleanup; } psurf = dc->dclevel.pSurface; if (!psurf) { ret = FALSE; goto cleanup; } if (pbrFill) { if (!(pbrFill->flAttrs & BR_IS_NULL)) { BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin); BrushOrigin.x += dc->ptlDCOrig.x; BrushOrigin.y += dc->ptlDCOrig.y; ret = IntEngBitBlt(&psurf->SurfObj, NULL, NULL, dc->rosdc.CombinedClip, NULL, &DestRect, NULL, NULL, &dc->eboFill.BrushObject, &BrushOrigin, ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); } } // Draw the rectangle with the current pen ret = TRUE; // Change default to success if (!(pbrLine->flAttrs & BR_IS_NULL)) { Mix = ROP2_TO_MIX(pdcattr->jROP2); ret = ret && IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, DestRect.left, DestRect.top, DestRect.right, DestRect.top, &DestRect, // Bounding rectangle Mix); ret = ret && IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, DestRect.right, DestRect.top, DestRect.right, DestRect.bottom, &DestRect, // Bounding rectangle Mix); ret = ret && IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom, &DestRect, // Bounding rectangle Mix); ret = ret && IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, DestRect.left, DestRect.bottom, DestRect.left, DestRect.top, &DestRect, // Bounding rectangle Mix); } cleanup: DC_vFinishBlit(dc, NULL); /* Move current position in DC? MSDN: The current position is neither used nor updated by Rectangle. */ return ret; }
VOID NTAPI IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) { GDIPOINTER *pgp; POINTL pt; RECTL rclSurf, rclPointer; ASSERT(ppdev); ASSERT(psoDest); pgp = &ppdev->Pointer; if (pgp->Enabled) { return; } pgp->Enabled = TRUE; /* Check if we have any mouse pointer */ if (!pgp->psurfSave) return; /* Calculate pointer coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; /* Calculate the rect on the surface */ rclSurf.left = max(pt.x, 0); rclSurf.top = max(pt.y, 0); rclSurf.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx); rclSurf.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy); /* Calculate the rect in the pointer bitmap */ rclPointer.left = rclSurf.left - pt.x; rclPointer.top = rclSurf.top - pt.y; rclPointer.right = min(pgp->Size.cx, psoDest->sizlBitmap.cx - pt.x); rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y); /* Copy the pixels under the cursor to temporary surface. */ IntEngBitBlt(&pgp->psurfSave->SurfObj, psoDest, NULL, NULL, NULL, &rclPointer, (POINTL*)&rclSurf, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); /* Blt the pointer on the screen. */ if (pgp->psurfColor) { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); IntEngBitBlt(psoDest, &pgp->psurfColor->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } else { IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); rclPointer.top += pgp->Size.cy; IntEngBitBlt(psoDest, &pgp->psurfMask->SurfObj, NULL, NULL, NULL, &rclSurf, (POINTL*)&rclPointer, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } }
BOOL APIENTRY NtGdiMaskBlt( HDC hdcDest, INT nXDest, INT nYDest, INT nWidth, INT nHeight, HDC hdcSrc, INT nXSrc, INT nYSrc, HBITMAP hbmMask, INT xMask, INT yMask, DWORD dwRop, IN DWORD crBackColor) { PDC DCDest; PDC DCSrc = NULL; HDC ahDC[2]; PGDIOBJ apObj[2]; PDC_ATTR pdcattr = NULL; SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; RECTL DestRect, SourceRect; POINTL SourcePoint, MaskPoint; BOOL Status = FALSE; EXLATEOBJ exlo; XLATEOBJ *XlateObj = NULL; BOOL UsesSource; FIXUP_ROP(dwRop); // FIXME: why do we need this??? //DPRINT1("dwRop : 0x%08x\n", dwRop); UsesSource = ROP_USES_SOURCE(dwRop); if (!hdcDest || (UsesSource && !hdcSrc)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Check if we need a mask and have a mask bitmap */ if (ROP_USES_MASK(dwRop) && (hbmMask != NULL)) { /* Reference the mask bitmap */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if (psurfMask == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* Make sure the mask bitmap is 1 BPP */ if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) { EngSetLastError(ERROR_INVALID_PARAMETER); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } } else { /* We use NULL, if we need a mask, the Eng function will take care of that and use the brushobject to get a mask */ psurfMask = NULL; } MaskPoint.x = xMask; MaskPoint.y = yMask; /* Take care of source and destination bitmap */ TRACE("Locking DCs\n"); ahDC[0] = hdcDest; ahDC[1] = UsesSource ? hdcSrc : NULL; if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; ASSERT(DCDest); if (NULL == DCDest) { if(DCSrc) DC_UnlockDc(DCSrc); WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest); return FALSE; } if (DCDest->dctype == DC_TYPE_INFO) { if(DCSrc) DC_UnlockDc(DCSrc); DC_UnlockDc(DCDest); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (UsesSource) { ASSERT(DCSrc); if (DCSrc->dctype == DC_TYPE_INFO) { DC_UnlockDc(DCDest); DC_UnlockDc(DCSrc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } } pdcattr = DCDest->pdcattr; DestRect.left = nXDest; DestRect.top = nYDest; DestRect.right = nXDest + nWidth; DestRect.bottom = nYDest + nHeight; IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); DestRect.left += DCDest->ptlDCOrig.x; DestRect.top += DCDest->ptlDCOrig.y; DestRect.right += DCDest->ptlDCOrig.x; DestRect.bottom += DCDest->ptlDCOrig.y; SourcePoint.x = nXSrc; SourcePoint.y = nYSrc; if (UsesSource) { IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); SourcePoint.x += DCSrc->ptlDCOrig.x; SourcePoint.y += DCSrc->ptlDCOrig.y; /* Calculate Source Rect */ SourceRect.left = SourcePoint.x; SourceRect.top = SourcePoint.y; SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; } else { SourceRect.left = 0; SourceRect.top = 0; SourceRect.right = 0; SourceRect.bottom = 0; } /* Prepare blit */ DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(DCDest); /* Determine surfaces to be used in the bitblt */ BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) goto cleanup; if (UsesSource) { { BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) goto cleanup; } } /* Create the XLATEOBJ. */ if (UsesSource) { EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); XlateObj = &exlo.xlo; } /* Perform the bitblt operation */ Status = IntEngBitBlt(&BitmapDest->SurfObj, BitmapSrc ? &BitmapSrc->SurfObj : NULL, psurfMask ? &psurfMask->SurfObj : NULL, &DCDest->co.ClipObj, XlateObj, &DestRect, &SourcePoint, &MaskPoint, &DCDest->eboFill.BrushObject, &DCDest->dclevel.pbrFill->ptOrigin, ROP_TO_ROP4(dwRop)); if (UsesSource) EXLATEOBJ_vCleanup(&exlo); cleanup: DC_vFinishBlit(DCDest, DCSrc); if (UsesSource) { DC_UnlockDc(DCSrc); } DC_UnlockDc(DCDest); if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask); return Status; }
/* * @implemented */ BOOL APIENTRY EngCopyBits( _In_ SURFOBJ *psoDest, _In_ SURFOBJ *psoSource, _In_opt_ CLIPOBJ *Clip, _In_opt_ XLATEOBJ *ColorTranslation, _In_ RECTL *DestRect, _In_ POINTL *SourcePoint) { BOOL ret; BYTE clippingType; RECT_ENUM RectEnum; BOOL EnumMore; BLTINFO BltInfo; SURFACE *psurfDest; SURFACE *psurfSource; RECTL rclDest = *DestRect; POINTL ptlSrc = *SourcePoint; ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL); psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); /* Clip dest rect against source surface size / source point */ if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left) rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x; if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top) rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y; /* Clip dest rect against target surface size */ if (rclDest.right > psoDest->sizlBitmap.cx) rclDest.right = psoDest->sizlBitmap.cx; if (rclDest.bottom > psoDest->sizlBitmap.cy) rclDest.bottom = psoDest->sizlBitmap.cy; if (RECTL_bIsEmptyRect(&rclDest)) return TRUE; DestRect = &rclDest; // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead, // mark the copy block function to be DrvCopyBits instead of the // GDI's copy bit function so as to remove clipping from the // driver's responsibility // If one of the surfaces isn't managed by the GDI if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP)) { // Destination surface is device managed if (psoDest->iType!=STYPE_BITMAP) { /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ if (psurfDest->flags & HOOK_COPYBITS) { ret = GDIDEVFUNCS(psoDest).CopyBits( psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); goto cleanup; } } // Source surface is device managed if (psoSource->iType!=STYPE_BITMAP) { /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ if (psurfSource->flags & HOOK_COPYBITS) { ret = GDIDEVFUNCS(psoSource).CopyBits( psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); goto cleanup; } } // If CopyBits wasn't hooked, BitBlt must be ret = IntEngBitBlt(psoDest, psoSource, NULL, Clip, ColorTranslation, DestRect, SourcePoint, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); goto cleanup; } // Determine clipping type if (!Clip) { clippingType = DC_TRIVIAL; } else { clippingType = Clip->iDComplexity; } BltInfo.DestSurface = psoDest; BltInfo.SourceSurface = psoSource; BltInfo.PatternSurface = NULL; BltInfo.XlateSourceToDest = ColorTranslation; BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY); switch (clippingType) { case DC_TRIVIAL: BltInfo.DestRect = *DestRect; BltInfo.SourcePoint = *SourcePoint; ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); break; case DC_RECT: // Clip the blt to the clip rectangle RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds); BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); break; case DC_COMPLEX: CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); if (RectEnum.c > 0) { RECTL* prclEnd = &RectEnum.arcl[RectEnum.c]; RECTL* prcl = &RectEnum.arcl[0]; do { RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect); BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo)) { ret = FALSE; goto cleanup; } prcl++; } while (prcl < prclEnd); } } while (EnumMore); ret = TRUE; break; default: ASSERT(FALSE); ret = FALSE; break; } cleanup: return ret; }
BOOL APIENTRY IntEngStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSource, SURFOBJ *MaskSurf, CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, COLORADJUSTMENT *pca, RECTL *DestRect, RECTL *SourceRect, POINTL *pMaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, DWORD Rop4) { BOOLEAN ret; POINTL MaskOrigin = {0, 0}; SURFACE *psurfDest; //SURFACE *psurfSource = NULL; RECTL InputClippedRect; RECTL InputRect; RECTL OutputRect; BOOL UsesSource = ROP4_USES_SOURCE(Rop4); LONG InputClWidth, InputClHeight, InputWidth, InputHeight; ASSERT(psoDest); //ASSERT(psoSource); // FIXME! ASSERT(DestRect); //ASSERT(SourceRect); // FIXME! //ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME! /* If no clip object is given, use trivial one */ if (!ClipRegion) ClipRegion = &gxcoTrivial.ClipObj; psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); /* Sanity check */ ASSERT(IS_VALID_ROP4(Rop4)); /* Check if source and dest size are equal */ if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) && ((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top))) { /* Pass the request to IntEngBitBlt */ return IntEngBitBlt(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, DestRect, (PPOINTL)SourceRect, pMaskOrigin, pbo, BrushOrigin, Rop4); } InputClippedRect = *DestRect; if (InputClippedRect.right < InputClippedRect.left) { InputClippedRect.left = DestRect->right; InputClippedRect.right = DestRect->left; } if (InputClippedRect.bottom < InputClippedRect.top) { InputClippedRect.top = DestRect->bottom; InputClippedRect.bottom = DestRect->top; } if (NULL == SourceRect || NULL == psoSource) { return FALSE; } InputRect = *SourceRect; if (InputRect.right < InputRect.left || InputRect.bottom < InputRect.top) { /* Everything clipped away, nothing to do */ return TRUE; } if (ClipRegion->iDComplexity != DC_TRIVIAL) { if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &ClipRegion->rclBounds)) { return TRUE; } /* Update source rect */ InputClWidth = InputClippedRect.right - InputClippedRect.left; InputClHeight = InputClippedRect.bottom - InputClippedRect.top; InputWidth = InputRect.right - InputRect.left; InputHeight = InputRect.bottom - InputRect.top; InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth; InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth; InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight; InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight; } else { OutputRect = InputClippedRect; } if (pMaskOrigin != NULL) { MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y; } /* No success yet */ ret = FALSE; if (UsesSource) { //psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); } /* Call the driver's DrvStretchBlt if available */ if (psurfDest->flags & HOOK_STRETCHBLTROP) { /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */ ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, pca, BrushOrigin, &OutputRect, &InputRect, &MaskOrigin, COLORONCOLOR, pbo, Rop4); } if (! ret) { ret = EngStretchBltROP(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, pca, BrushOrigin, &OutputRect, &InputRect, &MaskOrigin, COLORONCOLOR, pbo, Rop4); } return ret; }
int FASTCALL IntFillRect( DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush, BOOL Pen) { DWORD ROP = ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY); RECTL DestRect; SURFACE *psurf; POINTL BrushOrigin; BOOL Ret = TRUE; PDC_ATTR pdcattr; ASSERT(pbrush); psurf = dc->dclevel.pSurface; if (psurf == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return 0; } if (!(pbrush->flAttrs & BR_IS_NULL)) { pdcattr = dc->pdcattr; /* Fix negative spaces */ if (Width < 0) { XLeft += Width; Width = 0 - Width; } if (Height < 0) { YLeft += Height; Height = 0 - Height; } DestRect.left = XLeft; DestRect.right = XLeft + Width; DestRect.top = YLeft; DestRect.bottom = YLeft + Height; BrushOrigin.x = pbrush->ptOrigin.x; BrushOrigin.y = pbrush->ptOrigin.y; if (pdcattr->jROP2 == R2_XORPEN) ROP = ROP4_FROM_INDEX(R3_OPINDEX_PATINVERT); Ret = IntEngBitBlt( &psurf->SurfObj, NULL, NULL, dc->rosdc.CombinedClip, NULL, &DestRect, NULL, NULL, Pen ? &dc->eboLine.BrushObject : &dc->eboFill.BrushObject, &BrushOrigin, ROP); } return (int)Ret; }
BOOL FASTCALL IntPatBlt( PDC pdc, INT XLeft, INT YLeft, INT Width, INT Height, DWORD dwRop, PBRUSH pbrush) { RECTL DestRect; SURFACE *psurf; EBRUSHOBJ eboFill ; POINTL BrushOrigin; BOOL ret; ASSERT(pbrush); FIXUP_ROP(dwRop); if (pbrush->flAttrs & GDIBRUSH_IS_NULL) { return TRUE; } if (Width > 0) { DestRect.left = XLeft; DestRect.right = XLeft + Width; } else { DestRect.left = XLeft + Width + 1; DestRect.right = XLeft + 1; } if (Height > 0) { DestRect.top = YLeft; DestRect.bottom = YLeft + Height; } else { DestRect.top = YLeft + Height + 1; DestRect.bottom = YLeft + 1; } IntLPtoDP(pdc, (LPPOINT)&DestRect, 2); DestRect.left += pdc->ptlDCOrig.x; DestRect.top += pdc->ptlDCOrig.y; DestRect.right += pdc->ptlDCOrig.x; DestRect.bottom += pdc->ptlDCOrig.y; #ifdef _USE_DIBLIB_ BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft; #else BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x; BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y; #endif DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect); psurf = pdc->dclevel.pSurface; if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(pdc); EBRUSHOBJ_vInit(&eboFill, pbrush, pdc); ret = IntEngBitBlt( &psurf->SurfObj, NULL, NULL, pdc->rosdc.CombinedClip, NULL, &DestRect, NULL, NULL, &eboFill.BrushObject, &BrushOrigin, ROP_TO_ROP4(dwRop)); DC_vFinishBlit(pdc, NULL); EBRUSHOBJ_vCleanup(&eboFill); return ret; }
/* 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; }