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