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.10 2003/12/18 18:30:48 fireball Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
23 #include <win32k/bitmaps.h>
24 #include <win32k/debug.h>
26 #include <ddk/winddi.h>
27 #include "../eng/objects.h"
31 DIB_8BPP_PutPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
, ULONG c
)
33 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
+ x
;
39 DIB_8BPP_GetPixel(PSURFOBJ SurfObj
, LONG x
, LONG y
)
41 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
+ x
;
43 return (ULONG
)(*byteaddr
);
47 DIB_8BPP_HLine(PSURFOBJ SurfObj
, LONG x1
, LONG x2
, LONG y
, ULONG c
)
49 PBYTE byteaddr
= SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
;
50 PBYTE addr
= byteaddr
+ x1
;
61 DIB_8BPP_VLine(PSURFOBJ SurfObj
, LONG x
, LONG y1
, LONG y2
, ULONG c
)
63 PBYTE byteaddr
= SurfObj
->pvScan0
+ y1
* SurfObj
->lDelta
;
64 PBYTE addr
= byteaddr
+ x
;
65 LONG lDelta
= SurfObj
->lDelta
;
76 DIB_8BPP_BitBltSrcCopy(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
77 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
78 PRECTL DestRect
, POINTL
*SourcePoint
,
79 XLATEOBJ
*ColorTranslation
)
81 LONG i
, j
, sx
, sy
, xColor
, f1
;
82 PBYTE SourceBits
, DestBits
, SourceLine
, DestLine
;
83 PBYTE SourceBits_4BPP
, SourceLine_4BPP
;
85 DestBits
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + DestRect
->left
;
87 switch(SourceGDI
->BitsPerPixel
)
93 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
96 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
98 if(DIB_1BPP_GetPixel(SourceSurf
, sx
, sy
) == 0)
100 DIB_8BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 0));
102 DIB_8BPP_PutPixel(DestSurf
, i
, j
, XLATEOBJ_iXlate(ColorTranslation
, 1));
111 SourceBits_4BPP
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + (SourcePoint
->x
>> 1);
113 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
115 SourceLine_4BPP
= SourceBits_4BPP
;
119 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
121 xColor
= XLATEOBJ_iXlate(ColorTranslation
,
122 (*SourceLine_4BPP
& altnotmask
[sx
&1]) >> (4 * (1-(sx
& 1))));
123 DIB_8BPP_PutPixel(DestSurf
, i
, j
, xColor
);
124 if(f1
== 1) { SourceLine_4BPP
++; f1
= 0; } else { f1
= 1; }
128 SourceBits_4BPP
+= SourceSurf
->lDelta
;
133 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
135 if (DestRect
->top
< SourcePoint
->y
)
137 SourceBits
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
138 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
140 RtlMoveMemory(DestBits
, SourceBits
, DestRect
->right
- DestRect
->left
);
141 SourceBits
+= SourceSurf
->lDelta
;
142 DestBits
+= DestSurf
->lDelta
;
147 SourceBits
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + SourcePoint
->x
;
148 DestBits
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + DestRect
->left
;
149 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
151 RtlMoveMemory(DestBits
, SourceBits
, DestRect
->right
- DestRect
->left
);
152 SourceBits
-= SourceSurf
->lDelta
;
153 DestBits
-= DestSurf
->lDelta
;
159 if (DestRect
->top
< SourcePoint
->y
)
161 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + SourcePoint
->x
;
163 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
165 SourceBits
= SourceLine
;
167 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
169 *DestBits
++ = XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
++);
171 SourceLine
+= SourceSurf
->lDelta
;
172 DestLine
+= DestSurf
->lDelta
;
177 SourceLine
= SourceSurf
->pvScan0
+ ((SourcePoint
->y
+ DestRect
->bottom
- DestRect
->top
- 1) * SourceSurf
->lDelta
) + SourcePoint
->x
;
178 DestLine
= DestSurf
->pvScan0
+ ((DestRect
->bottom
- 1) * DestSurf
->lDelta
) + DestRect
->left
;
179 for (j
= DestRect
->bottom
- 1; DestRect
->top
<= j
; j
--)
181 SourceBits
= SourceLine
;
183 for (i
=DestRect
->left
; i
<DestRect
->right
; i
++)
185 *DestBits
++ = XLATEOBJ_iXlate(ColorTranslation
, *SourceBits
++);
187 SourceLine
-= SourceSurf
->lDelta
;
188 DestLine
-= DestSurf
->lDelta
;
195 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 2 * SourcePoint
->x
;
198 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
200 SourceBits
= SourceLine
;
203 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
205 xColor
= *((PWORD
) SourceBits
);
206 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
211 SourceLine
+= SourceSurf
->lDelta
;
212 DestLine
+= DestSurf
->lDelta
;
217 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 3 * SourcePoint
->x
;
220 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
222 SourceBits
= SourceLine
;
225 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
227 xColor
= (*(SourceBits
+ 2) << 0x10) +
228 (*(SourceBits
+ 1) << 0x08) +
230 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
235 SourceLine
+= SourceSurf
->lDelta
;
236 DestLine
+= DestSurf
->lDelta
;
241 SourceLine
= SourceSurf
->pvScan0
+ (SourcePoint
->y
* SourceSurf
->lDelta
) + 4 * SourcePoint
->x
;
244 for (j
= DestRect
->top
; j
< DestRect
->bottom
; j
++)
246 SourceBits
= SourceLine
;
249 for (i
= DestRect
->left
; i
< DestRect
->right
; i
++)
251 xColor
= *((PDWORD
) SourceBits
);
252 *DestBits
= XLATEOBJ_iXlate(ColorTranslation
, xColor
);
257 SourceLine
+= SourceSurf
->lDelta
;
258 DestLine
+= DestSurf
->lDelta
;
263 DbgPrint("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);
271 DIB_8BPP_BitBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
272 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
273 PRECTL DestRect
, POINTL
*SourcePoint
,
274 PBRUSHOBJ Brush
, PPOINTL BrushOrigin
,
275 XLATEOBJ
*ColorTranslation
, ULONG Rop4
)
277 LONG i
, j
, k
, sx
, sy
;
278 ULONG Dest
, Source
, Pattern
;
280 BOOL UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
281 BOOL UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
282 LONG RoundedRight
= DestRect
->right
- ((DestRect
->right
- DestRect
->left
) & 0x3);
286 return(DIB_8BPP_BitBltSrcCopy(DestSurf
, SourceSurf
, DestGDI
, SourceGDI
, DestRect
, SourcePoint
, ColorTranslation
));
292 for (j
=DestRect
->top
; j
<DestRect
->bottom
; j
++)
295 DestBits
= (PULONG
)(DestSurf
->pvScan0
+ DestRect
->left
+ j
* DestSurf
->lDelta
);
296 for (i
=DestRect
->left
; i
<RoundedRight
; i
+=4, DestBits
++)
302 for (k
= 0; k
< 4; k
++)
304 Source
|= (DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
) + k
, sy
, ColorTranslation
) << (k
* 8));
309 /* FIXME: No support for pattern brushes. */
310 Pattern
= (Brush
->iSolidColor
& 0xFF) |
311 ((Brush
->iSolidColor
& 0xFF) << 8) |
312 ((Brush
->iSolidColor
& 0xFF) << 16) |
313 ((Brush
->iSolidColor
& 0xFF) << 24);
315 *DestBits
= DIB_DoRop(Rop4
, Dest
, Source
, Pattern
);
317 if (i
< DestRect
->right
)
320 for (; i
< DestRect
->right
; i
++)
324 Source
= DIB_GetSource(SourceSurf
, SourceGDI
, sx
+ (i
- DestRect
->left
), sy
, ColorTranslation
);
328 /* FIXME: No support for pattern brushes. */
329 Pattern
= (Brush
->iSolidColor
& 0xFF) |
330 ((Brush
->iSolidColor
& 0xFF) << 8) |
331 ((Brush
->iSolidColor
& 0xFF) << 16) |
332 ((Brush
->iSolidColor
& 0xFF) << 24);
334 DIB_8BPP_PutPixel(DestSurf
, i
, j
, DIB_DoRop(Rop4
, Dest
, Source
, Pattern
) & 0xFFFF);
345 =======================================
346 Stretching functions goes below
347 Some parts of code are based on an
348 article "Bresenhame image scaling"
349 Dr. Dobb Journal, May 2002
350 =======================================
353 typedef unsigned char PIXEL
;
355 /* 16-bit HiColor (565 format) */
356 inline PIXEL
average8(PIXEL a
, PIXEL b
)
358 return a
; // FIXME: Depend on SetStretchMode
361 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
362 void ScaleLineAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int TgtWidth
)
364 int NumPixels
= TgtWidth
;
365 int IntPart
= SrcWidth
/ TgtWidth
;
366 int FractPart
= SrcWidth
% TgtWidth
;
367 int Mid
= TgtWidth
/ 2;
372 skip
= (TgtWidth
< SrcWidth
) ? 0 : (TgtWidth
/ (2*SrcWidth
) + 1);
375 while (NumPixels
-- > 0) {
378 p
= average8(p
, *(Source
+1));
391 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
392 void ScaleRectAvg8(PIXEL
*Target
, PIXEL
*Source
, int SrcWidth
, int SrcHeight
,
393 int TgtWidth
, int TgtHeight
, int srcPitch
, int dstPitch
)
395 int NumPixels
= TgtHeight
;
396 int IntPart
= (SrcHeight
/ TgtHeight
) * (SrcWidth
+1);
397 int FractPart
= SrcHeight
% TgtHeight
;
398 int Mid
= TgtHeight
/ 2;
401 PIXEL
*ScanLine
, *ScanLineAhead
;
402 PIXEL
*PrevSource
= NULL
;
403 PIXEL
*PrevSourceAhead
= NULL
;
405 skip
= (TgtHeight
< SrcHeight
) ? 0 : (TgtHeight
/ (2*SrcHeight
) + 1);
408 ScanLine
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
)); // FIXME: Should we use PagedPool here?
409 ScanLineAhead
= (PIXEL
*)ExAllocatePool(NonPagedPool
, TgtWidth
*sizeof(PIXEL
));
411 while (NumPixels
-- > 0) {
412 if (Source
!= PrevSource
) {
413 if (Source
== PrevSourceAhead
) {
414 /* the next scan line has already been scaled and stored in
415 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
418 PIXEL
*tmp
= ScanLine
;
419 ScanLine
= ScanLineAhead
;
422 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
427 if (E
>= Mid
&& PrevSourceAhead
!= (PIXEL
*)((BYTE
*)Source
+ srcPitch
)) {
429 ScaleLineAvg8(ScanLineAhead
, (PIXEL
*)((BYTE
*)Source
+ srcPitch
), SrcWidth
, TgtWidth
);
430 for (x
= 0; x
< TgtWidth
; x
++)
431 ScanLine
[x
] = average8(ScanLine
[x
], ScanLineAhead
[x
]);
432 PrevSourceAhead
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
435 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
436 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
439 if (E
>= TgtHeight
) {
441 Source
= (PIXEL
*)((BYTE
*)Source
+ srcPitch
);
445 if (skip
> 0 && Source
!= PrevSource
)
446 ScaleLineAvg8(ScanLine
, Source
, SrcWidth
, TgtWidth
);
448 memcpy(Target
, ScanLine
, TgtWidth
*sizeof(PIXEL
));
449 Target
= (PIXEL
*)((BYTE
*)Target
+ dstPitch
);
452 ExFreePool(ScanLine
);
453 ExFreePool(ScanLineAhead
);
456 BOOLEAN
DIB_8BPP_StretchBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
457 SURFGDI
*DestGDI
, SURFGDI
*SourceGDI
,
458 RECTL
* DestRect
, RECTL
*SourceRect
,
459 POINTL
* MaskOrigin
, POINTL
* BrushOrigin
,
460 XLATEOBJ
*ColorTranslation
, ULONG Mode
)
462 BYTE
*SourceLine
, *DestLine
;
464 DbgPrint("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
465 SourceGDI
->BitsPerPixel
, SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
466 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
468 switch(SourceGDI
->BitsPerPixel
)
479 SourceLine
= SourceSurf
->pvScan0
+ (SourceRect
->top
* SourceSurf
->lDelta
) + SourceRect
->left
;
480 DestLine
= DestSurf
->pvScan0
+ (DestRect
->top
* DestSurf
->lDelta
) + DestRect
->left
;
482 ScaleRectAvg8((PIXEL
*)DestLine
, (PIXEL
*)SourceLine
,
483 SourceRect
->right
-SourceRect
->left
, SourceRect
->bottom
-SourceRect
->top
,
484 DestRect
->right
-DestRect
->left
, DestRect
->bottom
-DestRect
->top
, SourceSurf
->lDelta
, DestSurf
->lDelta
);
500 DbgPrint("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI
->BitsPerPixel
);