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.21 2004/04/07 15:37:50 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
= 0, PatternY
;
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)) && Brush
;
308 if (Brush
->iSolidColor
== 0xFFFFFFFF)
310 PBITMAPOBJ PatternBitmap
;
312 GdiBrush
= CONTAINING_RECORD(
317 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
318 PatternSurface
= BitmapToSurf(PatternBitmap
, NULL
);
319 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
321 PatternObj
= (PSURFOBJ
)AccessUserObject((ULONG
)PatternSurface
);
322 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
323 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
330 Pattern
= (Brush
->iSolidColor
& 0xFF) |
331 ((Brush
->iSolidColor
& 0xFF) << 8) |
332 ((Brush
->iSolidColor
& 0xFF) << 16) |
333 ((Brush
->iSolidColor
& 0xFF) << 24);
337 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x3);
340 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
343 DestBits
= (PULONG
)(DestSurf
->pvScan0
+ DestRect
->left
+ j
* DestSurf
->lDelta
);
346 PatternY
= j
% PatternHeight
;
348 for (i
= DestRect
->left
; i
< RoundedRight
; i
+= 4, DestBits
++)
355 for (k
= 0; k
< 4; k
++)
356 Source
|= (DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
) + k
, sy
, ColorTranslation
) << (k
* 8));
361 Pattern
= DIB_1BPP_GetPixel(PatternObj
, i
% PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
362 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 1) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 8;
363 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 2) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 16;
364 Pattern
|= (DIB_1BPP_GetPixel(PatternObj
, (i
+ 3) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
) << 24;
366 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
369 if (i
< DestRect
->right
)
372 for (; i
< DestRect
->right
; i
++)
376 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
), sy
, ColorTranslation
);
381 Pattern
= DIB_1BPP_GetPixel(PatternObj
, i
% PatternWidth
,PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
;
384 DIB_8BPP_PutPixel(DestSurf
, i
, j
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
392 if (PatternSurface
!= NULL
)
393 EngDeleteSurface(PatternSurface
);
399 =======================================
400 Stretching functions goes below
401 Some parts of code are based on an
402 article "Bresenhame image scaling"
403 Dr. Dobb Journal, May 2002
404 =======================================
407 typedef unsigned char PIXEL
;
409 /* 16-bit HiColor (565 format) */
410 inline PIXEL
average8(PIXEL a
, PIXEL b
)
412 return a
; // FIXME: Depend on SetStretchMode
415 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
416 void ScaleLineAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
418 int NumPixels
= TgtWidth
;
419 int IntPart
= SrcWidth
/ TgtWidth
;
420 int FractPart
= SrcWidth
% TgtWidth
;
421 int Mid
= TgtWidth
>> 1;
426 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
429 while (NumPixels
-- > 0) {
432 p
= average8(p
, *(Source
+1));
445 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
446 void ScaleRectAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
447 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
449 int NumPixels
= TgtHeight
;
450 int IntPart
= ((SrcHeight
/ TgtHeight
) * srcPitch
); //(SrcHeight / TgtHeight) * SrcWidth;
451 int FractPart
= SrcHeight
% TgtHeight
;
452 int Mid
= TgtHeight
>> 1;
455 PIXEL
*ScanLine
, *ScanLineAhead
;
456 PIXEL
*PrevSource
= NULL
;
457 PIXEL
*PrevSourceAhead
= NULL
;
459 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
462 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
463 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
465 while (NumPixels
-- > 0) {
466 if (Source
!= PrevSource
) {
467 if (Source
== PrevSourceAhead
) {
468 /* the next scan line has already been scaled and stored in
469 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
472 PIXEL
*tmp
= ScanLine
;
473 ScanLine
= ScanLineAhead
;
476 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
481 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
483 ScaleLineAvg8(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
484 for (x
= 0; x
< TgtWidth
; x
++)
485 ScanLine
[x
] = average8(ScanLine
[x
], ScanLineAhead
[x
]);
486 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
489 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
490 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
493 if (E
>= TgtHeight
) {
495 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
499 if (skip
> 0 && Source
!= PrevSource
)
500 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
502 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
503 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
506 ExFreePool(ScanLine
);
507 ExFreePool(ScanLineAhead
);
510 BOOLEAN
DIB_8BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
511 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
512 RECTL
* DestRect
, RECTL
*SourceRect
,
513 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
514 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
516 BYTE
*SourceLine
, *DestLine
;
518 DbgPrint("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
519 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
520 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
522 switch(SourceGDI
->BitsPerPixel
)
533 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + SourceRect
->left
;
534 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + DestRect
->left
;
536 ScaleRectAvg8((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
537 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
538 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
554 DbgPrint("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
562 DIB_8BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
563 PSURFGDI DestGDI
, PSURFGDI SourceGDI
,
564 RECTL
* DestRect
, POINTL
*SourcePoint
,
565 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
567 ULONG RoundedRight
, X
, Y
, SourceX
, SourceY
, Source
, wd
, Dest
;
570 RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x3);
571 SourceY
= SourcePoint
->y
;
572 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+ DestRect
->left
+
573 (DestRect
->top
* DestSurf
->lDelta
));
574 wd
= DestSurf
->lDelta
- (DestRect
->right
- DestRect
->left
);
576 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
578 DestBits
= (ULONG
*)(DestSurf
->pvScan0
+ DestRect
->left
+
579 (Y
* DestSurf
->lDelta
));
580 SourceX
= SourcePoint
->x
;
581 for (X
= DestRect
->left
; X
< RoundedRight
; X
+= 4, DestBits
++)
585 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
586 if(Source
!= iTransColor
)
589 Dest
|= (XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFF);
592 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
593 if(Source
!= iTransColor
)
596 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 8) & 0xFF00);
599 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
600 if(Source
!= iTransColor
)
603 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 16) & 0xFF0000);
606 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
607 if(Source
!= iTransColor
)
610 Dest
|= ((XLATEOBJ_iXlate(ColorTranslation
, Source
) << 24) & 0xFF000000);
616 if(X
< DestRect
->right
)
618 for (; X
< DestRect
->right
; X
++)
620 Source
= DIB_GetSourceIndex(SourceSurf
, SourceGDI
, SourceX
++, SourceY
);
621 if(Source
!= iTransColor
)
623 *((BYTE
*)DestBits
) = (BYTE
)(XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFF);
625 DestBits
= (PULONG
)((ULONG_PTR
)DestBits
+ 1);