1 // File: OpenGl_Workspace_2.cxx
2 // Created: 20 September 2011
3 // Author: Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
6 #define RIC120302 /* GG Enable to use the application display
7 // callback at end of traversal
10 #include <OpenGl_tgl_all.hxx>
11 #include <OpenGl_FrameBuffer.hxx>
12 #include <TColStd_Array2OfReal.hxx>
14 #include <OpenGl_telem_util.hxx>
17 #include <NCollection_Handle.hxx>
18 #include <FreeImagePlus.h>
20 #pragma comment( lib, "FreeImage.lib" )
21 #pragma comment( lib, "FreeImagePlus.lib" )
23 typedef NCollection_Handle<fipImage> FipHandle;
26 #include <OpenGl_PrinterContext.hxx>
27 #include <OpenGl_Workspace.hxx>
28 #include <OpenGl_View.hxx>
29 #include <OpenGl_Display.hxx>
31 //10-05-96 : CAL ; Ajout d'un nouveau delta dans les copies de pixels (voir CALL_DEF_DELTA)
32 #define CALL_DEF_DELTA 10
34 // ---------------------------------------------------------------
35 // Function: getNearestPowOfTwo
36 // Purpose: get the nearest power of two for theNumber
37 // ---------------------------------------------------------------
38 static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
41 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
45 // ---------------------------------------------------------------
46 // Function: getMaxFrameSize
47 // Purpose: get the maximum possible frame size
48 // ---------------------------------------------------------------
49 static void getMaxFrameSize(Standard_Integer& theWidth,
50 Standard_Integer& theHeight)
55 glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
56 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
57 (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim :
58 aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
59 (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
60 aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
62 theWidth = (Standard_Integer)aMaxX;
63 theHeight = (Standard_Integer)aMaxY;
66 // ---------------------------------------------------------------
67 // Function: fitDimensionsRatio
68 // Purpose: calculate correct width/height ratio for theWidth and
69 // theHeight parameters
70 // ---------------------------------------------------------------
71 static void fitDimensionsRatio (Standard_Integer& theWidth,
72 Standard_Integer& theHeight,
73 const Standard_Real theViewRatio)
75 // set dimensions in accordance with the viewratio
76 if (theHeight < theWidth/theViewRatio)
77 theWidth = (Standard_Integer)(theHeight*theViewRatio);
79 if (theWidth < theHeight*theViewRatio)
80 theHeight = (Standard_Integer)(theWidth/theViewRatio);
83 // ---------------------------------------------------------------
84 // Function: getDimensionsTiling
85 // Purpose: calculate maximum possible dimensions for framebuffer
86 // in tiling mode according to the view size
87 // ---------------------------------------------------------------
88 static void getDimensionsTiling (Standard_Integer& theFrameWidth,
89 Standard_Integer& theFrameHeight,
90 const int theViewWidth,
91 const int theViewHeight)
93 // fit the maximum dimensions into the printing area
94 if (theFrameWidth > theViewWidth)
95 theFrameWidth = theViewWidth;
97 if (theFrameHeight > theViewHeight)
98 theFrameHeight = theViewHeight;
101 // ---------------------------------------------------------------
102 // Function: initBufferStretch
103 // Purpose: calculate initialization sizes for frame buffer
104 // when the stretch algorithm is selected
105 // ---------------------------------------------------------------
106 static void initBufferStretch (Standard_Integer& theFrameWidth,
107 Standard_Integer& theFrameHeight,
108 const int theViewWidth,
109 const int theViewHeight)
112 // Calculate correct width/height for framebuffer
113 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
114 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
116 // downscale the framebuffer if it is too large
117 Standard_Real aWidthRate = (Standard_Real)theFrameWidth /theViewWidth;
118 Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
120 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
121 (aWidthRate > 1 && aHeightRate <= 1))
123 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
124 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
126 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
127 (aWidthRate <= 1 && aHeightRate > 1))
129 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
130 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
135 // ---------------------------------------------------------------
136 // Function: initBufferTiling
137 // Purpose: calculate initialization sizes for frame buffer
138 // when the tile algorithm is selected
139 // ---------------------------------------------------------------
140 static void initBufferTiling (Standard_Integer& theFrameWidth,
141 Standard_Integer &theFrameHeight,
142 const int theViewWidth,
143 const int theViewHeight)
145 // fit framebuffer into the printing area
146 if (theFrameWidth > theViewWidth)
147 theFrameWidth = theViewWidth;
149 if (theFrameHeight > theViewHeight)
150 theFrameHeight = theViewHeight;
153 // ---------------------------------------------------------------
154 // Function: initBitmapBuffer
155 // Purpose: init device independent bitmap to hold printing data
156 // ---------------------------------------------------------------
158 #ifndef HAVE_FREEIMAGE
159 static void initBitmapBuffer (const HDC theMemoryDC,
160 HBITMAP &theMemoryBmp,
161 const Standard_Integer theBmpWidth,
162 const Standard_Integer theBmpHeight,
165 // define compatible bitmap
166 BITMAPINFO aBitmapData;
167 memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
168 aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
169 aBitmapData.bmiHeader.biWidth = theBmpWidth;
170 aBitmapData.bmiHeader.biHeight = theBmpHeight;
171 aBitmapData.bmiHeader.biPlanes = 1;
172 aBitmapData.bmiHeader.biBitCount = 24;
173 aBitmapData.bmiHeader.biXPelsPerMeter = 0;
174 aBitmapData.bmiHeader.biYPelsPerMeter = 0;
175 aBitmapData.bmiHeader.biClrUsed = 0;
176 aBitmapData.bmiHeader.biClrImportant = 0;
177 aBitmapData.bmiHeader.biCompression = BI_RGB;
178 aBitmapData.bmiHeader.biSizeImage = 0;
180 // Create Device Independent Bitmap
181 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
182 &theBufferPtr, NULL, 0);
185 // ---------------------------------------------------------------
186 // Function: imagePasteDC
187 // Purpose: copy the data from image buffer to the device context
188 // ---------------------------------------------------------------
189 static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
190 int theOffsetY, int theWidth, int theHeight,
191 int theLeft = 0, int theTop = 0)
193 // get image parameters
194 BITMAPINFO* aBitmapData = theImage->getInfo ();
195 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
197 // organize blocks data passing if memory isn't enough to pass all the data
199 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
200 aPassed = 0, aInverseLine = 0, aScan = 0;
202 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
204 // how much lines still to pass
205 aBlockWidth = theHeight - aLinesComplete;
207 // normalize count of lines to pass to maximum lines count at one pass.
208 if (aBlockWidth > aMaxBlockWidth)
209 aBlockWidth = aMaxBlockWidth;
211 // access image data at the start scan line, we need to calculate scan from
212 // the bottom of image (image is bottom-left, the src coord is top-left)
213 aInverseLine = theTop + aBlockWidth + aLinesComplete;
214 aScan = theImage->getHeight() - aInverseLine;
215 aDataPtr = theImage->getScanLine (aScan);
219 // try to pass block to the device
222 // instead of banded output we provide blocked as it isn't always passed
223 // to printer as it is expected
224 aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
225 theOffsetY + aLinesComplete,
226 theWidth, aBlockWidth, theLeft, 0,
228 aDataPtr, aBitmapData, DIB_RGB_COLORS);
230 // if result is bad, try to decrease band width
231 if (aPassed != aBlockWidth)
233 aMaxBlockWidth = aMaxBlockWidth >> 1;
237 aLinesComplete += aBlockWidth;
241 // check for total failure
242 if (aMaxBlockWidth < 1)
248 // ---------------------------------------------------------------
249 // Function: imageStretchDC
250 // Purpose: copy pixels from image to dc by stretching them
251 // ---------------------------------------------------------------
252 static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
253 int theOffsetY, int theWidth, int theHeight)
255 // access to raw image data
256 BYTE *aDataPtr = theImage->accessPixels ();
260 // get image parameters
261 unsigned int widthPx = theImage->getWidth ();
262 unsigned int heightPx = theImage->getHeight ();
263 BITMAPINFO* aBitmapData = theImage->getInfo ();
264 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
266 // pass lines and check if operation is succesfull
268 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
269 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
270 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
272 if (aPassed != heightPx)
280 // ---------------------------------------------------------------
281 // ---------------------------------------------------------------
284 Standard_Boolean OpenGl_Workspace::Print
285 (const Graphic3d_CView& ACView,
286 const Aspect_CLayer2d& ACUnderLayer,
287 const Aspect_CLayer2d& ACOverLayer,
288 const Aspect_Handle hPrintDC,// const Aspect_Drawable hPrintDC,
289 const Standard_Boolean showBackground,
290 const Standard_CString filename,
291 const Aspect_PrintAlgo printAlgorithm,
292 const Standard_Real theScaleFactor)
298 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
299 // "The operation couldn't be completed.", MB_OK);
300 return Standard_False;
303 // printer page dimensions
304 HDC hPrnDC = (HDC) hPrintDC;
305 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
306 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
308 // if context is actually a memory dc, try to retrieve bitmap dimensions
309 // (memory dc could be used for testing purposes)
310 if (GetObjectType (hPrnDC) == OBJ_MEMDC)
312 // memory dc dimensions
314 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
316 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
318 devWidth = aBitmapInfo.bmWidth;
319 devHeight = aBitmapInfo.bmHeight;
323 Standard_Integer tempWidth = (Standard_Integer) devWidth;
324 Standard_Integer tempHeight = (Standard_Integer) devHeight;
327 int viewWidth = myWidth;
328 int viewHeight = myHeight;
329 if (viewWidth == 0 || viewHeight == 0)
331 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
332 // "The operation couldn't be completed.", MB_OK);
333 return Standard_False;
336 // calculate correct width/height ratio
337 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
338 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
340 // width and height for printing area
341 int width = (int) (tempWidth * theScaleFactor);
342 int height = (int) (tempHeight * theScaleFactor);
344 // device independent bitmap for the whole view
345 #ifdef HAVE_FREEIMAGE
346 FipHandle aViewImage = NULL;
347 BYTE* aViewBuffer = NULL;
349 HDC hMemDC = CreateCompatibleDC (hPrnDC);
350 HBITMAP hViewBitmap = NULL;
351 HGDIOBJ hViewBitmapOld = NULL;
352 VOID* aViewBuffer = NULL;
355 // Frame buffer initialization
356 OpenGl_FrameBuffer* aFrameBuffer = NULL;
357 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) ACView.ptrFBO;
358 Standard_Integer aFrameWidth (0), aFrameHeight (0),
359 aPrevBufferX (0), aPrevBufferY (0);
361 bool IsTiling = (printAlgorithm == 1);
363 // try to use existing frame buffer
366 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
367 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
368 bool isUsable = false;
370 // check if its possible to use previous frame buffer
371 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
373 aFrameWidth = (Standard_Integer) width;
374 aFrameHeight = (Standard_Integer) height;
379 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
380 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
384 // if it is enough memory for image paste dc operation
387 #ifdef HAVE_FREEIMAGE
388 // try to allocate fipImage and necessary resources
389 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
392 // if allocated succesfully
393 if (anImagePtr->isValid())
395 aViewImage = anImagePtr;
396 aViewBuffer = aViewImage->accessPixels ();
408 // try to allocate compatible bitmap and necessary resources
409 initBitmapBuffer (hMemDC, hViewBitmap,
410 aFrameWidth, aFrameHeight, aViewBuffer);
415 DeleteObject (hViewBitmap);
419 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
423 // use previous frame buffer
426 aPrevBufferX = aPrevWidth;
427 aPrevBufferY = aPrevHeight;
428 aFrameBuffer = aPrevBuffer;
429 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
433 // if previous buffer cannot be used, try to init a new one
436 aFrameBuffer = new OpenGl_FrameBuffer();
438 // try to create the framebuffer with the best possible size
439 Standard_Integer aMaxWidth(0), aMaxHeight(0);
440 getMaxFrameSize (aMaxWidth, aMaxHeight);
441 while (aMaxWidth > 1 && aMaxHeight > 1)
443 aFrameWidth = aMaxWidth;
444 aFrameHeight = aMaxHeight;
446 // calculate dimensions for different printing algorithms
448 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
450 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
452 // try to initialize framebuffer
453 if (aFrameBuffer->Init (GetGlContext(), aFrameWidth, aFrameHeight))
455 #ifdef HAVE_FREEIMAGE
456 // try to allocate fipImage and necessary resources
457 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
460 // if allocated succesfully
461 if (anImagePtr->isValid())
463 aViewImage = anImagePtr;
464 aViewBuffer = aViewImage->accessPixels ();
471 aFrameBuffer->Release (GetGlContext());
478 // try to allocate compatible bitmap and necessary resources
479 initBitmapBuffer (hMemDC, hViewBitmap,
480 aFrameWidth, aFrameHeight, aViewBuffer);
484 DeleteObject (hViewBitmap);
485 aFrameBuffer->Release (GetGlContext());
490 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
496 // not initialized, decrease dimensions
497 aMaxWidth = aMaxWidth >> 1;
498 aMaxHeight = aMaxHeight >> 1;
501 // check if there are proper dimensions
502 if (aMaxWidth <= 1 || aMaxHeight <= 1)
504 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
505 "The operation couldn't be completed.", MB_OK);
509 #ifndef HAVE_FREEIMAGE
514 return Standard_False;
518 // setup printing context and viewport
519 GLint aViewPortBack[4];
520 GLint aReadBufferPrev = GL_BACK;
521 GLint anAlignBack = 1;
523 OpenGl_PrinterContext aPrinterContext (myGContext);
524 aPrinterContext.SetLayerViewport ((GLsizei)aFrameWidth,
525 (GLsizei)aFrameHeight);
526 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
527 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
528 glPixelStorei (GL_PACK_ALIGNMENT, 4);
530 // start document if the printer context is not actually a memory dc
531 // (memory dc could be used for testing purposes)
533 if (GetObjectType (hPrnDC) == OBJ_DC)
535 // Initalize printing procedure
536 di.cbSize = sizeof(DOCINFO);
537 di.lpszDocName = "Open Cascade Document - print v3d view";
538 di.lpszOutput = filename;
540 // if can't print the document
541 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
543 MessageBox (NULL, "Print failed: printer can't start operation.",
544 "The operation couldn't be completed.", MB_OK);
545 #ifndef HAVE_FREEIMAGE
548 SelectObject (hMemDC, hViewBitmapOld);
549 DeleteObject (hViewBitmap);
554 return Standard_False;
558 // activate the offscreen buffer
559 aFrameBuffer->BindBuffer (GetGlContext());
561 // calculate offset for centered printing
562 int aDevOffx = (int)(devWidth - width) /2;
563 int aDevOffy = (int)(devHeight - height)/2;
565 // operation complete flag
568 // Set up status for printing
569 NamedStatus |= OPENGL_NS_ISBITMAP;
571 NamedStatus |= OPENGL_NS_WHITEBACK;
575 aPrinterContext.SetScale ((GLfloat)aFrameWidth /viewWidth,
576 (GLfloat)aFrameHeight/viewHeight);
577 aFrameBuffer->SetupViewport ();
578 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
579 RedrawImmediatMode();
580 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
581 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
583 // copy result to the printer device and check for errors
584 #ifdef HAVE_FREEIMAGE
585 if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
586 !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
587 isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
590 if (width > aFrameWidth && height > aFrameHeight)
592 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
593 isDone = StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
594 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY);
598 isDone = BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
599 hMemDC, 0, 0, SRCCOPY);
605 // calculate total count of frames and cropping size
606 Standard_Integer aPxCropx = 0;
607 Standard_Integer aPxCropy = 0;
608 Standard_Integer aTotalx =
609 (Standard_Integer)floor ((float)width /aFrameWidth);
610 Standard_Integer aTotaly =
611 (Standard_Integer)floor ((float)height/aFrameHeight);
612 if (width %aFrameWidth != 0)
614 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
617 if (height%aFrameHeight != 0)
619 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
623 int anOddPixelx = (width %aFrameWidth) %2;
624 int anOddPixely = (height%aFrameHeight)%2;
626 // calculate scale factor for full frames
627 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
628 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
630 // calculate and set the text scaling factor for printing context
631 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
632 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
633 aPrinterContext.SetScale (aScaleRatex*(GLfloat)aScalex,
634 aScaleRatey*(GLfloat)aScaley);
636 // initialize projection matrix for printer context
637 TColStd_Array2OfReal aProj (0, 3, 0, 3);
638 Standard_Real aDef = 0;
643 // projection matrix offsets for printer context
644 // offsets are even numbers
645 Standard_Real aOffsetx(0), aOffsety(0);
646 aOffsetx = -(aTotalx-1);
647 aOffsety = -(aTotaly-1);
649 // rect of frame image that will be copied
650 // and coordinates in view image where to put it
651 Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
652 Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
653 Standard_Integer aSubTop = (Standard_Integer)aDevOffy;
655 // draw sequence of full frames
656 for (int i = 0; i < aTotalx; i++)
658 // offsets are even numbers
659 aOffsety = -(aTotaly-1);
660 aSubTop = (Standard_Integer)aDevOffy;
662 // calculate cropped frame rect
663 aLeft = (i == 0) ? aPxCropx : 0;
664 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
667 for (int j = 0; j < aTotaly; j++)
669 // no offset for single frames
670 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
671 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
673 // set projection matrix
674 aProj(0,0) = aScalex;
675 aProj(1,1) = aScaley;
676 aPrinterContext.SetProjTransformation (aProj);
678 // calculate cropped frame rect
679 aTop = (j == 0) ? aPxCropy : 0;
680 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
683 // draw to the offscreen buffer and capture the result
684 aFrameBuffer->SetupViewport ();
685 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
686 RedrawImmediatMode();
687 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
688 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
689 #ifdef HAVE_FREEIMAGE
690 // cut out pixels that are out of printing area
691 isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
692 aRight-aLeft, aBottom-aTop, aLeft, aTop);
694 isDone = BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
695 hMemDC, aLeft, aTop, SRCCOPY);
698 // stop operation if errors
702 // calculate new view offset for y-coordinate
704 aSubTop += aBottom-aTop;
707 // stop operation if errors
711 // calculate new view offset for x-coordinate
713 aSubLeft += aRight-aLeft;
717 // complete printing or indicate an error
718 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
723 else if (isDone == false)
725 MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
726 "The opeartion couldn't be completed.", MB_OK);
727 if (GetObjectType (hPrnDC) == OBJ_DC)
731 // return OpenGl to the previous state
732 aPrinterContext.Deactivate ();
733 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
734 aFrameBuffer->UnbindBuffer (GetGlContext());
735 glViewport (aViewPortBack[0], aViewPortBack[1],
736 aViewPortBack[2], aViewPortBack[3]);
738 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
743 #ifndef HAVE_FREEIMAGE
746 SelectObject (hMemDC, hViewBitmapOld);
747 DeleteObject (hViewBitmap);
752 // Reset status after printing
753 NamedStatus &= ~(OPENGL_NS_WHITEBACK | OPENGL_NS_ISBITMAP);
755 return (Standard_Boolean) isDone;
758 return Standard_False;
762 /*----------------------------------------------------------------------*/
765 void OpenGl_Workspace::Redraw1 (const Graphic3d_CView& ACView,
766 const Aspect_CLayer2d& ACUnderLayer,
767 const Aspect_CLayer2d& ACOverLayer,
770 if (myDisplay.IsNull() || myView.IsNull())
773 myDisplay->UpdateUserMarkers();
775 // Request reset of material
776 NamedStatus |= OPENGL_NS_RESMAT;
778 /* GL_DITHER on/off pour le background */
780 glEnable (GL_DITHER);
782 glDisable (GL_DITHER);
784 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
787 glDepthFunc(GL_LEQUAL);
788 glDepthMask(GL_TRUE);
790 // SAV checking if depth test was deprecated somewhere outside
791 if ( myUseDepthTest )
792 glEnable(GL_DEPTH_TEST);
794 glDisable(GL_DEPTH_TEST);
797 toClear |= GL_DEPTH_BUFFER_BIT;
801 glDisable(GL_DEPTH_TEST);
804 if ( NamedStatus & OPENGL_NS_WHITEBACK )
806 // Set background to white
807 glClearColor (1.F, 1.F, 1.F, 1.F);
808 toClear |= GL_DEPTH_BUFFER_BIT;
812 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.F);
816 Handle(OpenGl_Workspace) aWS(this);
817 myView->Render(aWS,ACView,ACUnderLayer,ACOverLayer);
823 glXSwapBuffers ((Display*)myDisplay->GetDisplay (), myWindow );
825 SwapBuffers ( wglGetCurrentDC () );
828 myBackBufferRestored = Standard_False;
833 myIsUpdated = Standard_True;
836 /*----------------------------------------------------------------------*/
839 void OpenGl_Workspace::CopyBuffers (Tint vid, int FrontToBack, Tfloat xm, Tfloat ym, Tfloat zm, Tfloat XM, Tfloat YM, Tfloat ZM, Tint flag)
841 if (FrontToBack) myBackBufferRestored = Standard_False;
843 glMatrixMode (GL_PROJECTION);
846 gluOrtho2D ((GLdouble) 0., (GLdouble) myWidth, 0., (GLdouble) myHeight);
847 glMatrixMode (GL_MODELVIEW);
853 GLsizei width = myWidth+1, height = myHeight+1;
854 Tfloat xmr = 0, ymr = 0;
858 if (!myView.IsNull()) //szvgl: use vid here!
860 // Calculate bounding box and store the projected rectangle
862 // Project bounding box
863 if (myView->ProjectObjectToRaster (myWidth, myHeight, xm, ym, zm, xr[0], yr[0]) &&
864 myView->ProjectObjectToRaster (myWidth, myHeight, xm, YM, zm, xr[1], yr[1]) &&
865 myView->ProjectObjectToRaster (myWidth, myHeight, XM, YM, zm, xr[2], yr[2]) &&
866 myView->ProjectObjectToRaster (myWidth, myHeight, XM, ym, zm, xr[3], yr[3]) &&
867 myView->ProjectObjectToRaster (myWidth, myHeight, xm, ym, ZM, xr[4], yr[4]) &&
868 myView->ProjectObjectToRaster (myWidth, myHeight, xm, YM, ZM, xr[5], yr[5]) &&
869 myView->ProjectObjectToRaster (myWidth, myHeight, XM, YM, ZM, xr[6], yr[6]) &&
870 myView->ProjectObjectToRaster (myWidth, myHeight, XM, ym, ZM, xr[7], yr[7]))
873 xmr = ymr = (float ) shortreallast ();
874 XMR = YMR = (float ) shortrealfirst ();
876 * Recherche du rectangle projete
879 for (i=0; i<8; i++) {
880 if (xmr > xr[i]) xmr = xr[i];
881 if (ymr > yr[i]) ymr = yr[i];
882 if (XMR < xr[i]) XMR = xr[i];
883 if (YMR < yr[i]) YMR = yr[i];
885 /* pour eviter les bavures de pixels ! */
890 * Ajout CAL : 10/05/96
891 * Si les MinMax viennent d'un ensemble de markers
892 * on ne tient pas compte du scale factor de ceux-ci
893 * dans les valeurs de MinMax. En effet, ce facteur
894 * est dans l'espace pixel et les MinMax dans l'espace
895 * du modele. Donc ajout d'un delta de pixels
896 * en esperant que les applis n'utilisent pas des
897 * markers tres gros !
899 xmr -= CALL_DEF_DELTA; ymr -= CALL_DEF_DELTA;
900 XMR += CALL_DEF_DELTA; YMR += CALL_DEF_DELTA;
903 * Le rectangle projete peut-etre clippe
905 width = (GLsizei) (XMR-xmr+1);
906 height = (GLsizei) (YMR-ymr+1);
908 * (xmr,ymr) coin inferieur gauche
909 * (XMR,YMR) coin superieur droit
911 /* cas ou 1 coin est en dehors de la fenetre */
912 if (xmr < 0) { width = (GLsizei) (XMR+1); xmr = 0; }
913 if (ymr < 0) { height = (GLsizei) (YMR+1); ymr = 0; }
914 if (XMR > myWidth) { width = (GLsizei) (myWidth-xmr+1); }
915 if (YMR > myHeight) { height = (GLsizei) (myHeight-ymr+1); }
917 /* cas ou les 2 coins sont en dehors de la fenetre */
918 if (XMR < 0) { xmr = 0; width = height = 1; }
919 if (YMR < 0) { ymr = 0; width = height = 1; }
920 if (xmr > myWidth) { xmr = 0; width = height = 1; }
921 if (ymr > myHeight) { ymr = 0; width = height = 1; }
926 glDrawBuffer (FrontToBack? GL_BACK : GL_FRONT);
927 glReadBuffer (FrontToBack? GL_FRONT : GL_BACK);
929 glRasterPos2i ((GLint) xmr, (GLint) ymr);
930 glCopyPixels ((GLint) xmr, (GLint) ymr, width, height, GL_COLOR);
934 glMatrixMode (GL_PROJECTION);
936 glMatrixMode (GL_MODELVIEW);
939 glDrawBuffer (GL_BACK);
942 /*----------------------------------------------------------------------*/
944 //call_subr_displayCB
945 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& ACView, int reason)
947 if( ACView.GDisplayCB )
949 Aspect_GraphicCallbackStruct callData;
950 callData.reason = reason;
951 callData.display = (DISPLAY*)myDisplay->GetDisplay();
952 callData.window = (WINDOW)myWindow;
953 callData.wsID = ACView.WsId;
954 callData.viewID = ACView.ViewId;
955 callData.gcontext = myGContext;
957 int status = (*ACView.GDisplayCB)( ACView.DefWindow.XWindow, ACView.GClientData, &callData );
961 /*----------------------------------------------------------------------*/