1. fixed crash in 1bpp blt code that was caused by an uninitialized variable.
[reactos.git] / reactos / 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: dib16bpp.c,v 1.26 2004/04/07 10:19:34 weiden Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <debug.h>
25 #include <ddk/winddi.h>
26 #include <win32k/bitmaps.h>
27 #include <win32k/brush.h>
28 #include <win32k/debug.h>
29 #include <include/object.h>
30 #include "../eng/objects.h"
31 #include "dib.h"
32
33 VOID
34 DIB_16BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c)
35 {
36 PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
37 PWORD addr = (PWORD)byteaddr + x;
38
39 *addr = (WORD)c;
40 }
41
42 ULONG
43 DIB_16BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y)
44 {
45 PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
46 PWORD addr = (PWORD)byteaddr + x;
47
48 return (ULONG)(*addr);
49 }
50
51 VOID
52 DIB_16BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
53 {
54 PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta;
55 PWORD addr = (PWORD)byteaddr + x1;
56 LONG cx = x1;
57
58 while(cx < x2) {
59 *addr = (WORD)c;
60 ++addr;
61 ++cx;
62 }
63 }
64
65 VOID
66 DIB_16BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
67 {
68 PBYTE byteaddr = SurfObj->pvScan0 + y1 * SurfObj->lDelta;
69 PWORD addr = (PWORD)byteaddr + x;
70 LONG lDelta = SurfObj->lDelta;
71
72 byteaddr = (PBYTE)addr;
73 while(y1++ < y2) {
74 *addr = (WORD)c;
75
76 byteaddr += lDelta;
77 addr = (PWORD)byteaddr;
78 }
79 }
80
81 BOOLEAN STATIC
82 DIB_16BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
83 SURFGDI *DestGDI, SURFGDI *SourceGDI,
84 PRECTL DestRect, POINTL *SourcePoint,
85 XLATEOBJ *ColorTranslation)
86 {
87 LONG i, j, sx, sy, xColor, f1;
88 PBYTE SourceBits, DestBits, SourceLine, DestLine;
89 PBYTE SourceBits_4BPP, SourceLine_4BPP;
90 DestBits = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left;
91
92 switch(SourceGDI->BitsPerPixel)
93 {
94 case 1:
95 sx = SourcePoint->x;
96 sy = SourcePoint->y;
97
98 for (j=DestRect->top; j<DestRect->bottom; j++)
99 {
100 sx = SourcePoint->x;
101 for (i=DestRect->left; i<DestRect->right; i++)
102 {
103 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
104 {
105 DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0));
106 } else {
107 DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1));
108 }
109 sx++;
110 }
111 sy++;
112 }
113 break;
114
115 case 4:
116 SourceBits_4BPP = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + (SourcePoint->x >> 1);
117
118 for (j=DestRect->top; j<DestRect->bottom; j++)
119 {
120 SourceLine_4BPP = SourceBits_4BPP;
121 sx = SourcePoint->x;
122 f1 = sx & 1;
123
124 for (i=DestRect->left; i<DestRect->right; i++)
125 {
126 xColor = XLATEOBJ_iXlate(ColorTranslation,
127 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
128 DIB_16BPP_PutPixel(DestSurf, i, j, xColor);
129 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
130 sx++;
131 }
132
133 SourceBits_4BPP += SourceSurf->lDelta;
134 }
135 break;
136
137 case 8:
138 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x;
139 DestLine = DestBits;
140
141 for (j = DestRect->top; j < DestRect->bottom; j++)
142 {
143 SourceBits = SourceLine;
144 DestBits = DestLine;
145
146 for (i = DestRect->left; i < DestRect->right; i++)
147 {
148 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *SourceBits);
149 SourceBits += 1;
150 DestBits += 2;
151 }
152
153 SourceLine += SourceSurf->lDelta;
154 DestLine += DestSurf->lDelta;
155 }
156 break;
157
158 case 16:
159 if (NULL == ColorTranslation || 0 != (ColorTranslation->flXlate & XO_TRIVIAL))
160 {
161 if (DestRect->top < SourcePoint->y)
162 {
163 SourceBits = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x;
164 for (j = DestRect->top; j < DestRect->bottom; j++)
165 {
166 RtlMoveMemory(DestBits, SourceBits, 2 * (DestRect->right - DestRect->left));
167 SourceBits += SourceSurf->lDelta;
168 DestBits += DestSurf->lDelta;
169 }
170 }
171 else
172 {
173 SourceBits = SourceSurf->pvScan0 + ((SourcePoint->y + DestRect->bottom - DestRect->top - 1) * SourceSurf->lDelta) + 2 * SourcePoint->x;
174 DestBits = DestSurf->pvScan0 + ((DestRect->bottom - 1) * DestSurf->lDelta) + 2 * DestRect->left;
175 for (j = DestRect->bottom - 1; DestRect->top <= j; j--)
176 {
177 RtlMoveMemory(DestBits, SourceBits, 2 * (DestRect->right - DestRect->left));
178 SourceBits -= SourceSurf->lDelta;
179 DestBits -= DestSurf->lDelta;
180 }
181 }
182 }
183 else
184 {
185 if (DestRect->top < SourcePoint->y)
186 {
187 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x;
188 DestLine = DestBits;
189 for (j = DestRect->top; j < DestRect->bottom; j++)
190 {
191 SourceBits = SourceLine;
192 DestBits = DestLine;
193 for (i = DestRect->left; i < DestRect->right; i++)
194 {
195 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((WORD *)SourceBits));
196 SourceBits += 2;
197 DestBits += 2;
198 }
199 SourceLine += SourceSurf->lDelta;
200 DestLine += DestSurf->lDelta;
201 }
202 }
203 else
204 {
205 SourceLine = SourceSurf->pvScan0 + ((SourcePoint->y + DestRect->bottom - DestRect->top - 1) * SourceSurf->lDelta) + 2 * SourcePoint->x;
206 DestLine = DestSurf->pvScan0 + ((DestRect->bottom - 1) * DestSurf->lDelta) + 2 * DestRect->left;
207 for (j = DestRect->bottom - 1; DestRect->top <= j; j--)
208 {
209 SourceBits = SourceLine;
210 DestBits = DestLine;
211 for (i = DestRect->left; i < DestRect->right; i++)
212 {
213 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((WORD *)SourceBits));
214 SourceBits += 2;
215 DestBits += 2;
216 }
217 SourceLine -= SourceSurf->lDelta;
218 DestLine -= DestSurf->lDelta;
219 }
220 }
221 }
222 break;
223
224 case 24:
225 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 3 * SourcePoint->x;
226 DestLine = DestBits;
227
228 for (j = DestRect->top; j < DestRect->bottom; j++)
229 {
230 SourceBits = SourceLine;
231 DestBits = DestLine;
232
233 for (i = DestRect->left; i < DestRect->right; i++)
234 {
235 xColor = (*(SourceBits + 2) << 0x10) +
236 (*(SourceBits + 1) << 0x08) +
237 (*(SourceBits));
238 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, xColor);
239 SourceBits += 3;
240 DestBits += 2;
241 }
242
243 SourceLine += SourceSurf->lDelta;
244 DestLine += DestSurf->lDelta;
245 }
246 break;
247
248 case 32:
249 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 4 * SourcePoint->x;
250 DestLine = DestBits;
251
252 for (j = DestRect->top; j < DestRect->bottom; j++)
253 {
254 SourceBits = SourceLine;
255 DestBits = DestLine;
256
257 for (i = DestRect->left; i < DestRect->right; i++)
258 {
259 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, *((PDWORD) SourceBits));
260 SourceBits += 4;
261 DestBits += 2;
262 }
263
264 SourceLine += SourceSurf->lDelta;
265 DestLine += DestSurf->lDelta;
266 }
267 break;
268
269 default:
270 DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
271 return FALSE;
272 }
273
274 return TRUE;
275 }
276
277 BOOLEAN
278 DIB_16BPP_BitBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
279 SURFGDI *DestGDI, SURFGDI *SourceGDI,
280 PRECTL DestRect, POINTL *SourcePoint,
281 PBRUSHOBJ Brush, PPOINTL BrushOrigin,
282 XLATEOBJ *ColorTranslation, ULONG Rop4)
283 {
284 ULONG X, Y;
285 ULONG SourceX, SourceY;
286 ULONG wd, Dest, Source, Pattern = 0, PatternY;
287 PULONG DestBits;
288 BOOL UsesSource;
289 BOOL UsesPattern, CalcPattern;
290 ULONG RoundedRight;
291 /* Pattern brushes */
292 PGDIBRUSHOBJ GdiBrush;
293 HBITMAP PatternSurface = NULL;
294 PSURFOBJ PatternObj;
295 ULONG PatternWidth, PatternHeight;
296
297 if (Rop4 == SRCCOPY)
298 {
299 return DIB_16BPP_BitBltSrcCopy(
300 DestSurf,
301 SourceSurf,
302 DestGDI,
303 SourceGDI,
304 DestRect,
305 SourcePoint,
306 ColorTranslation);
307 }
308
309 UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
310 UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);
311
312 if ((CalcPattern = UsesPattern))
313 {
314 if (Brush == NULL)
315 {
316 UsesPattern = CalcPattern = FALSE;
317 } else
318 if (Brush->iSolidColor == 0xFFFFFFFF)
319 {
320 PBITMAPOBJ PatternBitmap;
321
322 GdiBrush = CONTAINING_RECORD(
323 Brush,
324 GDIBRUSHOBJ,
325 BrushObject);
326
327 PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->hbmPattern);
328 PatternSurface = BitmapToSurf(PatternBitmap, NULL);
329 BITMAPOBJ_UnlockBitmap(GdiBrush->hbmPattern);
330
331 PatternObj = (PSURFOBJ)AccessUserObject((ULONG)PatternSurface);
332 PatternWidth = PatternObj->sizlBitmap.cx;
333 PatternHeight = PatternObj->sizlBitmap.cy;
334 CalcPattern = TRUE;
335 }
336 else
337 {
338 CalcPattern = FALSE;
339 Pattern = (Brush->iSolidColor & 0xFFFF) |
340 ((Brush->iSolidColor & 0xFFFF) << 16);
341 }
342 }
343
344 wd = ((DestRect->right - DestRect->left) << 1) - DestSurf->lDelta;
345 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
346 SourceY = SourcePoint->y;
347 DestBits = (PULONG)(
348 DestSurf->pvScan0 +
349 (DestRect->left << 1) +
350 DestRect->top * DestSurf->lDelta);
351
352 for (Y = DestRect->top; Y < DestRect->bottom; Y++)
353 {
354 SourceX = SourcePoint->x;
355
356 if(CalcPattern)
357 PatternY = Y % PatternHeight;
358
359 for (X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
360 {
361 Dest = *DestBits;
362
363 if (UsesSource)
364 {
365 Source = DIB_GetSource(SourceSurf, SourceGDI, SourceX, SourceY, ColorTranslation);
366 Source |= DIB_GetSource(SourceSurf, SourceGDI, SourceX + 1, SourceY, ColorTranslation) << 16;
367 }
368
369 if (UsesPattern && (Brush->iSolidColor == 0xFFFFFFFF))
370 {
371 Pattern = (DIB_1BPP_GetPixel(PatternObj, X % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack);
372 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + 1) % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack) << 16;
373 }
374
375 *DestBits = DIB_DoRop(Rop4, Dest, Source, Pattern);
376 }
377
378 if (X < DestRect->right)
379 {
380 Dest = *((PUSHORT)DestBits);
381
382 if (UsesSource)
383 {
384 Source = DIB_GetSource(SourceSurf, SourceGDI, SourceX, SourceY, ColorTranslation);
385 }
386
387 if (UsesPattern)
388 {
389 if (Brush->iSolidColor == 0xFFFFFFFF)
390 Pattern = DIB_1BPP_GetPixel(PatternObj, X % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack;
391 else
392 Pattern = Brush->iSolidColor & 0xFFFF;
393 }
394
395 DIB_16BPP_PutPixel(DestSurf, X, Y, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xFFFF);
396 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
397 }
398
399 SourceY++;
400 DestBits = (PULONG)(
401 (ULONG_PTR)DestBits - wd);
402 }
403
404 if (PatternSurface != NULL)
405 EngDeleteSurface(PatternSurface);
406
407 return TRUE;
408 }
409
410
411 /*
412 =======================================
413 Stretching functions goes below
414 Some parts of code are based on an
415 article "Bresenhame image scaling"
416 Dr. Dobb Journal, May 2002
417 =======================================
418 */
419
420 typedef unsigned short PIXEL;
421
422 /* 16-bit HiColor (565 format) */
423 inline PIXEL average16(PIXEL a, PIXEL b)
424 {
425 // This one doesn't work
426 /*
427 if (a == b) {
428 return a;
429 } else {
430 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
431 return ((a & mask) + (b & mask)) >> 1;
432 }*/ /* if */
433
434 // This one should be correct, but it's too long
435 /*
436 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
437 unsigned short res;
438
439 r1 = (a & 0xF800) >> 11;
440 g1 = (a & 0x7E0) >> 5;
441 b1 = (a & 0x1F);
442
443 r2 = (b & 0xF800) >> 11;
444 g2 = (b & 0x7E0) >> 5;
445 b2 = (b & 0x1F);
446
447 rr = (r1+r2) / 2;
448 gr = (g1+g2) / 2;
449 br = (b1+b2) / 2;
450
451 res = (rr << 11) + (gr << 5) + br;
452
453 return res;
454 */
455 return a; // FIXME: Depend on SetStretchMode
456 }
457
458 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
459 void ScaleLineAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
460 {
461 int NumPixels = TgtWidth;
462 int IntPart = SrcWidth / TgtWidth;
463 int FractPart = SrcWidth % TgtWidth;
464 int Mid = TgtWidth >> 1;
465 int E = 0;
466 int skip;
467 PIXEL p;
468
469 skip = (TgtWidth < SrcWidth) ? 0 : (TgtWidth / (2*SrcWidth) + 1);
470 NumPixels -= skip;
471
472 while (NumPixels-- > 0) {
473 p = *Source;
474 if (E >= Mid)
475 p = average16(p, *(Source+1));
476 *Target++ = p;
477 Source += IntPart;
478 E += FractPart;
479 if (E >= TgtWidth) {
480 E -= TgtWidth;
481 Source++;
482 } /* if */
483 } /* while */
484 while (skip-- > 0)
485 *Target++ = *Source;
486 }
487
488 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
489 void ScaleRectAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight,
490 int TgtWidth, int TgtHeight, int srcPitch, int dstPitch)
491 {
492 int NumPixels = TgtHeight;
493 int IntPart = ((SrcHeight / TgtHeight) * srcPitch) >> 1; //(SrcHeight / TgtHeight) * SrcWidth;
494 int FractPart = SrcHeight % TgtHeight;
495 int Mid = TgtHeight >> 1;
496 int E = 0;
497 int skip;
498 PIXEL *ScanLine, *ScanLineAhead;
499 PIXEL *PrevSource = NULL;
500 PIXEL *PrevSourceAhead = NULL;
501
502 skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1);
503 NumPixels -= skip;
504
505 ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here?
506 ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL));
507
508 while (NumPixels-- > 0) {
509 if (Source != PrevSource) {
510 if (Source == PrevSourceAhead) {
511 /* the next scan line has already been scaled and stored in
512 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
513 * point to
514 */
515 PIXEL *tmp = ScanLine;
516 ScanLine = ScanLineAhead;
517 ScanLineAhead = tmp;
518 } else {
519 ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth);
520 } /* if */
521 PrevSource = Source;
522 } /* if */
523
524 if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) {
525 int x;
526 ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth);
527 for (x = 0; x < TgtWidth; x++)
528 ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]);
529 PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch);
530 } /* if */
531
532 memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL));
533 Target = (PIXEL *)((BYTE *)Target + dstPitch);
534 Source += IntPart;
535 E += FractPart;
536 if (E >= TgtHeight) {
537 E -= TgtHeight;
538 Source = (PIXEL *)((BYTE *)Source + srcPitch);
539 } /* if */
540 } /* while */
541
542 if (skip > 0 && Source != PrevSource)
543 ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth);
544 while (skip-- > 0) {
545 memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL));
546 Target = (PIXEL *)((BYTE *)Target + dstPitch);
547 } /* while */
548
549 ExFreePool(ScanLine);
550 ExFreePool(ScanLineAhead);
551 }
552
553 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
554 BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
555 SURFGDI *DestGDI, SURFGDI *SourceGDI,
556 RECTL* DestRect, RECTL *SourceRect,
557 POINTL* MaskOrigin, POINTL* BrushOrigin,
558 XLATEOBJ *ColorTranslation, ULONG Mode)
559 {
560 BYTE *SourceLine, *DestLine;
561
562 DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
563 SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
564 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
565
566 switch(SourceGDI->BitsPerPixel)
567 {
568 case 1:
569 return FALSE;
570 break;
571
572 case 4:
573 return FALSE;
574 break;
575
576 case 8:
577 return FALSE;
578 break;
579
580 case 16:
581 SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left;
582 DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left;
583
584 ScaleRectAvg16((PIXEL *)DestLine, (PIXEL *)SourceLine,
585 SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top,
586 DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta);
587 break;
588
589 case 24:
590 return FALSE;
591 break;
592
593 case 32:
594 return FALSE;
595 break;
596
597 default:
598 DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
599 return FALSE;
600 }
601
602
603
604 return TRUE;
605 }
606
607 BOOLEAN
608 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
609 PSURFGDI DestGDI, PSURFGDI SourceGDI,
610 RECTL* DestRect, POINTL *SourcePoint,
611 XLATEOBJ *ColorTranslation, ULONG iTransColor)
612 {
613 ULONG RoundedRight, X, Y, SourceX, SourceY, Source, wd, Dest;
614 ULONG *DestBits;
615
616 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
617 SourceY = SourcePoint->y;
618 DestBits = (ULONG*)(DestSurf->pvScan0 +
619 (DestRect->left << 1) +
620 DestRect->top * DestSurf->lDelta);
621 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
622
623 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
624 {
625 SourceX = SourcePoint->x;
626 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
627 {
628 Dest = *DestBits;
629
630 Source = DIB_GetSourceIndex(SourceSurf, SourceGDI, SourceX, SourceY);
631 if(Source != iTransColor)
632 {
633 Dest &= 0xFFFF0000;
634 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
635 }
636
637 Source = DIB_GetSourceIndex(SourceSurf, SourceGDI, SourceX + 1, SourceY);
638 if(Source != iTransColor)
639 {
640 Dest &= 0xFFFF;
641 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
642 }
643
644 *DestBits = Dest;
645 }
646
647 if(X < DestRect->right)
648 {
649 Source = DIB_GetSourceIndex(SourceSurf, SourceGDI, SourceX, SourceY);
650 if(Source != iTransColor)
651 {
652 *((USHORT*)DestBits) = (USHORT)(XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
653 }
654
655 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
656 }
657 SourceY++;
658 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
659 }
660
661 return TRUE;
662 }
663
664 /* EOF */