Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

390 lines
14 KiB

/******************************Module*Header*******************************\
* Module Name: drawstream.c *
* *
* Client side draw stream support. Handles metafiling if primary *
* is a metafile. *
* *
* Created: 03-Mar-2001 *
* Author: Barton House [bhouse] *
* *
* Copyright (c) 1991-2001 Microsoft Corporation *
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
/******************************Public*Routine******************************\
* GdiDrawStream
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 3/21/2001 Barton House
*
\**************************************************************************/
BOOL
GdiDrawStream(
HDC hdcDst,
ULONG cjIn,
VOID *pvIn)
{
BOOL bRet = FALSE;
PDC_ATTR pdca;
FIXUP_HANDLE(hdcDst);
if (IS_ALTDC_TYPE(hdcDst))
{
HBITMAP hbmSource = NULL;
HRGN hrgnSaved = NULL;
HBITMAP hbmScratch = NULL;
HDC hdcScratch = NULL;
int iDstClip = -1;
ULONG * pul = (ULONG *) pvIn;
if(cjIn < sizeof(ULONG))
return FALSE;
if(*pul++ != 'DrwS')
return FALSE;
cjIn -= sizeof(ULONG);
while(cjIn >= sizeof(ULONG))
{
ULONG command = *pul;
ULONG commandSize;
RECTL rclDstClip;
switch(command)
{
case DS_SETTARGETID: // set target
{
DS_SETTARGET * cmd = (DS_SETTARGET *) pul;
commandSize = sizeof(*cmd);
if(cjIn < commandSize)
goto altExit;
if((HDC) ULongToHandle(cmd->hdc) != hdcDst)
{
// NOTE: This restriction is only in place for the
// initial implementation of GdiDrawStream.
WARNING("GdiDrawStream: target must match primary target");
goto altExit;
}
rclDstClip = cmd->rclDstClip;
if(hrgnSaved == NULL)
{
int iRet;
hrgnSaved = CreateRectRgn(0,0,0,0);
if(hrgnSaved == NULL)
{
WARNING("GdiDrawStream: unable to create saved region");
goto altExit;
}
iDstClip = GetClipRgn(hdcDst, hrgnSaved);
if(iDstClip == -1)
{
WARNING("GdiDrawStream: failed to get DC application clip");
goto altExit;
}
}
else
{
// need to restore target clip
if(iDstClip)
{
SelectClipRgn(hdcDst, hrgnSaved);
}
else
{
SelectClipRgn(hdcDst, NULL);
}
}
IntersectClipRect(hdcDst, rclDstClip.left, rclDstClip.top, rclDstClip.right, rclDstClip.bottom);
}
break;
case DS_SETSOURCEID: // set source
{
DS_SETSOURCE * cmd = (DS_SETSOURCE *) pul;
commandSize = sizeof(*cmd);
if(cjIn < commandSize)
goto altExit;
hbmSource = (HBITMAP) ULongToHandle(cmd->hbm);
}
break;
case DS_NINEGRIDID:
{
DS_NINEGRID * cmd = (DS_NINEGRID *) pul;
LONG lSrcWidth = cmd->rclSrc.right - cmd->rclSrc.left;
LONG lSrcHeight = cmd->rclSrc.bottom - cmd->rclSrc.top;
LONG lDstWidth = cmd->rclDst.right - cmd->rclDst.left;
LONG lDstHeight = cmd->rclDst.bottom - cmd->rclDst.top;
BOOL bRenderRet;
RECTL rclDst = cmd->rclDst;
struct {
BITMAPINFOHEADER bmih;
ULONG masks[3];
} bmi;
struct {
DS_HEADER hdr;
DS_SETTARGET setTarget;
DS_SETSOURCE setSource;
DS_NINEGRID ng;
} scratchStream;
RECTL rclScratch;
commandSize = sizeof(DS_NINEGRID);
// validate nine grid
#define DSDNG_MASK 0x007F // move to wingdip.h
if(cmd->ngi.flFlags & ~DSDNG_MASK)
{
WARNING("GreDrawStream: unrecognized nine grid flags set\n");
goto altExit;
}
if(lSrcWidth < 0 || lSrcHeight < 0)
{
WARNING("GreDrawStream: nine grid rclSrc is not well ordered\n");
goto altExit;
}
if(cmd->ngi.flFlags & DSDNG_TRUESIZE)
{
if(lDstWidth > lSrcWidth)
{
lDstWidth = lSrcWidth;
rclDst.right = rclDst.left + lDstWidth;
}
if(lDstHeight > lSrcHeight)
{
lDstHeight = lSrcHeight;
rclDst.bottom = rclDst.top + lDstHeight;
}
}
else
{
// NOTE: we have to check individual first then sum due to possible
// numerical overflows that could occur in the sum that might
// not be detected otherwise.
if(cmd->ngi.ulLeftWidth < 0 ||
cmd->ngi.ulRightWidth < 0 ||
cmd->ngi.ulTopHeight < 0 ||
cmd->ngi.ulBottomHeight < 0 ||
cmd->ngi.ulLeftWidth > lSrcWidth ||
cmd->ngi.ulRightWidth > lSrcWidth ||
cmd->ngi.ulTopHeight > lSrcHeight ||
cmd->ngi.ulBottomHeight > lSrcHeight ||
cmd->ngi.ulLeftWidth + cmd->ngi.ulRightWidth > lSrcWidth ||
cmd->ngi.ulTopHeight + cmd->ngi.ulBottomHeight > lSrcHeight)
{
WARNING("GreDrawStream: nine grid width is greater then rclSrc width or negative\n");
goto altExit;
}
}
if((cmd->ngi.flFlags & (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA)) == (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA))
{
WARNING("GreDrawStream: nine grid attempt to set both transparency and per pixel alpha\n");
goto altExit;
}
// create temporary to render nine grid into
bmi.bmih.biSize = sizeof(bmi.bmih);
bmi.bmih.biWidth = lDstWidth;
bmi.bmih.biHeight = lDstHeight;
bmi.bmih.biPlanes = 1;
bmi.bmih.biBitCount = 32;
bmi.bmih.biCompression = BI_BITFIELDS;
bmi.bmih.biSizeImage = 0;
bmi.bmih.biXPelsPerMeter = 0;
bmi.bmih.biYPelsPerMeter = 0;
bmi.bmih.biClrUsed = 3;
bmi.bmih.biClrImportant = 0;
bmi.masks[0] = 0xff0000; // red
bmi.masks[1] = 0x00ff00; // green
bmi.masks[2] = 0x0000ff; // blue
if(hbmScratch != NULL)
DeleteObject(hbmScratch);
hbmScratch = CreateDIBitmap(hdcDst, &bmi.bmih, CBM_CREATEDIB , NULL, (BITMAPINFO*)&bmi.bmih, DIB_RGB_COLORS);
if(hbmScratch == NULL)
{
WARNING("GdiDrawStream: unable to create temporary\n");
goto altExit;
}
if(hdcScratch == NULL)
{
hdcScratch = CreateCompatibleDC(hdcDst);
if(hdcScratch == NULL)
{
WARNING("GdiDrawStream: unable to create temporary dc\n");
goto altExit;
}
}
SelectObject(hdcScratch, hbmScratch);
rclScratch.left = 0;
rclScratch.top = 0;
rclScratch.right = lDstWidth;
rclScratch.bottom = lDstHeight;
scratchStream.hdr.magic = DS_MAGIC;
scratchStream.setTarget.ulCmdID = DS_SETTARGETID;
scratchStream.setTarget.hdc = HandleToULong(hdcScratch);
scratchStream.setTarget.rclDstClip = rclScratch;
scratchStream.setSource.ulCmdID = DS_SETSOURCEID;
scratchStream.setSource.hbm = HandleToULong(hbmSource);
scratchStream.ng.ulCmdID = DS_NINEGRIDID;
scratchStream.ng.rclDst = rclScratch;
scratchStream.ng.rclSrc = cmd->rclSrc;
scratchStream.ng.ngi = cmd->ngi;
scratchStream.ng.ngi.flFlags &= ~(DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA);
NtGdiDrawStream(hdcScratch, sizeof(scratchStream), &scratchStream);
if(cmd->ngi.flFlags & DSDNG_TRANSPARENT)
{
bRenderRet = GdiTransparentBlt(hdcDst,
rclDst.left,
rclDst.top,
lDstWidth,
lDstHeight,
hdcScratch,
0,
0,
lDstWidth,
lDstHeight,
cmd->ngi.crTransparent);
}
else if(cmd->ngi.flFlags & DSDNG_PERPIXELALPHA)
{
// alpha blend
BLENDFUNCTION bfx;
bfx.AlphaFormat = AC_SRC_ALPHA;
bfx.BlendFlags = 0;
bfx.BlendOp = AC_SRC_OVER;
bfx.SourceConstantAlpha = 255;
bRenderRet = GdiAlphaBlend(hdcDst,
rclDst.left,
rclDst.top,
lDstWidth,
lDstHeight,
hdcScratch,
0,
0,
lDstWidth,
lDstHeight,
bfx);
}
else
{
// bitblt
bRenderRet = BitBlt(hdcDst,
rclDst.left,
rclDst.top,
lDstWidth,
lDstHeight,
hdcScratch,
0,
0,
SRCCOPY);
}
if(!bRenderRet)
{
WARNING("GdiDrawStream: failed to render temporary to destination");
goto altExit;
}
}
break;
default:
WARNING("GdiDrawStream: unrecognized command");
goto altExit;
}
pul += commandSize / sizeof(ULONG);
cjIn -= commandSize;
}
bRet = TRUE;
altExit:
if(iDstClip == 1)
{
SelectClipRgn(hdcDst, hrgnSaved);
}
else if(iDstClip == 0)
{
SelectClipRgn(hdcDst, NULL);
}
if(hbmScratch != NULL)
DeleteObject(hbmScratch);
if(hdcScratch != NULL)
DeleteDC(hdcScratch);
if(hrgnSaved != NULL)
DeleteObject(hrgnSaved);
return bRet;
}
RESETUSERPOLLCOUNT();
bRet = NtGdiDrawStream(
hdcDst,
cjIn,
pvIn);
return(bRet);
}