Implement complex clipping for StretchBlt

svn path=/trunk/; revision=9388
This commit is contained in:
Gé van Geldorp 2004-05-14 22:56:18 +00:00
parent 0c9315b3dc
commit 4b8fc8e4e4
12 changed files with 516 additions and 284 deletions

View file

@ -21,7 +21,8 @@ BOOLEAN DIB_1BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,
@ -40,7 +41,8 @@ BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_4BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_4BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,
@ -59,7 +61,8 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_8BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_8BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,
@ -78,7 +81,8 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,
@ -97,7 +101,8 @@ BOOLEAN DIB_24BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,
@ -116,7 +121,8 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode); CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode);
BOOLEAN DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
PSURFGDI DestGDI, PSURFGDI SourceGDI, PSURFGDI DestGDI, PSURFGDI SourceGDI,
RECTL* DestRect, POINTL *SourcePoint, RECTL* DestRect, POINTL *SourcePoint,

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib16bpp.c,v 1.31 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib16bpp.c,v 1.32 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -256,7 +256,7 @@ DIB_16BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
default: default:
DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }
@ -468,26 +468,84 @@ void ScaleLineAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
*Target++ = *Source; *Target++ = *Source;
} }
//NOTE: If you change something here, please do the same in other dibXXbpp.c files! static BOOLEAN
void ScaleRectAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, FinalCopy16(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex,
int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) UINT DestY, RECTL *DestRect)
{ {
int NumPixels = TgtHeight; LONG Left, Right;
int IntPart = ((SrcHeight / TgtHeight) * srcPitch) >> 1; //(SrcHeight / TgtHeight) * SrcWidth;
int FractPart = SrcHeight % TgtHeight; while (ClipSpans[*SpanIndex].Y < DestY
int Mid = TgtHeight >> 1; || (ClipSpans[*SpanIndex].Y == DestY
&& ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left))
{
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
while (ClipSpans[*SpanIndex].Y == DestY)
{
if (ClipSpans[*SpanIndex].X < DestRect->right)
{
Left = max(ClipSpans[*SpanIndex].X, DestRect->left);
Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right);
memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left,
(Right - Left) * sizeof(PIXEL));
}
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
return TRUE;
}
//NOTE: If you change something here, please do the same in other dibXXbpp.c files!
BOOLEAN ScaleRectAvg16(SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin,
CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{
int NumPixels = DestRect->bottom - DestRect->top;
int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta) >> 1; /* ((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left); */
int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top);
int Mid = (DestRect->bottom - DestRect->top) >> 1;
int E = 0; int E = 0;
int skip; int skip;
PIXEL *ScanLine, *ScanLineAhead; PIXEL *ScanLine, *ScanLineAhead;
PIXEL *PrevSource = NULL; PIXEL *PrevSource = NULL;
PIXEL *PrevSourceAhead = NULL; PIXEL *PrevSourceAhead = NULL;
PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + 2 * DestRect->left);
PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + 2 * SourceRect->left);
PSPAN ClipSpans;
UINT ClipSpansCount;
UINT SpanIndex;
LONG DestY;
skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
{
return FALSE;
}
if (0 == ClipSpansCount)
{
/* No clip spans == empty clipping region, everything clipped away */
ASSERT(NULL == ClipSpans);
return TRUE;
}
skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1);
NumPixels -= skip; NumPixels -= skip;
ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
DestY = DestRect->top;
SpanIndex = 0;
while (NumPixels-- > 0) { while (NumPixels-- > 0) {
if (Source != PrevSource) { if (Source != PrevSource) {
if (Source == PrevSourceAhead) { if (Source == PrevSourceAhead) {
@ -499,38 +557,57 @@ void ScaleRectAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight,
ScanLine = ScanLineAhead; ScanLine = ScanLineAhead;
ScanLineAhead = tmp; ScanLineAhead = tmp;
} else { } else {
ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
} /* if */ } /* if */
PrevSource = Source; PrevSource = Source;
} /* if */ } /* if */
if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) {
int x; int x;
ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
for (x = 0; x < TgtWidth; x++) for (x = 0; x < DestRect->right - DestRect->left; x++)
ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]); ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]);
PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
Source += IntPart; Source += IntPart;
E += FractPart; E += FractPart;
if (E >= TgtHeight) { if (E >= DestRect->bottom - DestRect->top) {
E -= TgtHeight; E -= DestRect->bottom - DestRect->top;
Source = (PIXEL *)((BYTE *)Source + srcPitch); Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
} /* while */ } /* while */
if (skip > 0 && Source != PrevSource) if (skip > 0 && Source != PrevSource)
ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
while (skip-- > 0) { while (skip-- > 0) {
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
} /* while */ } /* while */
ExFreePool(ClipSpans);
ExFreePool(ScanLine); ExFreePool(ScanLine);
ExFreePool(ScanLineAhead); ExFreePool(ScanLineAhead);
return TRUE;
} }
//NOTE: If you change something here, please do the same in other dibXXbpp.c files! //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
@ -538,11 +615,10 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
BYTE *SourceLine, *DestLine; DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
@ -561,12 +637,8 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
case 16: case 16:
SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left; return ScaleRectAvg16(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin,
DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left; ClipRegion, ColorTranslation, Mode);
ScaleRectAvg16((PIXEL *)DestLine, (PIXEL *)SourceLine,
SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top,
DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta);
break; break;
case 24: case 24:
@ -578,7 +650,7 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
default: default:
DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib1bpp.c,v 1.27 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib1bpp.c,v 1.28 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -515,7 +515,8 @@ DIB_1BPP_StretchBlt (
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
DbgPrint("DIB_1BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); DbgPrint("DIB_1BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib24bpp.c,v 1.26 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib24bpp.c,v 1.27 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -345,7 +345,8 @@ BOOLEAN DIB_24BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
DbgPrint("DIB_24BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); DbgPrint("DIB_24BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib32bpp.c,v 1.26 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib32bpp.c,v 1.27 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -278,7 +278,7 @@ DIB_32BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
default: default:
DbgPrint("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }
@ -437,27 +437,85 @@ void ScaleLineAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
while (skip-- > 0) while (skip-- > 0)
*Target++ = *Source; *Target++ = *Source;
} }
static BOOLEAN
FinalCopy32(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex,
UINT DestY, RECTL *DestRect)
{
LONG Left, Right;
while (ClipSpans[*SpanIndex].Y < DestY
|| (ClipSpans[*SpanIndex].Y == DestY
&& ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left))
{
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
while (ClipSpans[*SpanIndex].Y == DestY)
{
if (ClipSpans[*SpanIndex].X < DestRect->right)
{
Left = max(ClipSpans[*SpanIndex].X, DestRect->left);
Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right);
memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left,
(Right - Left) * sizeof(PIXEL));
}
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
return TRUE;
}
//NOTE: If you change something here, please do the same in other dibXXbpp.c files! //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
void ScaleRectAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, BOOLEAN ScaleRectAvg32(SURFGDI *DestGDI, SURFGDI *SourceGDI,
int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin,
CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
int NumPixels = TgtHeight; int NumPixels = DestRect->bottom - DestRect->top;
int IntPart = ((SrcHeight / TgtHeight) * srcPitch) / 4; //(SrcHeight / TgtHeight) * SrcWidth; int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta) / 4; //((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left);
int FractPart = SrcHeight % TgtHeight; int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top);
int Mid = TgtHeight >> 1; int Mid = (DestRect->bottom - DestRect->top) >> 1;
int E = 0; int E = 0;
int skip; int skip;
PIXEL *ScanLine, *ScanLineAhead; PIXEL *ScanLine, *ScanLineAhead;
PIXEL *PrevSource = NULL; PIXEL *PrevSource = NULL;
PIXEL *PrevSourceAhead = NULL; PIXEL *PrevSourceAhead = NULL;
PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + 4 * DestRect->left);
PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + 4 * SourceRect->left);
PSPAN ClipSpans;
UINT ClipSpansCount;
UINT SpanIndex;
LONG DestY;
skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
{
return FALSE;
}
if (0 == ClipSpansCount)
{
/* No clip spans == empty clipping region, everything clipped away */
ASSERT(NULL == ClipSpans);
return TRUE;
}
skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1);
NumPixels -= skip; NumPixels -= skip;
ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
DestY = DestRect->top;
SpanIndex = 0;
while (NumPixels-- > 0) { while (NumPixels-- > 0) {
if (Source != PrevSource) { if (Source != PrevSource) {
if (Source == PrevSourceAhead) { if (Source == PrevSourceAhead) {
@ -469,38 +527,57 @@ void ScaleRectAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight,
ScanLine = ScanLineAhead; ScanLine = ScanLineAhead;
ScanLineAhead = tmp; ScanLineAhead = tmp;
} else { } else {
ScaleLineAvg32(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg32(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
} /* if */ } /* if */
PrevSource = Source; PrevSource = Source;
} /* if */ } /* if */
if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) {
int x; int x;
ScaleLineAvg32(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); ScaleLineAvg32(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
for (x = 0; x < TgtWidth; x++) for (x = 0; x < DestRect->right - DestRect->left; x++)
ScanLine[x] = average32(ScanLine[x], ScanLineAhead[x]); ScanLine[x] = average32(ScanLine[x], ScanLineAhead[x]);
PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy32(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
Source += IntPart; Source += IntPart;
E += FractPart; E += FractPart;
if (E >= TgtHeight) { if (E >= DestRect->bottom - DestRect->top) {
E -= TgtHeight; E -= DestRect->bottom - DestRect->top;
Source = (PIXEL *)((BYTE *)Source + srcPitch); Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
} /* while */ } /* while */
if (skip > 0 && Source != PrevSource) if (skip > 0 && Source != PrevSource)
ScaleLineAvg32(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg32(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
while (skip-- > 0) { while (skip-- > 0) {
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy32(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
} /* while */ } /* while */
ExFreePool(ClipSpans);
ExFreePool(ScanLine); ExFreePool(ScanLine);
ExFreePool(ScanLineAhead); ExFreePool(ScanLineAhead);
return TRUE;
} }
//NOTE: If you change something here, please do the same in other dibXXbpp.c files! //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
@ -508,11 +585,10 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
BYTE *SourceLine, *DestLine; DPRINT("DIB_32BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
DbgPrint("DIB_32BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
@ -539,15 +615,12 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
case 32: case 32:
SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 4 * SourceRect->left; return ScaleRectAvg32(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin,
DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 4 * DestRect->left; ClipRegion, ColorTranslation, Mode);
ScaleRectAvg32((PIXEL *)DestLine, (PIXEL *)SourceLine,
SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top,
DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta);
break; break;
default: default:
//DbgPrint("DIB_32BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); //DPRINT1("DIB_32BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib4bpp.c,v 1.34 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib4bpp.c,v 1.35 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -390,7 +390,8 @@ BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
DbgPrint("DIB_4BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); DbgPrint("DIB_4BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: dib8bpp.c,v 1.25 2004/05/10 17:07:17 weiden Exp $ */ /* $Id: dib8bpp.c,v 1.26 2004/05/14 22:56:17 gvg Exp $ */
#include <w32k.h> #include <w32k.h>
VOID VOID
@ -252,7 +252,7 @@ DIB_8BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
default: default:
DbgPrint("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); DPRINT1("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }
@ -432,26 +432,84 @@ void ScaleLineAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
*Target++ = *Source; *Target++ = *Source;
} }
//NOTE: If you change something here, please do the same in other dibXXbpp.c files! static BOOLEAN
void ScaleRectAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, FinalCopy8(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex,
int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) UINT DestY, RECTL *DestRect)
{ {
int NumPixels = TgtHeight; LONG Left, Right;
int IntPart = ((SrcHeight / TgtHeight) * srcPitch); //(SrcHeight / TgtHeight) * SrcWidth;
int FractPart = SrcHeight % TgtHeight; while (ClipSpans[*SpanIndex].Y < DestY
int Mid = TgtHeight >> 1; || (ClipSpans[*SpanIndex].Y == DestY
&& ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left))
{
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
while (ClipSpans[*SpanIndex].Y == DestY)
{
if (ClipSpans[*SpanIndex].X < DestRect->right)
{
Left = max(ClipSpans[*SpanIndex].X, DestRect->left);
Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right);
memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left,
(Right - Left) * sizeof(PIXEL));
}
(*SpanIndex)++;
if (ClipSpansCount <= *SpanIndex)
{
/* No more spans, everything else is clipped away, we're done */
return FALSE;
}
}
return TRUE;
}
//NOTE: If you change something here, please do the same in other dibXXbpp.c files!
BOOLEAN ScaleRectAvg8(SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin,
CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{
int NumPixels = DestRect->bottom - DestRect->top;
int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta); //((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left);
int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top);
int Mid = (DestRect->bottom - DestRect->top) >> 1;
int E = 0; int E = 0;
int skip; int skip;
PIXEL *ScanLine, *ScanLineAhead; PIXEL *ScanLine, *ScanLineAhead;
PIXEL *PrevSource = NULL; PIXEL *PrevSource = NULL;
PIXEL *PrevSourceAhead = NULL; PIXEL *PrevSourceAhead = NULL;
PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + DestRect->left);
PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + SourceRect->left);
PSPAN ClipSpans;
UINT ClipSpansCount;
UINT SpanIndex;
LONG DestY;
skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
{
return FALSE;
}
if (0 == ClipSpansCount)
{
/* No clip spans == empty clipping region, everything clipped away */
ASSERT(NULL == ClipSpans);
return TRUE;
}
skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1);
NumPixels -= skip; NumPixels -= skip;
ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
DestY = DestRect->top;
SpanIndex = 0;
while (NumPixels-- > 0) { while (NumPixels-- > 0) {
if (Source != PrevSource) { if (Source != PrevSource) {
if (Source == PrevSourceAhead) { if (Source == PrevSourceAhead) {
@ -463,49 +521,67 @@ void ScaleRectAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight,
ScanLine = ScanLineAhead; ScanLine = ScanLineAhead;
ScanLineAhead = tmp; ScanLineAhead = tmp;
} else { } else {
ScaleLineAvg8(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg8(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
} /* if */ } /* if */
PrevSource = Source; PrevSource = Source;
} /* if */ } /* if */
if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) {
int x; int x;
ScaleLineAvg8(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); ScaleLineAvg8(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
for (x = 0; x < TgtWidth; x++) for (x = 0; x < DestRect->right - DestRect->left; x++)
ScanLine[x] = average8(ScanLine[x], ScanLineAhead[x]); ScanLine[x] = average8(ScanLine[x], ScanLineAhead[x]);
PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy8(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
Source += IntPart; Source += IntPart;
E += FractPart; E += FractPart;
if (E >= TgtHeight) { if (E >= DestRect->bottom - DestRect->top) {
E -= TgtHeight; E -= DestRect->bottom - DestRect->top;
Source = (PIXEL *)((BYTE *)Source + srcPitch); Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta);
} /* if */ } /* if */
} /* while */ } /* while */
if (skip > 0 && Source != PrevSource) if (skip > 0 && Source != PrevSource)
ScaleLineAvg8(ScanLine, Source, SrcWidth, TgtWidth); ScaleLineAvg8(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
while (skip-- > 0) { while (skip-- > 0) {
memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); if (! FinalCopy8(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
Target = (PIXEL *)((BYTE *)Target + dstPitch); {
/* No more spans, everything else is clipped away, we're done */
ExFreePool(ClipSpans);
ExFreePool(ScanLine);
ExFreePool(ScanLineAhead);
return TRUE;
}
DestY++;
Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta);
} /* while */ } /* while */
ExFreePool(ClipSpans);
ExFreePool(ScanLine); ExFreePool(ScanLine);
ExFreePool(ScanLineAhead); ExFreePool(ScanLineAhead);
return TRUE;
} }
BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrigin, POINTL* MaskOrigin, POINTL BrushOrigin,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
BYTE *SourceLine, *DestLine; DPRINT("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
DbgPrint("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
@ -520,12 +596,8 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
case 8: case 8:
SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + SourceRect->left; return ScaleRectAvg8(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin,
DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + DestRect->left; ClipRegion, ColorTranslation, Mode);
ScaleRectAvg8((PIXEL *)DestLine, (PIXEL *)SourceLine,
SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top,
DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta);
break; break;
case 16: case 16:
@ -541,7 +613,7 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
break; break;
default: default:
DbgPrint("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); DPRINT1("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
return FALSE; return FALSE;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: bitblt.c,v 1.54 2004/05/10 17:07:17 weiden Exp $ /* $Id: bitblt.c,v 1.55 2004/05/14 22:56:18 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -45,6 +45,7 @@ typedef BOOLEAN STDCALL (*PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
SURFOBJ* InputObj, SURFOBJ* InputObj,
SURFGDI* InputGDI, SURFGDI* InputGDI,
SURFOBJ* Mask, SURFOBJ* Mask,
CLIPOBJ* ClipRegion,
XLATEOBJ* ColorTranslation, XLATEOBJ* ColorTranslation,
RECTL* OutputRect, RECTL* OutputRect,
RECTL* InputRect, RECTL* InputRect,
@ -593,6 +594,7 @@ CallDibStretchBlt(SURFOBJ* OutputObj,
SURFOBJ* InputObj, SURFOBJ* InputObj,
SURFGDI* InputGDI, SURFGDI* InputGDI,
SURFOBJ* Mask, SURFOBJ* Mask,
CLIPOBJ* ClipRegion,
XLATEOBJ* ColorTranslation, XLATEOBJ* ColorTranslation,
RECTL* OutputRect, RECTL* OutputRect,
RECTL* InputRect, RECTL* InputRect,
@ -609,7 +611,7 @@ CallDibStretchBlt(SURFOBJ* OutputObj,
{ {
RealBrushOrigin = *BrushOrigin; RealBrushOrigin = *BrushOrigin;
} }
return OutputGDI->DIB_StretchBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputRect, MaskOrigin, RealBrushOrigin, ColorTranslation, Mode); return OutputGDI->DIB_StretchBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputRect, MaskOrigin, RealBrushOrigin, ClipRegion, ColorTranslation, Mode);
} }
@ -631,10 +633,6 @@ EngStretchBlt(
{ {
// www.osr.com/ddk/graphics/gdifncs_0bs7.htm // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
BYTE clippingType;
RECTL CombinedRect;
// RECT_ENUM RectEnum;
// BOOL EnumMore;
SURFGDI* OutputGDI; SURFGDI* OutputGDI;
SURFGDI* InputGDI; SURFGDI* InputGDI;
POINTL InputPoint; POINTL InputPoint;
@ -645,30 +643,26 @@ EngStretchBlt(
INTENG_ENTER_LEAVE EnterLeaveDest; INTENG_ENTER_LEAVE EnterLeaveDest;
SURFOBJ* InputObj; SURFOBJ* InputObj;
SURFOBJ* OutputObj; SURFOBJ* OutputObj;
PSTRETCHRECTFUNC BltRectFunc; PSTRETCHRECTFUNC BltRectFunc;
BOOLEAN Ret; BOOLEAN Ret;
RECTL ClipRect; POINTL AdjustedBrushOrigin;
// unsigned i;
POINTL Pt;
// ULONG Direction;
POINTL AdjustedBrushOrigin;
InputRect.left = prclSrc->left; InputRect.left = prclSrc->left;
InputRect.right = prclSrc->right; InputRect.right = prclSrc->right;
InputRect.top = prclSrc->top; InputRect.top = prclSrc->top;
InputRect.bottom = prclSrc->bottom; InputRect.bottom = prclSrc->bottom;
if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj)) if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj))
{ {
return FALSE; return FALSE;
} }
InputPoint.x = InputRect.left + Translate.x; InputPoint.x = InputRect.left + Translate.x;
InputPoint.y = InputRect.top + Translate.y; InputPoint.y = InputRect.top + Translate.y;
if (NULL != InputObj) if (NULL != InputObj)
{ {
InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj); InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj);
} }
else else
{ {
@ -676,44 +670,19 @@ EngStretchBlt(
} }
OutputRect = *prclDest; OutputRect = *prclDest;
if (NULL != ClipRegion)
{
if (OutputRect.left < ClipRegion->rclBounds.left)
{
InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
OutputRect.left = ClipRegion->rclBounds.left;
}
if (ClipRegion->rclBounds.right < OutputRect.right)
{
InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right;
OutputRect.right = ClipRegion->rclBounds.right;
}
if (OutputRect.top < ClipRegion->rclBounds.top)
{
InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
OutputRect.top = ClipRegion->rclBounds.top;
}
if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
{
InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom;
OutputRect.bottom = ClipRegion->rclBounds.bottom;
}
}
/* Check for degenerate case: if height or width of OutputRect is 0 pixels there's /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
nothing to do */ nothing to do */
if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
{ {
IntEngLeave(&EnterLeaveSource); IntEngLeave(&EnterLeaveSource);
return TRUE; return TRUE;
} }
if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj)) if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
{ {
IntEngLeave(&EnterLeaveSource); IntEngLeave(&EnterLeaveSource);
return FALSE; return FALSE;
} }
OutputRect.left = prclDest->left + Translate.x; OutputRect.left = prclDest->left + Translate.x;
@ -721,28 +690,22 @@ EngStretchBlt(
OutputRect.top = prclDest->top + Translate.y; OutputRect.top = prclDest->top + Translate.y;
OutputRect.bottom = prclDest->bottom + Translate.y; OutputRect.bottom = prclDest->bottom + Translate.y;
if(BrushOrigin) if (NULL != BrushOrigin)
{ {
AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
} }
else else
AdjustedBrushOrigin = Translate; {
AdjustedBrushOrigin = Translate;
}
if (NULL != OutputObj) if (NULL != OutputObj)
{ {
OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj); OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj);
} }
// Determine clipping type if (Mask != NULL)
if (ClipRegion == (CLIPOBJ *) NULL)
{
clippingType = DC_TRIVIAL;
} else {
clippingType = ClipRegion->iDComplexity;
}
if (Mask != NULL)//(0xaacc == Rop4)
{ {
//BltRectFunc = BltMask; //BltRectFunc = BltMask;
DPRINT("EngStretchBlt isn't capable of handling mask yet.\n"); DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
@ -757,70 +720,9 @@ EngStretchBlt(
} }
switch(clippingType) Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ClipRegion,
{ ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
case DC_TRIVIAL: &AdjustedBrushOrigin, Mode);
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&OutputRect, &InputRect, MaskOrigin, &AdjustedBrushOrigin, Mode);
break;
case DC_RECT:
// Clip the blt to the clip rectangle
ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&OutputRect, &InputRect, MaskOrigin, &AdjustedBrushOrigin, Mode);
//Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
// &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n");
break;
// TODO: Complex clipping
/*
case DC_COMPLEX:
Ret = TRUE;
if (OutputObj == InputObj)
{
if (OutputRect.top < InputPoint.y)
{
Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
}
else
{
Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
}
}
else
{
Direction = CD_ANY;
}
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
do
{
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
for (i = 0; i < RectEnum.c; i++)
{
ClipRect.left = RectEnum.arcl[i].left + Translate.x;
ClipRect.right = RectEnum.arcl[i].right + Translate.x;
ClipRect.top = RectEnum.arcl[i].top + Translate.y;
ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
&CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4) &&
Ret;
}
}
while(EnumMore);
break;
*/
}
IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource); IntEngLeave(&EnterLeaveSource);
@ -844,8 +746,6 @@ IntEngStretchBlt(SURFOBJ *DestObj,
BOOLEAN ret; BOOLEAN ret;
SURFGDI *DestGDI; SURFGDI *DestGDI;
SURFGDI *SourceGDI; SURFGDI *SourceGDI;
RECTL OutputRect;
RECTL InputRect;
COLORADJUSTMENT ca; COLORADJUSTMENT ca;
POINT MaskOrigin; POINT MaskOrigin;
@ -854,43 +754,19 @@ IntEngStretchBlt(SURFOBJ *DestObj,
MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y; MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
} }
if (NULL != SourceRect)
{
InputRect = *SourceRect;
}
// FIXME: Clipping is taken from IntEngBitBlt w/o modifications!
/* Clip against the bounds of the clipping region so we won't try to write
* outside the surface */
if (NULL != ClipRegion)
{
if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
{
return TRUE;
}
DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n");
//InputPoint.x += OutputRect.left - DestRect->left;
//InputPoint.y += OutputRect.top - DestRect->top;
}
else
{
OutputRect = *DestRect;
}
if (NULL != SourceObj) if (NULL != SourceObj)
{ {
SourceGDI = (SURFGDI*) AccessInternalObjectFromUserObject(SourceObj); SourceGDI = (SURFGDI*) AccessInternalObjectFromUserObject(SourceObj);
MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputRect.left, InputRect.top, MouseSafetyOnDrawStart(SourceObj, SourceGDI, SourceRect->left, SourceRect->top,
(InputRect.left + abs(InputRect.right - InputRect.left)), (SourceRect->left + abs(SourceRect->right - SourceRect->left)),
(InputRect.top + abs(InputRect.bottom - InputRect.top))); (SourceRect->top + abs(SourceRect->bottom - SourceRect->top)));
} }
/* No success yet */ /* No success yet */
ret = FALSE; ret = FALSE;
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj); DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top, MouseSafetyOnDrawStart(DestObj, DestGDI, DestRect->left, DestRect->top,
OutputRect.right, OutputRect.bottom); DestRect->right, DestRect->bottom);
/* Prepare color adjustment */ /* Prepare color adjustment */
@ -902,7 +778,7 @@ IntEngStretchBlt(SURFOBJ *DestObj,
// FIXME: MaskOrigin is always NULL ! // FIXME: MaskOrigin is always NULL !
IntLockGDIDriver(DestGDI); IntLockGDIDriver(DestGDI);
ret = DestGDI->StretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, ret = DestGDI->StretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode); &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode);
IntUnLockGDIDriver(DestGDI); IntUnLockGDIDriver(DestGDI);
} }
@ -910,7 +786,7 @@ IntEngStretchBlt(SURFOBJ *DestObj,
{ {
// FIXME: see previous fixme // FIXME: see previous fixme
ret = EngStretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, ret = EngStretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode); &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode);
} }
MouseSafetyOnDrawEnd(DestObj, DestGDI); MouseSafetyOnDrawEnd(DestObj, DestGDI);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: clip.c,v 1.20 2004/05/10 17:07:17 weiden Exp $ /* $Id: clip.c,v 1.21 2004/05/14 22:56:18 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -333,4 +333,123 @@ CLIPOBJ_bEnum(IN CLIPOBJ* ClipObj,
return ClipGDI->EnumPos < ClipGDI->EnumRects.c; return ClipGDI->EnumPos < ClipGDI->EnumRects.c;
} }
static int
CompareSpans(const PSPAN Span1, const PSPAN Span2)
{
int Cmp;
if (Span1->Y < Span2->Y)
{
Cmp = -1;
}
else if (Span2->Y < Span1->Y)
{
Cmp = +1;
}
else
{
if (Span1->X < Span2->X)
{
Cmp = -1;
}
else if (Span2->X < Span1->X)
{
Cmp = +1;
}
else
{
Cmp = 0;
}
}
return Cmp;
}
BOOLEAN FASTCALL
ClipobjToSpans(PSPAN *Spans, UINT *Count, CLIPOBJ *ClipRegion, PRECTL Boundary)
{
BOOL EnumMore;
UINT i, NewCount;
RECT_ENUM RectEnum;
PSPAN NewSpans;
RECTL *Rect;
ASSERT(Boundary->top <= Boundary->bottom && Boundary->left <= Boundary->right);
*Spans = NULL;
if (NULL == ClipRegion || DC_TRIVIAL == ClipRegion->iDComplexity)
{
*Count = Boundary->bottom - Boundary->top;
if (0 != *Count)
{
*Spans = ExAllocatePoolWithTag(PagedPool, *Count * sizeof(SPAN), TAG_CLIP);
if (NULL == *Spans)
{
*Count = 0;
return FALSE;
}
for (i = 0; i < Boundary->bottom - Boundary->top; i++)
{
(*Spans)[i].X = Boundary->left;
(*Spans)[i].Y = Boundary->top + i;
(*Spans)[i].Width = Boundary->right - Boundary->left;
}
}
return TRUE;
}
*Count = 0;
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);
do
{
EnumMore = CLIPOBJ_bEnum(ClipRegion, (ULONG) sizeof(RECT_ENUM), (PVOID) &RectEnum);
NewCount = *Count;
for (i = 0; i < RectEnum.c; i++)
{
NewCount += RectEnum.arcl[i].bottom - RectEnum.arcl[i].top;
}
if (NewCount != *Count)
{
NewSpans = ExAllocatePoolWithTag(PagedPool, NewCount * sizeof(SPAN), TAG_CLIP);
if (NULL == NewSpans)
{
if (NULL != *Spans)
{
ExFreePool(*Spans);
*Spans = NULL;
}
*Count = 0;
return FALSE;
}
if (0 != *Count)
{
RtlCopyMemory(NewSpans, *Spans, *Count * sizeof(SPAN));
ExFreePool(*Spans);
}
*Spans = NewSpans;
}
for (Rect = RectEnum.arcl; Rect < RectEnum.arcl + RectEnum.c; Rect++)
{
for (i = 0; i < Rect->bottom - Rect->top; i++)
{
(*Spans)[*Count].X = Rect->left;
(*Spans)[*Count].Y = Rect->top + i;
(*Spans)[*Count].Width = Rect->right - Rect->left;
(*Count)++;
}
}
ASSERT(*Count == NewCount);
}
while (EnumMore);
if (0 != *Count)
{
EngSort((PBYTE) *Spans, sizeof(SPAN), *Count, (SORTCOMP) CompareSpans);
}
return TRUE;
}
/* EOF */ /* EOF */

