fix some bugs wih org with strechblt.
[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 int zoomX;
623 int zoomY;
624 int count;
625 int saveX;
626 int saveY;
627 BOOLEAN DesIsBiggerY=FALSE;
628
629 DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
630 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
631 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
632
633 SrcSizeY = SourceRect->bottom - SourceRect->top;
634 SrcSizeX = SourceRect->right - SourceRect->left;
635
636 DesSizeY = DestRect->bottom ;
637 DesSizeX = DestRect->right;
638
639 zoomX = DesSizeX / SrcSizeX;
640 if (zoomX==0) zoomX=1;
641
642 zoomY = DesSizeY / SrcSizeY;
643 if (zoomY==0) zoomY=1;
644
645 if (DesSizeY>SrcSizeY)
646 DesIsBiggerY = TRUE;
647
648
649
650 switch(SourceSurf->iBitmapFormat)
651 {
652
653
654 case BMF_1BPP:
655 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
656 /* This is a reference implementation, it hasn't been optimized for speed */
657 if (zoomX>1)
658 {
659 /* Draw one Hline on X - Led to the Des Zoom In*/
660 if (DesSizeX>SrcSizeX)
661 {
662 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
663 {
664 if (DesIsBiggerY)
665 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
666 else
667 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
668
669 if (sy > SourceRect->bottom) break;
670
671 saveY = DesY+zoomY;
672
673 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
674 {
675 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
676
677 if (sx > SourceRect->right) break;
678
679 saveX = DesX + zoomX;
680
681 if (DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
682 for (count=DesY;count<saveY;count++)
683 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, 0);
684 else
685 for (count=DesY;count<saveY;count++)
686 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, 1);
687
688 }
689 }
690 }
691 else
692 {
693 /* Draw one Hline on X - Led to the Des Zoom Out*/
694
695 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
696 {
697 if (DesIsBiggerY)
698 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
699 else
700 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
701
702 if (sy > SourceRect->bottom) break;
703
704 saveY = DesY+zoomY;
705
706 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
707 {
708 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
709
710 if (sx > SourceRect->right) break;
711
712 saveX = DesX + zoomX;
713
714 if (DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
715 for (count=DesY;count<saveY;count++)
716 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, 0);
717 else
718 for (count=DesY;count<saveY;count++)
719 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, 1);
720
721 }
722 }
723 }
724 }
725 else
726 {
727
728 if (DesSizeX>SrcSizeX)
729 {
730 /* Draw one pixel on X - Led to the Des Zoom In*/
731 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
732 {
733 if (DesIsBiggerY)
734 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
735 else
736 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
737
738 if (sy > SourceRect->bottom) break;
739
740 saveY = DesY+zoomY;
741
742 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
743 {
744 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
745
746 if (sx > SourceRect->right) break;
747
748 if (DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
749 for (count=DesY;count<saveY;count++)
750 DIB_16BPP_PutPixel(DestSurf, DesX, count, 0);
751 else
752 for (count=DesY;count<saveY;count++)
753 DIB_16BPP_PutPixel(DestSurf, DesX, count, 1);
754
755
756 }
757 }
758 }
759 else
760 {
761 /* Draw one pixel on X - Led to the Des Zoom Out*/
762 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
763 {
764 if (DesIsBiggerY)
765 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
766 else
767 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
768
769 if (sy > SourceRect->bottom) break;
770
771 saveY = DesY+zoomY;
772
773 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
774 {
775 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
776
777 if (sx > SourceRect->right) break;
778
779 if (DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
780 for (count=DesY;count<saveY;count++)
781 DIB_16BPP_PutPixel(DestSurf, DesX, count, 0);
782 else
783 for (count=DesY;count<saveY;count++)
784 DIB_16BPP_PutPixel(DestSurf, DesX, count, 1);
785
786 }
787 }
788 }
789 }
790 break;
791
792 case BMF_4BPP:
793 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
794 /* This is a reference implementation, it hasn't been optimized for speed */
795 if (zoomX>1)
796 {
797 /* Draw one Hline on X - Led to the Des Zoom In*/
798 if (DesSizeX>SrcSizeX)
799 {
800 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
801 {
802 if (DesIsBiggerY)
803 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
804 else
805 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
806
807 if (sy > SourceRect->bottom) break;
808
809 saveY = DesY+zoomY;
810
811 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
812 {
813 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
814
815 if (sx > SourceRect->right) break;
816
817 color = XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy));
818
819 saveX = DesX + zoomX;
820 for (count=DesY;count<saveY;count++)
821 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
822 }
823 }
824 }
825 else
826 {
827 /* Draw one Hline on X - Led to the Des Zoom Out*/
828
829 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
830 {
831 if (DesIsBiggerY)
832 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
833 else
834 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
835
836 if (sy > SourceRect->bottom) break;
837
838 saveY = DesY+zoomY;
839
840 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
841 {
842 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
843
844 if (sx > SourceRect->right) break;
845
846 color = XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy));
847
848 saveX = DesX + zoomX;
849 for (count=DesY;count<saveY;count++)
850 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
851 }
852 }
853 }
854 }
855
856 else
857 {
858
859 if (DesSizeX>SrcSizeX)
860 {
861 /* Draw one pixel on X - Led to the Des Zoom In*/
862 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
863 {
864 if (DesIsBiggerY)
865 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
866 else
867 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
868
869 if (sy > SourceRect->bottom) break;
870
871 saveY = DesY+zoomY;
872
873 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
874 {
875 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
876
877 if (sx > SourceRect->right) break;
878
879 color = XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy));
880
881 for (count=DesY;count<saveY;count++)
882 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
883 }
884 }
885 }
886 else
887 {
888 /* Draw one pixel on X - Led to the Des Zoom Out*/
889 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
890 {
891 if (DesIsBiggerY)
892 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
893 else
894 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
895
896 if (sy > SourceRect->bottom) break;
897
898 saveY = DesY+zoomY;
899
900 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
901 {
902 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
903
904 if (sx > SourceRect->right) break;
905
906 color = XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy));
907
908 for (count=DesY;count<saveY;count++)
909 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
910 }
911 }
912 }
913 }
914 break;
915
916 case BMF_8BPP:
917 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
918 /* This is a reference implementation, it hasn't been optimized for speed */
919 if (zoomX>1)
920 {
921 /* Draw one Hline on X - Led to the Des Zoom In*/
922 if (DesSizeX>SrcSizeX)
923 {
924 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
925 {
926 if (DesIsBiggerY)
927 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
928 else
929 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
930
931 if (sy > SourceRect->bottom) break;
932
933 saveY = DesY+zoomY;
934
935 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
936 {
937 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
938
939 if (sx > SourceRect->right) break;
940
941 color = XLATEOBJ_iXlate(ColorTranslation, DIB_8BPP_GetPixel(SourceSurf, sx, sy));
942
943 saveX = DesX + zoomX;
944 for (count=DesY;count<saveY;count++)
945 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
946 }
947 }
948 }
949 else
950 {
951 /* Draw one Hline on X - Led to the Des Zoom Out*/
952
953 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
954 {
955 if (DesIsBiggerY)
956 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
957 else
958 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
959
960 if (sy > SourceRect->bottom) break;
961
962 saveY = DesY+zoomY;
963
964 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
965 {
966 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
967
968 if (sx > SourceRect->right) break;
969
970 color = XLATEOBJ_iXlate(ColorTranslation, DIB_8BPP_GetPixel(SourceSurf, sx, sy));
971
972 saveX = DesX + zoomX;
973 for (count=DesY;count<saveY;count++)
974 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
975 }
976 }
977 }
978 }
979
980 else
981 {
982
983 if (DesSizeX>SrcSizeX)
984 {
985 /* Draw one pixel on X - Led to the Des Zoom In*/
986 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
987 {
988 if (DesIsBiggerY)
989 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
990 else
991 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
992
993 if (sy > SourceRect->bottom) break;
994
995 saveY = DesY+zoomY;
996
997 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
998 {
999 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
1000
1001 if (sx > SourceRect->right) break;
1002
1003 color = XLATEOBJ_iXlate(ColorTranslation, DIB_8BPP_GetPixel(SourceSurf, sx, sy));
1004
1005 for (count=DesY;count<saveY;count++)
1006 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1007 }
1008 }
1009 }
1010 else
1011 {
1012 /* Draw one pixel on X - Led to the Des Zoom Out*/
1013 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1014 {
1015 if (DesIsBiggerY)
1016 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1017 else
1018 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1019
1020 if (sy > SourceRect->bottom) break;
1021
1022 saveY = DesY+zoomY;
1023
1024 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1025 {
1026 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
1027
1028 if (sx > SourceRect->right) break;
1029
1030 color = XLATEOBJ_iXlate(ColorTranslation, DIB_8BPP_GetPixel(SourceSurf, sx, sy));
1031
1032 for (count=DesY;count<saveY;count++)
1033 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1034 }
1035 }
1036 }
1037 }
1038 break;
1039
1040 case BMF_16BPP:
1041 return ScaleRectAvg16(DestSurf, SourceSurf, DestRect, SourceRect, MaskOrigin, BrushOrigin,
1042 ClipRegion, ColorTranslation, Mode);
1043 break;
1044
1045 case BMF_24BPP:
1046 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
1047 /* This is a reference implementation, it hasn't been optimized for speed */
1048 if (zoomX>1)
1049 {
1050 /* Draw one Hline on X - Led to the Des Zoom In*/
1051 if (DesSizeX>SrcSizeX)
1052 {
1053 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1054 {
1055 if (DesIsBiggerY)
1056 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1057 else
1058 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1059
1060 if (sy > SourceRect->bottom) break;
1061
1062 saveY = DesY+zoomY;
1063
1064 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1065 {
1066 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
1067
1068 if (sx > SourceRect->right) break;
1069
1070 color = XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy));
1071
1072 saveX = DesX + zoomX;
1073 for (count=DesY;count<saveY;count++)
1074 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
1075 }
1076 }
1077 }
1078 else
1079 {
1080 /* Draw one Hline on X - Led to the Des Zoom Out*/
1081
1082 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1083 {
1084 if (DesIsBiggerY)
1085 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1086 else
1087 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1088
1089 if (sy > SourceRect->bottom) break;
1090
1091 saveY = DesY+zoomY;
1092
1093 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1094 {
1095 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
1096
1097 if (sx > SourceRect->right) break;
1098
1099 color = XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy));
1100
1101 saveX = DesX + zoomX;
1102 for (count=DesY;count<saveY;count++)
1103 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
1104 }
1105 }
1106 }
1107 }
1108
1109 else
1110 {
1111
1112 if (DesSizeX>SrcSizeX)
1113 {
1114 /* Draw one pixel on X - Led to the Des Zoom In*/
1115 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1116 {
1117 if (DesIsBiggerY)
1118 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1119 else
1120 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1121
1122 if (sy > SourceRect->bottom) break;
1123
1124 saveY = DesY+zoomY;
1125
1126 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1127 {
1128 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
1129
1130 if (sx > SourceRect->right) break;
1131
1132 color = XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy));
1133
1134 for (count=DesY;count<saveY;count++)
1135 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1136 }
1137 }
1138 }
1139 else
1140 {
1141 /* Draw one pixel on X - Led to the Des Zoom Out*/
1142 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1143 {
1144 if (DesIsBiggerY)
1145 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1146 else
1147 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1148
1149 if (sy > SourceRect->bottom) break;
1150
1151 saveY = DesY+zoomY;
1152
1153 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1154 {
1155 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
1156
1157 if (sx > SourceRect->right) break;
1158
1159 color = XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy));
1160
1161 for (count=DesY;count<saveY;count++)
1162 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1163 }
1164 }
1165 }
1166 }
1167 break;
1168
1169 case BMF_32BPP:
1170 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
1171 /* This is a reference implementation, it hasn't been optimized for speed */
1172 if (zoomX>1)
1173 {
1174 /* Draw one Hline on X - Led to the Des Zoom In*/
1175 if (DesSizeX>SrcSizeX)
1176 {
1177 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1178 {
1179 if (DesIsBiggerY)
1180 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1181 else
1182 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1183
1184 if (sy > SourceRect->bottom) break;
1185
1186 saveY = DesY+zoomY;
1187
1188 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1189 {
1190 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
1191
1192 if (sx > SourceRect->right) break;
1193
1194 color = XLATEOBJ_iXlate(ColorTranslation, DIB_32BPP_GetPixel(SourceSurf, sx, sy));
1195
1196 saveX = DesX + zoomX;
1197 for (count=DesY;count<saveY;count++)
1198 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
1199 }
1200 }
1201 }
1202 else
1203 {
1204 /* Draw one Hline on X - Led to the Des Zoom Out*/
1205
1206 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1207 {
1208 if (DesIsBiggerY)
1209 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1210 else
1211 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1212
1213 if (sy > SourceRect->bottom) break;
1214
1215 saveY = DesY+zoomY;
1216
1217 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1218 {
1219 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
1220
1221 if (sx > SourceRect->right) break;
1222
1223 color = XLATEOBJ_iXlate(ColorTranslation, DIB_32BPP_GetPixel(SourceSurf, sx, sy));
1224
1225 saveX = DesX + zoomX;
1226 for (count=DesY;count<saveY;count++)
1227 DIB_16BPP_HLine(DestSurf, DesX, saveX, count, color);
1228 }
1229 }
1230 }
1231 }
1232
1233 else
1234 {
1235
1236 if (DesSizeX>SrcSizeX)
1237 {
1238 /* Draw one pixel on X - Led to the Des Zoom In*/
1239 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1240 {
1241 if (DesIsBiggerY)
1242 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1243 else
1244 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1245
1246 if (sy > SourceRect->bottom) break;
1247
1248 saveY = DesY+zoomY;
1249
1250 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1251 {
1252 sx = (int) ((ULONG) SrcSizeX * (ULONG) DesX) / ((ULONG) DesSizeX);
1253
1254 if (sx > SourceRect->right) break;
1255
1256 color = XLATEOBJ_iXlate(ColorTranslation, DIB_32BPP_GetPixel(SourceSurf, sx, sy));
1257
1258 for (count=DesY;count<saveY;count++)
1259 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1260 }
1261 }
1262 }
1263 else
1264 {
1265 /* Draw one pixel on X - Led to the Des Zoom Out*/
1266 for (DesY=DestRect->bottom-zoomY; DesY>=DestRect->top; DesY-=zoomY)
1267 {
1268 if (DesIsBiggerY)
1269 sy = (int) ((ULONG) SrcSizeY * (ULONG) DesY) / ((ULONG) DesSizeY);
1270 else
1271 sy = (int) ((ULONG) DesSizeY * (ULONG) DesY) / ((ULONG) SrcSizeY);
1272
1273 if (sy > SourceRect->bottom) break;
1274
1275 saveY = DesY+zoomY;
1276
1277 for (DesX=DestRect->right-zoomX; DesX>=DestRect->left; DesX-=zoomX)
1278 {
1279 sx = (int) ((ULONG) DesSizeX * (ULONG) DesX) / ((ULONG) SrcSizeX);
1280
1281 if (sx > SourceRect->right) break;
1282
1283 color = XLATEOBJ_iXlate(ColorTranslation, DIB_32BPP_GetPixel(SourceSurf, sx, sy));
1284
1285 for (count=DesY;count<saveY;count++)
1286 DIB_16BPP_PutPixel(DestSurf, DesX, count, color);
1287 }
1288 }
1289 }
1290 }
1291 break;
1292
1293 break;
1294
1295 default:
1296 DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
1297 return FALSE;
1298 }
1299
1300
1301
1302 return TRUE;
1303 }
1304
1305 BOOLEAN
1306 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
1307 RECTL* DestRect, POINTL *SourcePoint,
1308 XLATEOBJ *ColorTranslation, ULONG iTransColor)
1309 {
1310 ULONG RoundedRight, X, Y, SourceX, SourceY, Source, wd, Dest;
1311 ULONG *DestBits;
1312
1313 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
1314 SourceY = SourcePoint->y;
1315 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
1316 (DestRect->left << 1) +
1317 DestRect->top * DestSurf->lDelta);
1318 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
1319
1320 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
1321 {
1322 SourceX = SourcePoint->x;
1323 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
1324 {
1325 Dest = *DestBits;
1326
1327 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
1328 if(Source != iTransColor)
1329 {
1330 Dest &= 0xFFFF0000;
1331 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
1332 }
1333
1334 Source = DIB_GetSourceIndex(SourceSurf, SourceX + 1, SourceY);
1335 if(Source != iTransColor)
1336 {
1337 Dest &= 0xFFFF;
1338 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
1339 }
1340
1341 *DestBits = Dest;
1342 }
1343
1344 if(X < DestRect->right)
1345 {
1346 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
1347 if(Source != iTransColor)
1348 {
1349 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, Source);
1350 }
1351
1352 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
1353 }
1354 SourceY++;
1355 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
1356 }
1357
1358 return TRUE;
1359 }
1360
1361 typedef union {
1362 ULONG ul;
1363 struct {
1364 UCHAR red;
1365 UCHAR green;
1366 UCHAR blue;
1367 UCHAR alpha;
1368 } col;
1369 } NICEPIXEL32;
1370
1371 typedef union {
1372 USHORT us;
1373 struct {
1374 USHORT red:5,
1375 green:6,
1376 blue:5;
1377 } col;
1378 } NICEPIXEL16;
1379
1380 STATIC inline UCHAR
1381 Clamp5(ULONG val)
1382 {
1383 return (val > 31) ? 31 : val;
1384 }
1385
1386 STATIC inline UCHAR
1387 Clamp6(ULONG val)
1388 {
1389 return (val > 63) ? 63 : val;
1390 }
1391
1392 BOOLEAN
1393 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
1394 RECTL* SourceRect, CLIPOBJ* ClipRegion,
1395 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
1396 {
1397 INT Rows, Cols, SrcX, SrcY;
1398 register PUSHORT Dst;
1399 ULONG DstDelta;
1400 BLENDFUNCTION BlendFunc;
1401 register NICEPIXEL16 DstPixel;
1402 register NICEPIXEL32 SrcPixel;
1403 UCHAR Alpha, SrcBpp;
1404
1405 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
1406 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
1407 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
1408
1409 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
1410 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
1411
1412 BlendFunc = BlendObj->BlendFunction;
1413 if (BlendFunc.BlendOp != AC_SRC_OVER)
1414 {
1415 DPRINT1("BlendOp != AC_SRC_OVER\n");
1416 return FALSE;
1417 }
1418 if (BlendFunc.BlendFlags != 0)
1419 {
1420 DPRINT1("BlendFlags != 0\n");
1421 return FALSE;
1422 }
1423 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
1424 {
1425 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
1426 return FALSE;
1427 }
1428 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
1429 BitsPerFormat(Source->iBitmapFormat) != 32)
1430 {
1431 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
1432 return FALSE;
1433 }
1434
1435 Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
1436 (DestRect->left << 1));
1437 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
1438 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
1439
1440 Rows = DestRect->bottom - DestRect->top;
1441 SrcY = SourceRect->top;
1442 while (--Rows >= 0)
1443 {
1444 Cols = DestRect->right - DestRect->left;
1445 SrcX = SourceRect->left;
1446 while (--Cols >= 0)
1447 {
1448 if (SrcBpp <= 16)
1449 {
1450 DstPixel.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
1451 SrcPixel.col.red = (DstPixel.col.red << 3) | (DstPixel.col.red >> 2);
1452 SrcPixel.col.green = (DstPixel.col.green << 2) | (DstPixel.col.green >> 4);
1453 SrcPixel.col.blue = (DstPixel.col.blue << 3) | (DstPixel.col.blue >> 2);
1454 }
1455 else
1456 {
1457 SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
1458 }
1459 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
1460 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
1461 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
1462 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
1463
1464 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
1465 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
1466
1467 DstPixel.us = *Dst;
1468 DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 + (SrcPixel.col.red >> 3));
1469 DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 + (SrcPixel.col.green >> 2));
1470 DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 + (SrcPixel.col.blue >> 3));
1471 *Dst++ = DstPixel.us;
1472 }
1473 Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
1474 SrcY++;
1475 }
1476
1477 return TRUE;
1478 }
1479
1480 /* EOF */