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: getMaxFrameSize
62 // Purpose: get the maximum possible frame size
63 // ---------------------------------------------------------------
64 static void getMaxFrameSize(Standard_Integer& theWidth,
65 Standard_Integer& theHeight)
70 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
71 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
72 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
73 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
74 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
75 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
77 theWidth = (Standard_Integer)aMaxX;
78 theHeight = (Standard_Integer)aMaxY;
81 // ---------------------------------------------------------------
82 // Function: fitDimensionsRatio
83 // Purpose: calculate correct width/height ratio for theWidth and
84 // theHeight parameters
85 // ---------------------------------------------------------------
86 static void fitDimensionsRatio (Standard_Integer& theWidth,
87 Standard_Integer& theHeight,
88 const Standard_Real theViewRatio)
90 // set dimensions in accordance with the viewratio
91 if (theHeight < theWidth/theViewRatio)
92 theWidth = (Standard_Integer)(theHeight*theViewRatio);
94 if (theWidth < theHeight*theViewRatio)
95 theHeight = (Standard_Integer)(theWidth/theViewRatio);
98 // ---------------------------------------------------------------
99 // Function: getDimensionsTiling
100 // Purpose: calculate maximum possible dimensions for framebuffer
101 // in tiling mode according to the view size
102 // ---------------------------------------------------------------
103 static void getDimensionsTiling (Standard_Integer& theFrameWidth,
104 Standard_Integer& theFrameHeight,
105 const int theViewWidth,
106 const int theViewHeight)
108 // fit the maximum dimensions into the printing area
109 if (theFrameWidth > theViewWidth)
110 theFrameWidth = theViewWidth;
112 if (theFrameHeight > theViewHeight)
113 theFrameHeight = theViewHeight;
116 // ---------------------------------------------------------------
117 // Function: initBufferStretch
118 // Purpose: calculate initialization sizes for frame buffer
119 // when the stretch algorithm is selected
120 // ---------------------------------------------------------------
121 static void initBufferStretch (Standard_Integer& theFrameWidth,
122 Standard_Integer& theFrameHeight,
123 const int theViewWidth,
124 const int theViewHeight)
127 // Calculate correct width/height for framebuffer
128 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
129 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
131 // downscale the framebuffer if it is too large
132 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
133 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
135 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
136 (aWidthRate > 1 && aHeightRate <= 1))
138 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
139 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
141 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
142 (aWidthRate <= 1 && aHeightRate > 1))
144 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
145 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
150 // ---------------------------------------------------------------
151 // Function: initBufferTiling
152 // Purpose: calculate initialization sizes for frame buffer
153 // when the tile algorithm is selected
154 // ---------------------------------------------------------------
155 static void initBufferTiling (Standard_Integer& theFrameWidth,
156 Standard_Integer &theFrameHeight,
157 const int theViewWidth,
158 const int theViewHeight)
160 // fit framebuffer into the printing area
161 if (theFrameWidth > theViewWidth)
162 theFrameWidth = theViewWidth;
164 if (theFrameHeight > theViewHeight)
165 theFrameHeight = theViewHeight;
168 // ---------------------------------------------------------------
169 // Function: initBitmapBuffer
170 // Purpose: init device independent bitmap to hold printing data
171 // ---------------------------------------------------------------
173 #ifndef HAVE_FREEIMAGE
174 static void initBitmapBuffer (const HDC theMemoryDC,
175 HBITMAP &theMemoryBmp,
176 const Standard_Integer theBmpWidth,
177 const Standard_Integer theBmpHeight,
180 // define compatible bitmap
181 BITMAPINFO aBitmapData;
182 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
183 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
184 aBitmapData.bmiHeader.biWidth = theBmpWidth;
185 aBitmapData.bmiHeader.biHeight = theBmpHeight;
186 aBitmapData.bmiHeader.biPlanes = 1;
187 aBitmapData.bmiHeader.biBitCount = 24;
188 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
189 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
190 aBitmapData.bmiHeader.biClrUsed = 0;
191 aBitmapData.bmiHeader.biClrImportant = 0;
192 aBitmapData.bmiHeader.biCompression = BI_RGB;
193 aBitmapData.bmiHeader.biSizeImage = 0;
195 // Create Device Independent Bitmap
196 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
197 &theBufferPtr, NULL, 0);
200 // ---------------------------------------------------------------
201 // Function: imagePasteDC
202 // Purpose: copy the data from image buffer to the device context
203 // ---------------------------------------------------------------
204 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
205 int theOffsetY, int theWidth, int theHeight,
206 int theLeft = 0, int theTop = 0)
208 // get image parameters
209 BITMAPINFO* aBitmapData = theImage->getInfo ();
210 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
212 // organize blocks data passing if memory isn't enough to pass all the data
214 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
215 aPassed = 0, aInverseLine = 0, aScan = 0;
217 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
219 // how much lines still to pass
220 aBlockWidth = theHeight - aLinesComplete;
222 // normalize count of lines to pass to maximum lines count at one pass.
223 if (aBlockWidth > aMaxBlockWidth)
224 aBlockWidth = aMaxBlockWidth;
226 // access image data at the start scan line, we need to calculate scan from
227 // the bottom of image (image is bottom-left, the src coord is top-left)
228 aInverseLine = theTop + aBlockWidth + aLinesComplete;
229 aScan = theImage->getHeight() - aInverseLine;
230 aDataPtr = theImage->getScanLine (aScan);
234 // try to pass block to the device
237 // instead of banded output we provide blocked as it isn't always passed
238 // to printer as it is expected
239 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
240 theOffsetY + aLinesComplete,
241 theWidth, aBlockWidth, theLeft, 0,
243 aDataPtr, aBitmapData, DIB_RGB_COLORS);
245 // if result is bad, try to decrease band width
246 if (aPassed != aBlockWidth)
248 aMaxBlockWidth = aMaxBlockWidth >> 1;
252 aLinesComplete += aBlockWidth;
256 // check for total failure
257 if (aMaxBlockWidth < 1)
263 // ---------------------------------------------------------------
264 // Function: imageStretchDC
265 // Purpose: copy pixels from image to dc by stretching them
266 // ---------------------------------------------------------------
267 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
268 int theOffsetY, int theWidth, int theHeight)
270 // access to raw image data
271 BYTE *aDataPtr = theImage->accessPixels ();
275 // get image parameters
276 unsigned int widthPx = theImage->getWidth ();
277 unsigned int heightPx = theImage->getHeight ();
278 BITMAPINFO* aBitmapData = theImage->getInfo ();
279 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
281 // pass lines and check if operation is succesfull
283 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
284 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
285 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
287 if (aPassed != heightPx)
295 // ---------------------------------------------------------------
296 // ---------------------------------------------------------------
299 Standard_Boolean OpenGl_Workspace::Print
300 (const Handle(OpenGl_PrinterContext)& thePrintContext,
301 const Graphic3d_CView& ACView,
302 const Aspect_CLayer2d& ACUnderLayer,
303 const Aspect_CLayer2d& ACOverLayer,
304 const Aspect_Handle hPrintDC,// const Aspect_Drawable hPrintDC,
305 const Standard_Boolean showBackground,
306 const Standard_CString filename,
307 const Aspect_PrintAlgo printAlgorithm,
308 const Standard_Real theScaleFactor)
310 if (thePrintContext.IsNull())
312 return Standard_False;
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 // printer page dimensions
325 HDC hPrnDC = (HDC) hPrintDC;
326 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
327 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
329 // if context is actually a memory dc, try to retrieve bitmap dimensions
330 // (memory dc could be used for testing purposes)
331 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
333 // memory dc dimensions
335 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
337 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
339 devWidth = aBitmapInfo.bmWidth;
340 devHeight = aBitmapInfo.bmHeight;
344 Standard_Integer tempWidth = (Standard_Integer) devWidth;
345 Standard_Integer tempHeight = (Standard_Integer) devHeight;
348 int viewWidth = myWidth;
349 int viewHeight = myHeight;
350 if (viewWidth == 0 || viewHeight == 0)
352 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
353 // "The operation couldn't be completed.", MB_OK);
354 return Standard_False;
357 // calculate correct width/height ratio
358 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
359 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
361 // width and height for printing area
362 int width = (int) (tempWidth * theScaleFactor);
363 int height = (int) (tempHeight * theScaleFactor);
365 // device independent bitmap for the whole view
366 #ifdef HAVE_FREEIMAGE
367 FipHandle aViewImage = NULL;
368 BYTE* aViewBuffer = NULL;
370 HDC hMemDC = CreateCompatibleDC (hPrnDC);
371 HBITMAP hViewBitmap = NULL;
372 HGDIOBJ hViewBitmapOld = NULL;
373 VOID* aViewBuffer = NULL;
376 // Frame buffer initialization
377 OpenGl_FrameBuffer* aFrameBuffer = NULL;
378 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) ACView.ptrFBO;
379 Standard_Integer aFrameWidth (0), aFrameHeight (0),
380 aPrevBufferX (0), aPrevBufferY (0);
382 bool IsTiling = (printAlgorithm == 1);
384 // try to use existing frame buffer
387 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
388 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
389 bool isUsable = false;
391 // check if its possible to use previous frame buffer
392 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
394 aFrameWidth = (Standard_Integer) width;
395 aFrameHeight = (Standard_Integer) height;
400 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
401 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
405 // if it is enough memory for image paste dc operation
408 #ifdef HAVE_FREEIMAGE
409 // try to allocate fipImage and necessary resources
410 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
413 // if allocated succesfully
414 if (anImagePtr->isValid())
416 aViewImage = anImagePtr;
417 aViewBuffer = aViewImage->accessPixels ();
429 // try to allocate compatible bitmap and necessary resources
430 initBitmapBuffer (hMemDC, hViewBitmap,
431 aFrameWidth, aFrameHeight, aViewBuffer);
436 DeleteObject (hViewBitmap);
440 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
444 // use previous frame buffer
447 aPrevBufferX = aPrevWidth;
448 aPrevBufferY = aPrevHeight;
449 aFrameBuffer = aPrevBuffer;
450 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
454 // if previous buffer cannot be used, try to init a new one
457 aFrameBuffer = new OpenGl_FrameBuffer();
459 // try to create the framebuffer with the best possible size
460 Standard_Integer aMaxWidth(0), aMaxHeight(0);
461 getMaxFrameSize (aMaxWidth, aMaxHeight);
462 while (aMaxWidth > 1 && aMaxHeight > 1)
464 aFrameWidth = aMaxWidth;
465 aFrameHeight = aMaxHeight;
467 // calculate dimensions for different printing algorithms
469 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
471 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
473 // try to initialize framebuffer
474 if (aFrameBuffer->Init (GetGlContext(), aFrameWidth, aFrameHeight))
476 #ifdef HAVE_FREEIMAGE
477 // try to allocate fipImage and necessary resources
478 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
481 // if allocated succesfully
482 if (anImagePtr->isValid())
484 aViewImage = anImagePtr;
485 aViewBuffer = aViewImage->accessPixels ();
492 aFrameBuffer->Release (GetGlContext());
499 // try to allocate compatible bitmap and necessary resources
500 initBitmapBuffer (hMemDC, hViewBitmap,
501 aFrameWidth, aFrameHeight, aViewBuffer);
505 DeleteObject (hViewBitmap);
506 aFrameBuffer->Release (GetGlContext());
511 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
517 // not initialized, decrease dimensions
518 aMaxWidth = aMaxWidth >> 1;
519 aMaxHeight = aMaxHeight >> 1;
522 // check if there are proper dimensions
523 if (aMaxWidth <= 1 || aMaxHeight <= 1)
525 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
526 "The operation couldn't be completed.", MB_OK);
530 #ifndef HAVE_FREEIMAGE
535 return Standard_False;
539 // setup printing context and viewport
540 myPrintContext = thePrintContext;
541 GLint aViewPortBack[4];
542 GLint anAlignBack = 1;
543 myPrintContext->SetLayerViewport ((GLsizei )aFrameWidth,
544 (GLsizei )aFrameHeight);
545 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
546 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
547 glPixelStorei (GL_PACK_ALIGNMENT, 4);
549 // start document if the printer context is not actually a memory dc
550 // (memory dc could be used for testing purposes)
552 if (GetObjectType (hPrnDC) == OBJ_DC)
554 // Initalize printing procedure
555 di.cbSize = sizeof(DOCINFO);
556 di.lpszDocName = "Open Cascade Document - print v3d view";
557 di.lpszOutput = filename;
559 // if can't print the document
560 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
562 MessageBox (NULL, "Print failed: printer can't start operation.",
563 "The operation couldn't be completed.", MB_OK);
564 #ifndef HAVE_FREEIMAGE
567 SelectObject (hMemDC, hViewBitmapOld);
568 DeleteObject (hViewBitmap);
573 myPrintContext.Nullify();
574 return Standard_False;
578 // activate the offscreen buffer
579 aFrameBuffer->BindBuffer (GetGlContext());
581 // calculate offset for centered printing
582 int aDevOffx = (int)(devWidth - width) /2;
583 int aDevOffy = (int)(devHeight - height)/2;
585 // operation complete flag
588 // Set up status for printing
590 NamedStatus |= OPENGL_NS_WHITEBACK;
594 myPrintContext->SetScale ((GLfloat )aFrameWidth /viewWidth,
595 (GLfloat )aFrameHeight/viewHeight);
596 aFrameBuffer->SetupViewport ();
597 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
598 if (!myTransientDrawToFront)
600 // render to FBO only if allowed to render to back buffer
601 RedrawImmediatMode();
603 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
604 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
606 // copy result to the printer device and check for errors
607 #ifdef HAVE_FREEIMAGE
608 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
609 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
610 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
613 if (width > aFrameWidth && height > aFrameHeight)
615 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
616 isDone = (StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
617 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY) != 0); // to avoid warning C4800
621 isDone = (BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
622 hMemDC, 0, 0, SRCCOPY) != 0); // to avoid warning C4800
628 // calculate total count of frames and cropping size
629 Standard_Integer aPxCropx = 0;
630 Standard_Integer aPxCropy = 0;
631 Standard_Integer aTotalx =
632 (Standard_Integer)floor ((float)width /aFrameWidth);
633 Standard_Integer aTotaly =
634 (Standard_Integer)floor ((float)height/aFrameHeight);
635 if (width %aFrameWidth != 0)
637 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
640 if (height%aFrameHeight != 0)
642 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
646 int anOddPixelx = (width %aFrameWidth) %2;
647 int anOddPixely = (height%aFrameHeight)%2;
649 // calculate scale factor for full frames
650 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
651 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
653 // calculate and set the text scaling factor for printing context
654 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
655 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
656 myPrintContext->SetScale (aScaleRatex * (GLfloat )aScalex,
657 aScaleRatey * (GLfloat )aScaley);
659 // initialize projection matrix for printer context
660 TColStd_Array2OfReal aProj (0, 3, 0, 3);
661 Standard_Real aDef = 0;
666 // projection matrix offsets for printer context
667 // offsets are even numbers
668 Standard_Real aOffsetx(0), aOffsety(0);
669 aOffsetx = -(aTotalx-1);
670 aOffsety = -(aTotaly-1);
672 // rect of frame image that will be copied
673 // and coordinates in view image where to put it
674 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
675 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
676 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
678 // draw sequence of full frames
679 for (int i = 0; i < aTotalx; i++)
681 // offsets are even numbers
682 aOffsety = -(aTotaly-1);
683 aSubTop = (Standard_Integer)aDevOffy;
685 // calculate cropped frame rect
686 aLeft = (i == 0) ? aPxCropx : 0;
687 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
690 for (int j = 0; j < aTotaly; j++)
692 // no offset for single frames
693 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
694 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
696 // set projection matrix
697 aProj(0,0) = aScalex;
698 aProj(1,1) = aScaley;
699 myPrintContext->SetProjTransformation (aProj);
701 // calculate cropped frame rect
702 aTop = (j == 0) ? aPxCropy : 0;
703 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
706 // draw to the offscreen buffer and capture the result
707 aFrameBuffer->SetupViewport ();
708 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
709 if (!myTransientDrawToFront)
711 // render to FBO only if forces to render to back buffer
712 RedrawImmediatMode();
714 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
715 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
716 #ifdef HAVE_FREEIMAGE
717 // cut out pixels that are out of printing area
718 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
719 aRight-aLeft, aBottom-aTop, aLeft, aTop);
721 isDone = (BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
722 hMemDC, aLeft, aTop, SRCCOPY) != 0); // to avoid warning C4800
725 // stop operation if errors
729 // calculate new view offset for y-coordinate
731 aSubTop += aBottom-aTop;
734 // stop operation if errors
738 // calculate new view offset for x-coordinate
740 aSubLeft += aRight-aLeft;
744 // complete printing or indicate an error
745 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
750 else if (isDone == false)
752 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
753 "The opeartion couldn't be completed.", MB_OK);
754 if (GetObjectType (hPrnDC) == OBJ_DC)
758 // return OpenGl to the previous state
759 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
760 aFrameBuffer->UnbindBuffer (GetGlContext());
761 glViewport (aViewPortBack[0], aViewPortBack[1],
762 aViewPortBack[2], aViewPortBack[3]);
765 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
769 aFrameBuffer->Release (GetGlContext ());
774 #ifndef HAVE_FREEIMAGE
777 SelectObject (hMemDC, hViewBitmapOld);
778 DeleteObject (hViewBitmap);
783 // Reset status after printing
784 NamedStatus &= ~OPENGL_NS_WHITEBACK;
786 myPrintContext.Nullify();
787 return (Standard_Boolean) isDone;
790 myPrintContext.Nullify();
791 return Standard_False;
795 /*----------------------------------------------------------------------*/
798 void OpenGl_Workspace::Redraw1 (const Graphic3d_CView& ACView,
799 const Aspect_CLayer2d& ACUnderLayer,
800 const Aspect_CLayer2d& ACOverLayer,
803 if (myDisplay.IsNull() || myView.IsNull())
806 // Request reset of material
807 NamedStatus |= OPENGL_NS_RESMAT;
809 /* GL_DITHER on/off pour le background */
811 glEnable (GL_DITHER);
813 glDisable (GL_DITHER);
815 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
818 glDepthFunc(GL_LEQUAL);
819 glDepthMask(GL_TRUE);
821 // SAV checking if depth test was deprecated somewhere outside
822 if ( myUseDepthTest )
823 glEnable(GL_DEPTH_TEST);
825 glDisable(GL_DEPTH_TEST);
828 toClear |= GL_DEPTH_BUFFER_BIT;
832 glDisable(GL_DEPTH_TEST);
835 if ( NamedStatus & OPENGL_NS_WHITEBACK )
837 // Set background to white
838 glClearColor (1.F, 1.F, 1.F, 1.F);
839 toClear |= GL_DEPTH_BUFFER_BIT;
843 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.F);
847 Handle(OpenGl_Workspace) aWS(this);
848 myView->Render (myPrintContext, aWS, ACView, ACUnderLayer, ACOverLayer);
853 GetGlContext()->SwapBuffers();
854 myBackBufferRestored = Standard_False;
860 /*----------------------------------------------------------------------*/
863 void OpenGl_Workspace::CopyBuffers (const Standard_Boolean theFrontToBack)
867 myBackBufferRestored = Standard_False;
870 glMatrixMode (GL_PROJECTION);
873 gluOrtho2D ((GLdouble) 0., (GLdouble) myWidth, 0., (GLdouble) myHeight);
874 glMatrixMode (GL_MODELVIEW);
880 glDrawBuffer (theFrontToBack ? GL_BACK : GL_FRONT);
881 glReadBuffer (theFrontToBack ? GL_FRONT : GL_BACK);
883 glRasterPos2i (0, 0);
884 glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
888 glMatrixMode (GL_PROJECTION);
890 glMatrixMode (GL_MODELVIEW);
893 glDrawBuffer (GL_BACK);
896 /*----------------------------------------------------------------------*/
898 //call_subr_displayCB
899 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
902 if (theCView.GDisplayCB == NULL)
907 Aspect_GraphicCallbackStruct aCallData;
908 aCallData.reason = theReason;
909 aCallData.glContext = GetGlContext();
910 aCallData.wsID = theCView.WsId;
911 aCallData.viewID = theCView.ViewId;
912 theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
915 /*----------------------------------------------------------------------*/