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.27 2004/04/07 15:37:49 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
;
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)) && Brush
;
314 if (Brush
->iSolidColor
== 0xFFFFFFFF)
316 PBITMAPOBJ PatternBitmap
;
318 GdiBrush
= CONTAINING_RECORD(
323 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
324 PatternSurface
= BitmapToSurf(PatternBitmap
, NULL
);
325 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
327 PatternObj
= (PSURFOBJ
)AccessUserObject((ULONG
)PatternSurface
);
328 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
329 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
336 Pattern
= (Brush
->iSolidColor
& 0xFFFF) |
337 ((Brush
->iSolidColor
& 0xFFFF) << 16);
341 wd
= ((DestRect
->right
- DestRect
->left
) << 1) - DestSurf
->lDelta
;
342 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
343 SourceY
= SourcePoint
->y
;
346 (DestRect
->left
<< 1) +
347 DestRect
->top
* DestSurf
->lDelta
);
349 for (Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
351 SourceX
= SourcePoint
->x
;
354 PatternY
= Y
% PatternHeight
;
356 for (X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
362 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
, SourceY
, ColorTranslation
);
363 Source
|= DIB_GetSource(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
, ColorTranslation
) << 16;
368 Pattern
= (DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
);
369 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (X
+ 1) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 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 Pattern
= DIB_1BPP_GetPixel(PatternObj
, X
% PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
389 DIB_16BPP_PutPixel(DestSurf
, X
, Y
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
390 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
395 (ULONG_PTR
)DestBits
- wd
);
398 if (PatternSurface
!= NULL
)
399 EngDeleteSurface(PatternSurface
);
406 =======================================
407 Stretching functions goes below
408 Some parts of code are based on an
409 article "Bresenhame image scaling"
410 Dr. Dobb Journal, May 2002
411 =======================================
414 typedef unsigned short PIXEL
;
416 /* 16-bit HiColor (565 format) */
417 inline PIXEL
average16(PIXEL a
, PIXEL b
)
419 // This one doesn't work
424 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
425 return ((a & mask) + (b & mask)) >> 1;
428 // This one should be correct, but it's too long
430 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
433 r1 = (a & 0xF800) >> 11;
434 g1 = (a & 0x7E0) >> 5;
437 r2 = (b & 0xF800) >> 11;
438 g2 = (b & 0x7E0) >> 5;
445 res = (rr << 11) + (gr << 5) + br;
449 return a
; // FIXME: Depend on SetStretchMode
452 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
453 void ScaleLineAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
455 int NumPixels
= TgtWidth
;
456 int IntPart
= SrcWidth
/ TgtWidth
;
457 int FractPart
= SrcWidth
% TgtWidth
;
458 int Mid
= TgtWidth
>> 1;
463 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
466 while (NumPixels
-- > 0) {
469 p
= average16(p
, *(Source
+1));
482 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
483 void ScaleRectAvg16(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
484 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
486 int NumPixels
= TgtHeight
;
487 int IntPart
= ((SrcHeight
/ TgtHeight
) * srcPitch
) >> 1; //(SrcHeight / TgtHeight) * SrcWidth;
488 int FractPart
= SrcHeight
% TgtHeight
;
489 int Mid
= TgtHeight
>> 1;
492 PIXEL
*ScanLine
, *ScanLineAhead
;
493 PIXEL
*PrevSource
= NULL
;
494 PIXEL
*PrevSourceAhead
= NULL
;
496 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
499 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
500 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
502 while (NumPixels
-- > 0) {
503 if (Source
!= PrevSource
) {
504 if (Source
== PrevSourceAhead
) {
505 /* the next scan line has already been scaled and stored in
506 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
509 PIXEL
*tmp
= ScanLine
;
510 ScanLine
= ScanLineAhead
;
513 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
518 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
520 ScaleLineAvg16(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
521 for (x
= 0; x
< TgtWidth
; x
++)
522 ScanLine
[x
] = average16(ScanLine
[x
], ScanLineAhead
[x
]);
523 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
526 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
527 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
530 if (E
>= TgtHeight
) {
532 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
536 if (skip
> 0 && Source
!= PrevSource
)
537 ScaleLineAvg16(ScanLine
, Source
, SrcWidth
, TgtWidth
);
539 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
540 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
543 ExFreePool(ScanLine
);
544 ExFreePool(ScanLineAhead
);
547 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
548 BOOLEAN
DIB_16BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
549 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
550 RECTL
* DestRect
, RECTL
*SourceRect
,
551 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
552 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
554 BYTE
*SourceLine
, *DestLine
;
556 DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
557 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
558 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
560 switch(SourceGDI
->BitsPerPixel
)
575 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + 2 * SourceRect
->left
;
576 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + 2 * DestRect
->left
;
578 ScaleRectAvg16((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
579 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
580 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
592 DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
602 DIB_16BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
603 PSURFGDI DestGDI
, PSURFGDI SourceGDI
,
604 RECTL
* DestRect
, POINTL
*SourcePoint
,
605 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
607 ULONG RoundedRight
, X
, Y
, SourceX
, SourceY
, Source
, wd
, Dest
;
610 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x1);
611 SourceY
= SourcePoint
->y
;
612 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+
613 (DestRect
->left
<< 1) +
614 DestRect
->top
* DestSurf
->lDelta
);
615 wd
= DestSurf
->lDelta
- ((DestRect
->right
- DestRect
->left
) << 1);
617 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
619 SourceX
= SourcePoint
->x
;
620 for(X
= DestRect
->left
; X
< RoundedRight
; X
+= 2, DestBits
++, SourceX
+= 2)
624 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
625 if(Source
!= iTransColor
)
628 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFFFF);
631 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
+ 1, SourceY
);
632 if(Source
!= iTransColor
)
635 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
641 if(X
< DestRect
->right
)
643 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
, SourceY
);
644 if(Source
!= iTransColor
)
646 *((USHORT
*)DestBits
) = (USHORT
)(XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16);
649 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 2);
652 DestBits
= (ULONG
*)((ULONG_PTR
)DestBits
+ wd
);