xref: /reactos/win32ss/gdi/eng/copybits.c (revision 5100859e)
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  * PROGRAMER:        Jason Filby
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 /*
15  * @implemented
16  */
17 BOOL APIENTRY
18 EngCopyBits(
19     _In_ SURFOBJ *psoDest,
20     _In_ SURFOBJ *psoSource,
21     _In_opt_ CLIPOBJ *Clip,
22     _In_opt_ XLATEOBJ *ColorTranslation,
23     _In_ RECTL *DestRect,
24     _In_ POINTL *SourcePoint)
25 {
26     BOOL      ret;
27     BYTE      clippingType;
28     RECT_ENUM RectEnum;
29     BOOL      EnumMore;
30     BLTINFO   BltInfo;
31     SURFACE *psurfDest;
32     SURFACE *psurfSource;
33     RECTL rclDest = *DestRect;
34     POINTL ptlSrc = *SourcePoint;
35 
36     ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
37 
38     psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
39     psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
40 
41     /* Clip dest rect against source surface size / source point */
42     if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left)
43         rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x;
44     if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top)
45         rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y;
46 
47     /* Clip dest rect against target surface size */
48     if (rclDest.right > psoDest->sizlBitmap.cx)
49         rclDest.right = psoDest->sizlBitmap.cx;
50     if (rclDest.bottom > psoDest->sizlBitmap.cy)
51         rclDest.bottom = psoDest->sizlBitmap.cy;
52     if (RECTL_bIsEmptyRect(&rclDest)) return TRUE;
53     DestRect = &rclDest;
54 
55     // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
56     //        mark the copy block function to be DrvCopyBits instead of the
57     //        GDI's copy bit function so as to remove clipping from the
58     //        driver's responsibility
59 
60     // If one of the surfaces isn't managed by the GDI
61     if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP))
62     {
63         // Destination surface is device managed
64         if (psoDest->iType!=STYPE_BITMAP)
65         {
66             /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
67             if (psurfDest->flags & HOOK_COPYBITS)
68             {
69                 ret = GDIDEVFUNCS(psoDest).CopyBits(
70                           psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
71 
72                 goto cleanup;
73             }
74         }
75 
76         // Source surface is device managed
77         if (psoSource->iType!=STYPE_BITMAP)
78         {
79             /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
80             if (psurfSource->flags & HOOK_COPYBITS)
81             {
82                 ret = GDIDEVFUNCS(psoSource).CopyBits(
83                           psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
84 
85                 goto cleanup;
86             }
87         }
88 
89         // If CopyBits wasn't hooked, BitBlt must be
90         ret = IntEngBitBlt(psoDest, psoSource,
91                            NULL, Clip, ColorTranslation, DestRect, SourcePoint,
92                            NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
93 
94         goto cleanup;
95     }
96 
97     // Determine clipping type
98     if (!Clip)
99     {
100         clippingType = DC_TRIVIAL;
101     }
102     else
103     {
104         clippingType = Clip->iDComplexity;
105     }
106 
107     BltInfo.DestSurface = psoDest;
108     BltInfo.SourceSurface = psoSource;
109     BltInfo.PatternSurface = NULL;
110     BltInfo.XlateSourceToDest = ColorTranslation;
111     BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY);
112 
113     switch (clippingType)
114     {
115         case DC_TRIVIAL:
116             BltInfo.DestRect = *DestRect;
117             BltInfo.SourcePoint = *SourcePoint;
118 
119             ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
120             break;
121 
122         case DC_RECT:
123             // Clip the blt to the clip rectangle
124             RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
125 
126             BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
127             BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top  - DestRect->top;
128 
129             ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
130             break;
131 
132         case DC_COMPLEX:
133 
134             CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);
135 
136             do
137             {
138                 EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
139 
140                 if (RectEnum.c > 0)
141                 {
142                     RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
143                     RECTL* prcl    = &RectEnum.arcl[0];
144 
145                     do
146                     {
147                         RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect);
148 
149                         BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
150                         BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
151 
152                         if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
153                         {
154                             ret = FALSE;
155                             goto cleanup;
156                         }
157 
158                         prcl++;
159 
160                     } while (prcl < prclEnd);
161                 }
162 
163             } while (EnumMore);
164             ret = TRUE;
165             break;
166 
167         default:
168             ASSERT(FALSE);
169             ret = FALSE;
170             break;
171     }
172 
173 cleanup:
174     return ret;
175 }
176 
177 BOOL APIENTRY
178 IntEngCopyBits(
179     SURFOBJ *psoDest,
180     SURFOBJ *psoSource,
181     CLIPOBJ *pco,
182     XLATEOBJ *pxlo,
183     RECTL *prclDest,
184     POINTL *ptlSource)
185 {
186     return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
187 }
188 
189 
190 /* EOF */
191