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