0022819: Redesign of OpenGl driver Additional integration
[occt.git] / src / OpenGl / OpenGl_Workspace_2.cxx
CommitLineData
2166f0fa
SK
1// File: OpenGl_Workspace_2.cxx
2// Created: 20 September 2011
3// Author: Sergey ZERCHANINOV
4// Copyright: OPEN CASCADE 2011
7fd59977 5
6#define RIC120302 /* GG Enable to use the application display
7// callback at end of traversal
8*/
9
10#include <OpenGl_tgl_all.hxx>
7edf74fd 11#include <OpenGl_FrameBuffer.hxx>
7edf74fd 12#include <TColStd_Array2OfReal.hxx>
7fd59977 13#include <string.h>
2166f0fa 14#include <OpenGl_telem_util.hxx>
7fd59977 15
7edf74fd
A
16#ifdef HAVE_FREEIMAGE
17 #include <NCollection_Handle.hxx>
18 #include <FreeImagePlus.h>
19 #ifdef _MSC_VER
20 #pragma comment( lib, "FreeImage.lib" )
21 #pragma comment( lib, "FreeImagePlus.lib" )
22 #endif
23 typedef NCollection_Handle<fipImage> FipHandle;
24#endif
7fd59977 25
2166f0fa
SK
26#include <OpenGl_PrinterContext.hxx>
27#include <OpenGl_Workspace.hxx>
28#include <OpenGl_View.hxx>
29#include <OpenGl_Display.hxx>
30
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
33
7edf74fd
A
34// ---------------------------------------------------------------
35// Function: getNearestPowOfTwo
36// Purpose: get the nearest power of two for theNumber
37// ---------------------------------------------------------------
38static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
39{
40 GLsizei aLast = 1;
41 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
42 return aLast;
43}
7fd59977 44
7edf74fd
A
45// ---------------------------------------------------------------
46// Function: getMaxFrameSize
47// Purpose: get the maximum possible frame size
48// ---------------------------------------------------------------
49static void getMaxFrameSize(Standard_Integer& theWidth,
50 Standard_Integer& theHeight)
51{
52 GLsizei aMaxX, aMaxY;
53 GLint aVpDim[2];
54 GLint aTexDim = 2048;
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]);
61
62 theWidth = (Standard_Integer)aMaxX;
63 theHeight = (Standard_Integer)aMaxY;
64}
7fd59977 65
7edf74fd
A
66// ---------------------------------------------------------------
67// Function: fitDimensionsRatio
68// Purpose: calculate correct width/height ratio for theWidth and
69// theHeight parameters
70// ---------------------------------------------------------------
71static void fitDimensionsRatio (Standard_Integer& theWidth,
72 Standard_Integer& theHeight,
73 const Standard_Real theViewRatio)
7fd59977 74{
7edf74fd
A
75 // set dimensions in accordance with the viewratio
76 if (theHeight < theWidth/theViewRatio)
77 theWidth = (Standard_Integer)(theHeight*theViewRatio);
78
79 if (theWidth < theHeight*theViewRatio)
80 theHeight = (Standard_Integer)(theWidth/theViewRatio);
7fd59977 81}
82
7edf74fd
A
83// ---------------------------------------------------------------
84// Function: getDimensionsTiling
85// Purpose: calculate maximum possible dimensions for framebuffer
86// in tiling mode according to the view size
87// ---------------------------------------------------------------
88static void getDimensionsTiling (Standard_Integer& theFrameWidth,
89 Standard_Integer& theFrameHeight,
90 const int theViewWidth,
91 const int theViewHeight)
7fd59977 92{
7edf74fd
A
93 // fit the maximum dimensions into the printing area
94 if (theFrameWidth > theViewWidth)
95 theFrameWidth = theViewWidth;
96
97 if (theFrameHeight > theViewHeight)
98 theFrameHeight = theViewHeight;
99}
100
101// ---------------------------------------------------------------
102// Function: initBufferStretch
103// Purpose: calculate initialization sizes for frame buffer
104// when the stretch algorithm is selected
105// ---------------------------------------------------------------
106static void initBufferStretch (Standard_Integer& theFrameWidth,
107 Standard_Integer& theFrameHeight,
108 const int theViewWidth,
109 const int theViewHeight)
110{
111
112 // Calculate correct width/height for framebuffer
113 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
114 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
115
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;
119
120 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
121 (aWidthRate > 1 && aHeightRate <= 1))
122 {
123 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
124 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
125 }
126 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
127 (aWidthRate <= 1 && aHeightRate > 1))
128 {
129 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
130 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
131 }
132
133}
134
135// ---------------------------------------------------------------
136// Function: initBufferTiling
137// Purpose: calculate initialization sizes for frame buffer
138// when the tile algorithm is selected
139// ---------------------------------------------------------------
140static void initBufferTiling (Standard_Integer& theFrameWidth,
141 Standard_Integer &theFrameHeight,
142 const int theViewWidth,
143 const int theViewHeight)
144{
145 // fit framebuffer into the printing area
146 if (theFrameWidth > theViewWidth)
147 theFrameWidth = theViewWidth;
148
149 if (theFrameHeight > theViewHeight)
150 theFrameHeight = theViewHeight;
7fd59977 151}
152
7edf74fd
A
153// ---------------------------------------------------------------
154// Function: initBitmapBuffer
155// Purpose: init device independent bitmap to hold printing data
156// ---------------------------------------------------------------
7fd59977 157#ifdef WNT
7edf74fd
A
158#ifndef HAVE_FREEIMAGE
159static void initBitmapBuffer (const HDC theMemoryDC,
160 HBITMAP &theMemoryBmp,
161 const Standard_Integer theBmpWidth,
162 const Standard_Integer theBmpHeight,
163 VOID* &theBufferPtr)
164{
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;
179
180 // Create Device Independent Bitmap
181 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
182 &theBufferPtr, NULL, 0);
183}
184#else
185// ---------------------------------------------------------------
186// Function: imagePasteDC
187// Purpose: copy the data from image buffer to the device context
188// ---------------------------------------------------------------
189static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
190 int theOffsetY, int theWidth, int theHeight,
191 int theLeft = 0, int theTop = 0)
192{
193 // get image parameters
194 BITMAPINFO* aBitmapData = theImage->getInfo ();
195 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
196
197 // organize blocks data passing if memory isn't enough to pass all the data
198 // at once
199 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
200 aPassed = 0, aInverseLine = 0, aScan = 0;
201 BYTE *aDataPtr = 0;
202 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
203 {
204 // how much lines still to pass
205 aBlockWidth = theHeight - aLinesComplete;
206
207 // normalize count of lines to pass to maximum lines count at one pass.
208 if (aBlockWidth > aMaxBlockWidth)
209 aBlockWidth = aMaxBlockWidth;
210
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);
216 if (!aDataPtr)
217 return false;
218
219 // try to pass block to the device
220 if (aBlockWidth > 0)
221 {
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,
227 0, aBlockWidth,
228 aDataPtr, aBitmapData, DIB_RGB_COLORS);
229
230 // if result is bad, try to decrease band width
231 if (aPassed != aBlockWidth)
232 {
233 aMaxBlockWidth = aMaxBlockWidth >> 1;
234 aLinesComplete = 0;
235 }
236 else
237 aLinesComplete += aBlockWidth;
238 }
7fd59977 239 }
7edf74fd
A
240
241 // check for total failure
242 if (aMaxBlockWidth < 1)
243 return false;
244
245 return true;
7fd59977 246}
7fd59977 247
7edf74fd
A
248// ---------------------------------------------------------------
249// Function: imageStretchDC
250// Purpose: copy pixels from image to dc by stretching them
251// ---------------------------------------------------------------
252static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
253 int theOffsetY, int theWidth, int theHeight)
254{
255 // access to raw image data
256 BYTE *aDataPtr = theImage->accessPixels ();
257 if (!aDataPtr)
258 return false;
259
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);
265
266 // pass lines and check if operation is succesfull
267 int aPassed = 0;
268 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
269 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
270 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
271
272 if (aPassed != heightPx)
273 return false;
274
275 return true;
276}
277#endif
278#endif
7fd59977 279
7edf74fd 280// ---------------------------------------------------------------
7edf74fd 281// ---------------------------------------------------------------
7fd59977 282
2166f0fa
SK
283//call_togl_print
284Standard_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)
293{
7fd59977 294#ifdef WNT
295
2166f0fa 296 if (!Activate())
7edf74fd 297 {
2166f0fa
SK
298 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
299 // "The operation couldn't be completed.", MB_OK);
7edf74fd
A
300 return Standard_False;
301 }
7fd59977 302
7edf74fd 303 // printer page dimensions
2166f0fa 304 HDC hPrnDC = (HDC) hPrintDC;
7edf74fd
A
305 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
306 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
7fd59977 307
7edf74fd
A
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)
311 {
312 // memory dc dimensions
313 BITMAP aBitmapInfo;
314 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
315 if (aMemoryBitmap)
316 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
317 {
318 devWidth = aBitmapInfo.bmWidth;
319 devHeight = aBitmapInfo.bmHeight;
320 }
321 }
7fd59977 322
7edf74fd
A
323 Standard_Integer tempWidth = (Standard_Integer) devWidth;
324 Standard_Integer tempHeight = (Standard_Integer) devHeight;
7fd59977 325
7edf74fd 326 // view dimensions
2166f0fa
SK
327 int viewWidth = myWidth;
328 int viewHeight = myHeight;
7edf74fd 329 if (viewWidth == 0 || viewHeight == 0)
7fd59977 330 {
2166f0fa
SK
331 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
332 // "The operation couldn't be completed.", MB_OK);
7edf74fd
A
333 return Standard_False;
334 }
335
336 // calculate correct width/height ratio
337 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
338 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
339
340 // width and height for printing area
341 int width = (int) (tempWidth * theScaleFactor);
342 int height = (int) (tempHeight * theScaleFactor);
343
344 // device independent bitmap for the whole view
345#ifdef HAVE_FREEIMAGE
346 FipHandle aViewImage = NULL;
347 BYTE* aViewBuffer = NULL;
7fd59977 348#else
7edf74fd
A
349 HDC hMemDC = CreateCompatibleDC (hPrnDC);
350 HBITMAP hViewBitmap = NULL;
351 HGDIOBJ hViewBitmapOld = NULL;
352 VOID* aViewBuffer = NULL;
7fd59977 353#endif
354
7edf74fd
A
355 // Frame buffer initialization
356 OpenGl_FrameBuffer* aFrameBuffer = NULL;
2166f0fa 357 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) ACView.ptrFBO;
7edf74fd
A
358 Standard_Integer aFrameWidth (0), aFrameHeight (0),
359 aPrevBufferX (0), aPrevBufferY (0);
7fd59977 360
2166f0fa
SK
361 bool IsTiling = (printAlgorithm == 1);
362
7edf74fd
A
363 // try to use existing frame buffer
364 if (aPrevBuffer)
365 {
366 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
367 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
368 bool isUsable = false;
369
370 // check if its possible to use previous frame buffer
371 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
7fd59977 372 {
7edf74fd
A
373 aFrameWidth = (Standard_Integer) width;
374 aFrameHeight = (Standard_Integer) height;
375 isUsable = true;
7fd59977 376 }
7edf74fd 377 else if (IsTiling)
7fd59977 378 {
7edf74fd
A
379 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
380 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
381 isUsable = true;
7fd59977 382 }
383
7edf74fd
A
384 // if it is enough memory for image paste dc operation
385 if (isUsable)
7fd59977 386 {
7edf74fd
A
387#ifdef HAVE_FREEIMAGE
388 // try to allocate fipImage and necessary resources
389 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
390 aFrameHeight, 24);
391
392 // if allocated succesfully
393 if (anImagePtr->isValid())
394 {
395 aViewImage = anImagePtr;
396 aViewBuffer = aViewImage->accessPixels ();
397 }
398 else
399 delete anImagePtr;
400
401 if (!aViewBuffer)
402 {
403 isUsable = false;
404 aViewBuffer = NULL;
405 aViewImage = NULL;
406 }
7fd59977 407#else
7edf74fd
A
408 // try to allocate compatible bitmap and necessary resources
409 initBitmapBuffer (hMemDC, hViewBitmap,
410 aFrameWidth, aFrameHeight, aViewBuffer);
411 if (!aViewBuffer)
412 {
413 isUsable = false;
414 if (hViewBitmap)
415 DeleteObject (hViewBitmap);
416 hViewBitmap = NULL;
417 }
418 else
419 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
420#endif
7fd59977 421 }
422
7edf74fd
A
423 // use previous frame buffer
424 if (isUsable)
7fd59977 425 {
7edf74fd
A
426 aPrevBufferX = aPrevWidth;
427 aPrevBufferY = aPrevHeight;
428 aFrameBuffer = aPrevBuffer;
429 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
7fd59977 430 }
7edf74fd 431 }
7fd59977 432
7edf74fd
A
433 // if previous buffer cannot be used, try to init a new one
434 if (!aFrameBuffer)
435 {
436 aFrameBuffer = new OpenGl_FrameBuffer();
7fd59977 437
7edf74fd
A
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)
7fd59977 442 {
7edf74fd
A
443 aFrameWidth = aMaxWidth;
444 aFrameHeight = aMaxHeight;
445
446 // calculate dimensions for different printing algorithms
447 if (!IsTiling)
448 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
449 else
450 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
451
452 // try to initialize framebuffer
2166f0fa 453 if (aFrameBuffer->Init (GetGlContext(), aFrameWidth, aFrameHeight))
7edf74fd
A
454 {
455#ifdef HAVE_FREEIMAGE
456 // try to allocate fipImage and necessary resources
457 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
458 aFrameHeight, 24);
459
460 // if allocated succesfully
461 if (anImagePtr->isValid())
462 {
463 aViewImage = anImagePtr;
464 aViewBuffer = aViewImage->accessPixels ();
465 }
466 else
467 delete anImagePtr;
468
469 if (!aViewBuffer)
470 {
2166f0fa 471 aFrameBuffer->Release (GetGlContext());
7edf74fd
A
472 aViewBuffer = NULL;
473 aViewImage = NULL;
474 }
475 else
476 break;
477#else
478 // try to allocate compatible bitmap and necessary resources
479 initBitmapBuffer (hMemDC, hViewBitmap,
480 aFrameWidth, aFrameHeight, aViewBuffer);
481 if (!aViewBuffer)
482 {
483 if (hViewBitmap)
484 DeleteObject (hViewBitmap);
c320e557 485 aFrameBuffer->Release (GetGlContext());
7edf74fd
A
486 hViewBitmap = NULL;
487 }
488 else
489 {
490 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
491 break;
492 }
7fd59977 493#endif
7edf74fd 494 }
7fd59977 495
7edf74fd
A
496 // not initialized, decrease dimensions
497 aMaxWidth = aMaxWidth >> 1;
498 aMaxHeight = aMaxHeight >> 1;
7fd59977 499 }
500
7edf74fd
A
501 // check if there are proper dimensions
502 if (aMaxWidth <= 1 || aMaxHeight <= 1)
503 {
504 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
505 "The operation couldn't be completed.", MB_OK);
506
507 if (aFrameBuffer)
508 delete aFrameBuffer;
509#ifndef HAVE_FREEIMAGE
510 if (hMemDC)
511 DeleteDC (hMemDC);
7fd59977 512#endif
513
7edf74fd
A
514 return Standard_False;
515 }
516 }
7fd59977 517
7edf74fd
A
518 // setup printing context and viewport
519 GLint aViewPortBack[4];
520 GLint aReadBufferPrev = GL_BACK;
521 GLint anAlignBack = 1;
2166f0fa
SK
522
523 OpenGl_PrinterContext aPrinterContext (myGContext);
7edf74fd
A
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);
529
530 // start document if the printer context is not actually a memory dc
531 // (memory dc could be used for testing purposes)
2166f0fa 532 DOCINFO di;
7edf74fd
A
533 if (GetObjectType (hPrnDC) == OBJ_DC)
534 {
535 // Initalize printing procedure
7fd59977 536 di.cbSize = sizeof(DOCINFO);
7edf74fd 537 di.lpszDocName = "Open Cascade Document - print v3d view";
7fd59977 538 di.lpszOutput = filename;
539
7edf74fd
A
540 // if can't print the document
541 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
542 {
543 MessageBox (NULL, "Print failed: printer can't start operation.",
544 "The operation couldn't be completed.", MB_OK);
545#ifndef HAVE_FREEIMAGE
546 if (hViewBitmap)
547 {
548 SelectObject (hMemDC, hViewBitmapOld);
549 DeleteObject (hViewBitmap);
550 }
551 DeleteDC (hMemDC);
552#endif
7fd59977 553
7edf74fd
A
554 return Standard_False;
555 }
556 }
7fd59977 557
7edf74fd 558 // activate the offscreen buffer
2166f0fa 559 aFrameBuffer->BindBuffer (GetGlContext());
7fd59977 560
7edf74fd
A
561 // calculate offset for centered printing
562 int aDevOffx = (int)(devWidth - width) /2;
563 int aDevOffy = (int)(devHeight - height)/2;
7fd59977 564
7edf74fd
A
565 // operation complete flag
566 bool isDone = true;
2166f0fa
SK
567
568 // Set up status for printing
569 NamedStatus |= OPENGL_NS_ISBITMAP;
570 if (!showBackground)
571 NamedStatus |= OPENGL_NS_WHITEBACK;
572
7edf74fd
A
573 if (!IsTiling)
574 {
575 aPrinterContext.SetScale ((GLfloat)aFrameWidth /viewWidth,
576 (GLfloat)aFrameHeight/viewHeight);
577 aFrameBuffer->SetupViewport ();
2166f0fa
SK
578 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
579 RedrawImmediatMode();
7edf74fd
A
580 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
581 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
582
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,
588 width, height);
7fd59977 589#else
7edf74fd 590 if (width > aFrameWidth && height > aFrameHeight)
7fd59977 591 {
7edf74fd
A
592 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
593 isDone = StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
594 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY);
7fd59977 595 }
7edf74fd 596 else
7fd59977 597 {
7edf74fd
A
598 isDone = BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
599 hMemDC, 0, 0, SRCCOPY);
7fd59977 600 }
7edf74fd
A
601#endif
602 }
603 else
604 {
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)
7fd59977 613 {
7edf74fd
A
614 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
615 aTotalx++;
7fd59977 616 }
7edf74fd 617 if (height%aFrameHeight != 0)
7fd59977 618 {
7edf74fd
A
619 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
620 aTotaly++;
7fd59977 621 }
7edf74fd
A
622
623 int anOddPixelx = (width %aFrameWidth) %2;
624 int anOddPixely = (height%aFrameHeight)%2;
625
626 // calculate scale factor for full frames
627 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
628 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
629
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);
635
636 // initialize projection matrix for printer context
637 TColStd_Array2OfReal aProj (0, 3, 0, 3);
638 Standard_Real aDef = 0;
639 aProj.Init (aDef);
640 aProj(2,2) = 1.0;
641 aProj(3,3) = 1.0;
642
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);
648
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;
654
655 // draw sequence of full frames
656 for (int i = 0; i < aTotalx; i++)
7fd59977 657 {
7edf74fd
A
658 // offsets are even numbers
659 aOffsety = -(aTotaly-1);
660 aSubTop = (Standard_Integer)aDevOffy;
661
662 // calculate cropped frame rect
663 aLeft = (i == 0) ? aPxCropx : 0;
664 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
665 aFrameWidth;
666
667 for (int j = 0; j < aTotaly; j++)
668 {
669 // no offset for single frames
670 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
671 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
672
673 // set projection matrix
674 aProj(0,0) = aScalex;
675 aProj(1,1) = aScaley;
676 aPrinterContext.SetProjTransformation (aProj);
677
678 // calculate cropped frame rect
679 aTop = (j == 0) ? aPxCropy : 0;
680 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
681 aFrameHeight;
682
683 // draw to the offscreen buffer and capture the result
684 aFrameBuffer->SetupViewport ();
2166f0fa
SK
685 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
686 RedrawImmediatMode();
7edf74fd
A
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);
693#else
694 isDone = BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
695 hMemDC, aLeft, aTop, SRCCOPY);
696#endif
697
698 // stop operation if errors
699 if (!isDone)
700 break;
701
702 // calculate new view offset for y-coordinate
703 aOffsety += 2.0;
704 aSubTop += aBottom-aTop;
705 }
706
707 // stop operation if errors
708 if (!isDone)
709 break;
710
711 // calculate new view offset for x-coordinate
712 aOffsetx += 2.0;
713 aSubLeft += aRight-aLeft;
7fd59977 714 }
7edf74fd 715 }
7fd59977 716
7edf74fd
A
717 // complete printing or indicate an error
718 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
719 {
720 EndPage (hPrnDC);
721 EndDoc (hPrnDC);
7fd59977 722 }
7edf74fd
A
723 else if (isDone == false)
724 {
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)
728 AbortDoc (hPrnDC);
729 }
730
731 // return OpenGl to the previous state
732 aPrinterContext.Deactivate ();
733 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
2166f0fa 734 aFrameBuffer->UnbindBuffer (GetGlContext());
7edf74fd
A
735 glViewport (aViewPortBack[0], aViewPortBack[1],
736 aViewPortBack[2], aViewPortBack[3]);
737 if (aPrevBuffer)
738 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
739 else
740 delete aFrameBuffer;
741
742 // delete resources
743#ifndef HAVE_FREEIMAGE
744 if (hViewBitmap)
745 {
746 SelectObject (hMemDC, hViewBitmapOld);
747 DeleteObject (hViewBitmap);
748 }
749 DeleteDC (hMemDC);
750#endif
751
2166f0fa
SK
752 // Reset status after printing
753 NamedStatus &= ~(OPENGL_NS_WHITEBACK | OPENGL_NS_ISBITMAP);
754
7edf74fd 755 return (Standard_Boolean) isDone;
7fd59977 756
7edf74fd
A
757#else // not WNT
758 return Standard_False;
759#endif
7fd59977 760}
7edf74fd 761
2166f0fa
SK
762/*----------------------------------------------------------------------*/
763
764//redrawView
765void OpenGl_Workspace::Redraw1 (const Graphic3d_CView& ACView,
766 const Aspect_CLayer2d& ACUnderLayer,
767 const Aspect_CLayer2d& ACOverLayer,
768 const int aswap)
769{
770 if (myDisplay.IsNull() || myView.IsNull())
771 return;
772
773 myDisplay->UpdateUserMarkers();
774
775 // Request reset of material
776 NamedStatus |= OPENGL_NS_RESMAT;
777
778 /* GL_DITHER on/off pour le background */
779 if (myBackDither)
780 glEnable (GL_DITHER);
781 else
782 glDisable (GL_DITHER);
783
784 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
785 if ( myUseZBuffer )
786 {
787 glDepthFunc(GL_LEQUAL);
788 glDepthMask(GL_TRUE);
789
790 // SAV checking if depth test was deprecated somewhere outside
791 if ( myUseDepthTest )
792 glEnable(GL_DEPTH_TEST);
793 else
794 glDisable(GL_DEPTH_TEST);
795
796 glClearDepth(1.0);
797 toClear |= GL_DEPTH_BUFFER_BIT;
798 }
799 else
800 {
801 glDisable(GL_DEPTH_TEST);
802 }
803
804 if ( NamedStatus & OPENGL_NS_WHITEBACK )
805 {
806 // Set background to white
807 glClearColor (1.F, 1.F, 1.F, 1.F);
808 toClear |= GL_DEPTH_BUFFER_BIT;
809 }
810 else
811 {
812 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.F);
813 }
814 glClear (toClear);
815
816 Handle(OpenGl_Workspace) aWS(this);
817 myView->Render(aWS,ACView,ACUnderLayer,ACOverLayer);
818
819 // Swap the buffers
820 if ( aswap )
821 {
822#ifndef WNT
823 glXSwapBuffers ((Display*)myDisplay->GetDisplay (), myWindow );
824#else
825 SwapBuffers ( wglGetCurrentDC () );
826 glFlush();
827#endif /* WNT */
828 myBackBufferRestored = Standard_False;
829 }
830 else
831 glFlush();
832
833 myIsUpdated = Standard_True;
834}
835
836/*----------------------------------------------------------------------*/
837
838//TelCopyBuffers
839void OpenGl_Workspace::CopyBuffers (Tint vid, int FrontToBack, Tfloat xm, Tfloat ym, Tfloat zm, Tfloat XM, Tfloat YM, Tfloat ZM, Tint flag)
840{
841 if (FrontToBack) myBackBufferRestored = Standard_False;
842
843 glMatrixMode (GL_PROJECTION);
844 glPushMatrix ();
845 glLoadIdentity ();
846 gluOrtho2D ((GLdouble) 0., (GLdouble) myWidth, 0., (GLdouble) myHeight);
847 glMatrixMode (GL_MODELVIEW);
848 glPushMatrix ();
849 glLoadIdentity ();
850
851 DisableFeatures();
852
853 GLsizei width = myWidth+1, height = myHeight+1;
854 Tfloat xmr = 0, ymr = 0;
855
856 if (flag)
857 {
858 if (!myView.IsNull()) //szvgl: use vid here!
859 {
860 // Calculate bounding box and store the projected rectangle
861 Tfloat xr[8], yr[8];
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]))
871 {
872 Tfloat XMR, YMR;
873 xmr = ymr = (float ) shortreallast ();
874 XMR = YMR = (float ) shortrealfirst ();
875 /*
876 * Recherche du rectangle projete
877 */
878 Tint i;
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];
884 }
885 /* pour eviter les bavures de pixels ! */
886 xmr--;ymr--;
887 XMR++;YMR++;
888
889 /*
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 !
898 */
899 xmr -= CALL_DEF_DELTA; ymr -= CALL_DEF_DELTA;
900 XMR += CALL_DEF_DELTA; YMR += CALL_DEF_DELTA;
901
902 /*
903 * Le rectangle projete peut-etre clippe
904 */
905 width = (GLsizei) (XMR-xmr+1);
906 height = (GLsizei) (YMR-ymr+1);
907 /*
908 * (xmr,ymr) coin inferieur gauche
909 * (XMR,YMR) coin superieur droit
910 */
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); }
916
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; }
922 }
923 }
924 }
925
926 glDrawBuffer (FrontToBack? GL_BACK : GL_FRONT);
927 glReadBuffer (FrontToBack? GL_FRONT : GL_BACK);
928 /* copie complete */
929 glRasterPos2i ((GLint) xmr, (GLint) ymr);
930 glCopyPixels ((GLint) xmr, (GLint) ymr, width, height, GL_COLOR);
931
932 EnableFeatures();
933
934 glMatrixMode (GL_PROJECTION);
935 glPopMatrix ();
936 glMatrixMode (GL_MODELVIEW);
937 glPopMatrix ();
938
939 glDrawBuffer (GL_BACK);
940}
941
942/*----------------------------------------------------------------------*/
943
944//call_subr_displayCB
945void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& ACView, int reason)
946{
947 if( ACView.GDisplayCB )
948 {
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;
956
957 int status = (*ACView.GDisplayCB)( ACView.DefWindow.XWindow, ACView.GClientData, &callData );
958 }
959}
960
961/*----------------------------------------------------------------------*/