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.25 2004/04/06 23:05:36 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;
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);
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
;
337 wd
= ((DestRect
->right
- DestRect
->left
) << 1) - DestSurf
->lDelta
;
338 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
339 SourceY
= SourcePoint
->y
;
342 (DestRect
->left
<< 1) +
343 DestRect
->top
* DestSurf
->lDelta
);
345 for (Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
347 SourceX
= SourcePoint
->x
;
348 for (X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
354 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
, SourceY
, ColorTranslation
);
355 Source
|= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
, ColorTranslation
) << 16;
360 if (Brush
->iSolidColor
== 0xFFFFFFFF)
362 Pattern
= (DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, Y
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
);
363 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (X
+ 1) % PatternWidth
, Y
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 16;
367 Pattern
= (Brush
->iSolidColor
& 0xFFFF) |
368 ((Brush
->iSolidColor
& 0xFFFF) << 16);
372 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
375 if (X
< DestRect
->right
)
377 Dest
= *((PUSHORT
)DestBits
);
381 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
, SourceY
, ColorTranslation
);
386 if (Brush
->iSolidColor
== 0xFFFFFFFF)
387 Pattern
= DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, Y
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
389 Pattern
= Brush
->iSolidColor
& 0xFFFF;
392 DIB_16BPP_PutPixel(DestSurf
, X
, Y
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
393 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
398 (ULONG_PTR
)DestBits
- wd
);
401 if (PatternSurface
!= NULL
)
402 EngDeleteSurface(PatternSurface
);
409 =======================================
410 Stretching functions goes below
411 Some parts of code are based on an
412 article "Bresenhame image scaling"
413 Dr. Dobb Journal, May 2002
414 =======================================
417 typedef unsigned short PIXEL
;
419 /* 16-bit HiColor (565 format) */
420 inline PIXEL
average16(PIXEL a
, PIXEL b
)
422 // This one doesn't work
427 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
428 return ((a & mask) + (b & mask)) >> 1;
431 // This one should be correct, but it's too long
433 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
436 r1 = (a & 0xF800) >> 11;
437 g1 = (a & 0x7E0) >> 5;
440 r2 = (b & 0xF800) >> 11;
441 g2 = (b & 0x7E0) >> 5;
448 res = (rr << 11) + (gr << 5) + br;
452 return a
; // FIXME: Depend on SetStretchMode
455 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
456 void ScaleLineAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
458 int NumPixels
= TgtWidth
;
459 int IntPart
= SrcWidth
/ TgtWidth
;
460 int FractPart
= SrcWidth
% TgtWidth
;
461 int Mid
= TgtWidth
>> 1;
466 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
469 while (NumPixels
-- > 0) {
472 p
= average16(p
, *(Source
+1));
485 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
486 void ScaleRectAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
487 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
489 int NumPixels
= TgtHeight
;
490 int IntPart
= ((SrcHeight
/ TgtHeight
) * srcPitch
) >> 1; //(SrcHeight / TgtHeight) * SrcWidth;
491 int FractPart
= SrcHeight
% TgtHeight
;
492 int Mid
= TgtHeight
>> 1;
495 PIXEL
*ScanLine
, *ScanLineAhead
;
496 PIXEL
*PrevSource
= NULL
;
497 PIXEL
*PrevSourceAhead
= NULL
;
499 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
502 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
503 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
505 while (NumPixels
-- > 0) {
506 if (Source
!= PrevSource
) {
507 if (Source
== PrevSourceAhead
) {
508 /* the next scan line has already been scaled and stored in
509 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
512 PIXEL
*tmp
= ScanLine
;
513 ScanLine
= ScanLineAhead
;
516 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
521 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
523 ScaleLineAvg16(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
524 for (x
= 0; x
< TgtWidth
; x
++)
525 ScanLine
[x
] = average16(ScanLine
[x
], ScanLineAhead
[x
]);
526 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
529 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
530 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
533 if (E
>= TgtHeight
) {
535 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
539 if (skip
> 0 && Source
!= PrevSource
)
540 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
542 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
543 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
546 ExFreePool(ScanLine
);
547 ExFreePool(ScanLineAhead
);
550 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
551 BOOLEAN
DIB_16BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
552 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
553 RECTL
* DestRect
, RECTL
*SourceRect
,
554 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
555 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
557 BYTE
*SourceLine
, *DestLine
;
559 DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
560 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
561 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
563 switch(SourceGDI
->BitsPerPixel
)
578 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + 2 * SourceRect
->left
;
579 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
581 ScaleRectAvg16((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
582 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
583 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
595 DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
605 DIB_16BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
606 PSURFGDI DestGDI
, PSURFGDI SourceGDI
,
607 RECTL
* DestRect
, POINTL
*SourcePoint
,
608 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
610 ULONG RoundedRight
, X
, Y
, SourceX
, SourceY
, Source
, wd
, Dest
;
613 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
614 SourceY
= SourcePoint
->y
;
615 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+
616 (DestRect
->left
<< 1) +
617 DestRect
->top
* DestSurf
->lDelta
);
618 wd
= DestSurf
->lDelta
- ((DestRect
->right
- DestRect
->left
) << 1);
620 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
622 SourceX
= SourcePoint
->x
;
623 for(X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
627 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
628 if(Source
!= iTransColor
)
631 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFFFF);
634 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
);
635 if(Source
!= iTransColor
)
638 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
644 if(X
< DestRect
->right
)
646 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
647 if(Source
!= iTransColor
)
649 *((USHORT
*)DestBits
) = (USHORT
)(XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
652 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
655 DestBits
= (ULONG
*)((ULONG_PTR
)DestBits
+ wd
);