/* * @implemented */ BOOL APIENTRY EngAlphaBlend(IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN PRECTL DestRect, IN PRECTL SourceRect, IN BLENDOBJ *BlendObj) { RECTL InputRect; RECTL OutputRect; RECTL ClipRect; RECTL CombinedRect; RECTL Rect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeaveSource; INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* InputObj; SURFOBJ* OutputObj; LONG ClippingType; RECT_ENUM RectEnum; BOOL EnumMore; INT i; BOOLEAN Ret; DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest, psoSource, ClipRegion, ColorTranslation); DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n", DestRect->left, DestRect->top, DestRect->right, DestRect->bottom, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj->BlendFunction.BlendOp, BlendObj->BlendFunction.BlendFlags, BlendObj->BlendFunction.SourceConstantAlpha, BlendObj->BlendFunction.AlphaFormat); /* Validate output */ OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } /* Validate input */ InputRect = *SourceRect; if ( (InputRect.top < 0) || (InputRect.bottom < 0) || (InputRect.left < 0) || (InputRect.right < 0) || InputRect.right > psoSource->sizlBitmap.cx || InputRect.bottom > psoSource->sizlBitmap.cy ) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (psoDest == psoSource && !(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right || OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom)) { DPRINT1("Source and destination rectangles overlap!\n"); return FALSE; } if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER) { DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp); return FALSE; } if (BlendObj->BlendFunction.BlendFlags != 0) { DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags); return FALSE; } if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0) { DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat); return FALSE; } /* Check if there is anything to draw */ if (ClipRegion != NULL && (ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right || ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom)) { /* Nothing to do */ return TRUE; } /* Now call the DIB function */ if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) { return FALSE; } OutputRect.left += Translate.x; OutputRect.right += Translate.x; OutputRect.top += Translate.y; OutputRect.bottom += Translate.y; Ret = FALSE; ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity; switch (ClippingType) { case DC_TRIVIAL: Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj); break; case DC_RECT: ClipRect.left = ClipRegion->rclBounds.left + Translate.x; ClipRect.right = ClipRegion->rclBounds.right + Translate.x; ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj); } break; case DC_COMPLEX: Ret = TRUE; CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret; } } } while (EnumMore); break; default: UNIMPLEMENTED; ASSERT(FALSE); break; } IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); return Ret; }
BOOL APIENTRY EngTransparentBlt( SURFOBJ *psoDest, SURFOBJ *psoSource, CLIPOBJ *Clip, XLATEOBJ *ColorTranslation, PRECTL DestRect, PRECTL SourceRect, ULONG iTransColor, ULONG Reserved) { BOOL Ret = TRUE; BYTE ClippingType; INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest; SURFOBJ *InputObj, *OutputObj; RECTL OutputRect, InputRect; POINTL Translate; LONG DstHeight; LONG DstWidth; LONG SrcHeight; LONG SrcWidth; InputRect = *SourceRect; if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.top = DestRect->bottom; OutputRect.bottom = DestRect->top; } if (Clip) { if (OutputRect.left < Clip->rclBounds.left) { InputRect.left += Clip->rclBounds.left - OutputRect.left; OutputRect.left = Clip->rclBounds.left; } if (Clip->rclBounds.right < OutputRect.right) { InputRect.right -= OutputRect.right - Clip->rclBounds.right; OutputRect.right = Clip->rclBounds.right; } if (OutputRect.top < Clip->rclBounds.top) { InputRect.top += Clip->rclBounds.top - OutputRect.top; OutputRect.top = Clip->rclBounds.top; } if (Clip->rclBounds.bottom < OutputRect.bottom) { InputRect.bottom -= OutputRect.bottom - Clip->rclBounds.bottom; OutputRect.bottom = Clip->rclBounds.bottom; } } /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's nothing to do */ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) { IntEngLeave(&EnterLeaveSource); return TRUE; } if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) { IntEngLeave(&EnterLeaveSource); return FALSE; } OutputRect.left = DestRect->left + Translate.x; OutputRect.right = DestRect->right + Translate.x; OutputRect.top = DestRect->top + Translate.y; OutputRect.bottom = DestRect->bottom + Translate.y; ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL); DstHeight = OutputRect.bottom - OutputRect.top; DstWidth = OutputRect.right - OutputRect.left; SrcHeight = InputRect.bottom - InputRect.top; SrcWidth = InputRect.right - InputRect.left; switch (ClippingType) { case DC_TRIVIAL: { Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &OutputRect, &InputRect, ColorTranslation, iTransColor); break; } case DC_RECT: { RECTL ClipRect, CombinedRect; RECTL InputToCombinedRect; ClipRect.left = Clip->rclBounds.left + Translate.x; ClipRect.right = Clip->rclBounds.right + Translate.x; ClipRect.top = Clip->rclBounds.top + Translate.y; ClipRect.bottom = Clip->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor); } break; } case DC_COMPLEX: { ULONG Direction, i; RECT_ENUM RectEnum; BOOL EnumMore; if (OutputObj == InputObj) { if (OutputRect.top < InputRect.top) { Direction = OutputRect.left < (InputRect.left ? CD_RIGHTDOWN : CD_LEFTDOWN); } else { Direction = OutputRect.left < (InputRect.left ? CD_RIGHTUP : CD_LEFTUP); } } else { Direction = CD_ANY; } CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID)&RectEnum); for (i = 0; i < RectEnum.c; i++) { RECTL ClipRect, CombinedRect; RECTL InputToCombinedRect; ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor); if (!Ret) { break; } } } } while (EnumMore && Ret); break; } default: { Ret = FALSE; break; } } IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); return Ret; }
BOOL FASTCALL IntEngGradientFillTriangle( IN SURFOBJ *psoDest, IN CLIPOBJ *pco, IN XLATEOBJ *pxlo, IN TRIVERTEX *pVertex, IN ULONG nVertex, IN PGRADIENT_TRIANGLE gTriangle, IN RECTL *prclExtents, IN POINTL *pptlDitherOrg) { SURFOBJ *psoOutput; PTRIVERTEX v1, v2, v3; //RECT_ENUM RectEnum; //BOOL EnumMore; //ULONG i; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; RECTL FillRect = { 0, 0, 0, 0 }; //ULONG Color; //BOOL sx[NLINES]; //LONG x[NLINES], dx[NLINES], dy[NLINES], incx[NLINES], ex[NLINES], destx[NLINES]; //LONG c[NLINES][3], dc[NLINES][3], ec[NLINES][3], ic[NLINES][3]; /* colors on lines */ //LONG g, gx, gxi, gc[3], gd[3], ge[3], gi[3]; /* colors in triangle */ //LONG sy, y, bt; v1 = (pVertex + gTriangle->Vertex1); v2 = (pVertex + gTriangle->Vertex2); v3 = (pVertex + gTriangle->Vertex3); /* bubble sort */ if (SMALLER(v2, v1)) { TRIVERTEX *t; SWAP(v1, v2, t); } if (SMALLER(v3, v2)) { TRIVERTEX *t; SWAP(v2, v3, t); if (SMALLER(v2, v1)) { SWAP(v1, v2, t); } } DPRINT("Triangle: (%i,%i) (%i,%i) (%i,%i)\n", v1->x, v1->y, v2->x, v2->y, v3->x, v3->y); /* FIXME: commented out because of an endless loop - fix triangles first */ DPRINT("FIXME: IntEngGradientFillTriangle is broken\n"); if (!IntEngEnter(&EnterLeave, psoDest, &FillRect, FALSE, &Translate, &psoOutput)) { return FALSE; } //if (VCMPCLRS(v1, v2, v3)) //{ // CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); // do // { // EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); // for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++) // { // if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents)) // { // BOOL InY; // DOINIT(v1, v3, 0); // DOINIT(v1, v2, 1); // DOINIT(v2, v3, 2); // y = v1->y; // sy = v1->y + pptlDitherOrg->y; // bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom); // while (sy < bt) // { // InY = !(sy < FillRect.top || sy >= FillRect.bottom); // GOLINE(v1, v3, 0); // DOLINE(v1, v3, 0); // ENDLINE(v1, v3, 0); // GOLINE(v1, v2, 1); // DOLINE(v1, v2, 1); // FILLLINE(0, 1); // ENDLINE(v1, v2, 1); // GOLINE(v2, v3, 2); // DOLINE(v2, v3, 2); // FILLLINE(0, 2); // ENDLINE(23, v3, 2); // y++; // sy++; // } // } // } // } while (EnumMore); // return IntEngLeave(&EnterLeave); //} ///* fill triangle with one solid color */ //Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red >> 8, v1->Green >> 8, v1->Blue >> 8)); //CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); //do //{ // EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); // for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++) // { // if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents)) // { // S_INITLINE(v1, v3, 0); // S_INITLINE(v1, v2, 1); // S_INITLINE(v2, v3, 2); // y = v1->y; // sy = v1->y + pptlDitherOrg->y; // bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom); // while (sy < bt) // { // S_GOLINE(v1, v3, 0); // S_DOLINE(v1, v3, 0); // S_ENDLINE(v1, v3, 0); // S_GOLINE(v1, v2, 1); // S_DOLINE(v1, v2, 1); // S_FILLLINE(0, 1); // S_ENDLINE(v1, v2, 1); // S_GOLINE(v2, v3, 2); // S_DOLINE(v2, v3, 2); // S_FILLLINE(0, 2); // S_ENDLINE(23, v3, 2); // y++; // sy++; // } // } // } //} while (EnumMore); return IntEngLeave(&EnterLeave); }
BOOL FASTCALL IntEngGradientFillRect( IN SURFOBJ *psoDest, IN CLIPOBJ *pco, IN XLATEOBJ *pxlo, IN TRIVERTEX *pVertex, IN ULONG nVertex, IN PGRADIENT_RECT gRect, IN RECTL *prclExtents, IN POINTL *pptlDitherOrg, IN BOOL Horizontal) { SURFOBJ *psoOutput; TRIVERTEX *v1, *v2; RECTL rcGradient, rcSG; RECT_ENUM RectEnum; BOOL EnumMore; ULONG i; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; LONG y, dy, c[3], dc[3], ec[3], ic[3]; v1 = (pVertex + gRect->UpperLeft); v2 = (pVertex + gRect->LowerRight); rcGradient.left = min(v1->x, v2->x); rcGradient.right = max(v1->x, v2->x); rcGradient.top = min(v1->y, v2->y); rcGradient.bottom = max(v1->y, v2->y); rcSG = rcGradient; RECTL_vOffsetRect(&rcSG, pptlDitherOrg->x, pptlDitherOrg->y); if(Horizontal) { dy = abs(rcGradient.right - rcGradient.left); } else { dy = abs(rcGradient.bottom - rcGradient.top); } if(!IntEngEnter(&EnterLeave, psoDest, &rcSG, FALSE, &Translate, &psoOutput)) { return FALSE; } if((v1->Red != v2->Red || v1->Green != v2->Green || v1->Blue != v2->Blue) && dy > 1) { CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color; if (Horizontal) { EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.left; y < FillRect.right; y++) { if (y >= FillRect.left) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_VLine( psoOutput, y + Translate.x, FillRect.top + Translate.y, FillRect.bottom + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } continue; } /* vertical */ EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.top; y < FillRect.bottom; y++) { if (y >= FillRect.top) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, y + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); } /* rectangle has only one color, no calculation required */ CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red, v1->Green, v1->Blue)); EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { for (; FillRect.top < FillRect.bottom; FillRect.top++) { DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, FillRect.top + Translate.y, Color); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); }
/* * @implemented */ BOOL APIENTRY EngStretchBltROP( 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, IN BRUSHOBJ *pbo, IN ROP4 Rop4) { RECTL InputRect; RECTL OutputRect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeaveSource; INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* psoInput; SURFOBJ* psoOutput; PSTRETCHRECTFUNC BltRectFunc; BOOLEAN Ret = TRUE; POINTL AdjustedBrushOrigin; BOOL UsesSource = ROP4_USES_SOURCE(Rop4); BYTE clippingType; RECTL ClipRect; RECT_ENUM RectEnum; BOOL EnumMore; ULONG Direction; RECTL CombinedRect; RECTL InputToCombinedRect; unsigned i; LONG DstHeight; LONG DstWidth; LONG SrcHeight; LONG SrcWidth; if (Rop4 == ROP4_NOOP) { /* Copy destination onto itself: nop */ return TRUE; } /* Determine clipping type */ if (ClipRegion == (CLIPOBJ *) NULL) { clippingType = DC_TRIVIAL; } else { clippingType = ClipRegion->iDComplexity; } OutputRect = *prclDest; if (OutputRect.right < OutputRect.left) { OutputRect.left = prclDest->right; OutputRect.right = prclDest->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.top = prclDest->bottom; OutputRect.bottom = prclDest->top; } if (UsesSource) { if (NULL == prclSrc) { return FALSE; } InputRect = *prclSrc; if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &psoInput)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; } else { InputRect.left = 0; InputRect.right = OutputRect.right - OutputRect.left; InputRect.top = 0; InputRect.bottom = OutputRect.bottom - OutputRect.top; psoInput = NULL; } if (NULL != ClipRegion) { if (OutputRect.left < ClipRegion->rclBounds.left) { InputRect.left += ClipRegion->rclBounds.left - OutputRect.left; OutputRect.left = ClipRegion->rclBounds.left; } if (ClipRegion->rclBounds.right < OutputRect.right) { InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right; OutputRect.right = ClipRegion->rclBounds.right; } if (OutputRect.top < ClipRegion->rclBounds.top) { InputRect.top += ClipRegion->rclBounds.top - OutputRect.top; OutputRect.top = ClipRegion->rclBounds.top; } if (ClipRegion->rclBounds.bottom < OutputRect.bottom) { InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom; OutputRect.bottom = ClipRegion->rclBounds.bottom; } } /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's nothing to do */ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) { if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return TRUE; } if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput)) { if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return FALSE; } OutputRect.left += Translate.x; OutputRect.right += Translate.x; OutputRect.top += Translate.y; OutputRect.bottom += Translate.y; if (BrushOrigin) { AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; } else { AdjustedBrushOrigin = Translate; } BltRectFunc = CallDibStretchBlt; DstHeight = OutputRect.bottom - OutputRect.top; DstWidth = OutputRect.right - OutputRect.left; SrcHeight = InputRect.bottom - InputRect.top; SrcWidth = InputRect.right - InputRect.left; switch (clippingType) { case DC_TRIVIAL: Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &OutputRect, &InputRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); break; case DC_RECT: // Clip the blt to the clip rectangle ClipRect.left = ClipRegion->rclBounds.left + Translate.x; ClipRect.right = ClipRegion->rclBounds.right + Translate.x; ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &CombinedRect, &InputToCombinedRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); } break; case DC_COMPLEX: if (psoOutput == psoInput) { if (OutputRect.top < InputRect.top) { Direction = OutputRect.left < InputRect.left ? CD_RIGHTDOWN : CD_LEFTDOWN; } else { Direction = OutputRect.left < InputRect.left ? CD_RIGHTUP : CD_LEFTUP; } } else { Direction = CD_ANY; } CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &CombinedRect, &InputToCombinedRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); } } } while (EnumMore); break; } IntEngLeave(&EnterLeaveDest); if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return Ret; }