[WIN32K]
[reactos.git] / reactos / win32ss / gdi / eng / copybits.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI EngCopyBits Function
5 * FILE: subsys/win32k/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 + prcl->left - DestRect->left;
150 BltInfo.SourcePoint.y = SourcePoint->y + prcl->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 */