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