8b5751ac7acb62c778892163bb4b007757cce0d6
[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 /* check clib region */
607 BOOLEAN CheckClipRegion(CLIPOBJ *ClipRegion, RECTL* DestRect, int DesX, int DesY)
608 {
609 BOOLEAN status = FALSE;
610 PSPAN ClipSpans;
611 UINT ClipSpansCount;
612 UINT SpanIndex = 0;
613
614 if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
615 {
616 return FALSE;
617 }
618
619 if (0 == ClipSpansCount)
620 {
621 /* No clip spans == empty clipping region, everything clipped away */
622 ASSERT(NULL == ClipSpans);
623 return FALSE;
624 }
625
626 for (SpanIndex=0; SpanIndex<ClipSpansCount;SpanIndex++)
627 {
628 if (ClipSpans[SpanIndex].Y < DesY)
629 status = FALSE;
630
631 if (ClipSpans[SpanIndex].Y+ClipSpans[SpanIndex].Height > DesY)
632 status = FALSE;
633
634 if (ClipSpans[SpanIndex].X > DesX)
635 status = FALSE;
636
637 if (ClipSpans[SpanIndex].X+ClipSpans[SpanIndex].Width > DesX)
638 status = FALSE;
639 }
640
641 return status;
642 }
643
644
645 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
646 BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
647 RECTL* DestRect, RECTL *SourceRect,
648 POINTL* MaskOrigin, POINTL BrushOrigin,
649 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
650 ULONG Mode)
651 {
652 int SrcSizeY;
653 int SrcSizeX;
654 int DesSizeY;
655 int DesSizeX;
656 int sx;
657 int sy;
658 int DesX;
659 int DesY;
660 int color;
661 PULONG DestBits;
662
663
664 DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
665 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
666 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
667
668 SrcSizeY = SourceRect->bottom - SourceRect->top;
669 SrcSizeX = SourceRect->right - SourceRect->left;
670
671 DesSizeY = DestRect->bottom - DestRect->top;
672 DesSizeX = DestRect->right - DestRect->left;
673
674 switch(SourceSurf->iBitmapFormat)
675 {
676
677 case BMF_1BPP:
678 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
679 /* This is a reference implementation, it hasn't been optimized for speed */
680
681 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
682 DestRect->top * DestSurf->lDelta);
683
684 for (DesY=0; DesY<DesSizeY; DesY++)
685 {
686 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
687
688 for (DesX=0; DesX<DesSizeX; DesX++)
689 {
690
691 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
692
693 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
694 {
695 *DestBits = XLATEOBJ_iXlate(ColorTranslation, 0);
696 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
697 }
698 else
699 {
700 *DestBits = XLATEOBJ_iXlate(ColorTranslation, 1);
701 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
702 }
703 }
704 DestBits = (PULONG)((ULONG_PTR)DestBits - (DesSizeX << 1) + DestSurf->lDelta);
705 }
706 break;
707
708 case BMF_4BPP:
709 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
710 /* This is a reference implementation, it hasn't been optimized for speed */
711
712 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
713 DestRect->top * DestSurf->lDelta);
714
715 for (DesY=0; DesY<DesSizeY; DesY++)
716 {
717 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
718
719 for (DesX=0; DesX<DesSizeX; DesX++)
720 {
721
722 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
723 color = DIB_4BPP_GetPixel(SourceSurf, sx, sy);
724
725 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
726 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
727 }
728 DestBits = (PULONG)((ULONG_PTR)DestBits - (DesSizeX << 1) + DestSurf->lDelta);
729 }
730 break;
731
732 case BMF_8BPP:
733 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
734 /* This is a reference implementation, it hasn't been optimized for speed */
735
736 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
737 DestRect->top * DestSurf->lDelta);
738
739 for (DesY=0; DesY<DesSizeY; DesY++)
740 {
741 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
742
743 for (DesX=0; DesX<DesSizeX; DesX++)
744 {
745
746 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
747 color = DIB_8BPP_GetPixel(SourceSurf, sx, sy);
748
749 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
750 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
751 }
752 DestBits = (PULONG)((ULONG_PTR)DestBits - (DesSizeX << 1) + DestSurf->lDelta);
753 }
754 break;
755
756
757 case BMF_24BPP:
758 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
759 /* This is a reference implementation, it hasn't been optimized for speed */
760
761 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
762 DestRect->top * DestSurf->lDelta);
763
764 for (DesY=0; DesY<DesSizeY; DesY++)
765 {
766 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
767
768 for (DesX=0; DesX<DesSizeX; DesX++)
769 {
770
771 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
772 color = DIB_24BPP_GetPixel(SourceSurf, sx, sy);
773
774 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
775 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
776 }
777 DestBits = (PULONG)((ULONG_PTR)DestBits - (DesSizeX << 1) + DestSurf->lDelta);
778 } break;
779
780 case BMF_32BPP:
781 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
782 /* This is a reference implementation, it hasn't been optimized for speed */
783
784 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
785 DestRect->top * DestSurf->lDelta);
786
787 for (DesY=0; DesY<DesSizeY; DesY++)
788 {
789 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
790
791 for (DesX=0; DesX<DesSizeX; DesX++)
792 {
793
794 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
795 color = DIB_32BPP_GetPixel(SourceSurf, sx, sy);
796
797 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
798 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
799 }
800 DestBits = (PULONG)((ULONG_PTR)DestBits - (DesSizeX << 1) + DestSurf->lDelta);
801 }
802 break;
803
804 case BMF_16BPP:
805 return ScaleRectAvg16(DestSurf, SourceSurf, DestRect, SourceRect, MaskOrigin, BrushOrigin,
806 ClipRegion, ColorTranslation, Mode);
807 break;
808
809 default:
810 DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
811 return FALSE;
812 }
813
814
815
816 return TRUE;
817 }
818
819 BOOLEAN
820 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
821 RECTL* DestRect, POINTL *SourcePoint,
822 XLATEOBJ *ColorTranslation, ULONG iTransColor)
823 {
824 ULONG RoundedRight, X, Y, SourceX, SourceY, Source, wd, Dest;
825 ULONG *DestBits;
826
827 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
828 SourceY = SourcePoint->y;
829 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
830 (DestRect->left << 1) +
831 DestRect->top * DestSurf->lDelta);
832 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
833
834 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
835 {
836 SourceX = SourcePoint->x;
837 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
838 {
839 Dest = *DestBits;
840
841 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
842 if(Source != iTransColor)
843 {
844 Dest &= 0xFFFF0000;
845 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
846 }
847
848 Source = DIB_GetSourceIndex(SourceSurf, SourceX + 1, SourceY);
849 if(Source != iTransColor)
850 {
851 Dest &= 0xFFFF;
852 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
853 }
854
855 *DestBits = Dest;
856 }
857
858 if(X < DestRect->right)
859 {
860 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
861 if(Source != iTransColor)
862 {
863 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, Source);
864 }
865
866 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
867 }
868 SourceY++;
869 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
870 }
871
872 return TRUE;
873 }
874
875 typedef union {
876 ULONG ul;
877 struct {
878 UCHAR red;
879 UCHAR green;
880 UCHAR blue;
881 UCHAR alpha;
882 } col;
883 } NICEPIXEL32;
884
885 typedef union {
886 USHORT us;
887 struct {
888 USHORT red:5,
889 green:6,
890 blue:5;
891 } col;
892 } NICEPIXEL16;
893
894 STATIC inline UCHAR
895 Clamp5(ULONG val)
896 {
897 return (val > 31) ? 31 : val;
898 }
899
900 STATIC inline UCHAR
901 Clamp6(ULONG val)
902 {
903 return (val > 63) ? 63 : val;
904 }
905
906 BOOLEAN
907 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
908 RECTL* SourceRect, CLIPOBJ* ClipRegion,
909 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
910 {
911 INT Rows, Cols, SrcX, SrcY;
912 register PUSHORT Dst;
913 ULONG DstDelta;
914 BLENDFUNCTION BlendFunc;
915 register NICEPIXEL16 DstPixel;
916 register NICEPIXEL32 SrcPixel;
917 UCHAR Alpha, SrcBpp;
918
919 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
920 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
921 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
922
923 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
924 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
925
926 BlendFunc = BlendObj->BlendFunction;
927 if (BlendFunc.BlendOp != AC_SRC_OVER)
928 {
929 DPRINT1("BlendOp != AC_SRC_OVER\n");
930 return FALSE;
931 }
932 if (BlendFunc.BlendFlags != 0)
933 {
934 DPRINT1("BlendFlags != 0\n");
935 return FALSE;
936 }
937 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
938 {
939 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
940 return FALSE;
941 }
942 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
943 BitsPerFormat(Source->iBitmapFormat) != 32)
944 {
945 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
946 return FALSE;
947 }
948
949 Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
950 (DestRect->left << 1));
951 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
952 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
953
954 Rows = DestRect->bottom - DestRect->top;
955 SrcY = SourceRect->top;
956 while (--Rows >= 0)
957 {
958 Cols = DestRect->right - DestRect->left;
959 SrcX = SourceRect->left;
960 while (--Cols >= 0)
961 {
962 if (SrcBpp <= 16)
963 {
964 DstPixel.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
965 SrcPixel.col.red = (DstPixel.col.red << 3) | (DstPixel.col.red >> 2);
966 SrcPixel.col.green = (DstPixel.col.green << 2) | (DstPixel.col.green >> 4);
967 SrcPixel.col.blue = (DstPixel.col.blue << 3) | (DstPixel.col.blue >> 2);
968 }
969 else
970 {
971 SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
972 }
973 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
974 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
975 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
976 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
977
978 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
979 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
980
981 DstPixel.us = *Dst;
982 DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 + (SrcPixel.col.red >> 3));
983 DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 + (SrcPixel.col.green >> 2));
984 DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 + (SrcPixel.col.blue >> 3));
985 *Dst++ = DstPixel.us;
986 }
987 Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
988 SrcY++;
989 }
990
991 return TRUE;
992 }
993
994 /* EOF */