d5025958bec182b75fe8c4b67080c1d5bfa1ba0e
[reactos.git] / subsys / win32k / dib / dib16bpp.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 #undef WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <win32k/bitmaps.h>
24 #include <win32k/debug.h>
25 #include <debug.h>
26 #include <ddk/winddi.h>
27 #include "../eng/objects.h"
28 #include "dib.h"
29
30 VOID
31 DIB_16BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c)
32 {
33   PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
34   PWORD addr = (PWORD)byteaddr + x;
35
36   *addr = (WORD)c;
37 }
38
39 ULONG
40 DIB_16BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y)
41 {
42   PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
43   PWORD addr = (PWORD)byteaddr + x;
44
45   return (ULONG)(*addr);
46 }
47
48 VOID
49 DIB_16BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
50 {
51   PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
52   PWORD addr = (PWORD)byteaddr + x1;
53   LONG cx = x1;
54
55   while(cx < x2) {
56     *addr = (WORD)c;
57     ++addr;
58     ++cx;
59   }
60 }
61
62 VOID
63 DIB_16BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
64 {
65   PBYTE byteaddr = SurfObj->pvScan0 + y1 * SurfObj->lDelta;
66   PWORD addr = (PWORD)byteaddr + x;
67   LONG lDelta = SurfObj->lDelta;
68
69   byteaddr = (PBYTE)addr;
70   while(y1++ < y2) {
71     *addr = (WORD)c;
72
73     byteaddr += lDelta;
74     addr = (PWORD)byteaddr;
75   }
76 }
77
78 BOOLEAN STATIC
79 DIB_16BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
80                         SURFGDI *DestGDI,  SURFGDI *SourceGDI,
81                         PRECTL  DestRect,  POINTL  *SourcePoint,
82                         XLATEOBJ *ColorTranslation)
83 {
84   LONG     i, j, sx, sy, xColor, f1;
85   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
86   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
87   DestBits = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left;
88
89   switch(SourceGDI->BitsPerPixel)
90   {
91     case 1:
92       sx = SourcePoint->x;
93       sy = SourcePoint->y;
94
95       for (j=DestRect->top; j<DestRect->bottom; j++)
96       {
97         sx = SourcePoint->x;
98         for (i=DestRect->left; i<DestRect->right; i++)
99         {
100           if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
101           {
102             DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0));
103           } else {
104             DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1));
105           }
106           sx++;
107         }
108         sy++;
109       }
110       break;
111
112     case 4:
113       SourceBits_4BPP = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + (SourcePoint->x >> 1);
114
115       for (j=DestRect->top; j<DestRect->bottom; j++)
116       {
117         SourceLine_4BPP = SourceBits_4BPP;
118         sx = SourcePoint->x;
119         f1 = sx & 1;
120
121         for (i=DestRect->left; i<DestRect->right; i++)
122         {
123           xColor = XLATEOBJ_iXlate(ColorTranslation,
124               (*SourceLine_4BPP & altnotmask[sx&1]) >> (4 * (1-(sx & 1))));
125           DIB_16BPP_PutPixel(DestSurf, i, j, xColor);
126           if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
127           sx++;
128         }
129
130         SourceBits_4BPP += SourceSurf->lDelta;
131       }
132       break;
133
134     case 8:
135       SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x;
136       DestLine = DestBits;
137
138       for (j = DestRect->top; j < DestRect->bottom; j++)
139       {
140         SourceBits = SourceLine;
141         DestBits = DestLine;
142
143         for (i = DestRect->left; i < DestRect->right; i++)
144         {
145           *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *SourceBits);
146           SourceBits += 1;
147           DestBits += 2;
148         }
149
150         SourceLine += SourceSurf->lDelta;
151         DestLine += DestSurf->lDelta;
152       }
153       break;
154
155     case 16:
156       if (NULL == ColorTranslation || 0 != (ColorTranslation->flXlate & XO_TRIVIAL))
157       {
158         if (DestRect->top < SourcePoint->y)
159           {
160             SourceBits = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x;
161             for (j = DestRect->top; j < DestRect->bottom; j++)
162               {
163                 RtlMoveMemory(DestBits, SourceBits, 2 * (DestRect->right - DestRect->left));
164                 SourceBits += SourceSurf->lDelta;
165                 DestBits += DestSurf->lDelta;
166               }
167           }
168         else
169           {
170             SourceBits = SourceSurf->pvScan0 + ((SourcePoint->y + DestRect->bottom - DestRect->top - 1) * SourceSurf->lDelta) + 2 * SourcePoint->x;
171             DestBits = DestSurf->pvScan0 + ((DestRect->bottom - 1) * DestSurf->lDelta) + 2 * DestRect->left;
172             for (j = DestRect->bottom - 1; DestRect->top <= j; j--)
173               {
174                 RtlMoveMemory(DestBits, SourceBits, 2 * (DestRect->right - DestRect->left));
175                 SourceBits -= SourceSurf->lDelta;
176                 DestBits -= DestSurf->lDelta;
177               }
178           }
179       }
180       else
181       {
182         if (DestRect->top < SourcePoint->y)
183           {
184             SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x;
185             DestLine = DestBits;
186             for (j = DestRect->top; j < DestRect->bottom; j++)
187               {
188                 SourceBits = SourceLine;
189                 DestBits = DestLine;
190                 for (i = DestRect->left; i < DestRect->right; i++)
191                   {
192                     *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((WORD *)SourceBits));
193                     SourceBits += 2;
194                     DestBits += 2;
195                   }
196                 SourceLine += SourceSurf->lDelta;
197                 DestLine += DestSurf->lDelta;
198               }
199           }
200         else
201           {
202             SourceLine = SourceSurf->pvScan0 + ((SourcePoint->y + DestRect->bottom - DestRect->top - 1) * SourceSurf->lDelta) + 2 * SourcePoint->x;
203             DestLine = DestSurf->pvScan0 + ((DestRect->bottom - 1) * DestSurf->lDelta) + 2 * DestRect->left;
204             for (j = DestRect->bottom - 1; DestRect->top <= j; j--)
205               {
206                 SourceBits = SourceLine;
207                 DestBits = DestLine;
208                 for (i = DestRect->left; i < DestRect->right; i++)
209                   {
210                     *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((WORD *)SourceBits));
211                     SourceBits += 2;
212                     DestBits += 2;
213                   }
214                 SourceLine -= SourceSurf->lDelta;
215                 DestLine -= DestSurf->lDelta;
216               }
217           }
218       }
219       break;
220
221     case 24:
222       SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 3 * SourcePoint->x;
223       DestLine = DestBits;
224
225       for (j = DestRect->top; j < DestRect->bottom; j++)
226       {
227         SourceBits = SourceLine;
228         DestBits = DestLine;
229
230         for (i = DestRect->left; i < DestRect->right; i++)
231         {
232           xColor = (*(SourceBits + 2) << 0x10) +
233              (*(SourceBits + 1) << 0x08) +
234              (*(SourceBits));
235           *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, xColor);
236           SourceBits += 3;
237           DestBits += 2;
238         }
239
240         SourceLine += SourceSurf->lDelta;
241         DestLine += DestSurf->lDelta;
242       }
243       break;
244
245     case 32:
246       SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 4 * SourcePoint->x;
247       DestLine = DestBits;
248
249       for (j = DestRect->top; j < DestRect->bottom; j++)
250       {
251         SourceBits = SourceLine;
252         DestBits = DestLine;
253
254         for (i = DestRect->left; i < DestRect->right; i++)
255         {
256           *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((PDWORD) SourceBits));
257           SourceBits += 4;
258           DestBits += 2;
259         }
260
261         SourceLine += SourceSurf->lDelta;
262         DestLine += DestSurf->lDelta;
263       }
264       break;
265
266     default:
267       DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
268       return FALSE;
269   }
270
271   return TRUE;
272 }
273
274 BOOLEAN
275 DIB_16BPP_BitBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
276                  SURFGDI *DestGDI,  SURFGDI *SourceGDI,
277                  PRECTL  DestRect,  POINTL  *SourcePoint,
278                  PBRUSHOBJ Brush, PPOINTL BrushOrigin,
279                  XLATEOBJ *ColorTranslation, ULONG Rop4)
280 {
281   LONG     i, j, k, sx, sy;
282   ULONG    Dest, Source, Pattern;
283   PULONG   DestBits;
284   BOOL     UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
285   BOOL     UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);  
286   LONG     RoundedRight = DestRect->right - (DestRect->right & 0x1);
287
288   if (Rop4 == SRCCOPY)
289     {
290       return(DIB_16BPP_BitBltSrcCopy(DestSurf, SourceSurf, DestGDI, SourceGDI, DestRect, SourcePoint, ColorTranslation));
291     }
292   else
293     {
294       sy = SourcePoint->y;
295
296       for (j=DestRect->top; j<DestRect->bottom; j++)
297       {
298         sx = SourcePoint->x;
299         DestBits = (PULONG)(DestSurf->pvScan0 + 2 * DestRect->left + j * DestSurf->lDelta);
300         for (i=DestRect->left; i<RoundedRight; i+=2, DestBits++)
301           {
302             Dest = *DestBits;
303             if (UsesSource)
304               {
305                 Source = 0;
306                 for (k = 0; k < 2; k++)
307                   {
308                     Source |= (DIB_GetSource(SourceSurf, SourceGDI, sx + i + k, sy, ColorTranslation) << (k * 16));
309                   }
310               }
311             if (UsesPattern)
312               {
313                 /* FIXME: No support for pattern brushes. */
314                 Pattern = (Brush->iSolidColor & 0xFFFF) |
315                           ((Brush->iSolidColor & 0xFFFF) << 16);
316               }
317             *DestBits = DIB_DoRop(Rop4, Dest, Source, Pattern);     
318           }
319         if (i < DestRect->right)
320           {
321             Dest = *DestBits;
322             for (; i < DestRect->right; i++)
323               {
324                 if (UsesSource)
325                   {
326                     Source = DIB_GetSource(SourceSurf, SourceGDI, sx + i, sy, ColorTranslation);
327                   }
328                 if (UsesPattern)
329                   {
330                     /* FIXME: No support for pattern brushes. */
331                     Pattern = (Brush->iSolidColor & 0xFFFF) |
332                               ((Brush->iSolidColor & 0xFFFF) << 16);
333                   }                             
334                 DIB_16BPP_PutPixel(DestSurf, i, j, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xFFFF);
335                 Dest >>= 16;
336               }  
337           }
338       }
339     }
340   return TRUE;
341 }
342
343 /* EOF */