|
|
/******************************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; } }
|