2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
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.
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.
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.
19 /* $Id: dib16bpp.c,v 1.26 2004/04/07 10:19:34 weiden Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
25 #include <ddk/winddi.h>
26 #include <win32k/bitmaps.h>
27 #include <win32k/brush.h>
28 #include <win32k/debug.h>
29 #include <include/object.h>
30 #include "../eng/objects.h"
34 DIB_16BPP_PutPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
, ULONG c
)
36 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
37 PWORD addr
= (PWORD
)byteaddr
+ x
;
43 DIB_16BPP_GetPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
)
45 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
46 PWORD addr
= (PWORD
)byteaddr
+ x
;
48 return (ULONG
)(*addr
);
52 DIB_16BPP_HLine(PSURFOBJ SurfObj
, LONG x1
, LONG x2
, LONG y
, ULONG c
)
54 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
55 PWORD addr
= (PWORD
)byteaddr
+ x1
;
66 DIB_16BPP_VLine(PSURFOBJ SurfObj
, LONG x
, LONG y1
, LONG y2
, ULONG c
)
68 PBYTE byteaddr
= SurfObj
->pvScan0
+ y1
* SurfObj
->lDelta
;
69 PWORD addr
= (PWORD
)byteaddr
+ x
;
70 LONG lDelta
= SurfObj
->lDelta
;
72 byteaddr
= (PBYTE
)addr
;
77 addr
= (PWORD
)byteaddr
;
82 DIB_16BPP_BitBltSrcCopy(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
83 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
84 PRECTL DestRect
, POINTL
*SourcePoint
,
85 XLATEOBJ
*ColorTranslation
)
87 LONG i
, j
, sx
, sy
, xColor
, f1
;
88 PBYTE SourceBits
, DestBits
, SourceLine
, DestLine
;
89 PBYTE SourceBits_4BPP
, SourceLine_4BPP
;
90 DestBits
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
92 switch(SourceGDI
->BitsPerPixel
)
98 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
101 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
103 if(DIB_1BPP_GetPixel(SourceSurf
, sx
, sy
) == 0)
105 DIB_16BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 0));
107 DIB_16BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 1));
116 SourceBits_4BPP
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + (SourcePoint
->x
>> 1);
118 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
120 SourceLine_4BPP
= SourceBits_4BPP
;
124 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
126 xColor
= XLATEOBJ_iXlate(ColorTranslation
,
127 (*SourceLine_4BPP
& altnotmask
[f1
]) >> (4 * (1 - f1
)));
128 DIB_16BPP_PutPixel(DestSurf
, i
, j
, xColor
);
129 if(f1
== 1) { SourceLine_4BPP
++; f1
= 0; } else { f1
= 1; }
133 SourceBits_4BPP
+= SourceSurf
->lDelta
;
138 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
141 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
143 SourceBits
= SourceLine
;
146 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
148 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
);
153 SourceLine
+= SourceSurf
->lDelta
;
154 DestLine
+= DestSurf
->lDelta
;
159 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
161 if (DestRect
->top
< SourcePoint
->y
)
163 SourceBits
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
164 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
166 RtlMoveMemory(DestBits
, SourceBits
, 2 * (DestRect
->right
- DestRect
->left
));
167 SourceBits
+= SourceSurf
->lDelta
;
168 DestBits
+= DestSurf
->lDelta
;
173 SourceBits
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
174 DestBits
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + 2 * DestRect
->left
;
175 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
177 RtlMoveMemory(DestBits
, SourceBits
, 2 * (DestRect
->right
- DestRect
->left
));
178 SourceBits
-= SourceSurf
->lDelta
;
179 DestBits
-= DestSurf
->lDelta
;
185 if (DestRect
->top
< SourcePoint
->y
)
187 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
189 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
191 SourceBits
= SourceLine
;
193 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
195 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((WORD
*)SourceBits
));
199 SourceLine
+= SourceSurf
->lDelta
;
200 DestLine
+= DestSurf
->lDelta
;
205 SourceLine
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
206 DestLine
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + 2 * DestRect
->left
;
207 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
209 SourceBits
= SourceLine
;
211 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
213 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((WORD
*)SourceBits
));
217 SourceLine
-= SourceSurf
->lDelta
;
218 DestLine
-= DestSurf
->lDelta
;
225 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 3 * SourcePoint
->x
;
228 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
230 SourceBits
= SourceLine
;
233 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
235 xColor
= (*(SourceBits
+ 2) << 0x10) +
236 (*(SourceBits
+ 1) << 0x08) +
238 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, xColor
);
243 SourceLine
+= SourceSurf
->lDelta
;
244 DestLine
+= DestSurf
->lDelta
;
249 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 4 * SourcePoint
->x
;
252 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
254 SourceBits
= SourceLine
;
257 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
259 *((WORD
*)DestBits
) = (WORD
)XLATEOBJ_iXlate(ColorTranslation
, *((PDWORD
) SourceBits
));
264 SourceLine
+= SourceSurf
->lDelta
;
265 DestLine
+= DestSurf
->lDelta
;
270 DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
278 DIB_16BPP_BitBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
279 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
280 PRECTL DestRect
, POINTL
*SourcePoint
,
281 PBRUSHOBJ Brush
, PPOINTL BrushOrigin
,
282 XLATEOBJ
*ColorTranslation
, ULONG Rop4
)
285 ULONG SourceX
, SourceY
;
286 ULONG wd
, Dest
, Source
, Pattern
= 0, PatternY
;
289 BOOL UsesPattern
, CalcPattern
;
291 /* Pattern brushes */
292 PGDIBRUSHOBJ GdiBrush
;
293 HBITMAP PatternSurface
= NULL
;
295 ULONG PatternWidth
, PatternHeight
;
299 return DIB_16BPP_BitBltSrcCopy(
309 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
310 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
312 if ((CalcPattern
= UsesPattern
))
316 UsesPattern
= CalcPattern
= FALSE
;
318 if (Brush
->iSolidColor
== 0xFFFFFFFF)
320 PBITMAPOBJ PatternBitmap
;
322 GdiBrush
= CONTAINING_RECORD(
327 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
328 PatternSurface
= BitmapToSurf(PatternBitmap
, NULL
);
329 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
331 PatternObj
= (PSURFOBJ
)AccessUserObject((ULONG
)PatternSurface
);
332 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
333 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
339 Pattern
= (Brush
->iSolidColor
& 0xFFFF) |
340 ((Brush
->iSolidColor
& 0xFFFF) << 16);
344 wd
= ((DestRect
->right
- DestRect
->left
) << 1) - DestSurf
->lDelta
;
345 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
346 SourceY
= SourcePoint
->y
;
349 (DestRect
->left
<< 1) +
350 DestRect
->top
* DestSurf
->lDelta
);
352 for (Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
354 SourceX
= SourcePoint
->x
;
357 PatternY
= Y
% PatternHeight
;
359 for (X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
365 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
, SourceY
, ColorTranslation
);
366 Source
|= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
, ColorTranslation
) << 16;
369 if (UsesPattern
&& (Brush
->iSolidColor
== 0xFFFFFFFF))
371 Pattern
= (DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
);
372 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (X
+ 1) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 16;
375 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
378 if (X
< DestRect
->right
)
380 Dest
= *((PUSHORT
)DestBits
);
384 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
, SourceY
, ColorTranslation
);
389 if (Brush
->iSolidColor
== 0xFFFFFFFF)
390 Pattern
= DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
392 Pattern
= Brush
->iSolidColor
& 0xFFFF;
395 DIB_16BPP_PutPixel(DestSurf
, X
, Y
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
396 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
401 (ULONG_PTR
)DestBits
- wd
);
404 if (PatternSurface
!= NULL
)
405 EngDeleteSurface(PatternSurface
);
412 =======================================
413 Stretching functions goes below
414 Some parts of code are based on an
415 article "Bresenhame image scaling"
416 Dr. Dobb Journal, May 2002
417 =======================================
420 typedef unsigned short PIXEL
;
422 /* 16-bit HiColor (565 format) */
423 inline PIXEL
average16(PIXEL a
, PIXEL b
)
425 // This one doesn't work
430 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
431 return ((a & mask) + (b & mask)) >> 1;
434 // This one should be correct, but it's too long
436 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
439 r1 = (a & 0xF800) >> 11;
440 g1 = (a & 0x7E0) >> 5;
443 r2 = (b & 0xF800) >> 11;
444 g2 = (b & 0x7E0) >> 5;
451 res = (rr << 11) + (gr << 5) + br;
455 return a
; // FIXME: Depend on SetStretchMode
458 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
459 void ScaleLineAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
461 int NumPixels
= TgtWidth
;
462 int IntPart
= SrcWidth
/ TgtWidth
;
463 int FractPart
= SrcWidth
% TgtWidth
;
464 int Mid
= TgtWidth
>> 1;
469 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
472 while (NumPixels
-- > 0) {
475 p
= average16(p
, *(Source
+1));
488 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
489 void ScaleRectAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
490 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
492 int NumPixels
= TgtHeight
;
493 int IntPart
= ((SrcHeight
/ TgtHeight
) * srcPitch
) >> 1; //(SrcHeight / TgtHeight) * SrcWidth;
494 int FractPart
= SrcHeight
% TgtHeight
;
495 int Mid
= TgtHeight
>> 1;
498 PIXEL
*ScanLine
, *ScanLineAhead
;
499 PIXEL
*PrevSource
= NULL
;
500 PIXEL
*PrevSourceAhead
= NULL
;
502 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
505 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
506 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
508 while (NumPixels
-- > 0) {
509 if (Source
!= PrevSource
) {
510 if (Source
== PrevSourceAhead
) {
511 /* the next scan line has already been scaled and stored in
512 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
515 PIXEL
*tmp
= ScanLine
;
516 ScanLine
= ScanLineAhead
;
519 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
524 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
526 ScaleLineAvg16(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
527 for (x
= 0; x
< TgtWidth
; x
++)
528 ScanLine
[x
] = average16(ScanLine
[x
], ScanLineAhead
[x
]);
529 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
532 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
533 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
536 if (E
>= TgtHeight
) {
538 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
542 if (skip
> 0 && Source
!= PrevSource
)
543 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
545 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
546 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
549 ExFreePool(ScanLine
);
550 ExFreePool(ScanLineAhead
);
553 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
554 BOOLEAN
DIB_16BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
555 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
556 RECTL
* DestRect
, RECTL
*SourceRect
,
557 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
558 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
560 BYTE
*SourceLine
, *DestLine
;
562 DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
563 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
564 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
566 switch(SourceGDI
->BitsPerPixel
)
581 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + 2 * SourceRect
->left
;
582 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
584 ScaleRectAvg16((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
585 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
586 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
598 DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
608 DIB_16BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
609 PSURFGDI DestGDI
, PSURFGDI SourceGDI
,
610 RECTL
* DestRect
, POINTL
*SourcePoint
,
611 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
613 ULONG RoundedRight
, X
, Y
, SourceX
, SourceY
, Source
, wd
, Dest
;
616 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
617 SourceY
= SourcePoint
->y
;
618 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+
619 (DestRect
->left
<< 1) +
620 DestRect
->top
* DestSurf
->lDelta
);
621 wd
= DestSurf
->lDelta
- ((DestRect
->right
- DestRect
->left
) << 1);
623 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
625 SourceX
= SourcePoint
->x
;
626 for(X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
630 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
631 if(Source
!= iTransColor
)
634 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFFFF);
637 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
);
638 if(Source
!= iTransColor
)
641 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
647 if(X
< DestRect
->right
)
649 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
650 if(Source
!= iTransColor
)
652 *((USHORT
*)DestBits
) = (USHORT
)(XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
655 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
658 DestBits
= (ULONG
*)((ULONG_PTR
)DestBits
+ wd
);