- Evgeny Boltik, <BSTSoft AT narod DOT ru>: Add stretching support to TransparentBlt
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib8bpp.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 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 VOID
27 DIB_8BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
28 {
29 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x;
30
31 *byteaddr = c;
32 }
33
34 ULONG
35 DIB_8BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
36 {
37 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x;
38
39 return (ULONG)(*byteaddr);
40 }
41
42 VOID
43 DIB_8BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
44 {
45 memset((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x1, (BYTE) c, x2 - x1);
46 }
47
48 VOID
49 DIB_8BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
50 {
51 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
52 PBYTE addr = byteaddr + x;
53 LONG lDelta = SurfObj->lDelta;
54
55 byteaddr = addr;
56 while(y1++ < y2) {
57 *addr = c;
58
59 addr += lDelta;
60 }
61 }
62
63 BOOLEAN
64 DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
65 {
66 LONG i, j, sx, sy, xColor, f1;
67 PBYTE SourceBits, DestBits, SourceLine, DestLine;
68 PBYTE SourceBits_4BPP, SourceLine_4BPP;
69
70 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
71
72 switch(BltInfo->SourceSurface->iBitmapFormat)
73 {
74 case BMF_1BPP:
75 sx = BltInfo->SourcePoint.x;
76 sy = BltInfo->SourcePoint.y;
77
78 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
79 {
80 sx = BltInfo->SourcePoint.x;
81 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
82 {
83 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
84 {
85 DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
86 } else {
87 DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
88 }
89 sx++;
90 }
91 sy++;
92 }
93 break;
94
95 case BMF_4BPP:
96 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
97
98 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
99 {
100 SourceLine_4BPP = SourceBits_4BPP;
101 sx = BltInfo->SourcePoint.x;
102 f1 = sx & 1;
103
104 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
105 {
106 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
107 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
108 DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
109 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
110 sx++;
111 }
112
113 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
114 }
115 break;
116
117 case BMF_8BPP:
118 if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
119 {
120 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
121 {
122 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
123 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
124 {
125 RtlMoveMemory(DestBits, SourceBits, BltInfo->DestRect.right - BltInfo->DestRect.left);
126 SourceBits += BltInfo->SourceSurface->lDelta;
127 DestBits += BltInfo->DestSurface->lDelta;
128 }
129 }
130 else
131 {
132 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
133 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
134 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
135 {
136 RtlMoveMemory(DestBits, SourceBits, BltInfo->DestRect.right - BltInfo->DestRect.left);
137 SourceBits -= BltInfo->SourceSurface->lDelta;
138 DestBits -= BltInfo->DestSurface->lDelta;
139 }
140 }
141 }
142 else
143 {
144 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
145 {
146 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
147 DestLine = DestBits;
148 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
149 {
150 SourceBits = SourceLine;
151 DestBits = DestLine;
152 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
153 {
154 *DestBits++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits++);
155 }
156 SourceLine += BltInfo->SourceSurface->lDelta;
157 DestLine += BltInfo->DestSurface->lDelta;
158 }
159 }
160 else
161 {
162 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
163 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
164 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
165 {
166 SourceBits = SourceLine;
167 DestBits = DestLine;
168 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
169 {
170 *DestBits++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits++);
171 }
172 SourceLine -= BltInfo->SourceSurface->lDelta;
173 DestLine -= BltInfo->DestSurface->lDelta;
174 }
175 }
176 }
177 break;
178
179 case BMF_16BPP:
180 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
181 DestLine = DestBits;
182
183 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
184 {
185 SourceBits = SourceLine;
186 DestBits = DestLine;
187
188 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
189 {
190 xColor = *((PWORD) SourceBits);
191 *DestBits = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
192 SourceBits += 2;
193 DestBits += 1;
194 }
195
196 SourceLine += BltInfo->SourceSurface->lDelta;
197 DestLine += BltInfo->DestSurface->lDelta;
198 }
199 break;
200
201 case BMF_24BPP:
202 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
203 DestLine = DestBits;
204
205 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
206 {
207 SourceBits = SourceLine;
208 DestBits = DestLine;
209
210 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
211 {
212 xColor = (*(SourceBits + 2) << 0x10) +
213 (*(SourceBits + 1) << 0x08) +
214 (*(SourceBits));
215 *DestBits = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
216 SourceBits += 3;
217 DestBits += 1;
218 }
219
220 SourceLine += BltInfo->SourceSurface->lDelta;
221 DestLine += BltInfo->DestSurface->lDelta;
222 }
223 break;
224
225 case BMF_32BPP:
226 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
227 DestLine = DestBits;
228
229 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
230 {
231 SourceBits = SourceLine;
232 DestBits = DestLine;
233
234 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
235 {
236 xColor = *((PDWORD) SourceBits);
237 *DestBits = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
238 SourceBits += 4;
239 DestBits += 1;
240 }
241
242 SourceLine += BltInfo->SourceSurface->lDelta;
243 DestLine += BltInfo->DestSurface->lDelta;
244 }
245 break;
246
247 default:
248 DPRINT1("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
249 return FALSE;
250 }
251
252 return TRUE;
253 }
254
255 /* BitBlt Optimize */
256 BOOLEAN
257 DIB_8BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
258 {
259 ULONG DestY;
260 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
261 {
262 DIB_8BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
263 }
264
265 return TRUE;
266 }
267
268
269 BOOLEAN
270 DIB_8BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
271 RECTL* DestRect, RECTL *SourceRect,
272 XLATEOBJ *ColorTranslation, ULONG iTransColor)
273 {
274 ULONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, Source, wd, Dest;
275 ULONG *DestBits;
276
277 LONG DstHeight;
278 LONG DstWidth;
279 LONG SrcHeight;
280 LONG SrcWidth;
281
282 DstHeight = DestRect->bottom - DestRect->top;
283 DstWidth = DestRect->right - DestRect->left;
284 SrcHeight = SourceRect->bottom - SourceRect->top;
285 SrcWidth = SourceRect->right - SourceRect->left;
286
287 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x3);
288 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + DestRect->left +
289 (DestRect->top * DestSurf->lDelta));
290 wd = DestSurf->lDelta - (DestRect->right - DestRect->left);
291
292 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
293 {
294 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + DestRect->left +
295 (Y * DestSurf->lDelta));
296 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
297 for (X = DestRect->left; X < RoundedRight; X += 4, DestBits++)
298 {
299 Dest = *DestBits;
300
301 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
302 if (SourceX >= 0 && SourceY >= 0 &&
303 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
304 {
305 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
306 if(Source != iTransColor)
307 {
308 Dest &= 0xFFFFFF00;
309 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFF);
310 }
311 }
312
313 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
314 if (SourceX >= 0 && SourceY >= 0 &&
315 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
316 {
317 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
318 if(Source != iTransColor)
319 {
320 Dest &= 0xFFFF00FF;
321 Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 8) & 0xFF00);
322 }
323 }
324
325 SourceX = SourceRect->left+(X+2 - DestRect->left) * SrcWidth / DstWidth;
326 if (SourceX >= 0 && SourceY >= 0 &&
327 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
328 {
329 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
330 if(Source != iTransColor)
331 {
332 Dest &= 0xFF00FFFF;
333 Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 16) & 0xFF0000);
334 }
335 }
336
337 SourceX = SourceRect->left+(X+3 - DestRect->left) * SrcWidth / DstWidth;
338 if (SourceX >= 0 && SourceY >= 0 &&
339 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
340 {
341 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
342 if(Source != iTransColor)
343 {
344 Dest &= 0x00FFFFFF;
345 Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 24) & 0xFF000000);
346 }
347 }
348
349 *DestBits = Dest;
350 }
351
352 if(X < DestRect->right)
353 {
354 for (; X < DestRect->right; X++)
355 {
356 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
357 if (SourceX >= 0 && SourceY >= 0 &&
358 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
359 {
360 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
361 if(Source != iTransColor)
362 {
363 *((BYTE*)DestBits) = (BYTE)(XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFF);
364 }
365 }
366 DestBits = (PULONG)((ULONG_PTR)DestBits + 1);
367 }
368 }
369 }
370
371 return TRUE;
372 }
373
374 typedef union {
375 ULONG ul;
376 struct {
377 UCHAR red;
378 UCHAR green;
379 UCHAR blue;
380 UCHAR alpha;
381 } col;
382 } NICEPIXEL32;
383
384 typedef union {
385 USHORT us;
386 struct {
387 USHORT red:5,
388 green:6,
389 blue:5;
390 } col;
391 } NICEPIXEL16;
392
393 static __inline UCHAR
394 Clamp8(ULONG val)
395 {
396 return (val > 255) ? 255 : val;
397 }
398
399 BOOLEAN
400 DIB_8BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
401 RECTL* SourceRect, CLIPOBJ* ClipRegion,
402 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
403 {
404 INT Rows, Cols, SrcX, SrcY;
405 register PUCHAR Dst;
406 ULONG DstDelta;
407 BLENDFUNCTION BlendFunc;
408 register NICEPIXEL32 DstPixel32;
409 register NICEPIXEL32 SrcPixel32;
410 register NICEPIXEL16 SrcPixel16;
411 UCHAR Alpha, SrcBpp;
412 XLATEGDI* XlateGDI;
413 XLATEOBJ* SrcXlateObj;
414
415 DPRINT("DIB_8BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
416 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
417 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
418
419 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
420 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
421
422 BlendFunc = BlendObj->BlendFunction;
423 if (BlendFunc.BlendOp != AC_SRC_OVER)
424 {
425 DPRINT1("BlendOp != AC_SRC_OVER\n");
426 return FALSE;
427 }
428 if (BlendFunc.BlendFlags != 0)
429 {
430 DPRINT1("BlendFlags != 0\n");
431 return FALSE;
432 }
433 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
434 {
435 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
436 return FALSE;
437 }
438 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
439 BitsPerFormat(Source->iBitmapFormat) != 32)
440 {
441 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
442 return FALSE;
443 }
444 if (!ColorTranslation)
445 {
446 DPRINT1("ColorTranslation must not be NULL!\n");
447 return FALSE;
448 }
449
450 XlateGDI = ObjToGDI(ColorTranslation, XLATE);
451 SrcXlateObj = IntEngCreateXlate(0, 0, XlateGDI->SourcePal, XlateGDI->DestPal);
452
453 if (!SrcXlateObj)
454 {
455 DPRINT1("IntEngCreateXlate failed\n");
456 return FALSE;
457 }
458
459 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
460 DestRect->left);
461 DstDelta = Dest->lDelta - (DestRect->right - DestRect->left);
462 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
463
464 Rows = DestRect->bottom - DestRect->top;
465 SrcY = SourceRect->top;
466 while (--Rows >= 0)
467 {
468 Cols = DestRect->right - DestRect->left;
469 SrcX = SourceRect->left;
470 while (--Cols >= 0)
471 {
472 if (SrcBpp <= 16)
473 {
474 SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
475 SrcPixel32.col.red = (SrcPixel16.col.red << 3) | (SrcPixel16.col.red >> 2);
476 SrcPixel32.col.green = (SrcPixel16.col.green << 2) | (SrcPixel16.col.green >> 4);
477 SrcPixel32.col.blue = (SrcPixel16.col.blue << 3) | (SrcPixel16.col.blue >> 2);
478 }
479 else
480 {
481 SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
482 }
483 SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
484 SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
485 SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
486 SrcPixel32.col.alpha = (SrcBpp == 32) ? (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
487
488 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
489 SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
490
491 DstPixel32.ul = XLATEOBJ_iXlate(SrcXlateObj, *Dst);
492 SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
493 SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
494 SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 + SrcPixel32.col.blue);
495 *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
496 }
497 Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
498 SrcY++;
499 }
500
501 if (SrcXlateObj)
502 EngDeleteXlate(SrcXlateObj);
503
504 return TRUE;
505 }
506
507 /* EOF */