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: dib8bpp.c,v 1.19 2004/04/06 23:05:36 weiden Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
23 #include <win32k/bitmaps.h>
24 #include <win32k/brush.h>
25 #include <win32k/debug.h>
27 #include <include/object.h>
28 #include <ddk/winddi.h>
29 #include "../eng/objects.h"
33 DIB_8BPP_PutPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
, ULONG c
)
35 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
+ x
;
41 DIB_8BPP_GetPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
)
43 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
+ x
;
45 return (ULONG
)(*byteaddr
);
49 DIB_8BPP_HLine(PSURFOBJ SurfObj
, LONG x1
, LONG x2
, LONG y
, ULONG c
)
51 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
52 PBYTE addr
= byteaddr
+ x1
;
63 DIB_8BPP_VLine(PSURFOBJ SurfObj
, LONG x
, LONG y1
, LONG y2
, ULONG c
)
65 PBYTE byteaddr
= SurfObj
->pvScan0
+ y1
* SurfObj
->lDelta
;
66 PBYTE addr
= byteaddr
+ x
;
67 LONG lDelta
= SurfObj
->lDelta
;
78 DIB_8BPP_BitBltSrcCopy(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
79 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
80 PRECTL DestRect
, POINTL
*SourcePoint
,
81 XLATEOBJ
*ColorTranslation
)
83 LONG i
, j
, sx
, sy
, xColor
, f1
;
84 PBYTE SourceBits
, DestBits
, SourceLine
, DestLine
;
85 PBYTE SourceBits_4BPP
, SourceLine_4BPP
;
87 DestBits
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + DestRect
->left
;
89 switch(SourceGDI
->BitsPerPixel
)
95 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
98 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
100 if(DIB_1BPP_GetPixel(SourceSurf
, sx
, sy
) == 0)
102 DIB_8BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 0));
104 DIB_8BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 1));
113 SourceBits_4BPP
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + (SourcePoint
->x
>> 1);
115 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
117 SourceLine_4BPP
= SourceBits_4BPP
;
121 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
123 xColor
= XLATEOBJ_iXlate(ColorTranslation
,
124 (*SourceLine_4BPP
& altnotmask
[f1
]) >> (4 * (1 - f1
)));
125 DIB_8BPP_PutPixel(DestSurf
, i
, j
, xColor
);
126 if(f1
== 1) { SourceLine_4BPP
++; f1
= 0; } else { f1
= 1; }
130 SourceBits_4BPP
+= SourceSurf
->lDelta
;
135 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
137 if (DestRect
->top
< SourcePoint
->y
)
139 SourceBits
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
140 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
142 RtlMoveMemory(DestBits
, SourceBits
, DestRect
->right
- DestRect
->left
);
143 SourceBits
+= SourceSurf
->lDelta
;
144 DestBits
+= DestSurf
->lDelta
;
149 SourceBits
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + SourcePoint
->x
;
150 DestBits
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + DestRect
->left
;
151 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
153 RtlMoveMemory(DestBits
, SourceBits
, DestRect
->right
- DestRect
->left
);
154 SourceBits
-= SourceSurf
->lDelta
;
155 DestBits
-= DestSurf
->lDelta
;
161 if (DestRect
->top
< SourcePoint
->y
)
163 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
165 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
167 SourceBits
= SourceLine
;
169 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
171 *DestBits
++ = XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
++);
173 SourceLine
+= SourceSurf
->lDelta
;
174 DestLine
+= DestSurf
->lDelta
;
179 SourceLine
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + SourcePoint
->x
;
180 DestLine
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + DestRect
->left
;
181 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
183 SourceBits
= SourceLine
;
185 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
187 *DestBits
++ = XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
++);
189 SourceLine
-= SourceSurf
->lDelta
;
190 DestLine
-= DestSurf
->lDelta
;
197 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
200 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
202 SourceBits
= SourceLine
;
205 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
207 xColor
= *((PWORD
) SourceBits
);
208 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
213 SourceLine
+= SourceSurf
->lDelta
;
214 DestLine
+= DestSurf
->lDelta
;
219 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 3 * SourcePoint
->x
;
222 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
224 SourceBits
= SourceLine
;
227 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
229 xColor
= (*(SourceBits
+ 2) << 0x10) +
230 (*(SourceBits
+ 1) << 0x08) +
232 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
237 SourceLine
+= SourceSurf
->lDelta
;
238 DestLine
+= DestSurf
->lDelta
;
243 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 4 * SourcePoint
->x
;
246 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
248 SourceBits
= SourceLine
;
251 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
253 xColor
= *((PDWORD
) SourceBits
);
254 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
259 SourceLine
+= SourceSurf
->lDelta
;
260 DestLine
+= DestSurf
->lDelta
;
265 DbgPrint("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
273 DIB_8BPP_BitBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
274 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
275 PRECTL DestRect
, POINTL
*SourcePoint
,
276 PBRUSHOBJ Brush
, PPOINTL BrushOrigin
,
277 XLATEOBJ
*ColorTranslation
, ULONG Rop4
)
279 LONG i
, j
, k
, sx
, sy
;
280 ULONG Dest
, Source
, Pattern
;
285 /* Pattern brushes */
286 PGDIBRUSHOBJ GdiBrush
;
287 HBITMAP PatternSurface
= NULL
;
289 ULONG PatternWidth
, PatternHeight
;
293 return DIB_8BPP_BitBltSrcCopy(
303 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
304 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
312 if (Brush
->iSolidColor
== 0xFFFFFFFF)
314 PBITMAPOBJ PatternBitmap
;
316 GdiBrush
= CONTAINING_RECORD(
321 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
322 PatternSurface
= BitmapToSurf(PatternBitmap
, NULL
);
323 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
325 PatternObj
= (PSURFOBJ
)AccessUserObject((ULONG
)PatternSurface
);
326 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
327 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
331 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x3);
334 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
337 DestBits
= (PULONG
)(DestSurf
->pvScan0
+ DestRect
->left
+ j
* DestSurf
->lDelta
);
339 for (i
= DestRect
->left
; i
< RoundedRight
; i
+= 4, DestBits
++)
346 for (k
= 0; k
< 4; k
++)
347 Source
|= (DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
) + k
, sy
, ColorTranslation
) << (k
* 8));
352 if (Brush
->iSolidColor
== 0xFFFFFFFF)
354 Pattern
= DIB_1BPP_GetPixel(PatternObj
, i
% PatternWidth
, j
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
355 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 1) % PatternWidth
, j
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 8;
356 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 2) % PatternWidth
, j
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 16;
357 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 3) % PatternWidth
, j
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 24;
361 Pattern
= (Brush
->iSolidColor
& 0xFF) |
362 ((Brush
->iSolidColor
& 0xFF) << 8) |
363 ((Brush
->iSolidColor
& 0xFF) << 16) |
364 ((Brush
->iSolidColor
& 0xFF) << 24);
367 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
370 if (i
< DestRect
->right
)
373 for (; i
< DestRect
->right
; i
++)
377 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
), sy
, ColorTranslation
);
382 if (Brush
->iSolidColor
== 0xFFFFFFFF)
383 Pattern
= DIB_1BPP_GetPixel(PatternObj
, i
% PatternWidth
, j
% PatternHeight
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
385 Pattern
= Brush
->iSolidColor
& 0xFF;
388 DIB_8BPP_PutPixel(DestSurf
, i
, j
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
396 if (PatternSurface
!= NULL
)
397 EngDeleteSurface(PatternSurface
);
403 =======================================
404 Stretching functions goes below
405 Some parts of code are based on an
406 article "Bresenhame image scaling"
407 Dr. Dobb Journal, May 2002
408 =======================================
411 typedef unsigned char PIXEL
;
413 /* 16-bit HiColor (565 format) */
414 inline PIXEL
average8(PIXEL a
, PIXEL b
)
416 return a
; // FIXME: Depend on SetStretchMode
419 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
420 void ScaleLineAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
422 int NumPixels
= TgtWidth
;
423 int IntPart
= SrcWidth
/ TgtWidth
;
424 int FractPart
= SrcWidth
% TgtWidth
;
425 int Mid
= TgtWidth
>> 1;
430 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
433 while (NumPixels
-- > 0) {
436 p
= average8(p
, *(Source
+1));
449 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
450 void ScaleRectAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
451 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
453 int NumPixels
= TgtHeight
;
454 int IntPart
= ((SrcHeight
/ TgtHeight
) * srcPitch
); //(SrcHeight / TgtHeight) * SrcWidth;
455 int FractPart
= SrcHeight
% TgtHeight
;
456 int Mid
= TgtHeight
>> 1;
459 PIXEL
*ScanLine
, *ScanLineAhead
;
460 PIXEL
*PrevSource
= NULL
;
461 PIXEL
*PrevSourceAhead
= NULL
;
463 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
466 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
467 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
469 while (NumPixels
-- > 0) {
470 if (Source
!= PrevSource
) {
471 if (Source
== PrevSourceAhead
) {
472 /* the next scan line has already been scaled and stored in
473 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
476 PIXEL
*tmp
= ScanLine
;
477 ScanLine
= ScanLineAhead
;
480 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
485 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
487 ScaleLineAvg8(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
488 for (x
= 0; x
< TgtWidth
; x
++)
489 ScanLine
[x
] = average8(ScanLine
[x
], ScanLineAhead
[x
]);
490 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
493 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
494 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
497 if (E
>= TgtHeight
) {
499 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
503 if (skip
> 0 && Source
!= PrevSource
)
504 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
506 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
507 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
510 ExFreePool(ScanLine
);
511 ExFreePool(ScanLineAhead
);
514 BOOLEAN
DIB_8BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
515 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
516 RECTL
* DestRect
, RECTL
*SourceRect
,
517 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
518 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
520 BYTE
*SourceLine
, *DestLine
;
522 DbgPrint("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
523 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
524 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
526 switch(SourceGDI
->BitsPerPixel
)
537 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + SourceRect
->left
;
538 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + DestRect
->left
;
540 ScaleRectAvg8((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
541 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
542 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
558 DbgPrint("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
566 DIB_8BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
567 PSURFGDI DestGDI
, PSURFGDI SourceGDI
,
568 RECTL
* DestRect
, POINTL
*SourcePoint
,
569 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
571 ULONG RoundedRight
, X
, Y
, SourceX
, SourceY
, Source
, wd
, Dest
;
574 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x3);
575 SourceY
= SourcePoint
->y
;
576 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+ DestRect
->left
+
577 (DestRect
->top
* DestSurf
->lDelta
));
578 wd
= DestSurf
->lDelta
- (DestRect
->right
- DestRect
->left
);
580 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
582 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+ DestRect
->left
+
583 (Y
* DestSurf
->lDelta
));
584 SourceX
= SourcePoint
->x
;
585 for (X
= DestRect
->left
; X
< RoundedRight
; X
+= 4, DestBits
++)
589 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
590 if(Source
!= iTransColor
)
593 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFF);
596 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
597 if(Source
!= iTransColor
)
600 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 8) & 0xFF00);
603 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
604 if(Source
!= iTransColor
)
607 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16) & 0xFF0000);
610 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
611 if(Source
!= iTransColor
)
614 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 24) & 0xFF000000);
620 if(X
< DestRect
->right
)
622 for (; X
< DestRect
->right
; X
++)
624 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
625 if(Source
!= iTransColor
)
627 *((BYTE
*)DestBits
) = (BYTE
)(XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFF);
629 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 1);