/* * @implemented */ BOOL APIENTRY EngStretchBlt( IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN SURFOBJ *Mask, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN COLORADJUSTMENT *pca, IN POINTL *BrushOrigin, IN RECTL *prclDest, IN RECTL *prclSrc, IN POINTL *MaskOrigin, IN ULONG Mode) { return EngStretchBltROP( psoDest, psoSource, Mask, ClipRegion, ColorTranslation, pca, BrushOrigin, prclDest, prclSrc, MaskOrigin, Mode, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); }
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 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)); } }
/* * @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; }
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; }