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