1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
21 #include <OpenGl_GlCore11.hxx>
23 #include <OpenGl_FrameBuffer.hxx>
24 #include <TColStd_Array2OfReal.hxx>
25 #include <OpenGl_telem_util.hxx>
31 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_FREEIMAGE)
32 #include <NCollection_Handle.hxx>
33 #include <FreeImagePlus.h>
35 #pragma comment( lib, "FreeImage.lib" )
36 #pragma comment( lib, "FreeImagePlus.lib" )
38 typedef NCollection_Handle<fipImage> FipHandle;
41 #include <OpenGl_PrinterContext.hxx>
42 #include <OpenGl_Workspace.hxx>
43 #include <OpenGl_View.hxx>
44 #include <OpenGl_Display.hxx>
46 //10-05-96 : CAL ; Ajout d'un nouveau delta dans les copies de pixels (voir CALL_DEF_DELTA)
47 #define CALL_DEF_DELTA 10
49 // ---------------------------------------------------------------
50 // Function: getNearestPowOfTwo
51 // Purpose: get the nearest power of two for theNumber
52 // ---------------------------------------------------------------
53 static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
56 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
60 // ---------------------------------------------------------------
61 // Function: fitDimensionsRatio
62 // Purpose: calculate correct width/height ratio for theWidth and
63 // theHeight parameters
64 // ---------------------------------------------------------------
65 static void fitDimensionsRatio (Standard_Integer& theWidth,
66 Standard_Integer& theHeight,
67 const Standard_Real theViewRatio)
69 // set dimensions in accordance with the viewratio
70 if (theHeight < theWidth/theViewRatio)
71 theWidth = (Standard_Integer)(theHeight*theViewRatio);
73 if (theWidth < theHeight*theViewRatio)
74 theHeight = (Standard_Integer)(theWidth/theViewRatio);
77 // ---------------------------------------------------------------
78 // Function: initBitmapBuffer
79 // Purpose: init device independent bitmap to hold printing data
80 // ---------------------------------------------------------------
82 #ifndef HAVE_FREEIMAGE
83 static void initBitmapBuffer (const HDC theMemoryDC,
84 HBITMAP &theMemoryBmp,
85 const Standard_Integer theBmpWidth,
86 const Standard_Integer theBmpHeight,
89 // define compatible bitmap
90 BITMAPINFO aBitmapData;
91 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
92 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
93 aBitmapData.bmiHeader.biWidth = theBmpWidth;
94 aBitmapData.bmiHeader.biHeight = theBmpHeight;
95 aBitmapData.bmiHeader.biPlanes = 1;
96 aBitmapData.bmiHeader.biBitCount = 24;
97 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
98 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
99 aBitmapData.bmiHeader.biClrUsed = 0;
100 aBitmapData.bmiHeader.biClrImportant = 0;
101 aBitmapData.bmiHeader.biCompression = BI_RGB;
102 aBitmapData.bmiHeader.biSizeImage = 0;
104 // Create Device Independent Bitmap
105 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
106 &theBufferPtr, NULL, 0);
109 // ---------------------------------------------------------------
110 // Function: imagePasteDC
111 // Purpose: copy the data from image buffer to the device context
112 // ---------------------------------------------------------------
113 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
114 int theOffsetY, int theWidth, int theHeight,
115 int theLeft = 0, int theTop = 0)
117 // get image parameters
118 BITMAPINFO* aBitmapData = theImage->getInfo ();
119 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
121 // organize blocks data passing if memory isn't enough to pass all the data
123 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
124 aPassed = 0, aInverseLine = 0, aScan = 0;
126 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
128 // how much lines still to pass
129 aBlockWidth = theHeight - aLinesComplete;
131 // normalize count of lines to pass to maximum lines count at one pass.
132 if (aBlockWidth > aMaxBlockWidth)
133 aBlockWidth = aMaxBlockWidth;
135 // access image data at the start scan line, we need to calculate scan from
136 // the bottom of image (image is bottom-left, the src coord is top-left)
137 aInverseLine = theTop + aBlockWidth + aLinesComplete;
138 aScan = theImage->getHeight() - aInverseLine;
139 aDataPtr = theImage->getScanLine (aScan);
143 // try to pass block to the device
146 // instead of banded output we provide blocked as it isn't always passed
147 // to printer as it is expected
148 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
149 theOffsetY + aLinesComplete,
150 theWidth, aBlockWidth, theLeft, 0,
152 aDataPtr, aBitmapData, DIB_RGB_COLORS);
154 // if result is bad, try to decrease band width
155 if (aPassed != aBlockWidth)
157 aMaxBlockWidth = aMaxBlockWidth >> 1;
161 aLinesComplete += aBlockWidth;
165 // check for total failure
166 if (aMaxBlockWidth < 1)
172 // ---------------------------------------------------------------
173 // Function: imageStretchDC
174 // Purpose: copy pixels from image to dc by stretching them
175 // ---------------------------------------------------------------
176 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
177 int theOffsetY, int theWidth, int theHeight)
179 // access to raw image data
180 BYTE *aDataPtr = theImage->accessPixels ();
184 // get image parameters
185 unsigned int widthPx = theImage->getWidth ();
186 unsigned int heightPx = theImage->getHeight ();
187 BITMAPINFO* aBitmapData = theImage->getInfo ();
188 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
190 // pass lines and check if operation is succesfull
192 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
193 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
194 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
196 if ((unsigned)aPassed != heightPx)
203 // ---------------------------------------------------------------
204 // Function: getMaxFrameSize
205 // Purpose: get the maximum possible frame size
206 // ---------------------------------------------------------------
207 static void getMaxFrameSize(Standard_Integer& theWidth,
208 Standard_Integer& theHeight)
210 GLsizei aMaxX, aMaxY;
212 GLint aTexDim = 2048;
213 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
214 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
215 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
216 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
217 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
218 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
220 theWidth = (Standard_Integer)aMaxX;
221 theHeight = (Standard_Integer)aMaxY;
223 // ---------------------------------------------------------------
224 // Function: getDimensionsTiling
225 // Purpose: calculate maximum possible dimensions for framebuffer
226 // in tiling mode according to the view size
227 // ---------------------------------------------------------------
228 static void getDimensionsTiling (Standard_Integer& theFrameWidth,
229 Standard_Integer& theFrameHeight,
230 const int theViewWidth,
231 const int theViewHeight)
233 // fit the maximum dimensions into the printing area
234 if (theFrameWidth > theViewWidth)
235 theFrameWidth = theViewWidth;
237 if (theFrameHeight > theViewHeight)
238 theFrameHeight = theViewHeight;
240 // ---------------------------------------------------------------
241 // Function: initBufferStretch
242 // Purpose: calculate initialization sizes for frame buffer
243 // when the stretch algorithm is selected
244 // ---------------------------------------------------------------
245 static void initBufferStretch (Standard_Integer& theFrameWidth,
246 Standard_Integer& theFrameHeight,
247 const int theViewWidth,
248 const int theViewHeight)
251 // Calculate correct width/height for framebuffer
252 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
253 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
255 // downscale the framebuffer if it is too large
256 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
257 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
259 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
260 (aWidthRate > 1 && aHeightRate <= 1))
262 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
263 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
265 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
266 (aWidthRate <= 1 && aHeightRate > 1))
268 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
269 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
272 // ---------------------------------------------------------------
273 // Function: initBufferTiling
274 // Purpose: calculate initialization sizes for frame buffer
275 // when the tile algorithm is selected
276 // ---------------------------------------------------------------
277 static void initBufferTiling (Standard_Integer& theFrameWidth,
278 Standard_Integer &theFrameHeight,
279 const int theViewWidth,
280 const int theViewHeight)
282 // fit framebuffer into the printing area
283 if (theFrameWidth > theViewWidth)
284 theFrameWidth = theViewWidth;
286 if (theFrameHeight > theViewHeight)
287 theFrameHeight = theViewHeight;
291 // ---------------------------------------------------------------
292 // ---------------------------------------------------------------
296 Standard_Boolean OpenGl_Workspace::Print
297 (const Handle(OpenGl_PrinterContext)& thePrintContext,
298 const Graphic3d_CView& ACView,
299 const Aspect_CLayer2d& ACUnderLayer,
300 const Aspect_CLayer2d& ACOverLayer,
301 const Aspect_Handle hPrintDC,// const Aspect_Drawable hPrintDC,
302 const Standard_Boolean showBackground,
303 const Standard_CString filename,
304 const Aspect_PrintAlgo printAlgorithm,
305 const Standard_Real theScaleFactor)
307 if (thePrintContext.IsNull())
309 return Standard_False;
316 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
317 // "The operation couldn't be completed.", MB_OK);
318 return Standard_False;
321 // printer page dimensions
322 HDC hPrnDC = (HDC) hPrintDC;
323 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
324 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
326 // if context is actually a memory dc, try to retrieve bitmap dimensions
327 // (memory dc could be used for testing purposes)
328 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
330 // memory dc dimensions
332 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
334 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
336 devWidth = aBitmapInfo.bmWidth;
337 devHeight = aBitmapInfo.bmHeight;
341 Standard_Integer tempWidth = (Standard_Integer) devWidth;
342 Standard_Integer tempHeight = (Standard_Integer) devHeight;
345 int viewWidth = myWidth;
346 int viewHeight = myHeight;
347 if (viewWidth == 0 || viewHeight == 0)
349 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
350 // "The operation couldn't be completed.", MB_OK);
351 return Standard_False;
354 // calculate correct width/height ratio
355 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
356 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
358 // width and height for printing area
359 int width = (int) (tempWidth * theScaleFactor);
360 int height = (int) (tempHeight * theScaleFactor);
362 // device independent bitmap for the whole view
363 #ifdef HAVE_FREEIMAGE
364 FipHandle aViewImage = NULL;
365 BYTE* aViewBuffer = NULL;
367 HDC hMemDC = CreateCompatibleDC (hPrnDC);
368 HBITMAP hViewBitmap = NULL;
369 HGDIOBJ hViewBitmapOld = NULL;
370 VOID* aViewBuffer = NULL;
373 // Frame buffer initialization
374 OpenGl_FrameBuffer* aFrameBuffer = NULL;
375 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) ACView.ptrFBO;
376 Standard_Integer aFrameWidth (0), aFrameHeight (0),
377 aPrevBufferX (0), aPrevBufferY (0);
379 bool IsTiling = (printAlgorithm == 1);
381 // try to use existing frame buffer
384 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
385 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
386 bool isUsable = false;
388 // check if its possible to use previous frame buffer
389 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
391 aFrameWidth = (Standard_Integer) width;
392 aFrameHeight = (Standard_Integer) height;
397 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
398 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
402 // if it is enough memory for image paste dc operation
405 #ifdef HAVE_FREEIMAGE
406 // try to allocate fipImage and necessary resources
407 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
410 // if allocated succesfully
411 if (anImagePtr->isValid())
413 aViewImage = anImagePtr;
414 aViewBuffer = aViewImage->accessPixels ();
426 // try to allocate compatible bitmap and necessary resources
427 initBitmapBuffer (hMemDC, hViewBitmap,
428 aFrameWidth, aFrameHeight, aViewBuffer);
433 DeleteObject (hViewBitmap);
437 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
441 // use previous frame buffer
444 aPrevBufferX = aPrevWidth;
445 aPrevBufferY = aPrevHeight;
446 aFrameBuffer = aPrevBuffer;
447 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
451 // if previous buffer cannot be used, try to init a new one
454 aFrameBuffer = new OpenGl_FrameBuffer();
456 // try to create the framebuffer with the best possible size
457 Standard_Integer aMaxWidth(0), aMaxHeight(0);
458 getMaxFrameSize (aMaxWidth, aMaxHeight);
459 while (aMaxWidth > 1 && aMaxHeight > 1)
461 aFrameWidth = aMaxWidth;
462 aFrameHeight = aMaxHeight;
464 // calculate dimensions for different printing algorithms
466 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
468 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
470 // try to initialize framebuffer
471 if (aFrameBuffer->Init (GetGlContext(), aFrameWidth, aFrameHeight))
473 #ifdef HAVE_FREEIMAGE
474 // try to allocate fipImage and necessary resources
475 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
478 // if allocated succesfully
479 if (anImagePtr->isValid())
481 aViewImage = anImagePtr;
482 aViewBuffer = aViewImage->accessPixels ();
489 aFrameBuffer->Release (GetGlContext().operator->());
496 // try to allocate compatible bitmap and necessary resources
497 initBitmapBuffer (hMemDC, hViewBitmap,
498 aFrameWidth, aFrameHeight, aViewBuffer);
502 DeleteObject (hViewBitmap);
503 aFrameBuffer->Release (GetGlContext().operator->());
508 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
514 // not initialized, decrease dimensions
515 aMaxWidth = aMaxWidth >> 1;
516 aMaxHeight = aMaxHeight >> 1;
519 // check if there are proper dimensions
520 if (aMaxWidth <= 1 || aMaxHeight <= 1)
522 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
523 "The operation couldn't be completed.", MB_OK);
527 #ifndef HAVE_FREEIMAGE
532 return Standard_False;
536 // setup printing context and viewport
537 myPrintContext = thePrintContext;
538 GLint aViewPortBack[4];
539 GLint anAlignBack = 1;
540 myPrintContext->SetLayerViewport ((GLsizei )aFrameWidth,
541 (GLsizei )aFrameHeight);
542 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
543 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
544 glPixelStorei (GL_PACK_ALIGNMENT, 4);
546 // start document if the printer context is not actually a memory dc
547 // (memory dc could be used for testing purposes)
549 if (GetObjectType (hPrnDC) == OBJ_DC)
551 // Initalize printing procedure
552 di.cbSize = sizeof(DOCINFO);
553 di.lpszDocName = "Open Cascade Document - print v3d view";
554 di.lpszOutput = filename;
556 // if can't print the document
557 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
559 MessageBox (NULL, "Print failed: printer can't start operation.",
560 "The operation couldn't be completed.", MB_OK);
561 #ifndef HAVE_FREEIMAGE
564 SelectObject (hMemDC, hViewBitmapOld);
565 DeleteObject (hViewBitmap);
570 myPrintContext.Nullify();
571 return Standard_False;
575 // activate the offscreen buffer
576 aFrameBuffer->BindBuffer (GetGlContext());
578 // calculate offset for centered printing
579 int aDevOffx = (int)(devWidth - width) /2;
580 int aDevOffy = (int)(devHeight - height)/2;
582 // operation complete flag
585 // Set up status for printing
587 NamedStatus |= OPENGL_NS_WHITEBACK;
591 myPrintContext->SetScale ((GLfloat )aFrameWidth /viewWidth,
592 (GLfloat )aFrameHeight/viewHeight);
593 aFrameBuffer->SetupViewport (GetGlContext());
594 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
595 if (!myTransientDrawToFront)
597 // render to FBO only if allowed to render to back buffer
598 RedrawImmediatMode();
600 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
601 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
603 // copy result to the printer device and check for errors
604 #ifdef HAVE_FREEIMAGE
605 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
606 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
607 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
610 if (width > aFrameWidth && height > aFrameHeight)
612 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
613 isDone = (StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
614 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY) != 0); // to avoid warning C4800
618 isDone = (BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
619 hMemDC, 0, 0, SRCCOPY) != 0); // to avoid warning C4800
625 // calculate total count of frames and cropping size
626 Standard_Integer aPxCropx = 0;
627 Standard_Integer aPxCropy = 0;
628 Standard_Integer aTotalx =
629 (Standard_Integer)floor ((float)width /aFrameWidth);
630 Standard_Integer aTotaly =
631 (Standard_Integer)floor ((float)height/aFrameHeight);
632 if (width %aFrameWidth != 0)
634 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
637 if (height%aFrameHeight != 0)
639 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
643 int anOddPixelx = (width %aFrameWidth) %2;
644 int anOddPixely = (height%aFrameHeight)%2;
646 // calculate scale factor for full frames
647 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
648 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
650 // calculate and set the text scaling factor for printing context
651 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
652 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
653 myPrintContext->SetScale (aScaleRatex * (GLfloat )aScalex,
654 aScaleRatey * (GLfloat )aScaley);
656 // initialize projection matrix for printer context
657 TColStd_Array2OfReal aProj (0, 3, 0, 3);
658 Standard_Real aDef = 0;
663 // projection matrix offsets for printer context
664 // offsets are even numbers
665 Standard_Real aOffsetx(0), aOffsety(0);
666 aOffsetx = -(aTotalx-1);
667 aOffsety = -(aTotaly-1);
669 // rect of frame image that will be copied
670 // and coordinates in view image where to put it
671 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
672 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
673 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
675 // draw sequence of full frames
676 for (int i = 0; i < aTotalx; i++)
678 // offsets are even numbers
679 aOffsety = -(aTotaly-1);
680 aSubTop = (Standard_Integer)aDevOffy;
682 // calculate cropped frame rect
683 aLeft = (i == 0) ? aPxCropx : 0;
684 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
687 for (int j = 0; j < aTotaly; j++)
689 // no offset for single frames
690 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
691 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
693 // set projection matrix
694 aProj(0,0) = aScalex;
695 aProj(1,1) = aScaley;
696 myPrintContext->SetProjTransformation (aProj);
698 // calculate cropped frame rect
699 aTop = (j == 0) ? aPxCropy : 0;
700 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
703 // draw to the offscreen buffer and capture the result
704 aFrameBuffer->SetupViewport (GetGlContext());
705 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
706 if (!myTransientDrawToFront)
708 // render to FBO only if forces to render to back buffer
709 RedrawImmediatMode();
711 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
712 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
713 #ifdef HAVE_FREEIMAGE
714 // cut out pixels that are out of printing area
715 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
716 aRight-aLeft, aBottom-aTop, aLeft, aTop);
718 isDone = (BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
719 hMemDC, aLeft, aTop, SRCCOPY) != 0); // to avoid warning C4800
722 // stop operation if errors
726 // calculate new view offset for y-coordinate
728 aSubTop += aBottom-aTop;
731 // stop operation if errors
735 // calculate new view offset for x-coordinate
737 aSubLeft += aRight-aLeft;
741 // complete printing or indicate an error
742 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
747 else if (isDone == false)
749 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
750 "The opeartion couldn't be completed.", MB_OK);
751 if (GetObjectType (hPrnDC) == OBJ_DC)
755 // return OpenGl to the previous state
756 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
757 aFrameBuffer->UnbindBuffer (GetGlContext());
758 glViewport (aViewPortBack[0], aViewPortBack[1],
759 aViewPortBack[2], aViewPortBack[3]);
762 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
766 aFrameBuffer->Release (GetGlContext().operator->());
771 #ifndef HAVE_FREEIMAGE
774 SelectObject (hMemDC, hViewBitmapOld);
775 DeleteObject (hViewBitmap);
780 // Reset status after printing
781 NamedStatus &= ~OPENGL_NS_WHITEBACK;
783 myPrintContext.Nullify();
784 return (Standard_Boolean) isDone;
787 myPrintContext.Nullify();
788 return Standard_False;
792 /*----------------------------------------------------------------------*/
795 void OpenGl_Workspace::Redraw1 (const Graphic3d_CView& ACView,
796 const Aspect_CLayer2d& ACUnderLayer,
797 const Aspect_CLayer2d& ACOverLayer,
800 if (myDisplay.IsNull() || myView.IsNull())
803 // Request reset of material
804 NamedStatus |= OPENGL_NS_RESMAT;
806 /* GL_DITHER on/off pour le background */
808 glEnable (GL_DITHER);
810 glDisable (GL_DITHER);
812 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
815 glDepthFunc(GL_LEQUAL);
816 glDepthMask(GL_TRUE);
818 // SAV checking if depth test was deprecated somewhere outside
819 if ( myUseDepthTest )
820 glEnable(GL_DEPTH_TEST);
822 glDisable(GL_DEPTH_TEST);
825 toClear |= GL_DEPTH_BUFFER_BIT;
829 glDisable(GL_DEPTH_TEST);
832 if ( NamedStatus & OPENGL_NS_WHITEBACK )
834 // Set background to white
835 glClearColor (1.F, 1.F, 1.F, 1.F);
836 toClear |= GL_DEPTH_BUFFER_BIT;
840 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.F);
844 Handle(OpenGl_Workspace) aWS(this);
845 myView->Render (myPrintContext, aWS, ACView, ACUnderLayer, ACOverLayer);
850 GetGlContext()->SwapBuffers();
851 myBackBufferRestored = Standard_False;
857 /*----------------------------------------------------------------------*/
860 void OpenGl_Workspace::CopyBuffers (const Standard_Boolean theFrontToBack)
864 myBackBufferRestored = Standard_False;
867 glMatrixMode (GL_PROJECTION);
870 gluOrtho2D ((GLdouble) 0., (GLdouble) myWidth, 0., (GLdouble) myHeight);
871 glMatrixMode (GL_MODELVIEW);
877 glDrawBuffer (theFrontToBack ? GL_BACK : GL_FRONT);
878 glReadBuffer (theFrontToBack ? GL_FRONT : GL_BACK);
880 glRasterPos2i (0, 0);
881 glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
885 glMatrixMode (GL_PROJECTION);
887 glMatrixMode (GL_MODELVIEW);
890 glDrawBuffer (GL_BACK);
893 /*----------------------------------------------------------------------*/
895 //call_subr_displayCB
896 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
899 if (theCView.GDisplayCB == NULL)
904 Aspect_GraphicCallbackStruct aCallData;
905 aCallData.reason = theReason;
906 aCallData.glContext = GetGlContext();
907 aCallData.wsID = theCView.WsId;
908 aCallData.viewID = theCView.ViewId;
909 theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
912 /*----------------------------------------------------------------------*/