1 /* File OpenGL_togl_print.c
4 e-mail t-hartl@muenchen.matra-dtv.fr */
6 #define RIC120302 /* GG Enable to use the application display
7 // callback at end of traversal
10 #include <OpenGl_tgl_all.hxx>
11 #include <InterfaceGraphic_Graphic3d.hxx>
12 #include <InterfaceGraphic_Visual3d.hxx>
13 #include <OpenGl_tsm_ws.hxx>
14 #include <OpenGl_tgl.hxx>
15 #include <OpenGl_txgl.hxx>
16 #include <OpenGl_tgl_tox.hxx>
17 #include <OpenGl_tgl_funcs.hxx>
18 #include <OpenGl_tgl_subrvis.hxx>
19 #include <OpenGl_animation.hxx>
20 #include <OpenGl_FrameBuffer.hxx>
21 #include <OpenGl_PrinterContext.hxx>
22 #include <Visual3d_Layer.hxx>
23 #include <TColStd_Array2OfReal.hxx>
27 #include <NCollection_Handle.hxx>
28 #include <FreeImagePlus.h>
30 #pragma comment( lib, "FreeImage.lib" )
31 #pragma comment( lib, "FreeImagePlus.lib" )
33 typedef NCollection_Handle<fipImage> FipHandle;
36 // ---------------------------------------------------------------
37 // Function: getNearestPowOfTwo
38 // Purpose: get the nearest power of two for theNumber
39 // ---------------------------------------------------------------
40 static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
43 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
47 // ---------------------------------------------------------------
48 // Function: getMaxFrameSize
49 // Purpose: get the maximum possible frame size
50 // ---------------------------------------------------------------
51 static void getMaxFrameSize(Standard_Integer& theWidth,
52 Standard_Integer& theHeight)
57 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
58 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
59 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
60 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
61 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
62 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
64 theWidth = (Standard_Integer)aMaxX;
65 theHeight = (Standard_Integer)aMaxY;
68 // ---------------------------------------------------------------
69 // Function: fitDimensionsRatio
70 // Purpose: calculate correct width/height ratio for theWidth and
71 // theHeight parameters
72 // ---------------------------------------------------------------
73 static void fitDimensionsRatio (Standard_Integer& theWidth,
74 Standard_Integer& theHeight,
75 const Standard_Real theViewRatio)
77 // set dimensions in accordance with the viewratio
78 if (theHeight < theWidth/theViewRatio)
79 theWidth = (Standard_Integer)(theHeight*theViewRatio);
81 if (theWidth < theHeight*theViewRatio)
82 theHeight = (Standard_Integer)(theWidth/theViewRatio);
85 // ---------------------------------------------------------------
86 // Function: getDimensionsTiling
87 // Purpose: calculate maximum possible dimensions for framebuffer
88 // in tiling mode according to the view size
89 // ---------------------------------------------------------------
90 static void getDimensionsTiling (Standard_Integer& theFrameWidth,
91 Standard_Integer& theFrameHeight,
92 const int theViewWidth,
93 const int theViewHeight)
95 // fit the maximum dimensions into the printing area
96 if (theFrameWidth > theViewWidth)
97 theFrameWidth = theViewWidth;
99 if (theFrameHeight > theViewHeight)
100 theFrameHeight = theViewHeight;
103 // ---------------------------------------------------------------
104 // Function: initBufferStretch
105 // Purpose: calculate initialization sizes for frame buffer
106 // when the stretch algorithm is selected
107 // ---------------------------------------------------------------
108 static void initBufferStretch (Standard_Integer& theFrameWidth,
109 Standard_Integer& theFrameHeight,
110 const int theViewWidth,
111 const int theViewHeight)
114 // Calculate correct width/height for framebuffer
115 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
116 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
118 // downscale the framebuffer if it is too large
119 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
120 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
122 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
123 (aWidthRate > 1 && aHeightRate <= 1))
125 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
126 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
128 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
129 (aWidthRate <= 1 && aHeightRate > 1))
131 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
132 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
137 // ---------------------------------------------------------------
138 // Function: initBufferTiling
139 // Purpose: calculate initialization sizes for frame buffer
140 // when the tile algorithm is selected
141 // ---------------------------------------------------------------
142 static void initBufferTiling (Standard_Integer& theFrameWidth,
143 Standard_Integer &theFrameHeight,
144 const int theViewWidth,
145 const int theViewHeight)
147 // fit framebuffer into the printing area
148 if (theFrameWidth > theViewWidth)
149 theFrameWidth = theViewWidth;
151 if (theFrameHeight > theViewHeight)
152 theFrameHeight = theViewHeight;
155 // ---------------------------------------------------------------
156 // Function: redrawView
157 // Purpose: redraw view in printing mode
158 // ---------------------------------------------------------------
159 static void redrawView (CALL_DEF_VIEW *aview,
160 CALL_DEF_LAYER *anunderlayer,
161 CALL_DEF_LAYER *anoverlayer,
162 const int isBackground)
164 // prepare for redraw
165 call_func_redraw_all_structs_begin (aview->WsId);
166 call_subr_displayCB (aview, OCC_REDRAW_BITMAP | OCC_PRE_REDRAW);
167 call_togl_setplane (aview);
170 if (isBackground == 0)
172 glClearColor (1.0, 1.0, 1.0, 1.0);
173 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
177 if (anunderlayer->ptrLayer)
179 call_togl_redraw_layer2d (aview, anunderlayer);
183 call_func_redraw_all_structs_proc (aview->WsId);
184 call_subr_displayCB (aview,OCC_REDRAW_BITMAP | OCC_PRE_OVERLAY);
186 if (anoverlayer->ptrLayer)
188 call_togl_redraw_layer2d (aview, anoverlayer);
190 call_subr_displayCB (aview,OCC_REDRAW_BITMAP);
193 // tell to end redrawing
194 call_func_redraw_all_structs_end (aview->WsId, 0);
195 call_togl_redraw_immediat_mode (aview);
198 // ---------------------------------------------------------------
199 // Function: initBitmapBuffer
200 // Purpose: init device independent bitmap to hold printing data
201 // ---------------------------------------------------------------
203 #ifndef HAVE_FREEIMAGE
204 static void initBitmapBuffer (const HDC theMemoryDC,
205 HBITMAP &theMemoryBmp,
206 const Standard_Integer theBmpWidth,
207 const Standard_Integer theBmpHeight,
210 // define compatible bitmap
211 BITMAPINFO aBitmapData;
212 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
213 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
214 aBitmapData.bmiHeader.biWidth = theBmpWidth;
215 aBitmapData.bmiHeader.biHeight = theBmpHeight;
216 aBitmapData.bmiHeader.biPlanes = 1;
217 aBitmapData.bmiHeader.biBitCount = 24;
218 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
219 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
220 aBitmapData.bmiHeader.biClrUsed = 0;
221 aBitmapData.bmiHeader.biClrImportant = 0;
222 aBitmapData.bmiHeader.biCompression = BI_RGB;
223 aBitmapData.bmiHeader.biSizeImage = 0;
225 // Create Device Independent Bitmap
226 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
227 &theBufferPtr, NULL, 0);
230 // ---------------------------------------------------------------
231 // Function: imagePasteDC
232 // Purpose: copy the data from image buffer to the device context
233 // ---------------------------------------------------------------
234 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
235 int theOffsetY, int theWidth, int theHeight,
236 int theLeft = 0, int theTop = 0)
238 // get image parameters
239 BITMAPINFO* aBitmapData = theImage->getInfo ();
240 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
242 // organize blocks data passing if memory isn't enough to pass all the data
244 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
245 aPassed = 0, aInverseLine = 0, aScan = 0;
247 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
249 // how much lines still to pass
250 aBlockWidth = theHeight - aLinesComplete;
252 // normalize count of lines to pass to maximum lines count at one pass.
253 if (aBlockWidth > aMaxBlockWidth)
254 aBlockWidth = aMaxBlockWidth;
256 // access image data at the start scan line, we need to calculate scan from
257 // the bottom of image (image is bottom-left, the src coord is top-left)
258 aInverseLine = theTop + aBlockWidth + aLinesComplete;
259 aScan = theImage->getHeight() - aInverseLine;
260 aDataPtr = theImage->getScanLine (aScan);
264 // try to pass block to the device
267 // instead of banded output we provide blocked as it isn't always passed
268 // to printer as it is expected
269 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
270 theOffsetY + aLinesComplete,
271 theWidth, aBlockWidth, theLeft, 0,
273 aDataPtr, aBitmapData, DIB_RGB_COLORS);
275 // if result is bad, try to decrease band width
276 if (aPassed != aBlockWidth)
278 aMaxBlockWidth = aMaxBlockWidth >> 1;
282 aLinesComplete += aBlockWidth;
286 // check for total failure
287 if (aMaxBlockWidth < 1)
293 // ---------------------------------------------------------------
294 // Function: imageStretchDC
295 // Purpose: copy pixels from image to dc by stretching them
296 // ---------------------------------------------------------------
297 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
298 int theOffsetY, int theWidth, int theHeight)
300 // access to raw image data
301 BYTE *aDataPtr = theImage->accessPixels ();
305 // get image parameters
306 unsigned int widthPx = theImage->getWidth ();
307 unsigned int heightPx = theImage->getHeight ();
308 BITMAPINFO* aBitmapData = theImage->getInfo ();
309 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
311 // pass lines and check if operation is succesfull
313 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
314 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
315 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
317 if (aPassed != heightPx)
325 // ---------------------------------------------------------------
326 // Function: call_togl_print
328 // ---------------------------------------------------------------
329 Standard_Boolean EXPORT
332 CALL_DEF_VIEW *aview,
333 CALL_DEF_LAYER *anunderlayer,
334 CALL_DEF_LAYER *anoverlayer,
335 const Aspect_Drawable hPrintDC,
336 const int background,
337 const char* filename,
339 const float theScaleFactor
347 bool IsTiling = (printalgo == 1);
348 HDC hPrnDC = (HDC) hPrintDC;
350 TsmGetWSAttri (aview->WsId, WSWindow, &data);
351 if (TxglWinset (call_thedisplay, (WINDOW) data.ldata) != TSuccess)
353 MessageBox (NULL, "Print failed: can't setup the view for printing.",
354 "The operation couldn't be completed.", MB_OK);
355 return Standard_False;
358 // printer page dimensions
359 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
360 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
362 // if context is actually a memory dc, try to retrieve bitmap dimensions
363 // (memory dc could be used for testing purposes)
364 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
366 // memory dc dimensions
368 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
370 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
372 devWidth = aBitmapInfo.bmWidth;
373 devHeight = aBitmapInfo.bmHeight;
377 Standard_Integer tempWidth = (Standard_Integer) devWidth;
378 Standard_Integer tempHeight = (Standard_Integer) devHeight;
382 GetClientRect((WINDOW) data.ldata, &rect);
383 int viewWidth = rect.right-rect.left;
384 int viewHeight = rect.bottom-rect.top;
385 if (viewWidth == 0 || viewHeight == 0)
387 MessageBox (NULL, "Print failed: can't setup the view for printing.",
388 "The operation couldn't be completed.", MB_OK);
389 return Standard_False;
392 // calculate correct width/height ratio
393 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
394 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
396 // width and height for printing area
397 int width = (int) (tempWidth * theScaleFactor);
398 int height = (int) (tempHeight * theScaleFactor);
400 // device independent bitmap for the whole view
401 #ifdef HAVE_FREEIMAGE
402 FipHandle aViewImage = NULL;
403 BYTE* aViewBuffer = NULL;
405 HDC hMemDC = CreateCompatibleDC (hPrnDC);
406 HBITMAP hViewBitmap = NULL;
407 HGDIOBJ hViewBitmapOld = NULL;
408 VOID* aViewBuffer = NULL;
411 // Frame buffer initialization
412 OpenGl_FrameBuffer* aFrameBuffer = NULL;
413 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) aview->ptrFBO;
414 Standard_Integer aFrameWidth (0), aFrameHeight (0),
415 aPrevBufferX (0), aPrevBufferY (0);
417 // try to use existing frame buffer
420 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
421 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
422 bool isUsable = false;
424 // check if its possible to use previous frame buffer
425 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
427 aFrameWidth = (Standard_Integer) width;
428 aFrameHeight = (Standard_Integer) height;
433 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
434 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
438 // if it is enough memory for image paste dc operation
441 #ifdef HAVE_FREEIMAGE
442 // try to allocate fipImage and necessary resources
443 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
446 // if allocated succesfully
447 if (anImagePtr->isValid())
449 aViewImage = anImagePtr;
450 aViewBuffer = aViewImage->accessPixels ();
462 // try to allocate compatible bitmap and necessary resources
463 initBitmapBuffer (hMemDC, hViewBitmap,
464 aFrameWidth, aFrameHeight, aViewBuffer);
469 DeleteObject (hViewBitmap);
473 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
477 // use previous frame buffer
480 aPrevBufferX = aPrevWidth;
481 aPrevBufferY = aPrevHeight;
482 aFrameBuffer = aPrevBuffer;
483 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
487 // if previous buffer cannot be used, try to init a new one
490 aFrameBuffer = new OpenGl_FrameBuffer();
492 // try to create the framebuffer with the best possible size
493 Standard_Integer aMaxWidth(0), aMaxHeight(0);
494 getMaxFrameSize (aMaxWidth, aMaxHeight);
495 while (aMaxWidth > 1 && aMaxHeight > 1)
497 aFrameWidth = aMaxWidth;
498 aFrameHeight = aMaxHeight;
500 // calculate dimensions for different printing algorithms
502 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
504 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
506 // try to initialize framebuffer
507 if (aFrameBuffer->Init (aFrameWidth, aFrameHeight))
509 #ifdef HAVE_FREEIMAGE
510 // try to allocate fipImage and necessary resources
511 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
514 // if allocated succesfully
515 if (anImagePtr->isValid())
517 aViewImage = anImagePtr;
518 aViewBuffer = aViewImage->accessPixels ();
525 aFrameBuffer->Release ();
532 // try to allocate compatible bitmap and necessary resources
533 initBitmapBuffer (hMemDC, hViewBitmap,
534 aFrameWidth, aFrameHeight, aViewBuffer);
538 DeleteObject (hViewBitmap);
539 aFrameBuffer->Release ();
544 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
550 // not initialized, decrease dimensions
551 aMaxWidth = aMaxWidth >> 1;
552 aMaxHeight = aMaxHeight >> 1;
555 // check if there are proper dimensions
556 if (aMaxWidth <= 1 || aMaxHeight <= 1)
558 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
559 "The operation couldn't be completed.", MB_OK);
563 #ifndef HAVE_FREEIMAGE
568 return Standard_False;
572 // setup printing context and viewport
573 GLint aViewPortBack[4];
574 GLint aReadBufferPrev = GL_BACK;
575 GLint anAlignBack = 1;
576 OpenGl_PrinterContext aPrinterContext (GET_GL_CONTEXT());
577 aPrinterContext.SetLayerViewport ((GLsizei)aFrameWidth,
578 (GLsizei)aFrameHeight);
579 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
580 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
581 glPixelStorei (GL_PACK_ALIGNMENT, 4);
583 // start document if the printer context is not actually a memory dc
584 // (memory dc could be used for testing purposes)
585 if (GetObjectType (hPrnDC) == OBJ_DC)
587 // Initalize printing procedure
588 di.cbSize = sizeof(DOCINFO);
589 di.lpszDocName = "Open Cascade Document - print v3d view";
590 di.lpszOutput = filename;
592 // if can't print the document
593 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
595 MessageBox (NULL, "Print failed: printer can't start operation.",
596 "The operation couldn't be completed.", MB_OK);
597 #ifndef HAVE_FREEIMAGE
600 SelectObject (hMemDC, hViewBitmapOld);
601 DeleteObject (hViewBitmap);
606 return Standard_False;
610 // activate the offscreen buffer
611 aFrameBuffer->BindBuffer ();
613 // calculate offset for centered printing
614 int aDevOffx = (int)(devWidth - width) /2;
615 int aDevOffy = (int)(devHeight - height)/2;
617 // operation complete flag
622 aPrinterContext.SetScale ((GLfloat)aFrameWidth /viewWidth,
623 (GLfloat)aFrameHeight/viewHeight);
624 aFrameBuffer->SetupViewport ();
625 redrawView (aview, anunderlayer, anoverlayer, background);
626 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
627 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
629 // copy result to the printer device and check for errors
630 #ifdef HAVE_FREEIMAGE
631 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
632 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
633 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
636 if (width > aFrameWidth && height > aFrameHeight)
638 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
639 isDone = StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
640 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY);
644 isDone = BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
645 hMemDC, 0, 0, SRCCOPY);
651 // calculate total count of frames and cropping size
652 Standard_Integer aPxCropx = 0;
653 Standard_Integer aPxCropy = 0;
654 Standard_Integer aTotalx =
655 (Standard_Integer)floor ((float)width /aFrameWidth);
656 Standard_Integer aTotaly =
657 (Standard_Integer)floor ((float)height/aFrameHeight);
658 if (width %aFrameWidth != 0)
660 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
663 if (height%aFrameHeight != 0)
665 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
669 int anOddPixelx = (width %aFrameWidth) %2;
670 int anOddPixely = (height%aFrameHeight)%2;
672 // calculate scale factor for full frames
673 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
674 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
676 // calculate and set the text scaling factor for printing context
677 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
678 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
679 aPrinterContext.SetScale (aScaleRatex*(GLfloat)aScalex,
680 aScaleRatey*(GLfloat)aScaley);
682 // initialize projection matrix for printer context
683 TColStd_Array2OfReal aProj (0, 3, 0, 3);
684 Standard_Real aDef = 0;
689 // projection matrix offsets for printer context
690 // offsets are even numbers
691 Standard_Real aOffsetx(0), aOffsety(0);
692 aOffsetx = -(aTotalx-1);
693 aOffsety = -(aTotaly-1);
695 // rect of frame image that will be copied
696 // and coordinates in view image where to put it
697 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
698 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
699 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
701 // draw sequence of full frames
702 for (int i = 0; i < aTotalx; i++)
704 // offsets are even numbers
705 aOffsety = -(aTotaly-1);
706 aSubTop = (Standard_Integer)aDevOffy;
708 // calculate cropped frame rect
709 aLeft = (i == 0) ? aPxCropx : 0;
710 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
713 for (int j = 0; j < aTotaly; j++)
715 // no offset for single frames
716 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
717 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
719 // set projection matrix
720 aProj(0,0) = aScalex;
721 aProj(1,1) = aScaley;
722 aPrinterContext.SetProjTransformation (aProj);
724 // calculate cropped frame rect
725 aTop = (j == 0) ? aPxCropy : 0;
726 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
729 // draw to the offscreen buffer and capture the result
730 aFrameBuffer->SetupViewport ();
731 redrawView (aview, anunderlayer, anoverlayer, background);
732 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
733 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
734 #ifdef HAVE_FREEIMAGE
735 // cut out pixels that are out of printing area
736 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
737 aRight-aLeft, aBottom-aTop, aLeft, aTop);
739 isDone = BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
740 hMemDC, aLeft, aTop, SRCCOPY);
743 // stop operation if errors
747 // calculate new view offset for y-coordinate
749 aSubTop += aBottom-aTop;
752 // stop operation if errors
756 // calculate new view offset for x-coordinate
758 aSubLeft += aRight-aLeft;
762 // complete printing or indicate an error
763 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
768 else if (isDone == false)
770 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
771 "The opeartion couldn't be completed.", MB_OK);
772 if (GetObjectType (hPrnDC) == OBJ_DC)
776 // return OpenGl to the previous state
777 aPrinterContext.Deactivate ();
778 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
779 aFrameBuffer->UnbindBuffer();
780 glViewport (aViewPortBack[0], aViewPortBack[1],
781 aViewPortBack[2], aViewPortBack[3]);
783 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
788 #ifndef HAVE_FREEIMAGE
791 SelectObject (hMemDC, hViewBitmapOld);
792 DeleteObject (hViewBitmap);
797 return (Standard_Boolean) isDone;
800 return Standard_False;