de569716586f4fb9a89a13afc5b06cba1da1d5b7
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib16bpp.c
1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib16bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 16bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 */
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 VOID
17 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
20 PWORD addr = (PWORD)byteaddr + x;
21
22 *addr = (WORD)c;
23 }
24
25 ULONG
26 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29 PWORD addr = (PWORD)byteaddr + x;
30 return (ULONG)(*addr);
31 }
32
33 VOID
34 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
35 {
36 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
37
38 #if defined(_M_IX86) && !defined(_MSC_VER)
39 /* This is about 10% faster than the generic C code below */
40 LONG Count = x2 - x1;
41
42 __asm__ __volatile__ (
43 " cld\n"
44 " mov %0, %%eax\n"
45 " shl $16, %%eax\n"
46 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
47 " or %0, %%eax\n"
48 " mov %2, %%edi\n"
49 " test $0x03, %%edi\n" /* Align to fullword boundary */
50 " jz 0f\n"
51 " stosw\n"
52 " dec %1\n"
53 " jz 1f\n"
54 "0:\n"
55 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */
56 " shr $1,%%ecx\n"
57 " rep stosl\n" /* The actual fill */
58 " test $0x01, %1\n" /* One left to do at the right side? */
59 " jz 1f\n"
60 " stosw\n"
61 "1:\n"
62 : /* no output */
63 : "r"(c), "r"(Count), "m"(addr)
64 : "%eax", "%ecx", "%edi");
65 #else /* _M_IX86 */
66 LONG cx = x1;
67 DWORD cc;
68
69 if (0 != (cx & 0x01))
70 {
71 *((PWORD) addr) = c;
72 cx++;
73 addr = (PDWORD)((PWORD)(addr) + 1);
74 }
75 cc = ((c & 0xffff) << 16) | (c & 0xffff);
76 while(cx + 1 < x2)
77 {
78 *addr++ = cc;
79 cx += 2;
80 }
81 if (cx < x2)
82 {
83 *((PWORD) addr) = c;
84 }
85 #endif /* _M_IX86 */
86 }
87
88
89 VOID
90 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
91 {
92 #if defined(_M_IX86) && !defined(_MSC_VER)
93 asm volatile(
94 " testl %2, %2" "\n\t"
95 " jle 2f" "\n\t"
96 " movl %2, %%ecx" "\n\t"
97 " shrl $2, %2" "\n\t"
98 " andl $3, %%ecx" "\n\t"
99 " jz 1f" "\n\t"
100 "0:" "\n\t"
101 " movw %%ax, (%0)" "\n\t"
102 " addl %1, %0" "\n\t"
103 " decl %%ecx" "\n\t"
104 " jnz 0b" "\n\t"
105 " testl %2, %2" "\n\t"
106 " jz 2f" "\n\t"
107 "1:" "\n\t"
108 " movw %%ax, (%0)" "\n\t"
109 " addl %1, %0" "\n\t"
110 " movw %%ax, (%0)" "\n\t"
111 " addl %1, %0" "\n\t"
112 " movw %%ax, (%0)" "\n\t"
113 " addl %1, %0" "\n\t"
114 " movw %%ax, (%0)" "\n\t"
115 " addl %1, %0" "\n\t"
116 " decl %2" "\n\t"
117 " jnz 1b" "\n\t"
118 "2:" "\n\t"
119 : /* no output */
120 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
121 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
122 : "cc", "memory", "%ecx");
123 #else
124 PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
125 PWORD addr = (PWORD)byteaddr + x;
126 LONG lDelta = SurfObj->lDelta;
127
128 byteaddr = (PBYTE)addr;
129 while(y1++ < y2)
130 {
131 *addr = (WORD)c;
132
133 byteaddr += lDelta;
134 addr = (PWORD)byteaddr;
135 }
136 #endif
137 }
138
139 BOOLEAN
140 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
141 {
142 LONG i, j, sx, sy, xColor, f1;
143 PBYTE SourceBits, DestBits, SourceLine, DestLine;
144 PBYTE SourceBits_4BPP, SourceLine_4BPP;
145 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
146
147 switch(BltInfo->SourceSurface->iBitmapFormat)
148 {
149 case BMF_1BPP:
150 sx = BltInfo->SourcePoint.x;
151 sy = BltInfo->SourcePoint.y;
152 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
153 {
154 sx = BltInfo->SourcePoint.x;
155 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
156 {
157 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
158 {
159 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
160 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
161 }
162 else
163 {
164 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
165 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
166 }
167 sx++;
168 }
169 sy++;
170 }
171 break;
172
173 case BMF_4BPP:
174 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
175 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
176 (BltInfo->SourcePoint.x >> 1);
177
178 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
179 {
180 SourceLine_4BPP = SourceBits_4BPP;
181 sx = BltInfo->SourcePoint.x;
182 f1 = sx & 1;
183
184 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
185 {
186 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
187 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
188 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
189 if(f1 == 1)
190 {
191 SourceLine_4BPP++;
192 f1 = 0;
193 }
194 else
195 {
196 f1 = 1;
197 }
198 sx++;
199 }
200 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
201 }
202 break;
203
204 case BMF_8BPP:
205 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
206 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
207 BltInfo->SourcePoint.x;
208 DestLine = DestBits;
209
210 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
211 {
212 SourceBits = SourceLine;
213 DestBits = DestLine;
214
215 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
216 {
217 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
218 BltInfo->XlateSourceToDest, *SourceBits);
219 SourceBits += 1;
220 DestBits += 2;
221 }
222
223 SourceLine += BltInfo->SourceSurface->lDelta;
224 DestLine += BltInfo->DestSurface->lDelta;
225 }
226 break;
227
228 case BMF_16BPP:
229 if (NULL == BltInfo->XlateSourceToDest || 0 !=
230 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
231 {
232 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
233 {
234 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
235 (BltInfo->SourcePoint.y *
236 BltInfo->SourceSurface->lDelta) + 2 *
237 BltInfo->SourcePoint.x;
238
239 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
240 {
241 RtlMoveMemory(DestBits, SourceBits,
242 2 * (BltInfo->DestRect.right -
243 BltInfo->DestRect.left));
244
245 SourceBits += BltInfo->SourceSurface->lDelta;
246 DestBits += BltInfo->DestSurface->lDelta;
247 }
248 }
249 else
250 {
251 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
252 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
253 BltInfo->DestRect.top - 1) *
254 BltInfo->SourceSurface->lDelta) + 2 *
255 BltInfo->SourcePoint.x;
256
257 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
258 ((BltInfo->DestRect.bottom - 1) *
259 BltInfo->DestSurface->lDelta) + 2 *
260 BltInfo->DestRect.left;
261
262 for (j = BltInfo->DestRect.bottom - 1;
263 BltInfo->DestRect.top <= j; j--)
264 {
265 RtlMoveMemory(DestBits, SourceBits, 2 *
266 (BltInfo->DestRect.right -
267 BltInfo->DestRect.left));
268
269 SourceBits -= BltInfo->SourceSurface->lDelta;
270 DestBits -= BltInfo->DestSurface->lDelta;
271 }
272 }
273 }
274 else
275 {
276 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
277 {
278 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
279 (BltInfo->SourcePoint.y *
280 BltInfo->SourceSurface->lDelta) + 2 *
281 BltInfo->SourcePoint.x;
282
283 DestLine = DestBits;
284 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
285 {
286 SourceBits = SourceLine;
287 DestBits = DestLine;
288 for (i = BltInfo->DestRect.left; i <
289 BltInfo->DestRect.right; i++)
290 {
291 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
292 BltInfo->XlateSourceToDest,
293 *((WORD *)SourceBits));
294 SourceBits += 2;
295 DestBits += 2;
296 }
297 SourceLine += BltInfo->SourceSurface->lDelta;
298 DestLine += BltInfo->DestSurface->lDelta;
299 }
300 }
301 else
302 {
303 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
304 ((BltInfo->SourcePoint.y +
305 BltInfo->DestRect.bottom -
306 BltInfo->DestRect.top - 1) *
307 BltInfo->SourceSurface->lDelta) + 2 *
308 BltInfo->SourcePoint.x;
309
310 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
311 ((BltInfo->DestRect.bottom - 1) *
312 BltInfo->DestSurface->lDelta) + 2 *
313 BltInfo->DestRect.left;
314
315 for (j = BltInfo->DestRect.bottom - 1;
316 BltInfo->DestRect.top <= j; j--)
317 {
318 SourceBits = SourceLine;
319 DestBits = DestLine;
320 for (i = BltInfo->DestRect.left; i <
321 BltInfo->DestRect.right; i++)
322 {
323 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
324 BltInfo->XlateSourceToDest,
325 *((WORD *)SourceBits));
326 SourceBits += 2;
327 DestBits += 2;
328 }
329 SourceLine -= BltInfo->SourceSurface->lDelta;
330 DestLine -= BltInfo->DestSurface->lDelta;
331 }
332 }
333 }
334 break;
335
336 case BMF_24BPP:
337 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
338 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
339 3 * BltInfo->SourcePoint.x;
340
341 DestLine = DestBits;
342
343 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
344 {
345 SourceBits = SourceLine;
346 DestBits = DestLine;
347
348 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
349 {
350 xColor = (*(SourceBits + 2) << 0x10) +
351 (*(SourceBits + 1) << 0x08) + (*(SourceBits));
352
353 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
354 BltInfo->XlateSourceToDest, xColor);
355
356 SourceBits += 3;
357 DestBits += 2;
358 }
359 SourceLine += BltInfo->SourceSurface->lDelta;
360 DestLine += BltInfo->DestSurface->lDelta;
361 }
362 break;
363
364 case BMF_32BPP:
365 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
366 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
367 4 * BltInfo->SourcePoint.x;
368
369 DestLine = DestBits;
370
371 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
372 {
373 SourceBits = SourceLine;
374 DestBits = DestLine;
375
376 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
377 {
378 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
379 BltInfo->XlateSourceToDest,
380 *((PDWORD) SourceBits));
381 SourceBits += 4;
382 DestBits += 2;
383 }
384
385 SourceLine += BltInfo->SourceSurface->lDelta;
386 DestLine += BltInfo->DestSurface->lDelta;
387 }
388 break;
389
390 default:
391 DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
392 BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
393 return FALSE;
394 }
395
396 return TRUE;
397 }
398
399 /* Optimize for bitBlt */
400 BOOLEAN
401 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
402 {
403 ULONG DestY;
404
405 #if defined(_M_IX86) && !defined(_MSC_VER)
406 /* This is about 10% faster than the generic C code below */
407 ULONG delta = DestSurface->lDelta;
408 ULONG width = (DestRect->right - DestRect->left) ;
409 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
410 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
411 color += (color<<16);
412
413 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
414 {
415 __asm__ __volatile__ (
416 " cld\n"
417 " mov %1,%%ebx\n"
418 " mov %2,%%edi\n"
419 " test $0x03, %%edi\n" /* Align to fullword boundary */
420 " jz .FL1\n"
421 " stosw\n"
422 " dec %%ebx\n"
423 " jz .FL2\n"
424 ".FL1:\n"
425 " mov %%ebx,%%ecx\n" /* Setup count of fullwords to fill */
426 " shr $1,%%ecx\n"
427 " rep stosl\n" /* The actual fill */
428 " test $0x01, %%ebx\n" /* One left to do at the right side? */
429 " jz .FL2\n"
430 " stosw\n"
431 ".FL2:\n"
432 :
433 : "a" (color), "r" (width), "m" (pos)
434 : "%ecx", "%ebx", "%edi");
435 pos =(PULONG)((ULONG_PTR)pos + delta);
436 }
437 #else /* _M_IX86 */
438
439 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
440 {
441 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
442 }
443 #endif
444 return TRUE;
445 }
446
447 BOOLEAN
448 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
449 RECTL* DestRect, RECTL *SourceRect,
450 XLATEOBJ *ColorTranslation, ULONG iTransColor)
451 {
452 ULONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, Source, wd, Dest;
453 ULONG *DestBits;
454
455 LONG DstHeight;
456 LONG DstWidth;
457 LONG SrcHeight;
458 LONG SrcWidth;
459
460 DstHeight = DestRect->bottom - DestRect->top;
461 DstWidth = DestRect->right - DestRect->left;
462 SrcHeight = SourceRect->bottom - SourceRect->top;
463 SrcWidth = SourceRect->right - SourceRect->left;
464
465 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
466 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
467 (DestRect->left << 1) +
468 DestRect->top * DestSurf->lDelta);
469 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
470
471 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
472 {
473 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
474 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
475 {
476 Dest = *DestBits;
477
478 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
479 if (SourceX >= 0 && SourceY >= 0 &&
480 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
481 {
482 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
483 if(Source != iTransColor)
484 {
485 Dest &= 0xFFFF0000;
486 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
487 }
488 }
489
490 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
491 if (SourceX >= 0 && SourceY >= 0 &&
492 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
493 {
494 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
495 if(Source != iTransColor)
496 {
497 Dest &= 0xFFFF;
498 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
499 }
500 }
501
502 *DestBits = Dest;
503 }
504
505 if(X < DestRect->right)
506 {
507 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
508 if (SourceX >= 0 && SourceY >= 0 &&
509 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
510 {
511 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
512 if(Source != iTransColor)
513 {
514 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
515 Source);
516 }
517 }
518
519 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
520 }
521
522 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
523 }
524
525 return TRUE;
526 }
527
528 typedef union
529 {
530 ULONG ul;
531 struct
532 {
533 UCHAR red;
534 UCHAR green;
535 UCHAR blue;
536 UCHAR alpha;
537 } col;
538 } NICEPIXEL32;
539
540 typedef union
541 {
542 USHORT us;
543 struct
544 {
545 USHORT red:5,
546 green:6,
547 blue:5;
548 } col;
549 } NICEPIXEL16;
550
551 static __inline UCHAR
552 Clamp5(ULONG val)
553 {
554 return (val > 31) ? 31 : val;
555 }
556
557 static __inline UCHAR
558 Clamp8(ULONG val)
559 {
560 return (val > 255) ? 255 : val;
561 }
562
563 static __inline UCHAR
564 Clamp6(ULONG val)
565 {
566 return (val > 63) ? 63 : val;
567 }
568
569 BOOLEAN
570 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
571 RECTL* SourceRect, CLIPOBJ* ClipRegion,
572 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
573 {
574 INT Rows, Cols, SrcX, SrcY;
575 register PUSHORT Dst;
576 ULONG DstDelta;
577 BLENDFUNCTION BlendFunc;
578 register NICEPIXEL16 SrcPixel16;
579 register NICEPIXEL16 DstPixel16;
580 register NICEPIXEL32 SrcPixel32;
581 register NICEPIXEL32 DstPixel32;
582 UCHAR Alpha, SrcBpp;
583 EXLATEOBJ *pexlo;
584 EXLATEOBJ exloDst2Src;
585
586 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
587 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
588 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
589
590 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
591 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
592
593 BlendFunc = BlendObj->BlendFunction;
594 if (BlendFunc.BlendOp != AC_SRC_OVER)
595 {
596 DPRINT1("BlendOp != AC_SRC_OVER\n");
597 return FALSE;
598 }
599 if (BlendFunc.BlendFlags != 0)
600 {
601 DPRINT1("BlendFlags != 0\n");
602 return FALSE;
603 }
604 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
605 {
606 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
607 return FALSE;
608 }
609 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
610 BitsPerFormat(Source->iBitmapFormat) != 32)
611 {
612 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
613 return FALSE;
614 }
615
616 if (!ColorTranslation)
617 {
618 DPRINT1("ColorTranslation must not be NULL!\n");
619 return FALSE;
620 }
621
622 pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
623 EXLATEOBJ_vInitialize(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
624
625 Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
626 (DestRect->left << 1));
627 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
628 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
629
630 Rows = DestRect->bottom - DestRect->top;
631 SrcY = SourceRect->top;
632 while (--Rows >= 0)
633 {
634 Cols = DestRect->right - DestRect->left;
635 SrcX = SourceRect->left;
636 while (--Cols >= 0)
637 {
638 if (SrcBpp <= 16)
639 {
640 SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
641 SrcPixel32.col.red = (SrcPixel16.col.red << 3);
642 SrcPixel32.col.green = (SrcPixel16.col.green << 2);
643 SrcPixel32.col.blue = (SrcPixel16.col.blue << 3);
644
645 SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
646 SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
647 SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
648 SrcPixel32.col.alpha = (SrcBpp == 32) ?
649 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
650 BlendFunc.SourceConstantAlpha;
651
652 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
653 SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
654
655 DstPixel16.us = *Dst;
656 DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
657 (SrcPixel32.col.red >> 3));
658
659 DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
660 (SrcPixel32.col.green >> 2));
661
662 DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
663 (SrcPixel32.col.blue >> 3));
664
665 *Dst++ = DstPixel16.us;
666 }
667 else
668 {
669 SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
670
671 SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
672 SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
673 SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
674 SrcPixel32.col.alpha = (SrcBpp == 32) ?
675 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
676 BlendFunc.SourceConstantAlpha;
677
678 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
679 SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
680
681 DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
682 SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
683 SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
684 SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 + SrcPixel32.col.blue);
685 *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
686 }
687 }
688
689 Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
690 SrcY++;
691 }
692
693 EXLATEOBJ_vCleanup(&exloDst2Src);
694
695 return TRUE;
696 }
697
698 /* EOF */