BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *MaskSurf, SURFOBJ *PatternSurface, RECTL *DestRect, RECTL *SourceRect, POINTL *MaskOrigin, BRUSHOBJ *Brush, POINTL *BrushOrigin, XLATEOBJ *ColorTranslation, ROP4 ROP) { LONG sx = 0; LONG sy = 0; LONG DesX; LONG DesY; LONG DstHeight; LONG DstWidth; LONG SrcHeight; LONG SrcWidth; LONG MaskCy; LONG SourceCy; ULONG Color; ULONG Dest, Source = 0, Pattern = 0; ULONG xxBPPMask; BOOLEAN CanDraw; PFN_DIB_GetPixel fnSource_GetPixel = NULL; PFN_DIB_GetPixel fnDest_GetPixel = NULL; PFN_DIB_PutPixel fnDest_PutPixel = NULL; PFN_DIB_GetPixel fnPattern_GetPixel = NULL; PFN_DIB_GetPixel fnMask_GetPixel = NULL; LONG PatternX = 0, PatternY = 0; BOOL UsesSource = ROP4_USES_SOURCE(ROP); BOOL UsesPattern = ROP4_USES_PATTERN(ROP); ASSERT(IS_VALID_ROP4(ROP)); fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel; fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel; DPRINT("Dest BPP: %u, dstRect: (%d,%d)-(%d,%d)\n", BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); if (UsesSource) { SourceCy = abs(SourceSurf->sizlBitmap.cy); fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel; DPRINT("Source BPP: %u, srcRect: (%d,%d)-(%d,%d)\n", BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); } if (MaskSurf) { fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel; MaskCy = abs(MaskSurf->sizlBitmap.cy); } DstHeight = DestRect->bottom - DestRect->top; DstWidth = DestRect->right - DestRect->left; SrcHeight = SourceRect->bottom - SourceRect->top; SrcWidth = SourceRect->right - SourceRect->left; /* FIXME: MaskOrigin? */ switch(DestSurf->iBitmapFormat) { case BMF_1BPP: xxBPPMask = 0x1; break; case BMF_4BPP: xxBPPMask = 0xF; break; case BMF_8BPP: xxBPPMask = 0xFF; break; case BMF_16BPP: xxBPPMask = 0xFFFF; break; case BMF_24BPP: xxBPPMask = 0xFFFFFF; break; default: xxBPPMask = 0xFFFFFFFF; } if (UsesPattern) { if (PatternSurface) { PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy; if (PatternY < 0) { PatternY += PatternSurface->sizlBitmap.cy; } fnPattern_GetPixel = DibFunctionsForBitmapFormat[PatternSurface->iBitmapFormat].DIB_GetPixel; } else { if (Brush) Pattern = Brush->iSolidColor; } } for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++) { if (PatternSurface) { PatternX = (DestRect->left - BrushOrigin->x) % PatternSurface->sizlBitmap.cx; if (PatternX < 0) { PatternX += PatternSurface->sizlBitmap.cx; } } if (UsesSource) sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight; for (DesX = DestRect->left; DesX < DestRect->right; DesX++) { CanDraw = TRUE; if (fnMask_GetPixel) { sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; if (sx < 0 || sy < 0 || MaskSurf->sizlBitmap.cx < sx || MaskCy < sy || fnMask_GetPixel(MaskSurf, sx, sy) != 0) { CanDraw = FALSE; } } if (UsesSource && CanDraw) { sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; if (sx >= 0 && sy >= 0 && SourceSurf->sizlBitmap.cx > sx && SourceCy > sy) { Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy)); } else { Source = 0; CanDraw = ((ROP & 0xFF) != R3_OPINDEX_SRCCOPY); } } if (CanDraw) { if (UsesPattern && PatternSurface) { Pattern = fnPattern_GetPixel(PatternSurface, PatternX, PatternY); PatternX++; PatternX %= PatternSurface->sizlBitmap.cx; } Dest = fnDest_GetPixel(DestSurf, DesX, DesY); Color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask; fnDest_PutPixel(DestSurf, DesX, DesY, Color); } } if (PatternSurface) { PatternY++; PatternY %= PatternSurface->sizlBitmap.cy; } } return TRUE; }
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; }