1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_GlCore11.hxx>
18 #include <OpenGl_FrameBuffer.hxx>
19 #include <TColStd_Array2OfReal.hxx>
20 #include <OpenGl_telem_util.hxx>
21 #include <Graphic3d_GraphicDriver.hxx>
23 #include <OpenGl_PrinterContext.hxx>
24 #include <OpenGl_Workspace.hxx>
25 #include <OpenGl_View.hxx>
27 #include <Standard_NotImplemented.hxx>
29 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_FREEIMAGE)
30 #include <NCollection_Handle.hxx>
31 #include <FreeImagePlus.h>
33 #pragma comment( lib, "FreeImage.lib" )
34 #pragma comment( lib, "FreeImagePlus.lib" )
36 typedef NCollection_Handle<fipImage> FipHandle;
41 #ifndef HAVE_FREEIMAGE
43 // =======================================================================
44 // function : initBitmapBuffer
45 // purpose : init device independent bitmap to hold printing data
46 // =======================================================================
47 static void initBitmapBuffer (const HDC theMemoryDC,
48 HBITMAP &theMemoryBmp,
49 const Standard_Integer theBmpWidth,
50 const Standard_Integer theBmpHeight,
53 // define compatible bitmap
54 BITMAPINFO aBitmapData;
55 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
56 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
57 aBitmapData.bmiHeader.biWidth = theBmpWidth;
58 aBitmapData.bmiHeader.biHeight = theBmpHeight;
59 aBitmapData.bmiHeader.biPlanes = 1;
60 aBitmapData.bmiHeader.biBitCount = 24;
61 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
62 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
63 aBitmapData.bmiHeader.biClrUsed = 0;
64 aBitmapData.bmiHeader.biClrImportant = 0;
65 aBitmapData.bmiHeader.biCompression = BI_RGB;
66 aBitmapData.bmiHeader.biSizeImage = 0;
68 // Create Device Independent Bitmap
69 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
70 &theBufferPtr, NULL, 0);
73 #else /* HAVE_FREEIMAGE */
75 // =======================================================================
76 // function : imagePasteDC
77 // purpose : copy the data from image buffer to the device context
78 // =======================================================================
79 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
80 int theOffsetY, int theWidth, int theHeight,
81 int theLeft = 0, int theTop = 0)
83 // get image parameters
84 BITMAPINFO* aBitmapData = theImage->getInfo ();
85 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
87 // organize blocks data passing if memory isn't enough to pass all the data
89 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
90 aPassed = 0, aInverseLine = 0, aScan = 0;
92 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
94 // how much lines still to pass
95 aBlockWidth = theHeight - aLinesComplete;
97 // normalize count of lines to pass to maximum lines count at one pass.
98 if (aBlockWidth > aMaxBlockWidth)
99 aBlockWidth = aMaxBlockWidth;
101 // access image data at the start scan line, we need to calculate scan from
102 // the bottom of image (image is bottom-left, the src coord is top-left)
103 aInverseLine = theTop + aBlockWidth + aLinesComplete;
104 aScan = theImage->getHeight() - aInverseLine;
105 aDataPtr = theImage->getScanLine (aScan);
109 // try to pass block to the device
112 // instead of banded output we provide blocked as it isn't always passed
113 // to printer as it is expected
114 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
115 theOffsetY + aLinesComplete,
116 theWidth, aBlockWidth, theLeft, 0,
118 aDataPtr, aBitmapData, DIB_RGB_COLORS);
120 // if result is bad, try to decrease band width
121 if (aPassed != aBlockWidth)
123 aMaxBlockWidth = aMaxBlockWidth >> 1;
127 aLinesComplete += aBlockWidth;
131 // check for total failure
132 if (aMaxBlockWidth < 1)
138 // =======================================================================
139 // function : imageStretchDC
140 // purpose : copy pixels from image to dc by stretching them
141 // =======================================================================
142 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
143 int theOffsetY, int theWidth, int theHeight)
145 // access to raw image data
146 BYTE *aDataPtr = theImage->accessPixels ();
150 // get image parameters
151 unsigned int widthPx = theImage->getWidth ();
152 unsigned int heightPx = theImage->getHeight ();
153 BITMAPINFO* aBitmapData = theImage->getInfo ();
154 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
156 // pass lines and check if operation is succesfull
158 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
159 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
160 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
162 if ((unsigned)aPassed != heightPx)
168 #endif /* HAVE_FREEIMAGE */
170 // =======================================================================
171 // function : getNearestPowOfTwo
172 // purpose : get the nearest power of two for theNumber
173 // =======================================================================
174 static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
177 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
181 // =======================================================================
182 // function : getMaxFrameSize
183 // purpose : get the maximum possible frame size
184 // =======================================================================
185 static void getMaxFrameSize(Standard_Integer& theWidth,
186 Standard_Integer& theHeight)
188 GLsizei aMaxX, aMaxY;
190 GLint aTexDim = 2048;
191 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
192 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
193 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
194 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
195 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
196 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
198 theWidth = (Standard_Integer)aMaxX;
199 theHeight = (Standard_Integer)aMaxY;
202 // =======================================================================
203 // function : fitDimensionsRatio
204 // purpose : calculate correct width/height ratio for theWidth and
205 // theHeight parameters
206 // =======================================================================
207 static void fitDimensionsRatio (Standard_Integer& theWidth,
208 Standard_Integer& theHeight,
209 const Standard_Real theViewRatio)
211 // set dimensions in accordance with the viewratio
212 if (theHeight < theWidth/theViewRatio)
213 theWidth = (Standard_Integer)(theHeight*theViewRatio);
215 if (theWidth < theHeight*theViewRatio)
216 theHeight = (Standard_Integer)(theWidth/theViewRatio);
219 // =======================================================================
220 // function : initBufferStretch
221 // purpose : calculate initialization sizes for frame buffer
222 // when the stretch algorithm is selected
223 // =======================================================================
224 static void initBufferStretch (Standard_Integer& theFrameWidth,
225 Standard_Integer& theFrameHeight,
226 const int theViewWidth,
227 const int theViewHeight)
230 // Calculate correct width/height for framebuffer
231 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
232 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
234 // downscale the framebuffer if it is too large
235 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
236 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
238 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
239 (aWidthRate > 1 && aHeightRate <= 1))
241 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
242 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
244 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
245 (aWidthRate <= 1 && aHeightRate > 1))
247 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
248 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
252 // =======================================================================
253 // function : initBufferTiling
254 // purpose : calculate initialization sizes for frame buffer
255 // when the tile algorithm is selected
256 // =======================================================================
257 static void initBufferTiling (Standard_Integer& theFrameWidth,
258 Standard_Integer &theFrameHeight,
259 const int theViewWidth,
260 const int theViewHeight)
262 // fit framebuffer into the printing area
263 if (theFrameWidth > theViewWidth)
264 theFrameWidth = theViewWidth;
266 if (theFrameHeight > theViewHeight)
267 theFrameHeight = theViewHeight;
272 // =======================================================================
275 // =======================================================================
276 Standard_Boolean OpenGl_View::Print (const Aspect_Handle thePrinterDC,
277 const Standard_Boolean theToShowBackground,
278 const Standard_CString theFileName,
279 const Aspect_PrintAlgo thePrintAlgorithm,
280 const Standard_Real theScaleFactor)
283 if (!myWorkspace->Activate())
285 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
286 // "The operation couldn't be completed.", MB_OK);
287 return Standard_False;
290 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
292 // printer page dimensions
293 HDC hPrnDC = (HDC) thePrinterDC;
294 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
295 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
297 // if context is actually a memory dc, try to retrieve bitmap dimensions
298 // (memory dc could be used for testing purposes)
299 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
301 // memory dc dimensions
303 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
305 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
307 devWidth = aBitmapInfo.bmWidth;
308 devHeight = aBitmapInfo.bmHeight;
312 Standard_Integer tempWidth = (Standard_Integer) devWidth;
313 Standard_Integer tempHeight = (Standard_Integer) devHeight;
316 int viewWidth = myWindow->Width();
317 int viewHeight = myWindow->Height();
318 if (viewWidth == 0 || viewHeight == 0)
320 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
321 // "The operation couldn't be completed.", MB_OK);
322 return Standard_False;
325 // calculate correct width/height ratio
326 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
327 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
329 // width and height for printing area
330 int width = (int) (tempWidth * theScaleFactor);
331 int height = (int) (tempHeight * theScaleFactor);
333 // device independent bitmap for the whole view
334 #ifdef HAVE_FREEIMAGE
335 FipHandle aViewImage = NULL;
336 BYTE* aViewBuffer = NULL;
338 HDC hMemDC = CreateCompatibleDC (hPrnDC);
339 HBITMAP hViewBitmap = NULL;
340 HGDIOBJ hViewBitmapOld = NULL;
341 VOID* aViewBuffer = NULL;
344 // Frame buffer initialization
345 OpenGl_FrameBuffer* aFrameBuffer = NULL;
346 OpenGl_FrameBuffer* aPrevBuffer = myFBO.operator->();
347 Standard_Integer aFrameWidth (0), aFrameHeight (0),
348 aPrevBufferX (0), aPrevBufferY (0);
350 bool IsTiling = (thePrintAlgorithm == Aspect_PA_TILE);
352 // try to use existing frame buffer
355 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
356 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
357 bool isUsable = false;
359 // check if its possible to use previous frame buffer
360 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
362 aFrameWidth = (Standard_Integer) width;
363 aFrameHeight = (Standard_Integer) height;
368 // use previous frame buffer with its dimensions
369 aFrameWidth = aPrevWidth;
370 aFrameHeight = aPrevHeight;
374 // if it is enough memory for image paste dc operation
377 #ifdef HAVE_FREEIMAGE
378 // try to allocate fipImage and necessary resources
379 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
382 // if allocated successfully
383 if (anImagePtr->isValid())
385 aViewImage = anImagePtr;
386 aViewBuffer = aViewImage->accessPixels ();
398 // try to allocate compatible bitmap and necessary resources
399 initBitmapBuffer (hMemDC, hViewBitmap,
400 aFrameWidth, aFrameHeight, aViewBuffer);
405 DeleteObject (hViewBitmap);
409 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
413 // use previous frame buffer
416 aPrevBufferX = aPrevWidth;
417 aPrevBufferY = aPrevHeight;
418 aFrameBuffer = aPrevBuffer;
419 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
423 // if previous buffer cannot be used, try to init a new one
426 aFrameBuffer = new OpenGl_FrameBuffer();
428 // try to create the framebuffer with the best possible size
429 Standard_Integer aMaxWidth(0), aMaxHeight(0);
430 getMaxFrameSize (aMaxWidth, aMaxHeight);
431 while (aMaxWidth > 1 && aMaxHeight > 1)
433 aFrameWidth = aMaxWidth;
434 aFrameHeight = aMaxHeight;
436 // calculate dimensions for different printing algorithms
438 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
440 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
442 // try to initialize framebuffer
443 if (aFrameBuffer->Init (aCtx, aFrameWidth, aFrameHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
445 #ifdef HAVE_FREEIMAGE
446 // try to allocate fipImage and necessary resources
447 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
450 // if allocated successfully
451 if (anImagePtr->isValid())
453 aViewImage = anImagePtr;
454 aViewBuffer = aViewImage->accessPixels ();
461 aFrameBuffer->Release (aCtx.operator->());
468 // try to allocate compatible bitmap and necessary resources
469 initBitmapBuffer (hMemDC, hViewBitmap,
470 aFrameWidth, aFrameHeight, aViewBuffer);
474 DeleteObject (hViewBitmap);
475 aFrameBuffer->Release (aCtx.operator->());
480 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
486 // not initialized, decrease dimensions
487 aMaxWidth = aMaxWidth >> 1;
488 aMaxHeight = aMaxHeight >> 1;
491 // check if there are proper dimensions
492 if (aMaxWidth <= 1 || aMaxHeight <= 1)
494 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
495 "The operation couldn't be completed.", MB_OK);
499 #ifndef HAVE_FREEIMAGE
504 return Standard_False;
508 // setup printing context and viewport
509 myWorkspace->PrinterContext() = new OpenGl_PrinterContext();
510 myWorkspace->PrinterContext()->SetLayerViewport ((GLsizei )aFrameWidth, (GLsizei )aFrameHeight);
511 GLint aViewPortBack[4];
512 GLint anAlignBack = 1;
513 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
514 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
515 glPixelStorei (GL_PACK_ALIGNMENT, 4);
517 // start document if the printer context is not actually a memory dc
518 // (memory dc could be used for testing purposes)
520 if (GetObjectType (hPrnDC) == OBJ_DC)
522 // Initialize printing procedure
523 di.cbSize = sizeof(DOCINFO);
524 di.lpszDocName = "Open Cascade Document - print v3d view";
525 di.lpszOutput = theFileName;
527 // if can't print the document
528 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
530 MessageBox (NULL, "Print failed: printer can't start operation.",
531 "The operation couldn't be completed.", MB_OK);
532 #ifndef HAVE_FREEIMAGE
535 SelectObject (hMemDC, hViewBitmapOld);
536 DeleteObject (hViewBitmap);
541 myWorkspace->PrinterContext().Nullify();
542 return Standard_False;
546 // calculate offset for centered printing
547 int aDevOffx = (int)(devWidth - width) /2;
548 int aDevOffy = (int)(devHeight - height)/2;
550 // operation complete flag
553 // Set up status for printing
554 if (!theToShowBackground)
556 myWorkspace->NamedStatus |= OPENGL_NS_WHITEBACK;
559 // switch to mono camera for image dump
560 const Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType() != Graphic3d_Camera::Projection_Stereo
561 ? myCamera->ProjectionType()
562 : Graphic3d_Camera::Projection_Perspective;
565 myWorkspace->PrinterContext()->SetScale ((GLfloat )aFrameWidth /viewWidth, (GLfloat )aFrameHeight/viewHeight);
566 redraw (aProjectType, aFrameBuffer);
567 if (!myTransientDrawToFront)
569 // render to FBO only if allowed to render to back buffer
570 myBackBufferRestored = Standard_True;
571 myIsImmediateDrawn = Standard_False;
572 redrawImmediate (aProjectType, NULL, aFrameBuffer);
573 myBackBufferRestored = Standard_False;
574 myIsImmediateDrawn = Standard_False;
576 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
577 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
579 // copy result to the printer device and check for errors
580 #ifdef HAVE_FREEIMAGE
581 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
582 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
583 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
586 if (width > aFrameWidth && height > aFrameHeight)
588 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
589 isDone = (StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
590 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY) != 0); // to avoid warning C4800
594 isDone = (BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
595 hMemDC, 0, 0, SRCCOPY) != 0); // to avoid warning C4800
601 // calculate total count of frames and cropping size
602 Standard_Integer aPxCropx = 0;
603 Standard_Integer aPxCropy = 0;
604 Standard_Integer aTotalx =
605 (Standard_Integer)floor ((float)width /aFrameWidth);
606 Standard_Integer aTotaly =
607 (Standard_Integer)floor ((float)height/aFrameHeight);
608 if (width %aFrameWidth != 0)
610 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
613 if (height%aFrameHeight != 0)
615 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
619 int anOddPixelx = (width %aFrameWidth) %2;
620 int anOddPixely = (height%aFrameHeight)%2;
622 // calculate scale factor for full frames
623 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
624 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
626 // calculate and set the text scaling factor for printing context
627 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
628 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
629 myWorkspace->PrinterContext()->SetScale (aScaleRatex * (GLfloat )aScalex, aScaleRatey * (GLfloat )aScaley);
631 // initialize projection matrix for printer context
632 TColStd_Array2OfReal aProj (0, 3, 0, 3);
633 Standard_Real aDef = 0;
638 // projection matrix offsets for printer context
639 // offsets are even numbers
640 Standard_Real aOffsetx(0), aOffsety(0);
641 aOffsetx = -(aTotalx-1);
642 aOffsety = -(aTotaly-1);
644 // rect of frame image that will be copied
645 // and coordinates in view image where to put it
646 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
647 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
648 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
650 // draw sequence of full frames
651 for (int i = 0; i < aTotalx; i++)
653 // offsets are even numbers
654 aOffsety = -(aTotaly-1);
655 aSubTop = (Standard_Integer)aDevOffy;
657 // calculate cropped frame rect
658 aLeft = (i == 0) ? aPxCropx : 0;
659 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
662 for (int j = 0; j < aTotaly; j++)
664 // no offset for single frames
665 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
666 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
668 // set projection matrix
669 aProj(0,0) = aScalex;
670 aProj(1,1) = aScaley;
671 myWorkspace->PrinterContext()->SetProjTransformation (aProj);
673 // calculate cropped frame rect
674 aTop = (j == 0) ? aPxCropy : 0;
675 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
678 // draw to the offscreen buffer and capture the result
679 redraw (aProjectType, aFrameBuffer);
680 if (!myTransientDrawToFront)
682 // render to FBO only if forces to render to back buffer
683 myBackBufferRestored = Standard_True;
684 myIsImmediateDrawn = Standard_False;
685 redrawImmediate (aProjectType, NULL, aFrameBuffer);
686 myBackBufferRestored = Standard_False;
687 myIsImmediateDrawn = Standard_False;
689 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
690 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
691 #ifdef HAVE_FREEIMAGE
692 // cut out pixels that are out of printing area
693 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
694 aRight-aLeft, aBottom-aTop, aLeft, aTop);
696 isDone = (BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
697 hMemDC, aLeft, aTop, SRCCOPY) != 0); // to avoid warning C4800
700 // stop operation if errors
704 // calculate new view offset for y-coordinate
706 aSubTop += aBottom-aTop;
709 // stop operation if errors
713 // calculate new view offset for x-coordinate
715 aSubLeft += aRight-aLeft;
719 // complete printing or indicate an error
720 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
725 else if (isDone == false)
727 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
728 "The opeartion couldn't be completed.", MB_OK);
729 if (GetObjectType (hPrnDC) == OBJ_DC)
733 // return OpenGl to the previous state
734 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
735 aFrameBuffer->UnbindBuffer (aCtx);
736 glViewport (aViewPortBack[0], aViewPortBack[1],
737 aViewPortBack[2], aViewPortBack[3]);
740 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
744 aFrameBuffer->Release (aCtx.operator->());
749 #ifndef HAVE_FREEIMAGE
752 SelectObject (hMemDC, hViewBitmapOld);
753 DeleteObject (hViewBitmap);
758 // Reset status after printing
759 myWorkspace->NamedStatus &= ~OPENGL_NS_WHITEBACK;
760 myWorkspace->PrinterContext().Nullify();
761 return (Standard_Boolean) isDone;
765 (void )theToShowBackground;
767 (void )thePrintAlgorithm;
768 (void )theScaleFactor;
769 Standard_NotImplemented::Raise ("OpenGl_View::Print is implemented only on Windows");
770 myWorkspace->PrinterContext().Nullify();
771 return Standard_False;