Identation corrected, many fixes and minor improvements, initial DIB support
[reactos.git] / reactos / subsys / win32k / eng / bitblt.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI BitBlt Functions
5 * FILE: subsys/win32k/eng/bitblt.c
6 * PROGRAMER: Jason Filby
7 * REVISION HISTORY:
8 * 2/10/1999: Created
9 */
10
11 #include <ddk/winddi.h>
12 #include <ddk/ntddk.h>
13 #include <ntos/minmax.h>
14 #include "brush.h"
15 #include "enum.h"
16 #include "objects.h"
17
18 BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
19 {
20 static const RECTL rclEmpty = { 0, 0, 0, 0 };
21
22 prcDst->left = max(prcSrc1->left, prcSrc2->left);
23 prcDst->right = min(prcSrc1->right, prcSrc2->right);
24
25 if (prcDst->left < prcDst->right)
26 {
27 prcDst->top = max(prcSrc1->top, prcSrc2->top);
28 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
29
30 if (prcDst->top < prcDst->bottom) return(TRUE);
31 }
32
33 *prcDst = rclEmpty;
34
35 return(FALSE);
36 }
37
38
39 BOOL EngBitBlt(SURFOBJ *Dest, SURFOBJ *Source,
40 SURFOBJ *Mask, CLIPOBJ *ClipRegion,
41 XLATEOBJ *ColorTranslation, RECTL *DestRect,
42 POINTL *SourcePoint, POINTL *MaskRect,
43 BRUSHOBJ *Brush, POINTL *BrushOrigin, ROP4 rop4)
44 {
45 BYTE clippingType;
46 RECTL rclTmp;
47 POINTL ptlTmp;
48 RECT_ENUM RectEnum;
49 BOOL EnumMore;
50 PSURFGDI DestGDI, SourceGDI;
51 HSURF hTemp;
52 PSURFOBJ TempSurf;
53 BOOLEAN canCopyBits;
54 POINTL TempPoint;
55 RECTL TempRect;
56 SIZEL TempSize;
57
58 SourceGDI = AccessInternalObjectFromUserObject(Source);
59
60 // If we don't have to do anything special, we can punt to DrvCopyBits
61 // if it exists
62 if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) &&
63 (BrushOrigin == NULL) && (rop4 == 0) )
64 {
65 canCopyBits = TRUE;
66 } else
67 canCopyBits = FALSE;
68
69 // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF:
70 // * The destination bitmap is not managed by the GDI OR
71 if(Dest->iType != STYPE_BITMAP)
72 {
73 // Destination surface is device managed
74 DestGDI = AccessInternalObjectFromUserObject(Dest);
75
76 if (DestGDI->BitBlt!=NULL)
77 {
78 // The destination is device managed, therefore get the source into a format compatible surface
79 TempPoint.x = 0;
80 TempPoint.y = 0;
81 TempRect.top = 0;
82 TempRect.left = 0;
83 TempRect.bottom = DestRect->bottom - DestRect->top;
84 TempRect.right = DestRect->right - DestRect->left;
85 TempSize.cx = TempRect.right;
86 TempSize.cy = TempRect.bottom;
87
88 hTemp = EngCreateBitmap(TempSize,
89 DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)),
90 Dest->iBitmapFormat, 0, NULL);
91 TempSurf = AccessUserObject(hTemp);
92
93 // FIXME: Skip creating a TempSurf if we have the same BPP and palette
94 EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0);
95
96 return DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion,
97 NULL, DestRect, &TempPoint,
98 MaskRect, Brush, BrushOrigin, rop4);
99 }
100 }
101
102 // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device
103 if(Source->iType != STYPE_BITMAP && SourceGDI->CopyBits == NULL)
104 {
105 if (SourceGDI->BitBlt!=NULL)
106 {
107 // Request the device driver to return the bitmap in a format compatible with the device
108 return SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion,
109 NULL, DestRect, SourcePoint,
110 MaskRect, Brush, BrushOrigin, rop4);
111
112 // Convert the surface from the driver into the required destination surface
113 }
114 }
115
116 DestGDI = AccessInternalObjectFromUserObject(Dest);
117 SourceGDI = AccessInternalObjectFromUserObject(Source);
118
119 // Determine clipping type
120 if (ClipRegion == (CLIPOBJ *) NULL)
121 {
122 clippingType = DC_TRIVIAL;
123 } else {
124 clippingType = ClipRegion->iDComplexity;
125 }
126
127 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
128 switch(clippingType)
129 {
130 case DC_TRIVIAL:
131 CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation);
132 return(TRUE);
133
134 case DC_RECT:
135
136 // Clip the blt to the clip rectangle
137 EngIntersectRect(&rclTmp, DestRect, &ClipRegion->rclBounds);
138
139 ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
140 ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top;
141
142 return(TRUE);
143
144 case DC_COMPLEX:
145
146 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
147
148 do {
149 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
150
151 if (RectEnum.c > 0)
152 {
153 RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
154 RECTL* prcl = &RectEnum.arcl[0];
155
156 do {
157 EngIntersectRect(prcl, prcl, DestRect);
158
159 ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left;
160 ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top;
161
162 prcl++;
163
164 } while (prcl < prclEnd);
165 }
166
167 } while(EnumMore);
168
169 return(TRUE);
170 }
171
172 return(FALSE);
173 }