Thx GvG for helping put to gather a new math formula that make alot of calc not neede...
[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
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 VOID
26 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
27 {
28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29 PWORD addr = (PWORD)byteaddr + x;
30
31 *addr = (WORD)c;
32 }
33
34 ULONG
35 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
36 {
37 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
38 PWORD addr = (PWORD)byteaddr + x;
39
40 return (ULONG)(*addr);
41 }
42
43 VOID
44 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
45 {
46 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
47
48
49 #ifdef _M_IX86
50 /* This is about 10% faster than the generic C code below */
51 LONG Count = x2 - x1;
52
53 __asm__ __volatile__ (
54 " cld\n"
55 " mov %0, %%eax\n"
56 " shl $16, %%eax\n"
57 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
58 " or %0, %%eax\n"
59 " mov %2, %%edi\n"
60 " test $0x03, %%edi\n" /* Align to fullword boundary */
61 " jz 0f\n"
62 " stosw\n"
63 " dec %1\n"
64 " jz 1f\n"
65 "0:\n"
66 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */
67 " shr $1,%%ecx\n"
68 " rep stosl\n" /* The actual fill */
69 " test $0x01, %1\n" /* One left to do at the right side? */
70 " jz 1f\n"
71 " stosw\n"
72 "1:\n"
73 : /* no output */
74 : "r"(c), "r"(Count), "m"(addr)
75 : "%eax", "%ecx", "%edi");
76 #else /* _M_IX86 */
77 LONG cx = x1;
78 DWORD cc;
79
80 if (0 != (cx & 0x01)) {
81 *((PWORD) addr) = c;
82 cx++;
83 addr = (PDWORD)((PWORD)(addr) + 1);
84 }
85 cc = ((c & 0xffff) << 16) | (c & 0xffff);
86 while(cx + 1 < x2) {
87 *addr++ = cc;
88 cx += 2;
89 }
90 if (cx < x2) {
91 *((PWORD) addr) = c;
92 }
93 #endif /* _M_IX86 */
94 }
95
96
97 VOID
98 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
99 {
100 #ifdef _M_IX86
101 asm volatile(
102 " testl %2, %2" "\n\t"
103 " jle 2f" "\n\t"
104 " movl %2, %%ecx" "\n\t"
105 " shrl $2, %2" "\n\t"
106 " andl $3, %%ecx" "\n\t"
107 " jz 1f" "\n\t"
108 "0:" "\n\t"
109 " movw %%ax, (%0)" "\n\t"
110 " addl %1, %0" "\n\t"
111 " decl %%ecx" "\n\t"
112 " jnz 0b" "\n\t"
113 " testl %2, %2" "\n\t"
114 " jz 2f" "\n\t"
115 "1:" "\n\t"
116 " movw %%ax, (%0)" "\n\t"
117 " addl %1, %0" "\n\t"
118 " movw %%ax, (%0)" "\n\t"
119 " addl %1, %0" "\n\t"
120 " movw %%ax, (%0)" "\n\t"
121 " addl %1, %0" "\n\t"
122 " movw %%ax, (%0)" "\n\t"
123 " addl %1, %0" "\n\t"
124 " decl %2" "\n\t"
125 " jnz 1b" "\n\t"
126 "2:" "\n\t"
127 : /* no output */
128 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
129 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
130 : "cc", "memory", "%ecx");
131 #else
132 PBYTE byteaddr = SurfObj->pvScan0 + y1 * SurfObj->lDelta;
133 PWORD addr = (PWORD)byteaddr + x;
134 LONG lDelta = SurfObj->lDelta;
135
136 byteaddr = (PBYTE)addr;
137 while(y1++ < y2) {
138 *addr = (WORD)c;
139
140 byteaddr += lDelta;
141 addr = (PWORD)byteaddr;
142 }
143 #endif
144 }
145
146 BOOLEAN
147 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
148 {
149 LONG i, j, sx, sy, xColor, f1;
150 PBYTE SourceBits, DestBits, SourceLine, DestLine;
151 PBYTE SourceBits_4BPP, SourceLine_4BPP;
152 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
153
154 switch(BltInfo->SourceSurface->iBitmapFormat)
155 {
156 case BMF_1BPP:
157 sx = BltInfo->SourcePoint.x;
158 sy = BltInfo->SourcePoint.y;
159
160 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
161 {
162 sx = BltInfo->SourcePoint.x;
163 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
164 {
165 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
166 {
167 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
168 } else {
169 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
170 }
171 sx++;
172 }
173 sy++;
174 }
175 break;
176
177 case BMF_4BPP:
178 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
179
180 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
181 {
182 SourceLine_4BPP = SourceBits_4BPP;
183 sx = BltInfo->SourcePoint.x;
184 f1 = sx & 1;
185
186 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
187 {
188 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
189 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
190 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
191 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
192 sx++;
193 }
194
195 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
196 }
197 break;
198
199 case BMF_8BPP:
200 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
201 DestLine = DestBits;
202
203 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
204 {
205 SourceBits = SourceLine;
206 DestBits = DestLine;
207
208 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
209 {
210 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
211 SourceBits += 1;
212 DestBits += 2;
213 }
214
215 SourceLine += BltInfo->SourceSurface->lDelta;
216 DestLine += BltInfo->DestSurface->lDelta;
217 }
218 break;
219
220 case BMF_16BPP:
221 if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
222 {
223 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
224 {
225 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
226 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
227 {
228 RtlMoveMemory(DestBits, SourceBits, 2 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
229 SourceBits += BltInfo->SourceSurface->lDelta;
230 DestBits += BltInfo->DestSurface->lDelta;
231 }
232 }
233 else
234 {
235 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
236 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
237 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
238 {
239 RtlMoveMemory(DestBits, SourceBits, 2 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
240 SourceBits -= BltInfo->SourceSurface->lDelta;
241 DestBits -= BltInfo->DestSurface->lDelta;
242 }
243 }
244 }
245 else
246 {
247 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
248 {
249 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
250 DestLine = DestBits;
251 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
252 {
253 SourceBits = SourceLine;
254 DestBits = DestLine;
255 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
256 {
257 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((WORD *)SourceBits));
258 SourceBits += 2;
259 DestBits += 2;
260 }
261 SourceLine += BltInfo->SourceSurface->lDelta;
262 DestLine += BltInfo->DestSurface->lDelta;
263 }
264 }
265 else
266 {
267 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
268 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
269 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
270 {
271 SourceBits = SourceLine;
272 DestBits = DestLine;
273 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
274 {
275 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((WORD *)SourceBits));
276 SourceBits += 2;
277 DestBits += 2;
278 }
279 SourceLine -= BltInfo->SourceSurface->lDelta;
280 DestLine -= BltInfo->DestSurface->lDelta;
281 }
282 }
283 }
284 break;
285
286 case BMF_24BPP:
287 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
288 DestLine = DestBits;
289
290 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
291 {
292 SourceBits = SourceLine;
293 DestBits = DestLine;
294
295 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
296 {
297 xColor = (*(SourceBits + 2) << 0x10) +
298 (*(SourceBits + 1) << 0x08) +
299 (*(SourceBits));
300 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
301 SourceBits += 3;
302 DestBits += 2;
303 }
304
305 SourceLine += BltInfo->SourceSurface->lDelta;
306 DestLine += BltInfo->DestSurface->lDelta;
307 }
308 break;
309
310 case BMF_32BPP:
311 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
312 DestLine = DestBits;
313
314 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
315 {
316 SourceBits = SourceLine;
317 DestBits = DestLine;
318
319 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
320 {
321 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
322 SourceBits += 4;
323 DestBits += 2;
324 }
325
326 SourceLine += BltInfo->SourceSurface->lDelta;
327 DestLine += BltInfo->DestSurface->lDelta;
328 }
329 break;
330
331 default:
332 DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
333 return FALSE;
334 }
335
336 return TRUE;
337 }
338
339 /* Optimize for bitBlt */
340 BOOLEAN
341 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
342 {
343 ULONG DestY;
344
345 #ifdef _M_IX86
346 /* This is about 10% faster than the generic C code below */
347 ULONG delta = DestSurface->lDelta;
348 ULONG width = (DestRect->right - DestRect->left) ;
349 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
350 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
351 color += (color<<16);
352
353 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
354 {
355 __asm__ __volatile__ (
356 " cld\n"
357 " mov %1,%%ebx\n"
358 " mov %2,%%edi\n"
359 " test $0x03, %%edi\n" /* Align to fullword boundary */
360 " jz .FL1\n"
361 " stosw\n"
362 " dec %%ebx\n"
363 " jz .FL2\n"
364 ".FL1:\n"
365 " mov %%ebx,%%ecx\n" /* Setup count of fullwords to fill */
366 " shr $1,%%ecx\n"
367 " rep stosl\n" /* The actual fill */
368 " test $0x01, %%ebx\n" /* One left to do at the right side? */
369 " jz .FL2\n"
370 " stosw\n"
371 ".FL2:\n"
372 :
373 : "a" (color), "r" (width), "m" (pos)
374 : "%ecx", "%ebx", "%edi");
375 pos =(PULONG)((ULONG_PTR)pos + delta);
376 }
377
378 #else /* _M_IX86 */
379
380 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
381 {
382 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
383 }
384 #endif
385 return TRUE;
386 }
387 /*
388 =======================================
389 Stretching functions goes below
390 Some parts of code are based on an
391 article "Bresenhame image scaling"
392 Dr. Dobb Journal, May 2002
393 =======================================
394 */
395
396 typedef unsigned short PIXEL;
397
398 /* 16-bit HiColor (565 format) */
399 __inline PIXEL average16(PIXEL a, PIXEL b)
400 {
401 // This one doesn't work
402 /*
403 if (a == b) {
404 return a;
405 } else {
406 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
407 return ((a & mask) + (b & mask)) >> 1;
408 }*/ /* if */
409
410 // This one should be correct, but it's too long
411 /*
412 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
413 unsigned short res;
414
415 r1 = (a & 0xF800) >> 11;
416 g1 = (a & 0x7E0) >> 5;
417 b1 = (a & 0x1F);
418
419 r2 = (b & 0xF800) >> 11;
420 g2 = (b & 0x7E0) >> 5;
421 b2 = (b & 0x1F);
422
423 rr = (r1+r2) / 2;
424 gr = (g1+g2) / 2;
425 br = (b1+b2) / 2;
426
427 res = (rr << 11) + (gr << 5) + br;
428
429 return res;
430 */
431 return a; // FIXME: Depend on SetStretchMode
432 }
433
434 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
435 void ScaleLineAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
436 {
437 int NumPixels = TgtWidth;
438 int IntPart = SrcWidth / TgtWidth;
439 int FractPart = SrcWidth % TgtWidth;
440 int Mid = TgtWidth >> 1;
441 int E = 0;
442 int skip;
443 PIXEL p;
444
445 skip = (TgtWidth < SrcWidth) ? 0 : (TgtWidth / (2*SrcWidth) + 1);
446 NumPixels -= skip;
447
448 while (NumPixels-- > 0) {
449 p = *Source;
450 if (E >= Mid)
451 p = average16(p, *(Source+1));
452 *Target++ = p;
453 Source += IntPart;
454 E += FractPart;
455 if (E >= TgtWidth) {
456 E -= TgtWidth;
457 Source++;
458 } /* if */
459 } /* while */
460 while (skip-- > 0)
461 *Target++ = *Source;
462 }
463
464 static BOOLEAN
465 FinalCopy16(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex,
466 UINT DestY, RECTL *DestRect)
467 {
468 LONG Left, Right;
469
470 while (ClipSpans[*SpanIndex].Y < DestY
471 || (ClipSpans[*SpanIndex].Y == DestY
472 && ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left))
473 {
474 (*SpanIndex)++;
475 if (ClipSpansCount <= *SpanIndex)
476 {
477 /* No more spans, everything else is clipped away, we're done */
478 return FALSE;
479 }
480 }
481 while (ClipSpans[*SpanIndex].Y == DestY)
482 {
483 if (ClipSpans[*SpanIndex].X < DestRect->right)
484 {
485 Left = max(ClipSpans[*SpanIndex].X, DestRect->left);
486 Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right);
487 memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left,
488 (Right - Left) * sizeof(PIXEL));
489 }
490 (*SpanIndex)++;
491 if (ClipSpansCount <= *SpanIndex)
492 {
493 /* No more spans, everything else is clipped away, we're done */
494 return FALSE;
495 }
496 }
497
498 return TRUE;
499 }
500
501 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
502 BOOLEAN ScaleRectAvg16(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
503 RECTL* DestRect, RECTL *SourceRect,
504 POINTL* MaskOrigin, POINTL BrushOrigin,
505 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
506 ULONG Mode)
507 {
508 int NumPixels = DestRect->bottom - DestRect->top;
509 int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceSurf->lDelta) >> 1;
510 int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top);
511 int Mid = (DestRect->bottom - DestRect->top) >> 1;
512 int E = 0;
513 int skip;
514 PIXEL *ScanLine, *ScanLineAhead;
515 PIXEL *PrevSource = NULL;
516 PIXEL *PrevSourceAhead = NULL;
517 PIXEL *Target = (PIXEL *) ((PBYTE)DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left);
518 PIXEL *Source = (PIXEL *) ((PBYTE)SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left);
519 PSPAN ClipSpans;
520 UINT ClipSpansCount;
521 UINT SpanIndex;
522 LONG DestY;
523
524 if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
525 {
526 return FALSE;
527 }
528 if (0 == ClipSpansCount)
529 {
530 /* No clip spans == empty clipping region, everything clipped away */
531 ASSERT(NULL == ClipSpans);
532 return TRUE;
533 }
534 skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1);
535 NumPixels -= skip;
536
537 ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
538 ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
539
540 DestY = DestRect->top;
541 SpanIndex = 0;
542 while (NumPixels-- > 0) {
543 if (Source != PrevSource) {
544 if (Source == PrevSourceAhead) {
545 /* the next scan line has already been scaled and stored in
546 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
547 * point to
548 */
549 PIXEL *tmp = ScanLine;
550 ScanLine = ScanLineAhead;
551 ScanLineAhead = tmp;
552 } else {
553 ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
554 } /* if */
555 PrevSource = Source;
556 } /* if */
557
558 if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceSurf->lDelta)) {
559 int x;
560 ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceSurf->lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
561 for (x = 0; x < DestRect->right - DestRect->left; x++)
562 ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]);
563 PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceSurf->lDelta);
564 } /* if */
565
566 if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
567 {
568 /* No more spans, everything else is clipped away, we're done */
569 ExFreePool(ClipSpans);
570 ExFreePool(ScanLine);
571 ExFreePool(ScanLineAhead);
572 return TRUE;
573 }
574 DestY++;
575 Target = (PIXEL *)((BYTE *)Target + DestSurf->lDelta);
576 Source += IntPart;
577 E += FractPart;
578 if (E >= DestRect->bottom - DestRect->top) {
579 E -= DestRect->bottom - DestRect->top;
580 Source = (PIXEL *)((BYTE *)Source + SourceSurf->lDelta);
581 } /* if */
582 } /* while */
583
584 if (skip > 0 && Source != PrevSource)
585 ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
586 while (skip-- > 0) {
587 if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
588 {
589 /* No more spans, everything else is clipped away, we're done */
590 ExFreePool(ClipSpans);
591 ExFreePool(ScanLine);
592 ExFreePool(ScanLineAhead);
593 return TRUE;
594 }
595 DestY++;
596 Target = (PIXEL *)((BYTE *)Target + DestSurf->lDelta);
597 } /* while */
598
599 ExFreePool(ClipSpans);
600 ExFreePool(ScanLine);
601 ExFreePool(ScanLineAhead);
602
603 return TRUE;
604 }
605
606 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
607 BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
608 RECTL* DestRect, RECTL *SourceRect,
609 POINTL* MaskOrigin, POINTL BrushOrigin,
610 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
611 ULONG Mode)
612 {
613 int SrcSizeY;
614 int SrcSizeX;
615 int DesSizeY;
616 int DesSizeX;
617 int sx;
618 int sy;
619 int DesX;
620 int DesY;
621 int color;
622
623 DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
624 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
625 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
626
627 SrcSizeY = SourceRect->bottom - SourceRect->top;
628 SrcSizeX = SourceRect->right - SourceRect->left;
629
630 DesSizeY = DestRect->bottom - DestRect->top;
631 DesSizeX = DestRect->right - DestRect->left;
632
633 switch(SourceSurf->iBitmapFormat)
634 {
635
636 case BMF_1BPP:
637 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
638 /* This is a reference implementation, it hasn't been optimized for speed */
639
640 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
641 {
642 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
643
644 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
645 {
646 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
647
648 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
649 {
650 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, 0));
651 }
652 else
653 {
654 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, 1));
655 }
656 }
657 }
658 break;
659
660 case BMF_4BPP:
661 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
662 /* This is a reference implementation, it hasn't been optimized for speed */
663
664 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
665 {
666 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
667
668 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
669 {
670 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
671 color = DIB_4BPP_GetPixel(SourceSurf, sx, sy);
672 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
673 }
674 }
675 break;
676
677 case BMF_8BPP:
678 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
679 /* This is a reference implementation, it hasn't been optimized for speed */
680
681 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
682 {
683 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
684
685 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
686 {
687 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
688 color = DIB_8BPP_GetPixel(SourceSurf, sx, sy);
689 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
690 }
691 }
692 break;
693
694 case BMF_24BPP:
695 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
696 /* This is a reference implementation, it hasn't been optimized for speed */
697
698 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
699 {
700 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
701
702 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
703 {
704 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
705 color = DIB_24BPP_GetPixel(SourceSurf, sx, sy);
706 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
707 }
708 }
709 break;
710
711 case BMF_32BPP:
712 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
713 /* This is a reference implementation, it hasn't been optimized for speed */
714
715 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
716 {
717 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
718
719 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
720 {
721 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
722 color = DIB_32BPP_GetPixel(SourceSurf, sx, sy);
723 DIB_16BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
724 }
725 }
726 break;
727
728 case BMF_16BPP:
729 return ScaleRectAvg16(DestSurf, SourceSurf, DestRect, SourceRect, MaskOrigin, BrushOrigin,
730 ClipRegion, ColorTranslation, Mode);
731 break;
732
733 default:
734 DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
735 return FALSE;
736 }
737
738
739
740 return TRUE;
741 }
742
743 BOOLEAN
744 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
745 RECTL* DestRect, POINTL *SourcePoint,
746 XLATEOBJ *ColorTranslation, ULONG iTransColor)
747 {
748 ULONG RoundedRight, X, Y, SourceX, SourceY, Source, wd, Dest;
749 ULONG *DestBits;
750
751 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
752 SourceY = SourcePoint->y;
753 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
754 (DestRect->left << 1) +
755 DestRect->top * DestSurf->lDelta);
756 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
757
758 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
759 {
760 SourceX = SourcePoint->x;
761 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
762 {
763 Dest = *DestBits;
764
765 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
766 if(Source != iTransColor)
767 {
768 Dest &= 0xFFFF0000;
769 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
770 }
771
772 Source = DIB_GetSourceIndex(SourceSurf, SourceX + 1, SourceY);
773 if(Source != iTransColor)
774 {
775 Dest &= 0xFFFF;
776 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
777 }
778
779 *DestBits = Dest;
780 }
781
782 if(X < DestRect->right)
783 {
784 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
785 if(Source != iTransColor)
786 {
787 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, Source);
788 }
789
790 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
791 }
792 SourceY++;
793 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
794 }
795
796 return TRUE;
797 }
798
799 typedef union {
800 ULONG ul;
801 struct {
802 UCHAR red;
803 UCHAR green;
804 UCHAR blue;
805 UCHAR alpha;
806 } col;
807 } NICEPIXEL32;
808
809 typedef union {
810 USHORT us;
811 struct {
812 USHORT red:5,
813 green:6,
814 blue:5;
815 } col;
816 } NICEPIXEL16;
817
818 STATIC inline UCHAR
819 Clamp5(ULONG val)
820 {
821 return (val > 31) ? 31 : val;
822 }
823
824 STATIC inline UCHAR
825 Clamp6(ULONG val)
826 {
827 return (val > 63) ? 63 : val;
828 }
829
830 BOOLEAN
831 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
832 RECTL* SourceRect, CLIPOBJ* ClipRegion,
833 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
834 {
835 INT Rows, Cols, SrcX, SrcY;
836 register PUSHORT Dst;
837 ULONG DstDelta;
838 BLENDFUNCTION BlendFunc;
839 register NICEPIXEL16 DstPixel;
840 register NICEPIXEL32 SrcPixel;
841 UCHAR Alpha, SrcBpp;
842
843 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
844 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
845 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
846
847 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
848 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
849
850 BlendFunc = BlendObj->BlendFunction;
851 if (BlendFunc.BlendOp != AC_SRC_OVER)
852 {
853 DPRINT1("BlendOp != AC_SRC_OVER\n");
854 return FALSE;
855 }
856 if (BlendFunc.BlendFlags != 0)
857 {
858 DPRINT1("BlendFlags != 0\n");
859 return FALSE;
860 }
861 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
862 {
863 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
864 return FALSE;
865 }
866 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
867 BitsPerFormat(Source->iBitmapFormat) != 32)
868 {
869 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
870 return FALSE;
871 }
872
873 Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
874 (DestRect->left << 1));
875 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
876 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
877
878 Rows = DestRect->bottom - DestRect->top;
879 SrcY = SourceRect->top;
880 while (--Rows >= 0)
881 {
882 Cols = DestRect->right - DestRect->left;
883 SrcX = SourceRect->left;
884 while (--Cols >= 0)
885 {
886 if (SrcBpp <= 16)
887 {
888 DstPixel.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
889 SrcPixel.col.red = (DstPixel.col.red << 3) | (DstPixel.col.red >> 2);
890 SrcPixel.col.green = (DstPixel.col.green << 2) | (DstPixel.col.green >> 4);
891 SrcPixel.col.blue = (DstPixel.col.blue << 3) | (DstPixel.col.blue >> 2);
892 }
893 else
894 {
895 SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
896 }
897 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
898 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
899 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
900 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
901
902 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
903 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
904
905 DstPixel.us = *Dst;
906 DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 + (SrcPixel.col.red >> 3));
907 DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 + (SrcPixel.col.green >> 2));
908 DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 + (SrcPixel.col.blue >> 3));
909 *Dst++ = DstPixel.us;
910 }
911 Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
912 SrcY++;
913 }
914
915 return TRUE;
916 }
917
918 /* EOF */