branch update for HEAD-2003050101
[reactos.git] / subsys / win32k / 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  * REVISION HISTORY:
8  *        8/18/1999: Created
9  */
10
11 #include <ddk/winddi.h>
12 #include "objects.h"
13 #include "clip.h"
14 #include "../dib/dib.h"
15 #include <include/mouse.h>
16 #include <include/object.h>
17 #include <include/eng.h>
18
19 BOOL STDCALL
20 EngCopyBits(SURFOBJ *Dest,
21             SURFOBJ *Source,
22             CLIPOBJ *Clip,
23             XLATEOBJ *ColorTranslation,
24             RECTL *DestRect,
25             POINTL *SourcePoint)
26 {
27   BOOLEAN   ret;
28   SURFGDI   *DestGDI, *SourceGDI;
29   BYTE      clippingType;
30   RECTL     rclTmp;
31   POINTL    ptlTmp;
32   RECT_ENUM RectEnum;
33   BOOL      EnumMore;
34
35   MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y,
36                          (SourcePoint->x + abs(DestRect->right - DestRect->left)),
37                          (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
38   MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
39
40   // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
41   //        mark the copy block function to be DrvCopyBits instead of the
42   //        GDI's copy bit function so as to remove clipping from the
43   //        driver's responsibility
44
45   // If one of the surfaces isn't managed by the GDI
46   if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP))
47   {
48     // Destination surface is device managed
49     if(Dest->iType!=STYPE_BITMAP)
50     {
51       DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
52
53       if (DestGDI->CopyBits!=NULL)
54       {
55         ret = DestGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
56
57         MouseSafetyOnDrawEnd(Source, SourceGDI);
58         MouseSafetyOnDrawEnd(Dest, DestGDI);
59
60         return ret;
61       }
62     }
63
64     // Source surface is device managed
65     if(Source->iType!=STYPE_BITMAP)
66     {
67       SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
68
69       if (SourceGDI->CopyBits!=NULL)
70       {
71         ret = SourceGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
72
73         MouseSafetyOnDrawEnd(Source, SourceGDI);
74         MouseSafetyOnDrawEnd(Dest, DestGDI);
75
76         return ret;
77       }
78     }
79
80     // If CopyBits wasn't hooked, BitBlt must be
81     ret = EngBitBlt(Dest, Source,
82                     NULL, Clip, ColorTranslation, DestRect, SourcePoint,
83                     NULL, NULL, NULL, 0);
84
85     MouseSafetyOnDrawEnd(Source, SourceGDI);
86     MouseSafetyOnDrawEnd(Dest, DestGDI);
87
88     return ret;
89   }
90
91   // Determine clipping type
92   if (Clip == (CLIPOBJ *) NULL)
93   {
94     clippingType = DC_TRIVIAL;
95   } else {
96     clippingType = Clip->iDComplexity;
97   }
98
99   // We only handle XO_TABLE translations at the momement
100   if ((ColorTranslation == NULL) || (ColorTranslation->flXlate & XO_TRIVIAL) ||
101       (ColorTranslation->flXlate & XO_TABLE))
102   {
103     SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
104     DestGDI   = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
105
106     switch(clippingType)
107     {
108       case DC_TRIVIAL:
109         DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, ColorTranslation);
110
111         MouseSafetyOnDrawEnd(Source, SourceGDI);
112         MouseSafetyOnDrawEnd(Dest, DestGDI);
113
114         return(TRUE);
115
116       case DC_RECT:
117         // Clip the blt to the clip rectangle
118         EngIntersectRect(&rclTmp, DestRect, &Clip->rclBounds);
119
120         ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
121         ptlTmp.y = SourcePoint->y + rclTmp.top  - DestRect->top;
122
123         DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI, &rclTmp, &ptlTmp, ColorTranslation);
124
125         MouseSafetyOnDrawEnd(Source, SourceGDI);
126         MouseSafetyOnDrawEnd(Dest, DestGDI);
127
128         return(TRUE);
129
130       case DC_COMPLEX:
131
132         CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
133
134         do {
135           EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
136
137           if (RectEnum.c > 0)
138           {
139             RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
140             RECTL* prcl    = &RectEnum.arcl[0];
141
142             do {
143               EngIntersectRect(prcl, prcl, DestRect);
144
145               ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left;
146               ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top;
147
148               if(!DestGDI->DIB_BitBlt(Dest, Source, DestGDI, SourceGDI,
149                                       prcl, &ptlTmp, ColorTranslation)) return FALSE;
150
151               prcl++;
152
153               } while (prcl < prclEnd);
154             }
155
156           } while(EnumMore);
157
158           MouseSafetyOnDrawEnd(Source, SourceGDI);\r
159           MouseSafetyOnDrawEnd(Dest, DestGDI);
160
161           return(TRUE);
162     }
163   }
164
165   MouseSafetyOnDrawEnd(Source, SourceGDI);
166   MouseSafetyOnDrawEnd(Dest, DestGDI);
167
168   return FALSE;
169 }