update for HEAD-2003091401
[reactos.git] / subsys / 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
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * COPYRIGHT:        See COPYING in the top level directory
22  * PROJECT:          ReactOS kernel
23  * PURPOSE:          GDI EngCopyBits Function
24  * FILE:             subsys/win32k/eng/copybits.c
25  * PROGRAMER:        Jason Filby
26  * REVISION HISTORY:
27  *        8/18/1999: Created
28  */
29
30 #include <ddk/winddi.h>
31 #include <ddk/ntddmou.h>
32 #include "objects.h"
33 #include "clip.h"
34 #include "../dib/dib.h"
35 #include <include/mouse.h>
36 #include <include/object.h>
37 #include <include/eng.h>
38
39 /*
40  * @implemented
41  */
42 BOOL STDCALL
43 EngCopyBits(SURFOBJ *Dest,
44             SURFOBJ *Source,
45             CLIPOBJ *Clip,
46             XLATEOBJ *ColorTranslation,
47             RECTL *DestRect,
48             POINTL *SourcePoint)
49 {
50   BOOLEAN   ret;
51   SURFGDI   *DestGDI, *SourceGDI;
52   BYTE      clippingType;
53   RECTL     rclTmp;
54   POINTL    ptlTmp;
55   RECT_ENUM RectEnum;
56   BOOL      EnumMore;
57
58   MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y,
59                          (SourcePoint->x + abs(DestRect->right - DestRect->left)),
60                          (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
61   MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
62
63   // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
64   //        mark the copy block function to be DrvCopyBits instead of the
65   //        GDI's copy bit function so as to remove clipping from the
66   //        driver's responsibility
67
68   // If one of the surfaces isn't managed by the GDI
69   if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP))
70   {
71     // Destination surface is device managed
72     if(Dest->iType!=STYPE_BITMAP)
73     {
74       DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
75
76       if (DestGDI->CopyBits!=NULL)
77       {
78         ret = DestGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
79
80         MouseSafetyOnDrawEnd(Source, SourceGDI);
81         MouseSafetyOnDrawEnd(Dest, DestGDI);
82
83         return ret;
84       }
85     }
86
87     // Source surface is device managed
88     if(Source->iType!=STYPE_BITMAP)
89     {
90       SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
91
92       if (SourceGDI->CopyBits!=NULL)
93       {
94         ret = SourceGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
95
96         MouseSafetyOnDrawEnd(Source, SourceGDI);
97         MouseSafetyOnDrawEnd(Dest, DestGDI);
98
99         return ret;
100       }
101     }
102
103     // If CopyBits wasn't hooked, BitBlt must be
104     ret = EngBitBlt(Dest, Source,
105                     NULL, Clip, ColorTranslation, DestRect, SourcePoint,
106                     NULL, NULL, NULL, 0);
107
108     MouseSafetyOnDrawEnd(Source, SourceGDI);
109     MouseSafetyOnDrawEnd(Dest, DestGDI);
110
111     return ret;
112   }
113
114   // Determine clipping type
115   if (Clip == (CLIPOBJ *) NULL)
116   {
117     clippingType = DC_TRIVIAL;
118   } else {
119     clippingType = Clip->iDComplexity;
120   }
121
122   SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
123   DestGDI   = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
124
125   switch(clippingType)
126     {
127       case DC_TRIVIAL:
128         DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, NULL, NULL, ColorTranslation, SRCCOPY);
129
130         MouseSafetyOnDrawEnd(Source, SourceGDI);
131         MouseSafetyOnDrawEnd(Dest, DestGDI);
132
133         return(TRUE);
134
135       case DC_RECT:
136         // Clip the blt to the clip rectangle
137         EngIntersectRect(&rclTmp, DestRect, &Clip->rclBounds);
138
139         ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
140         ptlTmp.y = SourcePoint->y + rclTmp.top  - DestRect->top;
141
142         DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI, &rclTmp, &ptlTmp, NULL, NULL, ColorTranslation, SRCCOPY);
143
144         MouseSafetyOnDrawEnd(Source, SourceGDI);
145         MouseSafetyOnDrawEnd(Dest, DestGDI);
146
147         return(TRUE);
148
149       case DC_COMPLEX:
150
151         CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
152
153         do {
154           EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
155
156           if (RectEnum.c > 0)
157           {
158             RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
159             RECTL* prcl    = &RectEnum.arcl[0];
160
161             do {
162               EngIntersectRect(prcl, prcl, DestRect);
163
164               ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left;
165               ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top;
166
167               if(!DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI,
168                                       prcl, &ptlTmp, NULL, NULL, ColorTranslation, SRCCOPY)) return FALSE;
169
170               prcl++;
171
172               } while (prcl < prclEnd);
173             }
174
175           } while(EnumMore);
176
177           MouseSafetyOnDrawEnd(Source, SourceGDI);
178
179           MouseSafetyOnDrawEnd(Dest, DestGDI);
180
181           return(TRUE);
182     }
183
184   MouseSafetyOnDrawEnd(Source, SourceGDI);
185   MouseSafetyOnDrawEnd(Dest, DestGDI);
186
187   return FALSE;
188 }
189
190 /* EOF */