0bec04a5af3c70a6deebcb2706d0003e45b6be43
[reactos.git] / reactos / subsystems / win32 / win32k / eng / copybits.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: GDI EngCopyBits Function
23 * FILE: subsys/win32k/eng/copybits.c
24 * PROGRAMER: Jason Filby
25 * REVISION HISTORY:
26 * 8/18/1999: Created
27 */
28
29 #include <win32k.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /*
35 * @implemented
36 */
37 BOOL APIENTRY
38 EngCopyBits(SURFOBJ *psoDest,
39 SURFOBJ *psoSource,
40 CLIPOBJ *Clip,
41 XLATEOBJ *ColorTranslation,
42 RECTL *DestRect,
43 POINTL *SourcePoint)
44 {
45 BOOL ret;
46 BYTE clippingType;
47 RECT_ENUM RectEnum;
48 BOOL EnumMore;
49 BLTINFO BltInfo;
50 SURFACE *psurfDest;
51 SURFACE *psurfSource;
52 RECTL rclDest = *DestRect;
53 POINTL ptlSrc = *SourcePoint;
54
55 ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
56
57 psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
58 psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
59
60 /* Clip dest rect against source surface size / source point */
61 if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left)
62 rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x;
63 if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top)
64 rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y;
65
66 /* Clip dest rect against target surface size */
67 if (rclDest.right > psoDest->sizlBitmap.cx)
68 rclDest.right = psoDest->sizlBitmap.cx;
69 if (rclDest.bottom > psoDest->sizlBitmap.cy)
70 rclDest.bottom = psoDest->sizlBitmap.cy;
71 if (RECTL_bIsEmptyRect(&rclDest)) return TRUE;
72 DestRect = &rclDest;
73
74 // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
75 // mark the copy block function to be DrvCopyBits instead of the
76 // GDI's copy bit function so as to remove clipping from the
77 // driver's responsibility
78
79 // If one of the surfaces isn't managed by the GDI
80 if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP))
81 {
82 // Destination surface is device managed
83 if (psoDest->iType!=STYPE_BITMAP)
84 {
85 /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
86 if (psurfDest->flags & HOOK_COPYBITS)
87 {
88 ret = GDIDEVFUNCS(psoDest).CopyBits(
89 psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
90
91 goto cleanup;
92 }
93 }
94
95 // Source surface is device managed
96 if (psoSource->iType!=STYPE_BITMAP)
97 {
98 /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
99 if (psurfSource->flags & HOOK_COPYBITS)
100 {
101 ret = GDIDEVFUNCS(psoSource).CopyBits(
102 psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
103
104 goto cleanup;
105 }
106 }
107
108 // If CopyBits wasn't hooked, BitBlt must be
109 ret = IntEngBitBlt(psoDest, psoSource,
110 NULL, Clip, ColorTranslation, DestRect, SourcePoint,
111 NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
112
113 goto cleanup;
114 }
115
116 // Determine clipping type
117 if (!Clip)
118 {
119 clippingType = DC_TRIVIAL;
120 }
121 else
122 {
123 clippingType = Clip->iDComplexity;
124 }
125
126 BltInfo.DestSurface = psoDest;
127 BltInfo.SourceSurface = psoSource;
128 BltInfo.PatternSurface = NULL;
129 BltInfo.XlateSourceToDest = ColorTranslation;
130 BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY);
131
132 switch (clippingType)
133 {
134 case DC_TRIVIAL:
135 BltInfo.DestRect = *DestRect;
136 BltInfo.SourcePoint = *SourcePoint;
137
138 ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
139 break;
140
141 case DC_RECT:
142 // Clip the blt to the clip rectangle
143 RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
144
145 BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
146 BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
147
148 ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
149 break;
150
151 case DC_COMPLEX:
152
153 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);
154
155 do
156 {
157 EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
158
159 if (RectEnum.c > 0)
160 {
161 RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
162 RECTL* prcl = &RectEnum.arcl[0];
163
164 do
165 {
166 RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect);
167
168 BltInfo.SourcePoint.x = SourcePoint->x + prcl->left - DestRect->left;
169 BltInfo.SourcePoint.y = SourcePoint->y + prcl->top - DestRect->top;
170
171 if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
172 {
173 ret = FALSE;
174 goto cleanup;
175 }
176
177 prcl++;
178
179 } while (prcl < prclEnd);
180 }
181
182 } while (EnumMore);
183 ret = TRUE;
184 break;
185
186 default:
187 ASSERT(FALSE);
188 ret = FALSE;
189 break;
190 }
191
192 cleanup:
193 return ret;
194 }
195
196 BOOL APIENTRY
197 IntEngCopyBits(
198 SURFOBJ *psoDest,
199 SURFOBJ *psoSource,
200 CLIPOBJ *pco,
201 XLATEOBJ *pxlo,
202 RECTL *prclDest,
203 POINTL *ptlSource)
204 {
205 return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
206 }
207
208
209 /* EOF */