#include <OpenGl_tgl_funcs.hxx>
#include <OpenGl_tgl_subrvis.hxx>
#include <OpenGl_animation.hxx>
-
+#include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_PrinterContext.hxx>
+#include <Visual3d_Layer.hxx>
+#include <TColStd_Array2OfReal.hxx>
#include <string.h>
-/* SAV - begin */
-/* MSDN says: point is 1/72 inch. But in our case text height in the 3D view
-differs from printed one. An experiment showed that delimeter equal to 2*72 gives
-practically equal text heights. */
-int defaultDelimeter = 72;
-int delimeter = 144;
-int defaultPntSize = 12;
+#ifdef HAVE_FREEIMAGE
+ #include <NCollection_Handle.hxx>
+ #include <FreeImagePlus.h>
+ #ifdef _MSC_VER
+ #pragma comment( lib, "FreeImage.lib" )
+ #pragma comment( lib, "FreeImagePlus.lib" )
+ #endif
+ typedef NCollection_Handle<fipImage> FipHandle;
+#endif
-GLuint printerFontBase = 0;
+// ---------------------------------------------------------------
+// Function: getNearestPowOfTwo
+// Purpose: get the nearest power of two for theNumber
+// ---------------------------------------------------------------
+static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
+{
+ GLsizei aLast = 1;
+ for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
+ return aLast;
+}
-/* printer DC needed to avoid passing OS specific type as a procedure parameter */
-#ifdef WNT
-HDC printer;
-HGDIOBJ oldObj;
-#endif
+// ---------------------------------------------------------------
+// Function: getMaxFrameSize
+// Purpose: get the maximum possible frame size
+// ---------------------------------------------------------------
+static void getMaxFrameSize(Standard_Integer& theWidth,
+ Standard_Integer& theHeight)
+{
+ GLsizei aMaxX, aMaxY;
+ GLint aVpDim[2];
+ GLint aTexDim = 2048;
+ glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
+ glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
+ (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
+ aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
+ (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
+ aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
+
+ theWidth = (Standard_Integer)aMaxX;
+ theHeight = (Standard_Integer)aMaxY;
+}
-GLuint createFont( char* typeFace, int height, int weight, int italic )
+// ---------------------------------------------------------------
+// Function: fitDimensionsRatio
+// Purpose: calculate correct width/height ratio for theWidth and
+// theHeight parameters
+// ---------------------------------------------------------------
+static void fitDimensionsRatio (Standard_Integer& theWidth,
+ Standard_Integer& theHeight,
+ const Standard_Real theViewRatio)
{
-#ifdef WNT
- /* no unicode support yet*/
- HFONT font;
- GLuint base;
- DWORD charSet = ANSI_CHARSET;
-
- if ( ( base = glGenLists( 96 ) ) == 0 )
- return 0;
-
- if ( _stricmp( typeFace, "symbol" ) == 0 )
- charSet = SYMBOL_CHARSET;
-
- font = CreateFont( height, 0, 0, 0, weight, italic, FALSE, FALSE,
- charSet, OUT_TT_PRECIS,
- CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
- DEFAULT_PITCH, typeFace );
- oldObj = SelectObject( printer, font );
- wglUseFontBitmaps( printer, 32, 96, base );
- return base;
-#endif
- return 0;
+ // set dimensions in accordance with the viewratio
+ if (theHeight < theWidth/theViewRatio)
+ theWidth = (Standard_Integer)(theHeight*theViewRatio);
+
+ if (theWidth < theHeight*theViewRatio)
+ theHeight = (Standard_Integer)(theWidth/theViewRatio);
}
-void deleteFont( GLuint base )
+// ---------------------------------------------------------------
+// Function: getDimensionsTiling
+// Purpose: calculate maximum possible dimensions for framebuffer
+// in tiling mode according to the view size
+// ---------------------------------------------------------------
+static void getDimensionsTiling (Standard_Integer& theFrameWidth,
+ Standard_Integer& theFrameHeight,
+ const int theViewWidth,
+ const int theViewHeight)
{
-#ifdef WNT
- HFONT currentFont;
-
- if ( base == 0 )
- /* no font created */
- return;
- /* deleting font list id */
- glDeleteLists( base, 96 );
- currentFont = (HFONT)SelectObject( printer, oldObj );
- /* deleting current font structure */
- DeleteObject( currentFont );
-#endif
+ // fit the maximum dimensions into the printing area
+ if (theFrameWidth > theViewWidth)
+ theFrameWidth = theViewWidth;
+
+ if (theFrameHeight > theViewHeight)
+ theFrameHeight = theViewHeight;
+}
+
+// ---------------------------------------------------------------
+// Function: initBufferStretch
+// Purpose: calculate initialization sizes for frame buffer
+// when the stretch algorithm is selected
+// ---------------------------------------------------------------
+static void initBufferStretch (Standard_Integer& theFrameWidth,
+ Standard_Integer& theFrameHeight,
+ const int theViewWidth,
+ const int theViewHeight)
+{
+
+ // Calculate correct width/height for framebuffer
+ Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
+ fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
+
+ // downscale the framebuffer if it is too large
+ Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
+ Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
+
+ if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
+ (aWidthRate > 1 && aHeightRate <= 1))
+ {
+ theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
+ theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
+ }
+ else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
+ (aWidthRate <= 1 && aHeightRate > 1))
+ {
+ theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
+ theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
+ }
+
+}
+
+// ---------------------------------------------------------------
+// Function: initBufferTiling
+// Purpose: calculate initialization sizes for frame buffer
+// when the tile algorithm is selected
+// ---------------------------------------------------------------
+static void initBufferTiling (Standard_Integer& theFrameWidth,
+ Standard_Integer &theFrameHeight,
+ const int theViewWidth,
+ const int theViewHeight)
+{
+ // fit framebuffer into the printing area
+ if (theFrameWidth > theViewWidth)
+ theFrameWidth = theViewWidth;
+
+ if (theFrameHeight > theViewHeight)
+ theFrameHeight = theViewHeight;
}
-void updatePrinterFont( char* type, int height )
+// ---------------------------------------------------------------
+// Function: redrawView
+// Purpose: redraw view in printing mode
+// ---------------------------------------------------------------
+static void redrawView (CALL_DEF_VIEW *aview,
+ CALL_DEF_LAYER *anunderlayer,
+ CALL_DEF_LAYER *anoverlayer,
+ const int isBackground)
{
+ // prepare for redraw
+ call_func_redraw_all_structs_begin (aview->WsId);
+ call_togl_setplane (aview);
+
+ // clear background
+ if (isBackground == 0)
+ {
+ glClearColor (1.0, 1.0, 1.0, 1.0);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ // draw underlayer
+ if (anunderlayer->ptrLayer)
+ {
+ call_togl_redraw_layer2d (aview, anunderlayer);
+ }
+
+ // redraw main plane
+ call_func_redraw_all_structs_proc (aview->WsId);
+ call_subr_displayCB (aview,OCC_REDRAW_BITMAP | OCC_PRE_OVERLAY);
+ // draw overlayer
+ if (anoverlayer->ptrLayer)
+ {
+ call_togl_redraw_layer2d (aview, anoverlayer);
+ }
+ call_subr_displayCB (aview,OCC_REDRAW_BITMAP);
+
+
+ // tell to end redrawing
+ call_func_redraw_all_structs_end (aview->WsId, 0);
+ call_togl_redraw_immediat_mode (aview);
+}
+
+// ---------------------------------------------------------------
+// Function: initBitmapBuffer
+// Purpose: init device independent bitmap to hold printing data
+// ---------------------------------------------------------------
#ifdef WNT
- int delim = delimeter;
- if ( height <= 0 ) {
- height = defaultPntSize;
- delim = defaultDelimeter;
+#ifndef HAVE_FREEIMAGE
+static void initBitmapBuffer (const HDC theMemoryDC,
+ HBITMAP &theMemoryBmp,
+ const Standard_Integer theBmpWidth,
+ const Standard_Integer theBmpHeight,
+ VOID* &theBufferPtr)
+{
+ // define compatible bitmap
+ BITMAPINFO aBitmapData;
+ memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
+ aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+ aBitmapData.bmiHeader.biWidth = theBmpWidth;
+ aBitmapData.bmiHeader.biHeight = theBmpHeight;
+ aBitmapData.bmiHeader.biPlanes = 1;
+ aBitmapData.bmiHeader.biBitCount = 24;
+ aBitmapData.bmiHeader.biXPelsPerMeter = 0;
+ aBitmapData.bmiHeader.biYPelsPerMeter = 0;
+ aBitmapData.bmiHeader.biClrUsed = 0;
+ aBitmapData.bmiHeader.biClrImportant = 0;
+ aBitmapData.bmiHeader.biCompression = BI_RGB;
+ aBitmapData.bmiHeader.biSizeImage = 0;
+
+ // Create Device Independent Bitmap
+ theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
+ &theBufferPtr, NULL, 0);
+}
+#else
+// ---------------------------------------------------------------
+// Function: imagePasteDC
+// Purpose: copy the data from image buffer to the device context
+// ---------------------------------------------------------------
+static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
+ int theOffsetY, int theWidth, int theHeight,
+ int theLeft = 0, int theTop = 0)
+{
+ // get image parameters
+ BITMAPINFO* aBitmapData = theImage->getInfo ();
+ SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
+
+ // organize blocks data passing if memory isn't enough to pass all the data
+ // at once
+ int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
+ aPassed = 0, aInverseLine = 0, aScan = 0;
+ BYTE *aDataPtr = 0;
+ while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
+ {
+ // how much lines still to pass
+ aBlockWidth = theHeight - aLinesComplete;
+
+ // normalize count of lines to pass to maximum lines count at one pass.
+ if (aBlockWidth > aMaxBlockWidth)
+ aBlockWidth = aMaxBlockWidth;
+
+ // access image data at the start scan line, we need to calculate scan from
+ // the bottom of image (image is bottom-left, the src coord is top-left)
+ aInverseLine = theTop + aBlockWidth + aLinesComplete;
+ aScan = theImage->getHeight() - aInverseLine;
+ aDataPtr = theImage->getScanLine (aScan);
+ if (!aDataPtr)
+ return false;
+
+ // try to pass block to the device
+ if (aBlockWidth > 0)
+ {
+ // instead of banded output we provide blocked as it isn't always passed
+ // to printer as it is expected
+ aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
+ theOffsetY + aLinesComplete,
+ theWidth, aBlockWidth, theLeft, 0,
+ 0, aBlockWidth,
+ aDataPtr, aBitmapData, DIB_RGB_COLORS);
+
+ // if result is bad, try to decrease band width
+ if (aPassed != aBlockWidth)
+ {
+ aMaxBlockWidth = aMaxBlockWidth >> 1;
+ aLinesComplete = 0;
+ }
+ else
+ aLinesComplete += aBlockWidth;
+ }
}
- /* deleting old font */
- deleteFont( printerFontBase );
- /* creating new one */
- printerFontBase = createFont( type, -MulDiv( height, GetDeviceCaps( printer, LOGPIXELSY ), delim ),
- (int)FW_NORMAL, 0 );
-#endif
+
+ // check for total failure
+ if (aMaxBlockWidth < 1)
+ return false;
+
+ return true;
}
-/* SAV - end */
+// ---------------------------------------------------------------
+// Function: imageStretchDC
+// Purpose: copy pixels from image to dc by stretching them
+// ---------------------------------------------------------------
+static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
+ int theOffsetY, int theWidth, int theHeight)
+{
+ // access to raw image data
+ BYTE *aDataPtr = theImage->accessPixels ();
+ if (!aDataPtr)
+ return false;
+
+ // get image parameters
+ unsigned int widthPx = theImage->getWidth ();
+ unsigned int heightPx = theImage->getHeight ();
+ BITMAPINFO* aBitmapData = theImage->getInfo ();
+ SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
+
+ // pass lines and check if operation is succesfull
+ int aPassed = 0;
+ aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
+ theHeight, 0, 0, widthPx, heightPx, aDataPtr,
+ aBitmapData, DIB_RGB_COLORS, SRCCOPY);
+
+ if (aPassed != heightPx)
+ return false;
+
+ return true;
+}
+#endif
+#endif
-void EXPORT
+// ---------------------------------------------------------------
+// Function: call_togl_print
+// Purpose:
+// ---------------------------------------------------------------
+Standard_Boolean EXPORT
call_togl_print
(
CALL_DEF_VIEW *aview,
CALL_DEF_LAYER *anoverlayer,
const Aspect_Drawable hPrintDC,
const int background,
- const char* filename
+ const char* filename,
+ const int printalgo,
+ const float theScaleFactor
)
{
#ifdef WNT
- CMN_KEY_DATA data;
- Tint swap = 1; /* swap buffers ? yes */
+ CMN_KEY_DATA data;
+ DOCINFO di;
+ bool IsTiling = (printalgo == 1);
+ HDC hPrnDC = (HDC) hPrintDC;
+
+ TsmGetWSAttri (aview->WsId, WSWindow, &data);
+ if (TxglWinset (call_thedisplay, (WINDOW) data.ldata) != TSuccess)
+ {
+ MessageBox (NULL, "Print failed: can't setup the view for printing.",
+ "The operation couldn't be completed.", MB_OK);
+ return Standard_False;
+ }
+ // printer page dimensions
+ int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
+ int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
- BOOL bRet = FALSE;
- HDC hPrnDC;
- DOCINFO di;
+ // if context is actually a memory dc, try to retrieve bitmap dimensions
+ // (memory dc could be used for testing purposes)
+ if (GetObjectType (hPrnDC) == OBJ_MEMDC)
+ {
+ // memory dc dimensions
+ BITMAP aBitmapInfo;
+ HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
+ if (aMemoryBitmap)
+ if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
+ {
+ devWidth = aBitmapInfo.bmWidth;
+ devHeight = aBitmapInfo.bmHeight;
+ }
+ }
- hPrnDC = (HDC) hPrintDC;
- printer = hPrnDC;
+ Standard_Integer tempWidth = (Standard_Integer) devWidth;
+ Standard_Integer tempHeight = (Standard_Integer) devHeight;
- /* Begin main routine **************************************************************/
- TsmGetWSAttri (aview->WsId, WSWindow, &data);
- if (TxglWinset (call_thedisplay, (WINDOW) data.ldata) == TSuccess)
+ // view dimensions
+ RECT rect;
+ GetClientRect((WINDOW) data.ldata, &rect);
+ int viewWidth = rect.right-rect.left;
+ int viewHeight = rect.bottom-rect.top;
+ if (viewWidth == 0 || viewHeight == 0)
{
- static PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, // version number
- PFD_SUPPORT_OPENGL|
- PFD_DRAW_TO_BITMAP,
- PFD_TYPE_RGBA,
- 0, 0, 0, 0, 0, 0, // color bits ignored
- 0, // no alpha buffer
- 0, // shift bit ignored
- 0, // no accumulation buffer
- 0, 0, 0, 0, // accum bits ignored
- 32, // 32-bit z-buffer
- 0, // no stencil buffer
- 0, // no auxiliary buffer
- PFD_MAIN_PLANE, // main layer
- 0, // reserved
- 0, 0, 0 // layer masks ignored
- };
- HWND w;
- HDC hDC;
- HDC hMemDC;
- HGLRC hGLRC;
- RECT rect;
-
- BITMAPINFO* pBMI;
- BITMAPINFOHEADER* bmHeader;
-
- BYTE biInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
- HGDIOBJ hBmOld;
- HBITMAP hBm;
- VOID* base;
-
- int nIndex;
- int bmiSize;
-
- float viewRatio;
- int devWidth;
- int devHeight;
- int viewWidth;
- int viewHeight;
- int width;
- int height;
- float tempWidth;
- float tempHeight;
- int offsetx = 0;
- int offsety = 0;
-
-#ifdef mydebug
- devWidth = 640;
- tempWidth = (float) devWidth;
- devHeight = 480;
- tempHeight = (float) devHeight;
+ MessageBox (NULL, "Print failed: can't setup the view for printing.",
+ "The operation couldn't be completed.", MB_OK);
+ return Standard_False;
+ }
+
+ // calculate correct width/height ratio
+ Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
+ fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
+
+ // width and height for printing area
+ int width = (int) (tempWidth * theScaleFactor);
+ int height = (int) (tempHeight * theScaleFactor);
+
+ // device independent bitmap for the whole view
+#ifdef HAVE_FREEIMAGE
+ FipHandle aViewImage = NULL;
+ BYTE* aViewBuffer = NULL;
#else
- devWidth = GetDeviceCaps(hPrnDC, HORZRES);
- tempWidth = (float) devWidth;
- devHeight = GetDeviceCaps(hPrnDC, VERTRES);
- tempHeight = (float) devHeight;
-#endif
- GetClientRect((WINDOW) data.ldata, &rect);
- viewWidth = rect.right-rect.left;
- viewHeight = rect.bottom-rect.top;
-
- viewRatio = (float) viewWidth/(float) viewHeight;
-
- // Calculate correct width/height ratio
- if (tempHeight < tempWidth/viewRatio)
- tempWidth = tempHeight*viewRatio;
- if (tempWidth < tempHeight*viewRatio)
- tempHeight = tempWidth/viewRatio;
-
- width = (int) tempWidth;
- height = (int) tempHeight;
-
- // Create virtual window
- w = CreateWindow(
- "Button",
- "",
- WS_OVERLAPPEDWINDOW |
- WS_CLIPCHILDREN |
- WS_CLIPSIBLINGS,
- 0, 0,
- width, height,
- NULL,
- NULL,
- NULL,
- NULL);
-#ifdef mydebug
- ShowWindow(w, SW_SHOW);
+ HDC hMemDC = CreateCompatibleDC (hPrnDC);
+ HBITMAP hViewBitmap = NULL;
+ HGDIOBJ hViewBitmapOld = NULL;
+ VOID* aViewBuffer = NULL;
#endif
- hDC = GetDC(w);
- if (!hDC)
- {
- MessageBox(0,"hDC == NULL", "Fehler", MB_OK);
- return;
- }
+ // Frame buffer initialization
+ OpenGl_FrameBuffer* aFrameBuffer = NULL;
+ OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) aview->ptrFBO;
+ Standard_Integer aFrameWidth (0), aFrameHeight (0),
+ aPrevBufferX (0), aPrevBufferY (0);
- // Initialize Bitmap Information
-
- pBMI = (BITMAPINFO *) biInfo;
- ZeroMemory(pBMI, sizeof(*pBMI));
- bmiSize = sizeof(*pBMI);
-
- pBMI = (BITMAPINFO *) calloc(1, bmiSize);
- bmHeader = &pBMI->bmiHeader;
-
- bmHeader->biSize = sizeof(*bmHeader);
- bmHeader->biWidth = width;
- bmHeader->biHeight = height;
- bmHeader->biPlanes = 1; /* must be 1 */
- bmHeader->biBitCount = 24;
- bmHeader->biXPelsPerMeter = 0;
- bmHeader->biYPelsPerMeter = 0;
- bmHeader->biClrUsed = 0; /* all are used */
- bmHeader->biClrImportant = 0; /* all are important */
- bmHeader->biCompression = BI_RGB;
- bmHeader->biSizeImage = 0;
-
- // Create Device Independent Bitmap
- hMemDC = CreateCompatibleDC(hPrnDC);
- hBm = CreateDIBSection(hMemDC, pBMI, DIB_RGB_COLORS, &base, NULL, 0);
- hBmOld = SelectObject(hMemDC, hBm);
-
- // Release Memory
- free(pBMI);
- // free(bmHeader);
-
- // further initialization
-#ifdef mydebug
- pfd.cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
- nIndex = ChoosePixelFormat(hDC, &pfd);
- if (nIndex == 0)
+ // try to use existing frame buffer
+ if (aPrevBuffer)
+ {
+ GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
+ GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
+ bool isUsable = false;
+
+ // check if its possible to use previous frame buffer
+ if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
{
- MessageBox(0,"ChoosePixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
+ aFrameWidth = (Standard_Integer) width;
+ aFrameHeight = (Standard_Integer) height;
+ isUsable = true;
}
-
-
- if (!SetPixelFormat(hDC, nIndex, &pfd))
+ else if (IsTiling)
{
- MessageBox(0,"SetPixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
+ getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
+ if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
+ isUsable = true;
}
- // Create Rendering Context
- hGLRC = wglCreateContext(hDC);
-
- if (hGLRC == NULL)
+ // if it is enough memory for image paste dc operation
+ if (isUsable)
{
- MessageBox(0,"No Rendering Context", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
- }
- wglMakeCurrent(hDC,hGLRC);
+#ifdef HAVE_FREEIMAGE
+ // try to allocate fipImage and necessary resources
+ fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
+ aFrameHeight, 24);
+
+ // if allocated succesfully
+ if (anImagePtr->isValid())
+ {
+ aViewImage = anImagePtr;
+ aViewBuffer = aViewImage->accessPixels ();
+ }
+ else
+ delete anImagePtr;
+
+ if (!aViewBuffer)
+ {
+ isUsable = false;
+ aViewBuffer = NULL;
+ aViewImage = NULL;
+ }
#else
- pfd.cColorBits = GetDeviceCaps(hMemDC, BITSPIXEL);
- nIndex = ChoosePixelFormat(hMemDC, &pfd);
- if (nIndex == 0)
- {
- MessageBox(0,"ChoosePixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
+ // try to allocate compatible bitmap and necessary resources
+ initBitmapBuffer (hMemDC, hViewBitmap,
+ aFrameWidth, aFrameHeight, aViewBuffer);
+ if (!aViewBuffer)
+ {
+ isUsable = false;
+ if (hViewBitmap)
+ DeleteObject (hViewBitmap);
+ hViewBitmap = NULL;
+ }
+ else
+ hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
+#endif
}
-
- if (!SetPixelFormat(hMemDC, nIndex, &pfd))
+ // use previous frame buffer
+ if (isUsable)
{
- MessageBox(0,"SetPixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
+ aPrevBufferX = aPrevWidth;
+ aPrevBufferY = aPrevHeight;
+ aFrameBuffer = aPrevBuffer;
+ aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
}
+ }
- // Create Rendering Context
- hGLRC = wglCreateContext(hMemDC);
+ // if previous buffer cannot be used, try to init a new one
+ if (!aFrameBuffer)
+ {
+ aFrameBuffer = new OpenGl_FrameBuffer();
- if (hGLRC == NULL)
+ // try to create the framebuffer with the best possible size
+ Standard_Integer aMaxWidth(0), aMaxHeight(0);
+ getMaxFrameSize (aMaxWidth, aMaxHeight);
+ while (aMaxWidth > 1 && aMaxHeight > 1)
{
- MessageBox(0,"No Rendering Context", "Error", MB_OK | MB_ICONSTOP);
- goto Error;
- }
- wglMakeCurrent(hMemDC,hGLRC);
+ aFrameWidth = aMaxWidth;
+ aFrameHeight = aMaxHeight;
+
+ // calculate dimensions for different printing algorithms
+ if (!IsTiling)
+ initBufferStretch (aFrameWidth, aFrameHeight, width, height);
+ else
+ initBufferTiling (aFrameWidth, aFrameHeight, width, height);
+
+ // try to initialize framebuffer
+ if (aFrameBuffer->Init (aFrameWidth, aFrameHeight))
+ {
+#ifdef HAVE_FREEIMAGE
+ // try to allocate fipImage and necessary resources
+ fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
+ aFrameHeight, 24);
+
+ // if allocated succesfully
+ if (anImagePtr->isValid())
+ {
+ aViewImage = anImagePtr;
+ aViewBuffer = aViewImage->accessPixels ();
+ }
+ else
+ delete anImagePtr;
+
+ if (!aViewBuffer)
+ {
+ aFrameBuffer->Release ();
+ aViewBuffer = NULL;
+ aViewImage = NULL;
+ }
+ else
+ break;
+#else
+ // try to allocate compatible bitmap and necessary resources
+ initBitmapBuffer (hMemDC, hViewBitmap,
+ aFrameWidth, aFrameHeight, aViewBuffer);
+ if (!aViewBuffer)
+ {
+ if (hViewBitmap)
+ DeleteObject (hViewBitmap);
+ aFrameBuffer->Release ();
+ hViewBitmap = NULL;
+ }
+ else
+ {
+ hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
+ break;
+ }
#endif
+ }
- /* creating default font */
- printerFontBase =
- createFont( "", -MulDiv( defaultPntSize, GetDeviceCaps( hPrnDC, LOGPIXELSY ), defaultDelimeter ),
- (int)FW_NORMAL, 0 );
-
- // redraw to new Rendering Context
- call_func_redraw_all_structs_begin (aview->WsId);
-
- call_togl_setplane( aview ); /* update clipping planes */
-
- if (background == 0)
- {
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ // not initialized, decrease dimensions
+ aMaxWidth = aMaxWidth >> 1;
+ aMaxHeight = aMaxHeight >> 1;
}
- if (anunderlayer->ptrLayer)
- call_togl_redraw_layer2d (aview, anunderlayer);
- call_func_redraw_all_structs_proc (aview->WsId);
-
- if (anoverlayer->ptrLayer)
- call_togl_redraw_layer2d (aview, anoverlayer);
-#ifdef RIC120302
- call_subr_displayCB(aview,OCC_REDRAW_BITMAP);
+ // check if there are proper dimensions
+ if (aMaxWidth <= 1 || aMaxHeight <= 1)
+ {
+ MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
+ "The operation couldn't be completed.", MB_OK);
+
+ if (aFrameBuffer)
+ delete aFrameBuffer;
+#ifndef HAVE_FREEIMAGE
+ if (hMemDC)
+ DeleteDC (hMemDC);
#endif
- call_func_redraw_all_structs_end (aview->WsId, swap);
+ return Standard_False;
+ }
+ }
- call_togl_redraw_immediat_mode (aview);
-#ifndef mydebug
- /* Start printing of DIB ********************************************************/
+ // setup printing context and viewport
+ GLint aViewPortBack[4];
+ GLint aReadBufferPrev = GL_BACK;
+ GLint anAlignBack = 1;
+ OpenGl_PrinterContext aPrinterContext (GET_GL_CONTEXT());
+ aPrinterContext.SetLayerViewport ((GLsizei)aFrameWidth,
+ (GLsizei)aFrameHeight);
+ glGetIntegerv (GL_VIEWPORT, aViewPortBack);
+ glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
+ glPixelStorei (GL_PACK_ALIGNMENT, 4);
+
+ // start document if the printer context is not actually a memory dc
+ // (memory dc could be used for testing purposes)
+ if (GetObjectType (hPrnDC) == OBJ_DC)
+ {
+ // Initalize printing procedure
di.cbSize = sizeof(DOCINFO);
- di.lpszDocName = "Text";
+ di.lpszDocName = "Open Cascade Document - print v3d view";
di.lpszOutput = filename;
- if (StartDoc(hPrnDC, &di) == SP_ERROR) goto Error;
- if (StartPage(hPrnDC) <= 0) goto Error;
+ // if can't print the document
+ if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
+ {
+ MessageBox (NULL, "Print failed: printer can't start operation.",
+ "The operation couldn't be completed.", MB_OK);
+#ifndef HAVE_FREEIMAGE
+ if (hViewBitmap)
+ {
+ SelectObject (hMemDC, hViewBitmapOld);
+ DeleteObject (hViewBitmap);
+ }
+ DeleteDC (hMemDC);
+#endif
- // calculate offset for centered printing
- if (width < devWidth)
- offsetx = (devWidth - width)/2;
- if (height < devHeight)
- offsety = (devHeight - height)/2;
+ return Standard_False;
+ }
+ }
- BitBlt(hPrnDC, offsetx, offsety, width, height, hMemDC, 0, 0, SRCCOPY);
+ // activate the offscreen buffer
+ aFrameBuffer->BindBuffer ();
- EndPage(hPrnDC);
- EndDoc(hPrnDC);
- /* releasing created font */
- deleteFont( printerFontBase );
- printerFontBase = 0;
+ // calculate offset for centered printing
+ int aDevOffx = (int)(devWidth - width) /2;
+ int aDevOffy = (int)(devHeight - height)/2;
- /* End of printing section ******************************************************/
+ // operation complete flag
+ bool isDone = true;
+
+ if (!IsTiling)
+ {
+ aPrinterContext.SetScale ((GLfloat)aFrameWidth /viewWidth,
+ (GLfloat)aFrameHeight/viewHeight);
+ aFrameBuffer->SetupViewport ();
+ redrawView (aview, anunderlayer, anoverlayer, background);
+ glReadPixels (0, 0, aFrameWidth, aFrameHeight,
+ GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
+
+ // copy result to the printer device and check for errors
+#ifdef HAVE_FREEIMAGE
+ if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
+ !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
+ isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
+ width, height);
#else
- Sleep(5000);
-#endif
-
-Error:
- /* Clean memory *****************************************************************/
- if(hBm != NULL)
+ if (width > aFrameWidth && height > aFrameHeight)
{
- SelectObject(hMemDC, hBmOld);
- DeleteObject(hBm);
- DeleteObject(hBmOld);
+ SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
+ isDone = StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
+ hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY);
}
- wglMakeCurrent(NULL, NULL);
- if (hGLRC != NULL)
+ else
{
- wglDeleteContext(hGLRC);
+ isDone = BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
+ hMemDC, 0, 0, SRCCOPY);
}
- if (hMemDC != NULL)
+#endif
+ }
+ else
+ {
+ // calculate total count of frames and cropping size
+ Standard_Integer aPxCropx = 0;
+ Standard_Integer aPxCropy = 0;
+ Standard_Integer aTotalx =
+ (Standard_Integer)floor ((float)width /aFrameWidth);
+ Standard_Integer aTotaly =
+ (Standard_Integer)floor ((float)height/aFrameHeight);
+ if (width %aFrameWidth != 0)
{
- DeleteDC(hMemDC);
+ aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
+ aTotalx++;
}
-
- if (hDC != NULL)
+ if (height%aFrameHeight != 0)
{
- ReleaseDC(w, hDC);
+ aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
+ aTotaly++;
}
- if (w != NULL)
+
+ int anOddPixelx = (width %aFrameWidth) %2;
+ int anOddPixely = (height%aFrameHeight)%2;
+
+ // calculate scale factor for full frames
+ Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
+ Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
+
+ // calculate and set the text scaling factor for printing context
+ GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
+ GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
+ aPrinterContext.SetScale (aScaleRatex*(GLfloat)aScalex,
+ aScaleRatey*(GLfloat)aScaley);
+
+ // initialize projection matrix for printer context
+ TColStd_Array2OfReal aProj (0, 3, 0, 3);
+ Standard_Real aDef = 0;
+ aProj.Init (aDef);
+ aProj(2,2) = 1.0;
+ aProj(3,3) = 1.0;
+
+ // projection matrix offsets for printer context
+ // offsets are even numbers
+ Standard_Real aOffsetx(0), aOffsety(0);
+ aOffsetx = -(aTotalx-1);
+ aOffsety = -(aTotaly-1);
+
+ // rect of frame image that will be copied
+ // and coordinates in view image where to put it
+ Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
+ Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
+ Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
+
+ // draw sequence of full frames
+ for (int i = 0; i < aTotalx; i++)
{
- DestroyWindow(w);
+ // offsets are even numbers
+ aOffsety = -(aTotaly-1);
+ aSubTop = (Standard_Integer)aDevOffy;
+
+ // calculate cropped frame rect
+ aLeft = (i == 0) ? aPxCropx : 0;
+ aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
+ aFrameWidth;
+
+ for (int j = 0; j < aTotaly; j++)
+ {
+ // no offset for single frames
+ aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
+ aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
+
+ // set projection matrix
+ aProj(0,0) = aScalex;
+ aProj(1,1) = aScaley;
+ aPrinterContext.SetProjTransformation (aProj);
+
+ // calculate cropped frame rect
+ aTop = (j == 0) ? aPxCropy : 0;
+ aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
+ aFrameHeight;
+
+ // draw to the offscreen buffer and capture the result
+ aFrameBuffer->SetupViewport ();
+ redrawView (aview, anunderlayer, anoverlayer, background);
+ glReadPixels (0, 0, aFrameWidth, aFrameHeight,
+ GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
+#ifdef HAVE_FREEIMAGE
+ // cut out pixels that are out of printing area
+ isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
+ aRight-aLeft, aBottom-aTop, aLeft, aTop);
+#else
+ isDone = BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
+ hMemDC, aLeft, aTop, SRCCOPY);
+#endif
+
+ // stop operation if errors
+ if (!isDone)
+ break;
+
+ // calculate new view offset for y-coordinate
+ aOffsety += 2.0;
+ aSubTop += aBottom-aTop;
+ }
+
+ // stop operation if errors
+ if (!isDone)
+ break;
+
+ // calculate new view offset for x-coordinate
+ aOffsetx += 2.0;
+ aSubLeft += aRight-aLeft;
}
+ }
- /* End of clean memory *****************************************************************/
+ // complete printing or indicate an error
+ if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
+ {
+ EndPage (hPrnDC);
+ EndDoc (hPrnDC);
}
+ else if (isDone == false)
+ {
+ MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
+ "The opeartion couldn't be completed.", MB_OK);
+ if (GetObjectType (hPrnDC) == OBJ_DC)
+ AbortDoc (hPrnDC);
+ }
+
+ // return OpenGl to the previous state
+ aPrinterContext.Deactivate ();
+ glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
+ aFrameBuffer->UnbindBuffer();
+ glViewport (aViewPortBack[0], aViewPortBack[1],
+ aViewPortBack[2], aViewPortBack[3]);
+ if (aPrevBuffer)
+ aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
+ else
+ delete aFrameBuffer;
+
+ // delete resources
+#ifndef HAVE_FREEIMAGE
+ if (hViewBitmap)
+ {
+ SelectObject (hMemDC, hViewBitmapOld);
+ DeleteObject (hViewBitmap);
+ }
+ DeleteDC (hMemDC);
+#endif
+
+ return (Standard_Boolean) isDone;
- /* End main routine ********************************************************************/
- return;
-#endif /*WNT*/
+#else // not WNT
+ return Standard_False;
+#endif
}
+