xref: /reactos/win32ss/gdi/eng/copybits.c (revision ce7836c6)
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