xref: /reactos/win32ss/gdi/dib/stretchblt.c (revision 40462c92)
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  */
10 
11 #include <win32k.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *MaskSurf,
17                             SURFOBJ *PatternSurface,
18                             RECTL *DestRect, RECTL *SourceRect,
19                             POINTL *MaskOrigin, BRUSHOBJ *Brush,
20                             POINTL *BrushOrigin, XLATEOBJ *ColorTranslation,
21                             ROP4 ROP)
22 {
23   LONG sx = 0;
24   LONG sy = 0;
25   LONG DesX;
26   LONG DesY;
27 
28   LONG DstHeight;
29   LONG DstWidth;
30   LONG SrcHeight;
31   LONG SrcWidth;
32   LONG MaskCy;
33   LONG SourceCy;
34 
35   ULONG Color;
36   ULONG Dest, Source = 0, Pattern = 0;
37   ULONG xxBPPMask;
38   BOOLEAN CanDraw;
39 
40   PFN_DIB_GetPixel fnSource_GetPixel = NULL;
41   PFN_DIB_GetPixel fnDest_GetPixel = NULL;
42   PFN_DIB_PutPixel fnDest_PutPixel = NULL;
43   PFN_DIB_GetPixel fnPattern_GetPixel = NULL;
44   PFN_DIB_GetPixel fnMask_GetPixel = NULL;
45 
46   LONG PatternX = 0, PatternY = 0;
47 
48   BOOL UsesSource = ROP4_USES_SOURCE(ROP);
49   BOOL UsesPattern = ROP4_USES_PATTERN(ROP);
50 
51   ASSERT(IS_VALID_ROP4(ROP));
52 
53   fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel;
54   fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel;
55 
56   DPRINT("Dest BPP: %u, dstRect: (%d,%d)-(%d,%d)\n",
57     BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
58 
59   if (UsesSource)
60   {
61     SourceCy = SourceSurf->sizlBitmap.cy;
62     fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel;
63     DPRINT("Source BPP: %u, srcRect: (%d,%d)-(%d,%d)\n",
64       BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom);
65   }
66 
67   if (MaskSurf)
68   {
69     fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel;
70     MaskCy = MaskSurf->sizlBitmap.cy;
71   }
72 
73   DstHeight = DestRect->bottom - DestRect->top;
74   DstWidth = DestRect->right - DestRect->left;
75   SrcHeight = SourceRect->bottom - SourceRect->top;
76   SrcWidth = SourceRect->right - SourceRect->left;
77 
78   /* FIXME: MaskOrigin? */
79 
80   switch(DestSurf->iBitmapFormat)
81   {
82   case BMF_1BPP: xxBPPMask = 0x1; break;
83   case BMF_4BPP: xxBPPMask = 0xF; break;
84   case BMF_8BPP: xxBPPMask = 0xFF; break;
85   case BMF_16BPP: xxBPPMask = 0xFFFF; break;
86   case BMF_24BPP: xxBPPMask = 0xFFFFFF; break;
87   default:
88     xxBPPMask = 0xFFFFFFFF;
89   }
90 
91   if (UsesPattern)
92   {
93     if (PatternSurface)
94     {
95       PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy;
96       if (PatternY < 0)
97       {
98         PatternY += PatternSurface->sizlBitmap.cy;
99       }
100       fnPattern_GetPixel = DibFunctionsForBitmapFormat[PatternSurface->iBitmapFormat].DIB_GetPixel;
101     }
102     else
103     {
104       if (Brush)
105         Pattern = Brush->iSolidColor;
106     }
107   }
108 
109 
110   for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++)
111   {
112     if (PatternSurface)
113     {
114       PatternX = (DestRect->left - BrushOrigin->x) % PatternSurface->sizlBitmap.cx;
115       if (PatternX < 0)
116       {
117         PatternX += PatternSurface->sizlBitmap.cx;
118       }
119     }
120     if (UsesSource)
121       sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;
122 
123     for (DesX = DestRect->left; DesX < DestRect->right; DesX++)
124     {
125       CanDraw = TRUE;
126 
127       if (fnMask_GetPixel)
128       {
129         sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
130         if (sx < 0 || sy < 0 ||
131           MaskSurf->sizlBitmap.cx < sx || MaskCy < sy ||
132           fnMask_GetPixel(MaskSurf, sx, sy) != 0)
133         {
134           CanDraw = FALSE;
135         }
136       }
137 
138       if (UsesSource && CanDraw)
139       {
140         sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
141         if (sx >= 0 && sy >= 0 &&
142           SourceSurf->sizlBitmap.cx > sx && SourceCy > sy)
143         {
144           Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy));
145         }
146         else
147         {
148           Source = 0;
149           CanDraw = ((ROP & 0xFF) != R3_OPINDEX_SRCCOPY);
150         }
151       }
152 
153       if (CanDraw)
154       {
155         if (UsesPattern && PatternSurface)
156         {
157           Pattern = fnPattern_GetPixel(PatternSurface, PatternX, PatternY);
158           PatternX++;
159           PatternX %= PatternSurface->sizlBitmap.cx;
160         }
161 
162         Dest = fnDest_GetPixel(DestSurf, DesX, DesY);
163         Color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask;
164 
165         fnDest_PutPixel(DestSurf, DesX, DesY, Color);
166       }
167     }
168 
169     if (PatternSurface)
170     {
171       PatternY++;
172       PatternY %= PatternSurface->sizlBitmap.cy;
173     }
174   }
175 
176   return TRUE;
177 }
178 
179 /* EOF */
180