[WIN32K]
[reactos.git] / reactos / win32ss / gdi / dib / stretchblt.c
1 /*
2 * PROJECT: ReactOS Win32k subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/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 = abs(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 = abs(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 */