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.
 
 
 
 
 
 

897 lines
25 KiB

/******************************Header*File*********************************\
*
* glsup.c
*
* GL metafiling and printing support
*
* History:
* Wed Mar 15 15:20:49 1995 -by- Drew Bliss [drewb]
* Created
*
* Copyright (c) 1995-1999 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "glsup.h"
// GL metafile callbacks in opengl32
typedef struct _GLMFCALLBACKS
{
BOOL (APIENTRY *GlmfInitPlayback)(HDC, ENHMETAHEADER *, LPRECTL);
BOOL (APIENTRY *GlmfBeginGlsBlock)(HDC);
BOOL (APIENTRY *GlmfPlayGlsRecord)(HDC, DWORD, BYTE *, LPRECTL);
BOOL (APIENTRY *GlmfEndGlsBlock)(HDC);
BOOL (APIENTRY *GlmfEndPlayback)(HDC);
BOOL (APIENTRY *GlmfCloseMetaFile)(HDC);
HGLRC (APIENTRY *wglCreateContext)(HDC);
BOOL (APIENTRY *wglDeleteContext)(HGLRC);
BOOL (APIENTRY *wglMakeCurrent)(HDC, HGLRC);
HGLRC (APIENTRY *wglGetCurrentContext)(void);
} GLMFCALLBACKS;
#define GL_MF_CALLBACKS (sizeof(GLMFCALLBACKS)/sizeof(PROC))
static char *pszGlmfEntryPoints[] =
{
"GlmfInitPlayback",
"GlmfBeginGlsBlock",
"GlmfPlayGlsRecord",
"GlmfEndGlsBlock",
"GlmfEndPlayback",
"GlmfCloseMetaFile",
"wglCreateContext",
"wglDeleteContext",
"wglMakeCurrent",
"wglGetCurrentContext"
};
#define GL_MF_ENTRYPOINTS (sizeof(pszGlmfEntryPoints)/sizeof(char *))
RTL_CRITICAL_SECTION semGlLoad;
static GLMFCALLBACKS gmcGlFuncs = {NULL};
static HMODULE hOpenGL = NULL;
static LONG lLoadCount = 0;
/*****************************Private*Routine******************************\
*
* LoadOpenGL
*
* Loads opengl32.dll if necessary
*
* History:
* Wed Mar 01 10:41:59 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL LoadOpenGL(void)
{
HMODULE hdll;
BOOL fRet;
PROC *ppfn;
int i;
GLMFCALLBACKS gmc;
ASSERTGDI(GL_MF_CALLBACKS == GL_MF_ENTRYPOINTS,
"Glmf callback/entry points mismatch\n");
ENTERCRITICALSECTION(&semGlLoad);
if (hOpenGL != NULL)
{
goto Success;
}
fRet = FALSE;
hdll = LoadLibrary("opengl32.dll");
if (hdll == NULL)
{
WARNING("Unable to load opengl32.dll\n");
goto Exit;
}
ppfn = (PROC *)&gmc;
for (i = 0; i < GL_MF_CALLBACKS; i++)
{
if (!(*ppfn = (PROC)GetProcAddress(hdll,
pszGlmfEntryPoints[i])))
{
WARNING("opengl32 missing '");
WARNING(pszGlmfEntryPoints[i]);
WARNING("'\n");
FreeLibrary(hdll);
goto Exit;
}
ppfn++;
}
gmcGlFuncs = gmc;
hOpenGL = hdll;
Success:
fRet = TRUE;
lLoadCount++;
Exit:
LEAVECRITICALSECTION(&semGlLoad);
return fRet;
}
/*****************************Private*Routine******************************\
*
* UnloadOpenGL
*
* Unloads opengl32.dll if necessary
*
* History:
* Wed Mar 01 11:02:06 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
void UnloadOpenGL(void)
{
ENTERCRITICALSECTION(&semGlLoad);
ASSERTGDI(lLoadCount > 0, "UnloadOpenGL called without Load\n");
if (--lLoadCount == 0)
{
HMODULE hdll;
ASSERTGDI(hOpenGL != NULL, "Positive load count with no DLL\n");
hdll = hOpenGL;
hOpenGL = NULL;
memset(&gmcGlFuncs, 0, sizeof(gmcGlFuncs));
FreeLibrary(hdll);
}
LEAVECRITICALSECTION(&semGlLoad);
}
/*****************************Private*Routine******************************\
*
* GlmfInitPlayback
*
* Stub to forward call to opengl
*
* History:
* Wed Mar 01 11:02:31 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfInitPlayback(HDC hdc, ENHMETAHEADER *pemh, LPRECTL prclDest)
{
ASSERTGDI(gmcGlFuncs.GlmfInitPlayback != NULL,
"GlmfInitPlayback not set\n");
return gmcGlFuncs.GlmfInitPlayback ? gmcGlFuncs.GlmfInitPlayback(hdc, pemh, prclDest) : FALSE;
}
/*****************************Private*Routine******************************\
*
* GlmfBeginGlsBlock
*
* Stub to forward call to opengl
*
* History:
* Mon Apr 10 11:38:13 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfBeginGlsBlock(HDC hdc)
{
ASSERTGDI(gmcGlFuncs.GlmfBeginGlsBlock != NULL,
"GlmfBeginGlsBlock not set\n");
return gmcGlFuncs.GlmfBeginGlsBlock ? gmcGlFuncs.GlmfBeginGlsBlock(hdc) : FALSE;
}
/*****************************Private*Routine******************************\
*
* GlmfPlayGlsRecord
*
* Stub to forward call to opengl
*
* History:
* Wed Mar 01 11:02:49 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfPlayGlsRecord(HDC hdc, DWORD cb, BYTE *pb,
LPRECTL prclBounds)
{
ASSERTGDI(gmcGlFuncs.GlmfPlayGlsRecord != NULL,
"GlmfPlayGlsRecord not set\n");
return gmcGlFuncs.GlmfPlayGlsRecord ? gmcGlFuncs.GlmfPlayGlsRecord(hdc, cb, pb, prclBounds) : FALSE;
}
/*****************************Private*Routine******************************\
*
* GlmfEndGlsBlock
*
* Stub to forward call to opengl
*
* History:
* Mon Apr 10 11:38:13 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfEndGlsBlock(HDC hdc)
{
ASSERTGDI(gmcGlFuncs.GlmfEndGlsBlock != NULL,
"GlmfEndGlsBlock not set\n");
return gmcGlFuncs.GlmfEndGlsBlock ? gmcGlFuncs.GlmfEndGlsBlock(hdc) : FALSE;
}
/*****************************Private*Routine******************************\
*
* GlmfEndPlayback
*
* Stub to forward call to opengl
*
* History:
* Wed Mar 01 11:03:02 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfEndPlayback(HDC hdc)
{
BOOL fRet;
ASSERTGDI(gmcGlFuncs.GlmfEndPlayback != NULL,
"GlmfEndPlayback not set\n");
fRet = gmcGlFuncs.GlmfEndPlayback ? gmcGlFuncs.GlmfEndPlayback(hdc) : FALSE;
// WINBUG #82850 2-7-2000 bhouse We might was to unload opengl32.dll
// This is not really a problem . This WINBUG is actually asking about
// if we should unload("opengl32.dll"). The opengl32.dll is loaded as
// a side effect of calling InitGlPrinting() call. This will only cause
// a ref count leak. Also as this is user mode code on the client side.
return fRet;
}
/*****************************Private*Routine******************************\
*
* GlmfCloseMetaFile
*
* Stub to forward call to opengl
*
* History:
* Fri Mar 03 17:50:57 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL APIENTRY GlmfCloseMetaFile(HDC hdc)
{
if (!LoadOpenGL())
{
return FALSE;
}
ASSERTGDI(gmcGlFuncs.GlmfCloseMetaFile != NULL,
"GlmfCloseMetaFile not set\n");
// WINBUG #82850 2-7-2000 bhouse Investigate need to unload
// Old Comment:
// - Unload?
// This is not really a problem . The WINBUG is actually asking about
// if we should unload("opengl32.dll"). The opengl32.dll is loaded as
// a side effect of calling InitGlPrinting() call. This will only cause
// a ref count leak. Also as this is user mode code on the client side.
return gmcGlFuncs.GlmfCloseMetaFile(hdc);
}
// WINBUG #82854 2-7-2000 bhouse Investigate magic value used for band memory limit
static DWORD cbBandMemoryLimit = 0x400000;
#define RECT_CB(w, h, cbp) ((cbp)*(w)*(h))
// GL has hardcoded limits on maximum rendering size
#define GL_WIDTH_LIMIT 16384
#define GL_HEIGHT_LIMIT 16384
/******************************Public*Routine******************************\
*
* EndGlPrinting
*
* Cleans up resources used while printing OpenGL metafiles
*
* History:
* Wed Apr 12 17:51:24 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
void EndGlPrinting(GLPRINTSTATE *pgps)
{
ASSERTGDI(hOpenGL != NULL, "EndGlPrinting: No opengl\n");
if (pgps->iReduceFactor > 1)
{
if (pgps->bBrushOrgSet)
{
SetBrushOrgEx(pgps->hdcDest,
pgps->ptBrushOrg.x, pgps->ptBrushOrg.y,
NULL);
}
if (pgps->iStretchMode != 0)
{
SetStretchBltMode(pgps->hdcDest, pgps->iStretchMode);
}
}
if (gmcGlFuncs.wglGetCurrentContext() != NULL)
{
gmcGlFuncs.wglMakeCurrent(pgps->hdcDib, NULL);
}
if (pgps->hrc != NULL)
{
gmcGlFuncs.wglDeleteContext(pgps->hrc);
}
if (pgps->hdcDib != NULL)
{
DeleteDC(pgps->hdcDib);
}
if (pgps->hbmDib != NULL)
{
DeleteObject(pgps->hbmDib);
}
// WINBUG #82850 2-7-2000 bhouse Investigate need to unload
// Old Comment:
// - Unload?
// This is not really a problem . The WINBUG is actually asking about
// if we should unload("opengl32.dll"). The opengl32.dll is loaded as
// a side effect of calling InitGlPrinting() call. This will only cause
// a ref count leak. Also as this is user mode code on the client side.
}
/******************************Public*Routine******************************\
*
* InitGlPrinting
*
* Performs all setup necessary for OpenGL printing
*
* History:
* Wed Apr 12 17:51:46 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL InitGlPrinting(HENHMETAFILE hemf, HDC hdcDest, RECT *rc,
DEVMODEW *pdm, GLPRINTSTATE *pgps)
{
PIXELFORMATDESCRIPTOR pfd;
int iFmt;
BITMAPINFO *pbmi;
BITMAPINFOHEADER *pbmih;
int iWidth, iHeight;
DWORD cbMeta;
POINT pt;
UINT cbPixelFormat;
UINT cbPixel;
UINT nColors;
PVOID pvBits;
// Zero out in case we need to do cleanup
memset(pgps, 0, sizeof(*pgps));
pgps->hdcDest = hdcDest;
if (!LoadOpenGL())
{
return FALSE;
}
pbmi = NULL;
// Set the reduction factor according to the dithering setting
// for the DC
switch(pdm->dmDitherType)
{
case DMDITHER_NONE:
case DMDITHER_LINEART:
pgps->iReduceFactor = 1;
break;
case DMDITHER_COARSE:
pgps->iReduceFactor = 2;
break;
default:
pgps->iReduceFactor = 4;
break;
}
// Put the destination DC into the mode we need for rendering
if (pgps->iReduceFactor > 1)
{
pgps->iStretchMode = SetStretchBltMode(hdcDest, HALFTONE);
if (pgps->iStretchMode == 0)
{
goto EH_Cleanup;
}
// Need to reset the brush origin after changing the stretch mode
if (!SetBrushOrgEx(hdcDest, 0, 0, &pgps->ptBrushOrg))
{
goto EH_Cleanup;
}
pgps->bBrushOrgSet = TRUE;
}
// Get the pixel format in the metafile if one exists
cbPixelFormat = GetEnhMetaFilePixelFormat(hemf, sizeof(pfd), &pfd);
if (cbPixelFormat == GDI_ERROR ||
(cbPixelFormat != 0 && cbPixelFormat != sizeof(pfd)))
{
goto EH_Cleanup;
}
// No pixel format in the header, so use a default
if (cbPixelFormat == 0)
{
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 16;
pfd.cRedBits = 5;
pfd.cRedShift = 0;
pfd.cGreenBits = 5;
pfd.cGreenShift = 5;
pfd.cBlueBits = 5;
pfd.cBlueShift = 10;
pfd.cAlphaBits = 0;
pfd.cAccumBits = 0;
pfd.cDepthBits = 16;
pfd.cStencilBits = 0;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
}
else
{
// Force draw-to-bitmap and single buffered
// Turn off flags not supported
pfd.dwFlags = (pfd.dwFlags &
~(PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER |
PFD_STEREO | PFD_SUPPORT_GDI)) |
PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
// What happens in color index mode?
if (pfd.iPixelType == PFD_TYPE_RGBA)
{
pfd.cColorBits = 16;
pfd.cRedBits = 5;
pfd.cRedShift = 0;
pfd.cGreenBits = 5;
pfd.cGreenShift = 5;
pfd.cBlueBits = 5;
pfd.cBlueShift = 10;
}
pfd.iLayerType = PFD_MAIN_PLANE;
}
// Determine the amount of memory used per pixel
// This rounds 4bpp to one byte per pixel but that's close
// enough
cbPixel =
(pfd.cColorBits+7)/8+
(pfd.cAlphaBits+7)/8+
(pfd.cAccumBits+7)/8+
(pfd.cDepthBits+7)/8+
(pfd.cStencilBits+7)/8;
// Determine the size of the band based on smaller of:
// The biggest DIB that can fit in cbBandMemoryLimit
// The size of the metafile
// The given rectangle is the size the metafile is supposed to
// be rendered into so base our computations on it
pgps->xSource = rc->left;
pgps->ySource = rc->top;
iWidth = rc->right-rc->left;
iHeight = rc->bottom-rc->top;
if (iWidth == 0 || iHeight == 0)
{
WARNING("InitGlPrinting: Metafile has no size\n");
return FALSE;
}
pgps->iSourceWidth = iWidth;
pgps->iSourceHeight = iHeight;
// Reduce the resolution somewhat to allow halftoning space to work
iWidth = iWidth/pgps->iReduceFactor;
iHeight = iHeight/pgps->iReduceFactor;
pgps->iReducedWidth = iWidth;
pgps->iReducedHeight = iHeight;
if (iWidth > GL_WIDTH_LIMIT)
{
iWidth = GL_WIDTH_LIMIT;
}
if (iHeight > GL_HEIGHT_LIMIT)
{
iHeight = GL_HEIGHT_LIMIT;
}
cbMeta = RECT_CB(iWidth, iHeight, cbPixel);
// Shrink the rectangle until it fits in our memory limit
if (cbMeta > cbBandMemoryLimit)
{
// How many scanlines will fit
iHeight = cbBandMemoryLimit/RECT_CB(iWidth, 1, cbPixel);
if (iHeight == 0)
{
// Can't fit a full scanline, so figure out how much
// of a scanline will fit
iWidth = cbBandMemoryLimit/cbPixel;
iHeight = 1;
}
}
if (iWidth < 1 || iHeight < 1)
{
WARNING("InitGlPrinting: "
"Not enough memory to render anything\n");
return FALSE;
}
// Create a DIB for the band
switch(pfd.cColorBits)
{
case 4:
nColors = 16;
break;
case 8:
nColors = 256;
break;
case 16:
case 32:
nColors = 3;
break;
case 24:
// Use one since it's already included in the BITMAPINFO definition
nColors = 1;
break;
}
pbmi = (BITMAPINFO *)LocalAlloc(LMEM_FIXED,
sizeof(BITMAPINFO)+(nColors-1)*
sizeof(RGBQUAD));
if (pbmi == NULL)
{
goto EH_Cleanup;
}
pbmih = &pbmi->bmiHeader;
pbmih->biSize = sizeof(BITMAPINFOHEADER);
pbmih->biWidth = iWidth;
pbmih->biHeight = iHeight;
pbmih->biPlanes = 1;
pbmih->biBitCount = pfd.cColorBits;
if (pfd.cColorBits == 16 || pfd.cColorBits == 32)
{
pbmih->biCompression = BI_BITFIELDS;
*((DWORD *)pbmi->bmiColors+0) =
((1 << pfd.cRedBits)-1) << pfd.cRedShift;
*((DWORD *)pbmi->bmiColors+1) =
((1 << pfd.cGreenBits)-1) << pfd.cGreenShift;
*((DWORD *)pbmi->bmiColors+2) =
((1 << pfd.cBlueBits)-1) << pfd.cBlueShift;
}
else if (pfd.cColorBits == 24)
{
pbmih->biCompression = BI_RGB;
}
else
{
UINT nEnt, i;
pbmih->biCompression = BI_RGB;
nEnt = GetEnhMetaFilePaletteEntries(hemf, nColors,
(PALETTEENTRY *)pbmi->bmiColors);
if (nEnt == GDI_ERROR)
{
goto EH_Cleanup;
}
// Force the flags byte to zero just to make sure
for (i = 0; i < nEnt; i++)
{
pbmi->bmiColors[i].rgbReserved = 0;
}
}
pbmih->biSizeImage= 0;
pbmih->biXPelsPerMeter = 0;
pbmih->biYPelsPerMeter = 0;
pbmih->biClrUsed = 0;
pbmih->biClrImportant = 0;
// It doesn't matter what this DC is compatible with because that
// will be overridden when we select the DIB into it
pgps->hdcDib = CreateCompatibleDC(NULL);
if (pgps->hdcDib == NULL)
{
WARNING("InitGlPrinting: CreateCompatibleDC failed\n");
goto EH_Cleanup;
}
pgps->hbmDib = CreateDIBSection(pgps->hdcDib, pbmi, DIB_RGB_COLORS,
&pvBits, NULL, 0);
if (pgps->hbmDib == NULL)
{
WARNING("InitGlPrinting: CreateDibSection failed\n");
goto EH_Cleanup;
}
if (SelectObject(pgps->hdcDib, pgps->hbmDib) == NULL)
{
WARNING("InitGlPrinting: SelectObject failed\n");
goto EH_Cleanup;
}
// Set the pixel format for the DC
iFmt = ChoosePixelFormat(pgps->hdcDib, &pfd);
if (iFmt == 0)
{
WARNING("InitGlPrinting: ChoosePixelFormat failed\n");
goto EH_Cleanup;
}
if (!SetPixelFormat(pgps->hdcDib, iFmt, &pfd))
{
WARNING("InitGlPrinting: SetPixelFormat failed\n");
goto EH_Cleanup;
}
pgps->hrc = gmcGlFuncs.wglCreateContext(pgps->hdcDib);
if (pgps->hrc == NULL)
{
WARNING("InitGlPrinting: wglCreateContext failed\n");
goto EH_Cleanup;
}
if (!gmcGlFuncs.wglMakeCurrent(pgps->hdcDib, pgps->hrc))
{
WARNING("InitGlPrinting: wglMakeCurrent failed\n");
goto EH_Cleanup;
}
pgps->iReducedBandWidth = iWidth;
pgps->iBandWidth = iWidth*pgps->iReduceFactor;
pgps->iReducedBandHeight = iHeight;
pgps->iBandHeight = iHeight*pgps->iReduceFactor;
return TRUE;
EH_Cleanup:
if (pbmi != NULL)
{
LocalFree(pbmi);
}
EndGlPrinting(pgps);
return FALSE;
}
/*****************************Private*Routine******************************\
*
* RenderGlBand
*
* Plays the metafile and stretches the resulting band into the
* appropriate location in the destination
*
* Uses PlayEnhMetaFile-style error reporting, where we remember errors
* but continue to complete processing. This avoids complete failure
* in cases where metafiles contain minor errors
*
* History:
* Wed Apr 12 18:22:08 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
static BOOL RenderGlBand(HENHMETAFILE hemf, GLPRINTSTATE *pgps, int x, int y)
{
RECT rcBand;
int iWidth, iHeight;
int iReducedWidth, iReducedHeight;
int ySrc;
BOOL fSuccess = TRUE;
// We want to render a band-size rectangle of the source metafile
// at (x,y), so we need to do a negative translation by (x,y)
// Size remains constant since we don't want any scaling
//
// The caller of this routine may have already shifted the
// viewport with SetViewport so we don't attempt to use it
// to do our translation
// WINBUG #82858 2-7-2000 bhouse Investigate propoer metafile handling
// Old Comment:
// - Proper handling of metafile left,top?
// x and y are guaranteed to be even multiples of pgps->iReduceFactor
rcBand.left = -x/pgps->iReduceFactor;
rcBand.right = rcBand.left+pgps->iReducedWidth;
rcBand.top = -y/pgps->iReduceFactor;
rcBand.bottom = rcBand.top+pgps->iReducedHeight;
if (!PlayEnhMetaFile(pgps->hdcDib, hemf, &rcBand))
{
WARNING("RenderBand: PlayEnhMetaFile failed\n");
fSuccess = FALSE;
}
// Copy the DIB bits to the destination
// Compute minimal width and height to avoid clipping problems
iWidth = pgps->iBandWidth;
iReducedWidth = pgps->iReducedBandWidth;
iHeight = pgps->iBandHeight;
iReducedHeight = pgps->iReducedBandHeight;
ySrc = 0;
// Check for X overflow
if (x+iWidth > pgps->iSourceWidth)
{
iWidth = pgps->iSourceWidth-x;
// If iWidth is not an even multiple of pgps->iReduceFactor then
// this can result in a different stretch factor
// I think this is more or less unavoidable
iReducedWidth = (iWidth+pgps->iReduceFactor-1)/pgps->iReduceFactor;
}
// Invert destination Y
y = pgps->iSourceHeight-pgps->iBandHeight-y;
// Check for Y underflow
if (y < 0)
{
iHeight += y;
iReducedHeight = (iHeight+pgps->iReduceFactor-1)/pgps->iReduceFactor;
// This can cause registration problems when y is not a
// multiple of pgps->iReduceFactor. Again, I'm not sure that
// anything can be done
ySrc -= (y+pgps->iReduceFactor-1)/pgps->iReduceFactor;
y = 0;
}
#if 0
DbgPrint("GL band (%d,%d - %d,%d)\n", x, y, iWidth, iHeight);
#endif
if (!StretchBlt(pgps->hdcDest,
x+pgps->xSource, y+pgps->ySource, iWidth, iHeight,
pgps->hdcDib,
0, ySrc, iReducedWidth, iReducedHeight,
SRCCOPY))
{
WARNING("RenderBand: StretchBlt failed\n");
fSuccess = FALSE;
}
return fSuccess;
}
/******************************Public*Routine******************************\
*
* PrintMfWithGl
*
* Prints a metafile that contains OpenGL records by rendering bands
* in a DIB and then stretching them to the printer DC
*
* Uses PlayEnhMetaFile-style error reporting, where we remember errors
* but continue to complete processing. This avoids complete failure
* in cases where metafiles contain minor errors
*
* History:
* Wed Apr 12 18:22:41 1995 -by- Drew Bliss [drewb]
* Created
*
\**************************************************************************/
BOOL PrintMfWithGl(HENHMETAFILE hemf, GLPRINTSTATE *pgps,
POINTL *pptlBand, SIZE *pszBand)
{
int iHorzBands, iVertBands;
int iH, iV;
int x, y;
BOOL fSuccess = TRUE;
int iStretchMode;
POINT ptBrushOrg;
ASSERTGDI(hOpenGL != NULL, "PrintMfWithGl: No opengl\n");
// To render banded to a destination we create a 24-bit DIB and
// play the metafile into that, then blt the DIB to
// the destination DC
//
// The DIB and Z buffer take a large amount of memory
// so the playback is banded into bands whose size is
// determined by the amount of memory we want to consume
iHorzBands = (pgps->iSourceWidth+pgps->iBandWidth-1)/pgps->iBandWidth;
iVertBands = (pgps->iSourceHeight+pgps->iBandHeight-1)/pgps->iBandHeight;
// Render high to low because the Y axis is positive up and
// we want to go down the page
y = (iVertBands-1)*pgps->iBandHeight;
for (iV = 0; iV < iVertBands; iV++)
{
x = 0;
for (iH = 0; iH < iHorzBands; iH++)
{
// If the current OpenGL band doesn't overlap any of the
// current printer band, there's no point in drawing anything
if (pptlBand != NULL &&
pszBand != NULL &&
(x+pgps->iBandWidth <= pptlBand->x ||
x >= pptlBand->x+pszBand->cx ||
y+pgps->iBandHeight <= pptlBand->y ||
y >= pptlBand->y+pszBand->cy))
{
// No band overlap
}
else if (!RenderGlBand(hemf, pgps, x, y))
{
fSuccess = FALSE;
}
x += pgps->iBandWidth;
}
y -= pgps->iBandHeight;
}
return fSuccess;
}
/******************************Public*Routine******************************\
*
* IsMetafileWithGl()
*
* IsMetafileWithGl will determines the matafile contains
* OpenGL records or not.
*
* History:
* Wed Jan 29 00:00:00 1997 -by- Hideyuki Nagase [hideyukn]
* Created.
*
\**************************************************************************/
BOOL IsMetafileWithGl(HENHMETAFILE hmeta)
{
ENHMETAHEADER emh;
UINT cbEmh;
cbEmh = GetEnhMetaFileHeader(hmeta, sizeof(emh), &emh);
if (cbEmh == 0)
{
WARNING("IsMetafileWithGl(): GetEnhMetaFileHeader failed\n");
return FALSE;
}
if (cbEmh >= META_HDR_SIZE_VERSION_2)
{
return emh.bOpenGL;
}
else
{
return FALSE;
}
}