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