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 <Graphic3d_GraphicDriver.hxx>
22 #include <OpenGl_PrinterContext.hxx>
23 #include <OpenGl_Workspace.hxx>
24 #include <OpenGl_View.hxx>
26 #include <Standard_NotImplemented.hxx>
28 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_FREEIMAGE)
29 #include <NCollection_Handle.hxx>
30 #include <FreeImagePlus.h>
32 #pragma comment( lib, "FreeImage.lib" )
33 #pragma comment( lib, "FreeImagePlus.lib" )
35 typedef NCollection_Handle<fipImage> FipHandle;
40 #ifndef HAVE_FREEIMAGE
42 // =======================================================================
43 // function : initBitmapBuffer
44 // purpose : init device independent bitmap to hold printing data
45 // =======================================================================
46 static void initBitmapBuffer (const HDC theMemoryDC,
47 HBITMAP &theMemoryBmp,
48 const Standard_Integer theBmpWidth,
49 const Standard_Integer theBmpHeight,
52 // define compatible bitmap
53 BITMAPINFO aBitmapData;
54 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
55 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
56 aBitmapData.bmiHeader.biWidth = theBmpWidth;
57 aBitmapData.bmiHeader.biHeight = theBmpHeight;
58 aBitmapData.bmiHeader.biPlanes = 1;
59 aBitmapData.bmiHeader.biBitCount = 24;
60 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
61 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
62 aBitmapData.bmiHeader.biClrUsed = 0;
63 aBitmapData.bmiHeader.biClrImportant = 0;
64 aBitmapData.bmiHeader.biCompression = BI_RGB;
65 aBitmapData.bmiHeader.biSizeImage = 0;
67 // Create Device Independent Bitmap
68 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
69 &theBufferPtr, NULL, 0);
72 #else /* HAVE_FREEIMAGE */
74 // =======================================================================
75 // function : imagePasteDC
76 // purpose : copy the data from image buffer to the device context
77 // =======================================================================
78 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
79 int theOffsetY, int theWidth, int theHeight,
80 int theLeft = 0, int theTop = 0)
82 // get image parameters
83 BITMAPINFO* aBitmapData = theImage->getInfo ();
84 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
86 // organize blocks data passing if memory isn't enough to pass all the data
88 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
89 aPassed = 0, aInverseLine = 0, aScan = 0;
91 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
93 // how much lines still to pass
94 aBlockWidth = theHeight - aLinesComplete;
96 // normalize count of lines to pass to maximum lines count at one pass.
97 if (aBlockWidth > aMaxBlockWidth)
98 aBlockWidth = aMaxBlockWidth;
100 // access image data at the start scan line, we need to calculate scan from
101 // the bottom of image (image is bottom-left, the src coord is top-left)
102 aInverseLine = theTop + aBlockWidth + aLinesComplete;
103 aScan = theImage->getHeight() - aInverseLine;
104 aDataPtr = theImage->getScanLine (aScan);
108 // try to pass block to the device
111 // instead of banded output we provide blocked as it isn't always passed
112 // to printer as it is expected
113 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
114 theOffsetY + aLinesComplete,
115 theWidth, aBlockWidth, theLeft, 0,
117 aDataPtr, aBitmapData, DIB_RGB_COLORS);
119 // if result is bad, try to decrease band width
120 if (aPassed != aBlockWidth)
122 aMaxBlockWidth = aMaxBlockWidth >> 1;
126 aLinesComplete += aBlockWidth;
130 // check for total failure
131 if (aMaxBlockWidth < 1)
137 // =======================================================================
138 // function : imageStretchDC
139 // purpose : copy pixels from image to dc by stretching them
140 // =======================================================================
141 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
142 int theOffsetY, int theWidth, int theHeight)
144 // access to raw image data
145 BYTE *aDataPtr = theImage->accessPixels ();
149 // get image parameters
150 unsigned int widthPx = theImage->getWidth ();
151 unsigned int heightPx = theImage->getHeight ();
152 BITMAPINFO* aBitmapData = theImage->getInfo ();
153 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
155 // pass lines and check if operation is succesfull
157 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
158 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
159 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
161 if ((unsigned)aPassed != heightPx)
167 #endif /* HAVE_FREEIMAGE */
169 // =======================================================================
170 // function : getNearestPowOfTwo
171 // purpose : get the nearest power of two for theNumber
172 // =======================================================================
173 static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
176 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
180 // =======================================================================
181 // function : getMaxFrameSize
182 // purpose : get the maximum possible frame size
183 // =======================================================================
184 static void getMaxFrameSize(Standard_Integer& theWidth,
185 Standard_Integer& theHeight)
187 GLsizei aMaxX, aMaxY;
189 GLint aTexDim = 2048;
190 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
191 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
192 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
193 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
194 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
195 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
197 theWidth = (Standard_Integer)aMaxX;
198 theHeight = (Standard_Integer)aMaxY;
201 // =======================================================================
202 // function : fitDimensionsRatio
203 // purpose : calculate correct width/height ratio for theWidth and
204 // theHeight parameters
205 // =======================================================================
206 static void fitDimensionsRatio (Standard_Integer& theWidth,
207 Standard_Integer& theHeight,
208 const Standard_Real theViewRatio)
210 // set dimensions in accordance with the viewratio
211 if (theHeight < theWidth/theViewRatio)
212 theWidth = (Standard_Integer)(theHeight*theViewRatio);
214 if (theWidth < theHeight*theViewRatio)
215 theHeight = (Standard_Integer)(theWidth/theViewRatio);
218 // =======================================================================
219 // function : initBufferStretch
220 // purpose : calculate initialization sizes for frame buffer
221 // when the stretch algorithm is selected
222 // =======================================================================
223 static void initBufferStretch (Standard_Integer& theFrameWidth,
224 Standard_Integer& theFrameHeight,
225 const int theViewWidth,
226 const int theViewHeight)
229 // Calculate correct width/height for framebuffer
230 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
231 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
233 // downscale the framebuffer if it is too large
234 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
235 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
237 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
238 (aWidthRate > 1 && aHeightRate <= 1))
240 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
241 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
243 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
244 (aWidthRate <= 1 && aHeightRate > 1))
246 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
247 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
251 // =======================================================================
252 // function : initBufferTiling
253 // purpose : calculate initialization sizes for frame buffer
254 // when the tile algorithm is selected
255 // =======================================================================
256 static void initBufferTiling (Standard_Integer& theFrameWidth,
257 Standard_Integer &theFrameHeight,
258 const int theViewWidth,
259 const int theViewHeight)
261 // fit framebuffer into the printing area
262 if (theFrameWidth > theViewWidth)
263 theFrameWidth = theViewWidth;
265 if (theFrameHeight > theViewHeight)
266 theFrameHeight = theViewHeight;
271 // =======================================================================
274 // =======================================================================
275 Standard_Boolean OpenGl_View::Print (const Aspect_Handle thePrinterDC,
276 const Standard_Boolean theToShowBackground,
277 const Standard_CString theFileName,
278 const Aspect_PrintAlgo thePrintAlgorithm,
279 const Standard_Real theScaleFactor)
282 if (!myWorkspace->Activate())
284 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
285 // "The operation couldn't be completed.", MB_OK);
286 return Standard_False;
289 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
291 // printer page dimensions
292 HDC hPrnDC = (HDC) thePrinterDC;
293 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
294 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
296 // if context is actually a memory dc, try to retrieve bitmap dimensions
297 // (memory dc could be used for testing purposes)
298 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
300 // memory dc dimensions
302 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
304 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
306 devWidth = aBitmapInfo.bmWidth;
307 devHeight = aBitmapInfo.bmHeight;
311 Standard_Integer tempWidth = (Standard_Integer) devWidth;
312 Standard_Integer tempHeight = (Standard_Integer) devHeight;
315 int viewWidth = myWindow->Width();
316 int viewHeight = myWindow->Height();
317 if (viewWidth == 0 || viewHeight == 0)
319 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
320 // "The operation couldn't be completed.", MB_OK);
321 return Standard_False;
324 // calculate correct width/height ratio
325 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
326 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
328 // width and height for printing area
329 int width = (int) (tempWidth * theScaleFactor);
330 int height = (int) (tempHeight * theScaleFactor);
332 // device independent bitmap for the whole view
333 #ifdef HAVE_FREEIMAGE
334 FipHandle aViewImage = NULL;
335 BYTE* aViewBuffer = NULL;
337 HDC hMemDC = CreateCompatibleDC (hPrnDC);
338 HBITMAP hViewBitmap = NULL;
339 HGDIOBJ hViewBitmapOld = NULL;
340 VOID* aViewBuffer = NULL;
343 // Frame buffer initialization
344 OpenGl_FrameBuffer* aFrameBuffer = NULL;
345 OpenGl_FrameBuffer* aPrevBuffer = myFBO.operator->();
346 Standard_Integer aFrameWidth (0), aFrameHeight (0),
347 aPrevBufferX (0), aPrevBufferY (0);
349 bool IsTiling = (thePrintAlgorithm == Aspect_PA_TILE);
351 // try to use existing frame buffer
354 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
355 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
356 bool isUsable = false;
358 // check if its possible to use previous frame buffer
359 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
361 aFrameWidth = (Standard_Integer) width;
362 aFrameHeight = (Standard_Integer) height;
367 // use previous frame buffer with its dimensions
368 aFrameWidth = aPrevWidth;
369 aFrameHeight = aPrevHeight;
373 // if it is enough memory for image paste dc operation
376 #ifdef HAVE_FREEIMAGE
377 // try to allocate fipImage and necessary resources
378 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
381 // if allocated successfully
382 if (anImagePtr->isValid())
384 aViewImage = anImagePtr;
385 aViewBuffer = aViewImage->accessPixels ();
397 // try to allocate compatible bitmap and necessary resources
398 initBitmapBuffer (hMemDC, hViewBitmap,
399 aFrameWidth, aFrameHeight, aViewBuffer);
404 DeleteObject (hViewBitmap);
408 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
412 // use previous frame buffer
415 aPrevBufferX = aPrevWidth;
416 aPrevBufferY = aPrevHeight;
417 aFrameBuffer = aPrevBuffer;
418 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
422 // if previous buffer cannot be used, try to init a new one
425 aFrameBuffer = new OpenGl_FrameBuffer();
427 // try to create the framebuffer with the best possible size
428 Standard_Integer aMaxWidth(0), aMaxHeight(0);
429 getMaxFrameSize (aMaxWidth, aMaxHeight);
430 while (aMaxWidth > 1 && aMaxHeight > 1)
432 aFrameWidth = aMaxWidth;
433 aFrameHeight = aMaxHeight;
435 // calculate dimensions for different printing algorithms
437 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
439 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
441 // try to initialize framebuffer
442 if (aFrameBuffer->Init (aCtx, aFrameWidth, aFrameHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
444 #ifdef HAVE_FREEIMAGE
445 // try to allocate fipImage and necessary resources
446 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
449 // if allocated successfully
450 if (anImagePtr->isValid())
452 aViewImage = anImagePtr;
453 aViewBuffer = aViewImage->accessPixels ();
460 aFrameBuffer->Release (aCtx.operator->());
467 // try to allocate compatible bitmap and necessary resources
468 initBitmapBuffer (hMemDC, hViewBitmap,
469 aFrameWidth, aFrameHeight, aViewBuffer);
473 DeleteObject (hViewBitmap);
474 aFrameBuffer->Release (aCtx.operator->());
479 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
485 // not initialized, decrease dimensions
486 aMaxWidth = aMaxWidth >> 1;
487 aMaxHeight = aMaxHeight >> 1;
490 // check if there are proper dimensions
491 if (aMaxWidth <= 1 || aMaxHeight <= 1)
493 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
494 "The operation couldn't be completed.", MB_OK);
498 #ifndef HAVE_FREEIMAGE
503 return Standard_False;
507 // setup printing context and viewport
508 myWorkspace->PrinterContext() = new OpenGl_PrinterContext();
509 myWorkspace->PrinterContext()->SetLayerViewport ((GLsizei )aFrameWidth, (GLsizei )aFrameHeight);
510 GLint aViewPortBack[4];
511 GLint anAlignBack = 1;
512 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
513 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
514 glPixelStorei (GL_PACK_ALIGNMENT, 4);
516 // start document if the printer context is not actually a memory dc
517 // (memory dc could be used for testing purposes)
519 if (GetObjectType (hPrnDC) == OBJ_DC)
521 // Initialize printing procedure
522 di.cbSize = sizeof(DOCINFO);
523 di.lpszDocName = "Open Cascade Document - print v3d view";
524 di.lpszOutput = theFileName;
526 // if can't print the document
527 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
529 MessageBox (NULL, "Print failed: printer can't start operation.",
530 "The operation couldn't be completed.", MB_OK);
531 #ifndef HAVE_FREEIMAGE
534 SelectObject (hMemDC, hViewBitmapOld);
535 DeleteObject (hViewBitmap);
540 myWorkspace->PrinterContext().Nullify();
541 return Standard_False;
545 // calculate offset for centered printing
546 int aDevOffx = (int)(devWidth - width) /2;
547 int aDevOffy = (int)(devHeight - height)/2;
549 // operation complete flag
552 // Set up status for printing
553 if (!theToShowBackground)
555 myWorkspace->NamedStatus |= OPENGL_NS_WHITEBACK;
558 // switch to mono camera for image dump
559 const Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType() != Graphic3d_Camera::Projection_Stereo
560 ? myCamera->ProjectionType()
561 : Graphic3d_Camera::Projection_Perspective;
564 myWorkspace->PrinterContext()->SetScale ((GLfloat )aFrameWidth /viewWidth, (GLfloat )aFrameHeight/viewHeight);
565 redraw (aProjectType, aFrameBuffer);
566 if (!myTransientDrawToFront)
568 // render to FBO only if allowed to render to back buffer
569 myBackBufferRestored = Standard_True;
570 myIsImmediateDrawn = Standard_False;
571 redrawImmediate (aProjectType, NULL, aFrameBuffer);
572 myBackBufferRestored = Standard_False;
573 myIsImmediateDrawn = Standard_False;
575 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
576 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
578 // copy result to the printer device and check for errors
579 #ifdef HAVE_FREEIMAGE
580 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
581 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
582 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
585 if (width > aFrameWidth && height > aFrameHeight)
587 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
588 isDone = (StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
589 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY) != 0); // to avoid warning C4800
593 isDone = (BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
594 hMemDC, 0, 0, SRCCOPY) != 0); // to avoid warning C4800
600 // calculate total count of frames and cropping size
601 Standard_Integer aPxCropx = 0;
602 Standard_Integer aPxCropy = 0;
603 Standard_Integer aTotalx =
604 (Standard_Integer)floor ((float)width /aFrameWidth);
605 Standard_Integer aTotaly =
606 (Standard_Integer)floor ((float)height/aFrameHeight);
607 if (width %aFrameWidth != 0)
609 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
612 if (height%aFrameHeight != 0)
614 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
618 int anOddPixelx = (width %aFrameWidth) %2;
619 int anOddPixely = (height%aFrameHeight)%2;
621 // calculate scale factor for full frames
622 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
623 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
625 // calculate and set the text scaling factor for printing context
626 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
627 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
628 myWorkspace->PrinterContext()->SetScale (aScaleRatex * (GLfloat )aScalex, aScaleRatey * (GLfloat )aScaley);
630 // initialize projection matrix for printer context
631 TColStd_Array2OfReal aProj (0, 3, 0, 3);
632 Standard_Real aDef = 0;
637 // projection matrix offsets for printer context
638 // offsets are even numbers
639 Standard_Real aOffsetx(0), aOffsety(0);
640 aOffsetx = -(aTotalx-1);
641 aOffsety = -(aTotaly-1);
643 // rect of frame image that will be copied
644 // and coordinates in view image where to put it
645 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
646 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
647 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
649 // draw sequence of full frames
650 for (int i = 0; i < aTotalx; i++)
652 // offsets are even numbers
653 aOffsety = -(aTotaly-1);
654 aSubTop = (Standard_Integer)aDevOffy;
656 // calculate cropped frame rect
657 aLeft = (i == 0) ? aPxCropx : 0;
658 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
661 for (int j = 0; j < aTotaly; j++)
663 // no offset for single frames
664 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
665 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
667 // set projection matrix
668 aProj(0,0) = aScalex;
669 aProj(1,1) = aScaley;
670 myWorkspace->PrinterContext()->SetProjTransformation (aProj);
672 // calculate cropped frame rect
673 aTop = (j == 0) ? aPxCropy : 0;
674 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
677 // draw to the offscreen buffer and capture the result
678 redraw (aProjectType, aFrameBuffer);
679 if (!myTransientDrawToFront)
681 // render to FBO only if forces to render to back buffer
682 myBackBufferRestored = Standard_True;
683 myIsImmediateDrawn = Standard_False;
684 redrawImmediate (aProjectType, NULL, aFrameBuffer);
685 myBackBufferRestored = Standard_False;
686 myIsImmediateDrawn = Standard_False;
688 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
689 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
690 #ifdef HAVE_FREEIMAGE
691 // cut out pixels that are out of printing area
692 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
693 aRight-aLeft, aBottom-aTop, aLeft, aTop);
695 isDone = (BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
696 hMemDC, aLeft, aTop, SRCCOPY) != 0); // to avoid warning C4800
699 // stop operation if errors
703 // calculate new view offset for y-coordinate
705 aSubTop += aBottom-aTop;
708 // stop operation if errors
712 // calculate new view offset for x-coordinate
714 aSubLeft += aRight-aLeft;
718 // complete printing or indicate an error
719 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
724 else if (isDone == false)
726 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
727 "The opeartion couldn't be completed.", MB_OK);
728 if (GetObjectType (hPrnDC) == OBJ_DC)
732 // return OpenGl to the previous state
733 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
734 aFrameBuffer->UnbindBuffer (aCtx);
735 glViewport (aViewPortBack[0], aViewPortBack[1],
736 aViewPortBack[2], aViewPortBack[3]);
739 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
743 aFrameBuffer->Release (aCtx.operator->());
748 #ifndef HAVE_FREEIMAGE
751 SelectObject (hMemDC, hViewBitmapOld);
752 DeleteObject (hViewBitmap);
757 // Reset status after printing
758 myWorkspace->NamedStatus &= ~OPENGL_NS_WHITEBACK;
759 myWorkspace->PrinterContext().Nullify();
760 return (Standard_Boolean) isDone;
764 (void )theToShowBackground;
766 (void )thePrintAlgorithm;
767 (void )theScaleFactor;
768 Standard_NotImplemented::Raise ("OpenGl_View::Print is implemented only on Windows");
769 myWorkspace->PrinterContext().Nullify();
770 return Standard_False;