static void dumpPCO(RECTL *prclTrg, CLIPOBJ *pco) { LOG(("pco = %p Trg = %d-%d %d-%d", pco, prclTrg->left, prclTrg->right, prclTrg->top, prclTrg->bottom)); if (pco) { BOOL bMore; CLIPRECTS cr; RECTL* prclClip; int cRects = 0; LOG(("pco = %d %d-%d %d-%d dc %d fc %d mode %d opt %d", pco->iUniq, pco->rclBounds.left, pco->rclBounds.right, pco->rclBounds.top, pco->rclBounds.bottom, pco->iDComplexity, pco->iFComplexity, pco->iMode, pco->fjOptions)); CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0); do { bMore = CLIPOBJ_bEnum(pco, sizeof(cr), (ULONG*)&cr); for (prclClip = &cr.arcl[0]; cr.c != 0; cr.c--, prclClip++) { LOG((" %d-%d %d-%d", prclClip->left, prclClip->right, prclClip->top, prclClip->bottom)); cRects++; } } while (bMore); LOG(("Total %d rects", cRects)); } }
/* * @implemented */ BOOL APIENTRY WNDOBJ_bEnum( IN WNDOBJ *pwo, IN ULONG cj, OUT ULONG *pul) { WNDGDI *WndObjInt = ObjToGDI(pwo, WND); BOOL Ret; DPRINT("WNDOBJ_bEnum: pwo = 0x%p, cj = %lu, pul = 0x%p\n", pwo, cj, pul); Ret = CLIPOBJ_bEnum(WndObjInt->ClientClipObj, cj, pul); DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret ? "True" : "False"); return Ret; }
BOOL APIENTRY EngPaintRgn(SURFOBJ *pso, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix, BRUSHOBJ *BrushObj, POINTL *BrushPoint) { RECT_ENUM RectEnum; BOOL EnumMore; ULONG i; ASSERT(pso); ASSERT(ClipRegion); DPRINT("ClipRegion->iMode:%u, ClipRegion->iDComplexity: %u\n Color: %lu", ClipRegion->iMode, ClipRegion->iDComplexity, iColor); switch(ClipRegion->iMode) { case TC_RECTANGLES: /* Rectangular clipping can be handled without enumeration. Note that trivial clipping is not possible, since the clipping region defines the area to fill */ if (ClipRegion->iDComplexity == DC_RECT) { FillSolid(pso, &(ClipRegion->rclBounds), iColor); } else { /* Enumerate all the rectangles and draw them */ CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { FillSolid(pso, RectEnum.arcl + i, iColor); } } while (EnumMore); } return(TRUE); default: return(FALSE); } }
static int vrdpGetIntersectingClipRects(VRDPCLIPRECTS *pClipRects, SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco, POINTL *pptlSrc) { BOOL bTooManyRects = FALSE; LOGF(("pso = %p, pptlSrc = %p", pso, pptlSrc)); pso = getSurfObj(pso); pClipRects->rclDstOrig = *prcl; pClipRects->rclDst = *prcl; pClipRects->rects.c = 0; vrdpAdjustRect(pso, &pClipRects->rclDst); if (pco && (pco->iDComplexity != DC_TRIVIAL)) { ULONG iDirection = CD_ANY; if (pptlSrc) { /* Operation is performed on the same (screen) surface and enumeration direction * must take into account the position of source and target rectangles. */ if (pptlSrc->x <= prcl->left) { if (pptlSrc->y <= prcl->top) { iDirection = CD_LEFTUP; } else { iDirection = CD_LEFTDOWN; } } else { if (pptlSrc->y <= prcl->top) { iDirection = CD_RIGHTUP; } else { iDirection = CD_RIGHTDOWN; } } } /* Clip the target rect by entire clipping region. Obtain the effective target. */ vrdpIntersectRects(&pClipRects->rclDst, &pClipRects->rclDst, &pco->rclBounds); /* Enumerate rectangles. Try to get all rectangles at once and if there is not * enough space (too many rectangles) fail with the bTooManyRects condition. */ CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0); bTooManyRects = CLIPOBJ_bEnum(pco, sizeof(pClipRects->rects), &pClipRects->rects.c); if (!bTooManyRects) { RECTL *prclClipSrc = &pClipRects->rects.arcl[0]; RECTL *prclClipDst = prclClipSrc; ULONG cRects = pClipRects->rects.c; LOGF(("%d rects", cRects)); if (cRects > 0) { for (; cRects != 0; cRects--, prclClipSrc++) { vrdpIntersectRects(prclClipDst, prclClipSrc, &pClipRects->rclDst); if (vrdpIsRectEmpty(prclClipDst)) { pClipRects->rects.c--; } else { prclClipDst++; } } } if (pClipRects->rects.c == 0) { pClipRects->rclDst.left = pClipRects->rclDst.right = 0; } LOGF(("%d rects remains", pClipRects->rects.c)); } } if (vrdpIsRectEmpty(&pClipRects->rclDst)) { return VRDP_CLIP_NO_INTERSECTION; } if (bTooManyRects) { pClipRects->rects.c = 0; return VRDP_CLIP_TOO_MANY_RECTS; } return VRDP_CLIP_OK; }
static void FASTCALL vgaSWtoNE( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c && (y < ClipRect->top || (y < ClipRect->bottom && ClipRect->right <= x))) || EnumMore) { if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if (ClipRect < RectEnum.arcl + RectEnum.c) { if (ClipRect->left <= x && y < ClipRect->bottom) vgaPutPixel(x, y, Pixel); if (deltax < deltay) { y--; error = error + deltax; if (deltay <= error) { x++; error = error - deltay; } } else { x++; error = error + deltay; if (deltax <= error) { y--; error = error - deltax; } } i++; } } }
/* * FIXME: Use Mix to perform ROPs * FIXME: Non-solid Brush */ BOOL APIENTRY DrvLineTo( IN SURFOBJ *DestObj, IN CLIPOBJ *Clip, IN BRUSHOBJ *Brush, IN LONG x1, IN LONG y1, IN LONG x2, IN LONG y2, IN RECTL *RectBounds, IN MIX mix) { LONG x, y, deltax, deltay, xchange, ychange, hx, vy; ULONG i; ULONG Pixel = Brush->iSolidColor; RECT_ENUM RectEnum; BOOL EnumMore; x = x1; y = y1; deltax = x2 - x1; deltay = y2 - y1; if (deltax < 0) { xchange = -1; deltax = - deltax; hx = x2+1; //x--; } else { xchange = 1; hx = x1; } if (deltay < 0) { ychange = -1; deltay = - deltay; vy = y2+1; //y--; } else { ychange = 1; vy = y1; } if (y1 == y2) { CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++) { if (y1 < RectEnum.arcl[i].bottom && RectEnum.arcl[i].left <= hx + deltax && hx < RectEnum.arcl[i].right) { vgaHLine(max(hx, RectEnum.arcl[i].left), y1, min(hx + deltax, RectEnum.arcl[i].right) -max(hx, RectEnum.arcl[i].left), Pixel); } } } while (EnumMore); } else if (x1 == x2) { CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { if (RectEnum.arcl[i].left <= x1 && x1 < RectEnum.arcl[i].right && RectEnum.arcl[i].top <= vy + deltay && vy < RectEnum.arcl[i].bottom) { vgaVLine(x1, max(vy, RectEnum.arcl[i].top), min(vy + deltay, RectEnum.arcl[i].bottom) - max(vy, RectEnum.arcl[i].top), Pixel); } } } while (EnumMore); } else { if (0 < xchange) { if (0 < ychange) vgaNWtoSE(Clip, Brush, x, y, deltax, deltay); else vgaSWtoNE(Clip, Brush, x, y, deltax, deltay); } else { if (0 < ychange) vgaNEtoSW(Clip, Brush, x, y, deltax, deltay); else vgaSEtoNW(Clip, Brush, x, y, deltax, deltay); } } return TRUE; }
/* * Draw a line from top-left to bottom-right */ static void FASTCALL vgaNWtoSE( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */ && (ClipRect->bottom <= y /* but it's above us */ || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */ || EnumMore) /* no current clip rect, but rects left */ { /* Skip to the next clip rect */ if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */ { if (ClipRect->left <= x && ClipRect->top <= y) vgaPutPixel ( x, y, Pixel ); if ( deltax < deltay ) { y++; error += deltax; if ( error >= deltay ) { x++; error -= deltay; } } else { x++; error += deltay; if ( error >= deltax ) { y++; error -= deltax; } } i++; } } }
/* * @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 DrvCopyBits( SURFOBJ *psoDst, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclDst, POINTL *pptlSrc) /*++ Routine Description: Code for "hooking" CopyBits function for Jaguar VXL. Arguments: Return Value: --*/ { RECTL BltRectl; ENUMRECTLIST ClipEnum; BYTE FixedComplexity; BOOL MoreClipRects; FLONG BltDir; BOOL JaguarDir; ULONG ClipRegions; POINTL SrcPoint; // // Check that there is no color translation. // if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) { // // Check that source and destination surfaces are the frame buffer. // if ((psoSrc->pvBits == (PVOID)Vxl.ScreenBase) && (psoDst->pvBits == (PVOID)Vxl.ScreenBase)) { // // check BLT direction for setting up clip regions // And for Jaguar BitBlt Commands as follows: // - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom // to Top except when Src & Dst are in the same scan line // and BltDir is not LEFTWARDS // BltDir = 0; JaguarDir = FALSE; if (pptlSrc->y <= prclDst->top) { BltDir = CD_UPWARDS; JaguarDir = TRUE; } if (pptlSrc->x <= prclDst->left) { BltDir |= CD_LEFTWARDS; } else { if ((JaguarDir) && (pptlSrc->y == prclDst->top)) { JaguarDir = FALSE; } } // // Figure out the real clipping complexity // if (pco == (CLIPOBJ *)NULL) { FixedComplexity = DC_TRIVIAL; } else { FixedComplexity = pco->iDComplexity; } switch (FixedComplexity) { // // Entire destination is to be updated. // Proceed with the BitBlt. // case DC_TRIVIAL: DrvpBitBlt(prclDst, // Target rectangle pptlSrc, // Source offset JaguarDir // Direction ); return(TRUE); // // Only one clip region. // case DC_RECT: // // only do the BLT if there is an intersection // if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) { // // Adjust the Source for the intersection rectangle. // pptlSrc->x += BltRectl.left - prclDst->left; pptlSrc->y += BltRectl.top - prclDst->top; DrvpBitBlt(&BltRectl, // Target rectangle pptlSrc, // Source offset JaguarDir // Direction ); } return(TRUE); // // Multiple clip regions. // case DC_COMPLEX: CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT); do { // // Get list of clip rectangles. // MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum); for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) { // // If the rectangles intersect calculate the offset to the // source start location to match and do the BitBlt. // if (DrvpIntersectRect(prclDst, &ClipEnum.arcl[ClipRegions], &BltRectl)) { SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left; SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top; DrvpBitBlt(&BltRectl, // Target rectangle &SrcPoint, // Source offset JaguarDir // Direction ); } } } while (MoreClipRects); return(TRUE); // // Unknown Clip complexity // default: break; } // end switch complexity } } // // If the copy operation could be performed by the accelerator, // this routine has already returned. // If execution falls here, call the Engine routine. // No need to Synchronize here since the Eng routine will call DrvSyncrhonize. // return EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc); }
BOOL DrvBitBlt( IN SURFOBJ *psoDst, // Target surface IN SURFOBJ *psoSrc, // Source surface IN SURFOBJ *psoMask, // Mask IN CLIPOBJ *pco, // Clip through this IN XLATEOBJ *pxlo, // Color translation IN PRECTL prclDst, // Target offset and extent IN PPOINTL pptlSrc, // Source offset IN PPOINTL pptlMask, // Mask offset IN BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush) IN PPOINTL pptlBrush, // Brush offset (origin) IN ROP4 rop4 // Raster operation ) /*++ Routine Description: Code for "hooking" Bit Blt functions for Jaguar VXL. Arguments: Return Value: --*/ { FLONG BltDir; BOOL JaguarDir; RECTL BltRectl; ENUMRECTLIST ClipEnum; BOOL MoreClipRects; ULONG ClipRegions; POINTL SrcPoint; PPDEV ppdev = (PPDEV) psoDst->dhpdev; BYTE FixedComplexity; // // Check that there is no color translation. // if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) { // // Check that the blt operation has the screen as target surface. // if (psoDst->pvBits == (PVOID)Vxl.ScreenBase) { // // Check for rops that Jaguar handles. // Solid Fills, // SRCCOPPY // switch(rop4) { case 0x00000000: // DDx (BLACKNESS) DrvpSolidFill(prclDst,pco,0); return(TRUE); case 0x0000FFFF: // DDxn (WHITENESS) DrvpSolidFill(prclDst,pco,0xFFFFFF); return(TRUE); case 0x0000F0F0: // P (PATCOPY) case 0x00000F0F: // Pn (NOTPATCOPY) // // This is a pattern fill. Check if the brush pattern // is just a plain color, in this case procede with the // Solid Color Fill. // if (pdbrush->iSolidColor != 0xFFFFFFFF) { DrvpSolidFill(prclDst, pco, (rop4 == 0xF0F) ? ~(pdbrush->iSolidColor) : pdbrush->iSolidColor); return(TRUE); } break; // // Source copy // case 0x0000CCCC: // // Check that Source and Destination Surfaces are the same. // This is enough as we already checked that the dst is the frame buffer // if (psoDst->pvBits == psoSrc->pvBits) { // // check BLT direction for setting up clip regions // And for Jaguar BitBlt Commands as follows: // - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom // to Top except when Src & Dst are in the same scan line // and BltDir is not LEFTWARDS // BltDir = 0; JaguarDir = FALSE; if (pptlSrc->y <= prclDst->top) { BltDir = CD_UPWARDS; JaguarDir = TRUE; } if (pptlSrc->x <= prclDst->left) { BltDir |= CD_LEFTWARDS; } else { if ((JaguarDir) && (pptlSrc->y == prclDst->top)) { JaguarDir = FALSE; } } // // Figure out the real clipping complexity // if (pco == (CLIPOBJ *)NULL) { FixedComplexity = DC_TRIVIAL; } else { FixedComplexity = pco->iDComplexity; } switch (FixedComplexity) { // // Entire destination is to be updated. // Proceed with the BitBlt. // case DC_TRIVIAL: DrvpBitBlt(prclDst, // Target rectangle pptlSrc, // Source offset JaguarDir // Direction ); return(TRUE); // // Only one clip region. // case DC_RECT: // // only do the BLT if there is an intersection // if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) { // // Adjust the Source for the intersection rectangle. // pptlSrc->x += BltRectl.left - prclDst->left; pptlSrc->y += BltRectl.top - prclDst->top; DrvpBitBlt(&BltRectl, // Target rectangle pptlSrc, // Source offset JaguarDir // Direction ); } return(TRUE); // // Multiple clip regions. // case DC_COMPLEX: CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT); do { // // Get list of clip rectangles. // MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum); for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) { // // If the rectangles intersect calculate the offset to the // source start location to match and do the BitBlt. // if (DrvpIntersectRect(prclDst, &ClipEnum.arcl[ClipRegions], &BltRectl)) { SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left; SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top; DrvpBitBlt(&BltRectl, // Target rectangle &SrcPoint, // Source offset JaguarDir // Direction ); } } } while (MoreClipRects); return(TRUE); // // Unknown Clip complexity // default: break; } // end switch complexity } // end if Src surface = Dst surface } // end switch rop4 } } // // Call GDI to do the Blt for us. No need to syncrhonize here since // EngXXX routines call DrvSynchronize. // return(EngBitBlt(psoDst, // Target surface psoSrc, // Source surface psoMask, // Mask pco, // Clip through this pxlo, // Color translation prclDst, // Target offset and extent pptlSrc, // Source offset pptlMask, // Mask offset pdbrush, // Brush data (from cbRealizeBrush) pptlBrush, // Brush offset (origin) rop4 // Raster operation ) ); }
VOID DrvpSolidFill( IN PRECTL DstRect, IN CLIPOBJ *pco, IN ULONG Color ) /*++ Routine Description: This routine fills the unclipped areas of the destination rectangle with the given color. Arguments: DstRect - Destination Rectangle pco - Clipping area. Color - Color to fill with. Return Value: None. --*/ { RECTL BltRectl; ENUMRECTLIST ClipEnum; BOOL MoreClipRects; ULONG ClipRegions; BYTE FixedComplexity; // // Figure out the real clipping complexity // if (pco == (CLIPOBJ *)NULL) { FixedComplexity = DC_TRIVIAL; } else { FixedComplexity = pco->iDComplexity; } switch (FixedComplexity) { // // Entire destination is to be updated. // Proceed with the Solid Fill. // case DC_TRIVIAL: DrvpFillRectangle(DstRect, // Target rectangle Color); // Color break; // // Only one clip region. // case DC_RECT: // // only do the Fill if there is an intersection // if (DrvpIntersectRect(DstRect,&pco->rclBounds,&BltRectl)) { DrvpFillRectangle(&BltRectl, // Target rectangle Color); // Color } break; // // Multiple clip regions. // case DC_COMPLEX: CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,CD_ANY,BB_RECT_LIMIT); do { // // Get list of clip rectangles. // MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum); for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) { // // If the rectangles intersect do the fill // if (DrvpIntersectRect(DstRect, &ClipEnum.arcl[ClipRegions], &BltRectl)) { DrvpFillRectangle(&BltRectl, // Target rectangle Color); // Color } } } while (MoreClipRects); break; } // end switch complexity }
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 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; }
/* * @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; }
VOID vClipSolid( PDEV* ppdev, LONG crcl, RECTL* prcl, ULONG iColor, CLIPOBJ* pco) { BOOL bMore; // Flag for clip enumeration CLIPENUM ce; // Clip enumeration object ULONG i; ULONG j; RECTL arclTmp[4]; ULONG crclTmp; RECTL* prclTmp; RECTL* prclClipTmp; LONG iLastBottom; RECTL* prclClip; RBRUSH_COLOR rbc; ASSERTDD((crcl > 0) && (crcl <= 4), "Expected 1 to 4 rectangles"); ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL), "Expected a non-null clip object"); rbc.iSolidColor = iColor; if (pco->iDComplexity == DC_RECT) { crcl = cIntersect(&pco->rclBounds, prcl, crcl); if (crcl != 0) { (ppdev->pfnFillSolid)(ppdev, crcl, prcl, OVERPAINT, OVERPAINT, rbc, NULL); } } else // iDComplexity == DC_COMPLEX { // Bottom of last rectangle to fill iLastBottom = prcl[crcl - 1].bottom; // Initialize the clip rectangle enumeration to right-down so we can // take advantage of the rectangle list being right-down: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); // Scan through all the clip rectangles, looking for intersects // of fill areas with region rectangles: do { // Get a batch of region rectangles: bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*)&ce); // Clip the rect list to each region rect: for (j = ce.c, prclClip = ce.arcl; j-- > 0; prclClip++) { // Since the rectangles and the region enumeration are both // right-down, we can zip through the region until we reach // the first fill rect, and are done when we've passed the // last fill rect. if (prclClip->top >= iLastBottom) { // Past last fill rectangle; nothing left to do: return; } // Do intersection tests only if we've reached the top of // the first rectangle to fill: if (prclClip->bottom > prcl->top) { // We've reached the top Y scan of the first rect, so // it's worth bothering checking for intersection. // Generate a list of the rects clipped to this region // rect: prclTmp = prcl; prclClipTmp = arclTmp; for (i = crcl, crclTmp = 0; i-- != 0; prclTmp++) { // Intersect fill and clip rectangles if (bIntersect(prclTmp, prclClip, prclClipTmp)) { // Add to list if anything's left to draw: crclTmp++; prclClipTmp++; } } // Draw the clipped rects if (crclTmp != 0) { (ppdev->pfnFillSolid)(ppdev, crclTmp, &arclTmp[0], OVERPAINT, OVERPAINT, rbc, NULL); } } } } while (bMore); } }
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); }