1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS kernel
4c2c66affSColin Finck * PURPOSE: GDI EngCopyBits Function
5c2c66affSColin Finck * FILE: win32ss/gdi/eng/copybits.c
6*ce7836c6SDoug Lyons * PROGRAMERS: Jason Filby
7*ce7836c6SDoug Lyons * Doug Lyons
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck #include <win32k.h>
11c2c66affSColin Finck
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck
15c2c66affSColin Finck /*
16c2c66affSColin Finck * @implemented
17c2c66affSColin Finck */
18c2c66affSColin Finck BOOL APIENTRY
EngCopyBits(_In_ SURFOBJ * psoDest,_In_ SURFOBJ * psoSource,_In_opt_ CLIPOBJ * Clip,_In_opt_ XLATEOBJ * ColorTranslation,_In_ RECTL * DestRect,_In_ POINTL * SourcePoint)19c2c66affSColin Finck EngCopyBits(
20c2c66affSColin Finck _In_ SURFOBJ *psoDest,
21c2c66affSColin Finck _In_ SURFOBJ *psoSource,
22c2c66affSColin Finck _In_opt_ CLIPOBJ *Clip,
23c2c66affSColin Finck _In_opt_ XLATEOBJ *ColorTranslation,
24c2c66affSColin Finck _In_ RECTL *DestRect,
25c2c66affSColin Finck _In_ POINTL *SourcePoint)
26c2c66affSColin Finck {
27c2c66affSColin Finck BOOL ret;
28c2c66affSColin Finck BYTE clippingType;
29c2c66affSColin Finck RECT_ENUM RectEnum;
30c2c66affSColin Finck BOOL EnumMore;
31c2c66affSColin Finck BLTINFO BltInfo;
32c2c66affSColin Finck SURFACE *psurfDest;
33c2c66affSColin Finck SURFACE *psurfSource;
34c2c66affSColin Finck RECTL rclDest = *DestRect;
35c2c66affSColin Finck POINTL ptlSrc = *SourcePoint;
36*ce7836c6SDoug Lyons LONG lTmp;
37*ce7836c6SDoug Lyons BOOL bTopToBottom;
38*ce7836c6SDoug Lyons
39*ce7836c6SDoug Lyons DPRINT("Entering EngCopyBits with SourcePoint (%d,%d) and DestRect (%d,%d)-(%d,%d).\n",
40*ce7836c6SDoug Lyons SourcePoint->x, SourcePoint->y, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
41*ce7836c6SDoug Lyons
42*ce7836c6SDoug Lyons DPRINT("psoSource cx/cy is %d/%d and psoDest cx/cy is %d/%d.\n",
43*ce7836c6SDoug Lyons psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
44*ce7836c6SDoug Lyons
45*ce7836c6SDoug Lyons /* Retrieve Top Down/flip here and then make Well-Ordered again */
46*ce7836c6SDoug Lyons if (DestRect->top > DestRect->bottom)
47*ce7836c6SDoug Lyons {
48*ce7836c6SDoug Lyons bTopToBottom = TRUE;
49*ce7836c6SDoug Lyons lTmp = DestRect->top;
50*ce7836c6SDoug Lyons DestRect->top = DestRect->bottom;
51*ce7836c6SDoug Lyons DestRect->bottom = lTmp;
52*ce7836c6SDoug Lyons rclDest = *DestRect;
53*ce7836c6SDoug Lyons }
54*ce7836c6SDoug Lyons else
55*ce7836c6SDoug Lyons {
56*ce7836c6SDoug Lyons bTopToBottom = FALSE;
57*ce7836c6SDoug Lyons }
58*ce7836c6SDoug Lyons
59*ce7836c6SDoug Lyons DPRINT("bTopToBottom is '%d'.\n", bTopToBottom);
60c2c66affSColin Finck
61c2c66affSColin Finck ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
62c2c66affSColin Finck
63c2c66affSColin Finck psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
64c2c66affSColin Finck psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
65c2c66affSColin Finck
66c2c66affSColin Finck /* Clip dest rect against source surface size / source point */
67c2c66affSColin Finck if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left)
68c2c66affSColin Finck rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x;
69c2c66affSColin Finck if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top)
70c2c66affSColin Finck rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y;
71c2c66affSColin Finck
72c2c66affSColin Finck /* Clip dest rect against target surface size */
73c2c66affSColin Finck if (rclDest.right > psoDest->sizlBitmap.cx)
74c2c66affSColin Finck rclDest.right = psoDest->sizlBitmap.cx;
75c2c66affSColin Finck if (rclDest.bottom > psoDest->sizlBitmap.cy)
76c2c66affSColin Finck rclDest.bottom = psoDest->sizlBitmap.cy;
77c2c66affSColin Finck if (RECTL_bIsEmptyRect(&rclDest)) return TRUE;
78c2c66affSColin Finck DestRect = &rclDest;
79c2c66affSColin Finck
80c2c66affSColin Finck // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
81c2c66affSColin Finck // mark the copy block function to be DrvCopyBits instead of the
82c2c66affSColin Finck // GDI's copy bit function so as to remove clipping from the
83c2c66affSColin Finck // driver's responsibility
84c2c66affSColin Finck
85c2c66affSColin Finck // If one of the surfaces isn't managed by the GDI
86c2c66affSColin Finck if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP))
87c2c66affSColin Finck {
88c2c66affSColin Finck // Destination surface is device managed
89c2c66affSColin Finck if (psoDest->iType!=STYPE_BITMAP)
90c2c66affSColin Finck {
91c2c66affSColin Finck /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
92c2c66affSColin Finck if (psurfDest->flags & HOOK_COPYBITS)
93c2c66affSColin Finck {
94c2c66affSColin Finck ret = GDIDEVFUNCS(psoDest).CopyBits(
95c2c66affSColin Finck psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
96c2c66affSColin Finck
97c2c66affSColin Finck goto cleanup;
98c2c66affSColin Finck }
99c2c66affSColin Finck }
100c2c66affSColin Finck
101c2c66affSColin Finck // Source surface is device managed
102c2c66affSColin Finck if (psoSource->iType!=STYPE_BITMAP)
103c2c66affSColin Finck {
104c2c66affSColin Finck /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
105c2c66affSColin Finck if (psurfSource->flags & HOOK_COPYBITS)
106c2c66affSColin Finck {
107c2c66affSColin Finck ret = GDIDEVFUNCS(psoSource).CopyBits(
108c2c66affSColin Finck psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
109c2c66affSColin Finck
110c2c66affSColin Finck goto cleanup;
111c2c66affSColin Finck }
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck // If CopyBits wasn't hooked, BitBlt must be
115c2c66affSColin Finck ret = IntEngBitBlt(psoDest, psoSource,
116c2c66affSColin Finck NULL, Clip, ColorTranslation, DestRect, SourcePoint,
117c2c66affSColin Finck NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
118c2c66affSColin Finck
119c2c66affSColin Finck goto cleanup;
120c2c66affSColin Finck }
121c2c66affSColin Finck
122c2c66affSColin Finck // Determine clipping type
123c2c66affSColin Finck if (!Clip)
124c2c66affSColin Finck {
125c2c66affSColin Finck clippingType = DC_TRIVIAL;
126c2c66affSColin Finck }
127c2c66affSColin Finck else
128c2c66affSColin Finck {
129c2c66affSColin Finck clippingType = Clip->iDComplexity;
130c2c66affSColin Finck }
131c2c66affSColin Finck
132c2c66affSColin Finck BltInfo.DestSurface = psoDest;
133c2c66affSColin Finck BltInfo.SourceSurface = psoSource;
134c2c66affSColin Finck BltInfo.PatternSurface = NULL;
135c2c66affSColin Finck BltInfo.XlateSourceToDest = ColorTranslation;
136c2c66affSColin Finck BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY);
137c2c66affSColin Finck
138c2c66affSColin Finck switch (clippingType)
139c2c66affSColin Finck {
140c2c66affSColin Finck case DC_TRIVIAL:
141*ce7836c6SDoug Lyons DPRINT("DC_TRIVIAL.\n");
142c2c66affSColin Finck BltInfo.DestRect = *DestRect;
143c2c66affSColin Finck BltInfo.SourcePoint = *SourcePoint;
144c2c66affSColin Finck
145*ce7836c6SDoug Lyons /* Now we set the Dest Rect top and bottom based on Top Down/flip */
146*ce7836c6SDoug Lyons if (bTopToBottom)
147*ce7836c6SDoug Lyons {
148*ce7836c6SDoug Lyons lTmp = BltInfo.DestRect.top;
149*ce7836c6SDoug Lyons BltInfo.DestRect.top = BltInfo.DestRect.bottom;
150*ce7836c6SDoug Lyons BltInfo.DestRect.bottom = lTmp;
151*ce7836c6SDoug Lyons }
152*ce7836c6SDoug Lyons
153c2c66affSColin Finck ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
154c2c66affSColin Finck break;
155c2c66affSColin Finck
156c2c66affSColin Finck case DC_RECT:
157*ce7836c6SDoug Lyons DPRINT("DC_RECT.\n");
158c2c66affSColin Finck // Clip the blt to the clip rectangle
159c2c66affSColin Finck RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
160c2c66affSColin Finck
161c2c66affSColin Finck BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
162c2c66affSColin Finck BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
163c2c66affSColin Finck
164*ce7836c6SDoug Lyons /* Now we set the Dest Rect top and bottom based on Top Down/flip */
165*ce7836c6SDoug Lyons if (bTopToBottom)
166*ce7836c6SDoug Lyons {
167*ce7836c6SDoug Lyons lTmp = BltInfo.DestRect.top;
168*ce7836c6SDoug Lyons BltInfo.DestRect.top = BltInfo.DestRect.bottom;
169*ce7836c6SDoug Lyons BltInfo.DestRect.bottom = lTmp;
170*ce7836c6SDoug Lyons }
171*ce7836c6SDoug Lyons
172c2c66affSColin Finck ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
173c2c66affSColin Finck break;
174c2c66affSColin Finck
175c2c66affSColin Finck case DC_COMPLEX:
176*ce7836c6SDoug Lyons DPRINT("DC_COMPLEX.\n");
177c2c66affSColin Finck CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);
178c2c66affSColin Finck
179c2c66affSColin Finck do
180c2c66affSColin Finck {
181c2c66affSColin Finck EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
182c2c66affSColin Finck
183c2c66affSColin Finck if (RectEnum.c > 0)
184c2c66affSColin Finck {
185c2c66affSColin Finck RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
186c2c66affSColin Finck RECTL* prcl = &RectEnum.arcl[0];
187c2c66affSColin Finck
188c2c66affSColin Finck do
189c2c66affSColin Finck {
190c2c66affSColin Finck RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect);
191c2c66affSColin Finck
192c2c66affSColin Finck BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
193c2c66affSColin Finck BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
194c2c66affSColin Finck
195*ce7836c6SDoug Lyons /* Now we set the Dest Rect top and bottom based on Top Down/flip */
196*ce7836c6SDoug Lyons if (bTopToBottom)
197*ce7836c6SDoug Lyons {
198*ce7836c6SDoug Lyons lTmp = BltInfo.DestRect.top;
199*ce7836c6SDoug Lyons BltInfo.DestRect.top = BltInfo.DestRect.bottom;
200*ce7836c6SDoug Lyons BltInfo.DestRect.bottom = lTmp;
201*ce7836c6SDoug Lyons }
202*ce7836c6SDoug Lyons
203c2c66affSColin Finck if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
204c2c66affSColin Finck {
205c2c66affSColin Finck ret = FALSE;
206c2c66affSColin Finck goto cleanup;
207c2c66affSColin Finck }
208c2c66affSColin Finck
209c2c66affSColin Finck prcl++;
210c2c66affSColin Finck
211c2c66affSColin Finck } while (prcl < prclEnd);
212c2c66affSColin Finck }
213c2c66affSColin Finck
214c2c66affSColin Finck } while (EnumMore);
215c2c66affSColin Finck ret = TRUE;
216c2c66affSColin Finck break;
217c2c66affSColin Finck
218c2c66affSColin Finck default:
219c2c66affSColin Finck ASSERT(FALSE);
220c2c66affSColin Finck ret = FALSE;
221c2c66affSColin Finck break;
222c2c66affSColin Finck }
223c2c66affSColin Finck
224c2c66affSColin Finck cleanup:
225c2c66affSColin Finck return ret;
226c2c66affSColin Finck }
227c2c66affSColin Finck
228c2c66affSColin Finck BOOL APIENTRY
IntEngCopyBits(SURFOBJ * psoDest,SURFOBJ * psoSource,CLIPOBJ * pco,XLATEOBJ * pxlo,RECTL * prclDest,POINTL * ptlSource)229c2c66affSColin Finck IntEngCopyBits(
230c2c66affSColin Finck SURFOBJ *psoDest,
231c2c66affSColin Finck SURFOBJ *psoSource,
232c2c66affSColin Finck CLIPOBJ *pco,
233c2c66affSColin Finck XLATEOBJ *pxlo,
234c2c66affSColin Finck RECTL *prclDest,
235c2c66affSColin Finck POINTL *ptlSource)
236c2c66affSColin Finck {
237c2c66affSColin Finck return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
238c2c66affSColin Finck }
239c2c66affSColin Finck
240c2c66affSColin Finck
241c2c66affSColin Finck /* EOF */
242