:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 BOOLEAN CopyBitsCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
20                      SURFGDI *DestGDI,  SURFGDI *SourceGDI,
21                      PRECTL  DestRect,  POINTL  *SourcePoint,
22                      LONG    Delta,     XLATEOBJ *ColorTranslation)
23 {
24   LONG DestWidth, DestHeight, CurrentDestLine, CurrentSourceLine, CurrentDestCol, CurrentSourceCol, i, TranslationPixel;
25
26   PFN_DIB_GetPixel Source_DIB_GetPixel;
27   PFN_DIB_PutPixel Dest_DIB_PutPixel;
28
29   DestWidth  = DestRect->right - DestRect->left;
30   DestHeight = DestRect->bottom - DestRect->top;
31   CurrentSourceCol = SourcePoint->x;
32   CurrentSourceLine = SourcePoint->y;
33
34   // Assign GetPixel DIB function according to bytes per pixel
35   switch(DestGDI->BitsPerPixel)
36   {
37     case 1:
38       return DIB_To_1BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI,
39                                 DestRect, SourcePoint, Delta, ColorTranslation);
40       break;
41
42     case 4:
43       return DIB_To_4BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI,
44                                 DestRect, SourcePoint, Delta, ColorTranslation);
45       break;
46
47     case 24:
48       return DIB_To_24BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI,
49                                  DestRect, SourcePoint, Delta, ColorTranslation);
50       break;
51
52     default:
53       return FALSE;
54   }
55
56   return TRUE;
57 }
58
59 BOOL STDCALL
60 EngCopyBits(SURFOBJ *Dest,
61             SURFOBJ *Source,
62             CLIPOBJ *Clip,
63             XLATEOBJ *ColorTranslation,
64             RECTL *DestRect,
65             POINTL *SourcePoint)
66 {
67   BOOLEAN   ret;
68   SURFGDI   *DestGDI, *SourceGDI;
69   BYTE      clippingType;
70   RECTL     rclTmp;
71   POINTL    ptlTmp;
72   RECT_ENUM RectEnum;
73   BOOL      EnumMore;
74
75   MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y,
76                          (SourcePoint->x + abs(DestRect->right - DestRect->left)),
77                          (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
78   MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
79
80   // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
81   //        mark the copy block function to be DrvCopyBits instead of the
82   //        GDI's copy bit function so as to remove clipping from the
83   //        driver's responsibility
84
85   // If one of the surfaces isn't managed by the GDI
86   if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP))
87   {
88     // Destination surface is device managed
89     if(Dest->iType!=STYPE_BITMAP)
90     {
91       DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
92
93       if (DestGDI->CopyBits!=NULL)
94       {
95         ret = DestGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
96
97         MouseSafetyOnDrawEnd(Source, SourceGDI);
98         MouseSafetyOnDrawEnd(Dest, DestGDI);
99
100         return ret;
101       }
102     }
103
104     // Source surface is device managed
105     if(Source->iType!=STYPE_BITMAP)
106     {
107       SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
108
109       if (SourceGDI->CopyBits!=NULL)
110       {
111         ret = SourceGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint);
112
113         MouseSafetyOnDrawEnd(Source, SourceGDI);
114         MouseSafetyOnDrawEnd(Dest, DestGDI);
115
116         return ret;
117       }
118     }
119
120     // If CopyBits wasn't hooked, BitBlt must be
121     ret = EngBitBlt(Dest, Source,
122                     NULL, Clip, ColorTranslation, DestRect, SourcePoint,
123                     NULL, NULL, NULL, 0);
124
125     MouseSafetyOnDrawEnd(Source, SourceGDI);
126     MouseSafetyOnDrawEnd(Dest, DestGDI);
127
128     return ret;
129   }
130
131   // Determine clipping type
132   if (Clip == (CLIPOBJ *) NULL)
133   {
134     clippingType = DC_TRIVIAL;
135   } else {
136     clippingType = Clip->iDComplexity;
137   }
138
139   // We only handle XO_TABLE translations at the momement
140   if ((ColorTranslation == NULL) || (ColorTranslation->flXlate & XO_TRIVIAL) ||
141       (ColorTranslation->flXlate & XO_TABLE))
142   {
143     SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
144     DestGDI   = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
145
146     switch(clippingType)
147     {
148       case DC_TRIVIAL:
149         CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation);
150
151         MouseSafetyOnDrawEnd(Source, SourceGDI);
152         MouseSafetyOnDrawEnd(Dest, DestGDI);
153
154         return(TRUE);
155
156       case DC_RECT:
157         // Clip the blt to the clip rectangle
158         EngIntersectRect(&rclTmp, DestRect, &Clip->rclBounds);
159
160         ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
161         ptlTmp.y = SourcePoint->y + rclTmp.top  - DestRect->top;
162
163         CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, &rclTmp, &ptlTmp, Source->lDelta, ColorTranslation);
164
165         MouseSafetyOnDrawEnd(Source, SourceGDI);
166         MouseSafetyOnDrawEnd(Dest, DestGDI);
167
168         return(TRUE);
169
170       case DC_COMPLEX:
171
172         CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
173
174         do {
175           EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
176
177           if (RectEnum.c > 0)
178           {
179             RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
180             RECTL* prcl    = &RectEnum.arcl[0];
181
182             do {
183               EngIntersectRect(prcl, prcl, DestRect);
184
185               ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left;
186               ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top;
187
188               if(!CopyBitsCopy(Dest, Source, DestGDI, SourceGDI,
189                                prcl, &ptlTmp, Source->lDelta, ColorTranslation)) return FALSE;
190
191               prcl++;
192
193               } while (prcl < prclEnd);
194             }
195
196           } while(EnumMore);
197
198           MouseSafetyOnDrawEnd(Source, SourceGDI);\r
199           MouseSafetyOnDrawEnd(Dest, DestGDI);
200
201           return(TRUE);
202     }
203   }
204
205   MouseSafetyOnDrawEnd(Source, SourceGDI);
206   MouseSafetyOnDrawEnd(Dest, DestGDI);
207
208   return FALSE;
209 }