1 /* 2 * PROJECT: ReactOS Win32k subsystem 3 * LICENSE: See COPYING in the top level directory 4 * FILE: win32ss/gdi/dib/stretchblt.c 5 * PURPOSE: StretchBlt implementation suitable for all bit depths 6 * PROGRAMMERS: Magnus Olsen 7 * Evgeniy Boltik 8 * Gregor Schneider 9 * Doug Lyons 10 */ 11 12 #include <win32k.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *MaskSurf, 18 SURFOBJ *PatternSurface, 19 RECTL *DestRect, RECTL *SourceRect, 20 POINTL *MaskOrigin, BRUSHOBJ *Brush, 21 POINTL *BrushOrigin, XLATEOBJ *ColorTranslation, 22 ROP4 ROP) 23 { 24 LONG sx = 0; 25 LONG sy = 0; 26 LONG DesX; 27 LONG DesY; 28 29 LONG DstHeight; 30 LONG DstWidth; 31 LONG SrcHeight; 32 LONG SrcWidth; 33 LONG MaskCy; 34 LONG SourceCy; 35 36 ULONG Color; 37 ULONG Dest, Source = 0, Pattern = 0; 38 ULONG xxBPPMask; 39 BOOLEAN CanDraw; 40 41 PFN_DIB_GetPixel fnSource_GetPixel = NULL; 42 PFN_DIB_GetPixel fnDest_GetPixel = NULL; 43 PFN_DIB_PutPixel fnDest_PutPixel = NULL; 44 PFN_DIB_GetPixel fnPattern_GetPixel = NULL; 45 PFN_DIB_GetPixel fnMask_GetPixel = NULL; 46 47 LONG PatternX = 0, PatternY = 0; 48 49 BOOL UsesSource = ROP4_USES_SOURCE(ROP); 50 BOOL UsesPattern = ROP4_USES_PATTERN(ROP); 51 BOOLEAN bTopToBottom, bLeftToRight; 52 53 ASSERT(IS_VALID_ROP4(ROP)); 54 55 fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel; 56 fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel; 57 58 DPRINT("Dest BPP: %u, DestRect: (%d,%d)-(%d,%d)\n", 59 BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); 60 61 DstHeight = DestRect->bottom - DestRect->top; 62 DstWidth = DestRect->right - DestRect->left; 63 SrcHeight = SourceRect->bottom - SourceRect->top; 64 SrcWidth = SourceRect->right - SourceRect->left; 65 66 /* Here we do the tests and set our conditions */ 67 if (((SrcWidth < 0) && (DstWidth < 0)) || ((SrcWidth >= 0) && (DstWidth >= 0))) 68 bLeftToRight = FALSE; 69 else 70 bLeftToRight = TRUE; 71 72 if (((SrcHeight < 0) && (DstHeight < 0)) || ((SrcHeight >= 0) && (DstHeight >= 0))) 73 bTopToBottom = FALSE; 74 else 75 bTopToBottom = TRUE; 76 77 /* Make Well Ordered to start */ 78 RECTL_vMakeWellOrdered(DestRect); 79 80 if (UsesSource) 81 { 82 SourceCy = SourceSurf->sizlBitmap.cy; 83 fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel; 84 DPRINT("Source BPP: %u, SourceRect: (%d,%d)-(%d,%d)\n", 85 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); 86 } 87 88 if (MaskSurf) 89 { 90 DPRINT("MaskSurf is not NULL.\n"); 91 fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel; 92 MaskCy = MaskSurf->sizlBitmap.cy; 93 } 94 95 DstHeight = DestRect->bottom - DestRect->top; 96 DstWidth = DestRect->right - DestRect->left; 97 SrcHeight = SourceRect->bottom - SourceRect->top; 98 SrcWidth = SourceRect->right - SourceRect->left; 99 100 /* FIXME: MaskOrigin? */ 101 102 switch(DestSurf->iBitmapFormat) 103 { 104 case BMF_1BPP: xxBPPMask = 0x1; break; 105 case BMF_4BPP: xxBPPMask = 0xF; break; 106 case BMF_8BPP: xxBPPMask = 0xFF; break; 107 case BMF_16BPP: xxBPPMask = 0xFFFF; break; 108 case BMF_24BPP: xxBPPMask = 0xFFFFFF; break; 109 default: 110 xxBPPMask = 0xFFFFFFFF; 111 } 112 DPRINT("xxBPPMask is 0x%x.\n", xxBPPMask); 113 114 if (UsesPattern) 115 { 116 DPRINT("UsesPattern is not NULL.\n"); 117 if (PatternSurface) 118 { 119 PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy; 120 if (PatternY < 0) 121 { 122 PatternY += PatternSurface->sizlBitmap.cy; 123 } 124 fnPattern_GetPixel = DibFunctionsForBitmapFormat[PatternSurface->iBitmapFormat].DIB_GetPixel; 125 } 126 else 127 { 128 if (Brush) 129 Pattern = Brush->iSolidColor; 130 } 131 } 132 133 if (PatternSurface) 134 { 135 DPRINT("PatternSurface is not NULL.\n"); 136 } 137 138 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom); 139 140 for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++) 141 { 142 if (PatternSurface) 143 { 144 PatternX = (DestRect->left - BrushOrigin->x) % PatternSurface->sizlBitmap.cx; 145 if (PatternX < 0) 146 { 147 PatternX += PatternSurface->sizlBitmap.cx; 148 } 149 } 150 if (UsesSource) 151 { 152 if (bTopToBottom) 153 { 154 sy = SourceRect->bottom-(DesY - DestRect->top) * SrcHeight / DstHeight; // flips about the x-axis 155 } 156 else 157 { 158 sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight; 159 } 160 } 161 162 for (DesX = DestRect->left; DesX < DestRect->right; DesX++) 163 { 164 CanDraw = TRUE; 165 166 if (fnMask_GetPixel) 167 { 168 if (bLeftToRight) 169 { 170 sx = SourceRect->right - (DesX - DestRect->left) * SrcWidth / DstWidth; // flips about the y-axis 171 } 172 else 173 { 174 sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; 175 } 176 if (sx < 0 || sy < 0 || 177 MaskSurf->sizlBitmap.cx < sx || MaskCy < sy || 178 fnMask_GetPixel(MaskSurf, sx, sy) != 0) 179 { 180 CanDraw = FALSE; 181 } 182 } 183 184 if (UsesSource && CanDraw) 185 { 186 if (bLeftToRight) 187 { 188 sx = SourceRect->right-(DesX - DestRect->left) * SrcWidth / DstWidth; // flips about the y-axis 189 } 190 else 191 { 192 sx = SourceRect->left + (DesX - DestRect->left) * SrcWidth / DstWidth; 193 } 194 if (sx >= 0 && sy >= 0 && 195 SourceSurf->sizlBitmap.cx > sx && SourceCy > sy) 196 { 197 Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy)); 198 } 199 else 200 { 201 Source = 0; 202 CanDraw = ((ROP & 0xFF) != R3_OPINDEX_SRCCOPY); 203 } 204 } 205 206 if (CanDraw) 207 { 208 if (UsesPattern && PatternSurface) 209 { 210 Pattern = fnPattern_GetPixel(PatternSurface, PatternX, PatternY); 211 PatternX++; 212 PatternX %= PatternSurface->sizlBitmap.cx; 213 } 214 215 Dest = fnDest_GetPixel(DestSurf, DesX, DesY); 216 Color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask; 217 218 fnDest_PutPixel(DestSurf, DesX, DesY, Color); 219 } 220 } 221 222 if (PatternSurface) 223 { 224 PatternY++; 225 PatternY %= PatternSurface->sizlBitmap.cy; 226 } 227 } 228 229 return TRUE; 230 } 231 232 /* EOF */ 233