View file

@ -32,4 +32,13 @@ typedef struct _RECT_ENUM
RECTL arcl[ENUM_RECT_LIMIT]; RECTL arcl[ENUM_RECT_LIMIT];
} RECT_ENUM; } RECT_ENUM;
typedef struct tagSPAN
{
LONG Y;
LONG X;
ULONG Width;
} SPAN, *PSPAN;
BOOLEAN FASTCALL ClipobjToSpans(PSPAN *Spans, UINT *Count, CLIPOBJ *ClipRegion, PRECTL Boundary);
#endif #endif

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: surface.c,v 1.38 2004/05/10 17:07:17 weiden Exp $ /* $Id: surface.c,v 1.39 2004/05/14 22:56:18 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -110,7 +110,8 @@ static BOOLEAN Dummy_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
SURFGDI *DestGDI, SURFGDI *SourceGDI, SURFGDI *DestGDI, SURFGDI *SourceGDI,
RECTL* DestRect, RECTL *SourceRect, RECTL* DestRect, RECTL *SourceRect,
POINTL* MaskOrigin, POINTL BrushOrign, POINTL* MaskOrigin, POINTL BrushOrign,
XLATEOBJ *ColorTranslation, ULONG Mode) CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
ULONG Mode)
{ {
return FALSE; return FALSE;
} }

View file

@ -26,6 +26,7 @@
#define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */ #define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */
#define TAG_BITMAP TAG('B', 'T', 'M', 'P') /* bitmap */ #define TAG_BITMAP TAG('B', 'T', 'M', 'P') /* bitmap */
#define TAG_PATBLT TAG('P', 'B', 'L', 'T') /* patblt */ #define TAG_PATBLT TAG('P', 'B', 'L', 'T') /* patblt */
#define TAG_CLIP TAG('C', 'L', 'I', 'P') /* clipping */
#define TAG_COORD TAG('C', 'O', 'R', 'D') /* coords */ #define TAG_COORD TAG('C', 'O', 'R', 'D') /* coords */
#define TAG_DC TAG('D', 'C', 'D', 'C') /* dc */ #define TAG_DC TAG('D', 'C', 'D', 'C') /* dc */
#define TAG_GDIOBJ TAG('G', 'D', 'I', 'O') /* gdi obj */ #define TAG_GDIOBJ TAG('G', 'D', 'I', 'O') /* gdi obj */