0024298: Eliminate GCC compiler warning about unused in linux functions
[occt.git] / src / OpenGl / OpenGl_Workspace_2.cxx
CommitLineData
b311480e 1// Created on: 2011-09-20
2// Created by: Sergey ZERCHANINOV
3// Copyright (c) 2011-2012 OPEN CASCADE SAS
4//
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.
9//
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.
12//
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.
19
7fd59977 20
5f8b738e 21#include <OpenGl_GlCore11.hxx>
7fd59977 22
7edf74fd 23#include <OpenGl_FrameBuffer.hxx>
7edf74fd 24#include <TColStd_Array2OfReal.hxx>
2166f0fa 25#include <OpenGl_telem_util.hxx>
7fd59977 26
498ce577 27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
4fe56619 31#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_FREEIMAGE)
7edf74fd
A
32 #include <NCollection_Handle.hxx>
33 #include <FreeImagePlus.h>
34 #ifdef _MSC_VER
4fe56619 35 #pragma comment( lib, "FreeImage.lib" )
36 #pragma comment( lib, "FreeImagePlus.lib" )
7edf74fd
A
37 #endif
38 typedef NCollection_Handle<fipImage> FipHandle;
39#endif
7fd59977 40
2166f0fa
SK
41#include <OpenGl_PrinterContext.hxx>
42#include <OpenGl_Workspace.hxx>
43#include <OpenGl_View.hxx>
44#include <OpenGl_Display.hxx>
45
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
48
7edf74fd
A
49// ---------------------------------------------------------------
50// Function: getNearestPowOfTwo
51// Purpose: get the nearest power of two for theNumber
52// ---------------------------------------------------------------
53static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
54{
55 GLsizei aLast = 1;
56 for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
57 return aLast;
58}
7fd59977 59
7edf74fd
A
60// ---------------------------------------------------------------
61// Function: fitDimensionsRatio
62// Purpose: calculate correct width/height ratio for theWidth and
63// theHeight parameters
64// ---------------------------------------------------------------
65static void fitDimensionsRatio (Standard_Integer& theWidth,
66 Standard_Integer& theHeight,
67 const Standard_Real theViewRatio)
7fd59977 68{
7edf74fd
A
69 // set dimensions in accordance with the viewratio
70 if (theHeight < theWidth/theViewRatio)
71 theWidth = (Standard_Integer)(theHeight*theViewRatio);
72
73 if (theWidth < theHeight*theViewRatio)
74 theHeight = (Standard_Integer)(theWidth/theViewRatio);
7fd59977 75}
76
7edf74fd
A
77// ---------------------------------------------------------------
78// Function: initBitmapBuffer
79// Purpose: init device independent bitmap to hold printing data
80// ---------------------------------------------------------------
47afc367 81#ifdef _WIN32
7edf74fd
A
82#ifndef HAVE_FREEIMAGE
83static void initBitmapBuffer (const HDC theMemoryDC,
84 HBITMAP &theMemoryBmp,
85 const Standard_Integer theBmpWidth,
86 const Standard_Integer theBmpHeight,
87 VOID* &theBufferPtr)
88{
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;
103
104 // Create Device Independent Bitmap
105 theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
106 &theBufferPtr, NULL, 0);
107}
108#else
109// ---------------------------------------------------------------
110// Function: imagePasteDC
111// Purpose: copy the data from image buffer to the device context
112// ---------------------------------------------------------------
113static bool imagePasteDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
4fe56619 114 int theOffsetY, int theWidth, int theHeight,
7edf74fd
A
115 int theLeft = 0, int theTop = 0)
116{
117 // get image parameters
118 BITMAPINFO* aBitmapData = theImage->getInfo ();
119 SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
4fe56619 120
7edf74fd
A
121 // organize blocks data passing if memory isn't enough to pass all the data
122 // at once
123 int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
124 aPassed = 0, aInverseLine = 0, aScan = 0;
125 BYTE *aDataPtr = 0;
126 while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
127 {
128 // how much lines still to pass
129 aBlockWidth = theHeight - aLinesComplete;
130
131 // normalize count of lines to pass to maximum lines count at one pass.
132 if (aBlockWidth > aMaxBlockWidth)
133 aBlockWidth = aMaxBlockWidth;
134
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);
140 if (!aDataPtr)
141 return false;
142
143 // try to pass block to the device
144 if (aBlockWidth > 0)
145 {
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,
151 0, aBlockWidth,
152 aDataPtr, aBitmapData, DIB_RGB_COLORS);
153
154 // if result is bad, try to decrease band width
155 if (aPassed != aBlockWidth)
156 {
157 aMaxBlockWidth = aMaxBlockWidth >> 1;
158 aLinesComplete = 0;
159 }
160 else
161 aLinesComplete += aBlockWidth;
162 }
7fd59977 163 }
7edf74fd
A
164
165 // check for total failure
166 if (aMaxBlockWidth < 1)
167 return false;
168
169 return true;
7fd59977 170}
7fd59977 171
7edf74fd
A
172// ---------------------------------------------------------------
173// Function: imageStretchDC
174// Purpose: copy pixels from image to dc by stretching them
175// ---------------------------------------------------------------
176static bool imageStretchDC(HDC theDstDC, FipHandle theImage, int theOffsetX,
177 int theOffsetY, int theWidth, int theHeight)
178{
179 // access to raw image data
180 BYTE *aDataPtr = theImage->accessPixels ();
181 if (!aDataPtr)
182 return false;
183
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);
4fe56619 189
7edf74fd
A
190 // pass lines and check if operation is succesfull
191 int aPassed = 0;
192 aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
193 theHeight, 0, 0, widthPx, heightPx, aDataPtr,
194 aBitmapData, DIB_RGB_COLORS, SRCCOPY);
195
105aae76 196 if ((unsigned)aPassed != heightPx)
7edf74fd 197 return false;
4fe56619 198
7edf74fd
A
199 return true;
200}
201#endif
47afc367 202
203// ---------------------------------------------------------------
204// Function: getMaxFrameSize
205// Purpose: get the maximum possible frame size
206// ---------------------------------------------------------------
207static void getMaxFrameSize(Standard_Integer& theWidth,
208 Standard_Integer& theHeight)
209{
210 GLsizei aMaxX, aMaxY;
211 GLint aVpDim[2];
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]);
219
220 theWidth = (Standard_Integer)aMaxX;
221 theHeight = (Standard_Integer)aMaxY;
222}
223// ---------------------------------------------------------------
224// Function: getDimensionsTiling
225// Purpose: calculate maximum possible dimensions for framebuffer
226// in tiling mode according to the view size
227// ---------------------------------------------------------------
228static void getDimensionsTiling (Standard_Integer& theFrameWidth,
229 Standard_Integer& theFrameHeight,
230 const int theViewWidth,
231 const int theViewHeight)
232{
233 // fit the maximum dimensions into the printing area
234 if (theFrameWidth > theViewWidth)
235 theFrameWidth = theViewWidth;
236
237 if (theFrameHeight > theViewHeight)
238 theFrameHeight = theViewHeight;
239}
240// ---------------------------------------------------------------
241// Function: initBufferStretch
242// Purpose: calculate initialization sizes for frame buffer
243// when the stretch algorithm is selected
244// ---------------------------------------------------------------
245static void initBufferStretch (Standard_Integer& theFrameWidth,
246 Standard_Integer& theFrameHeight,
247 const int theViewWidth,
248 const int theViewHeight)
249{
250
251 // Calculate correct width/height for framebuffer
252 Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
253 fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
254
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;
258
259 if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) ||
260 (aWidthRate > 1 && aHeightRate <= 1))
261 {
262 theFrameWidth = (Standard_Integer)(theFrameWidth /aWidthRate);
263 theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
264 }
265 else if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
266 (aWidthRate <= 1 && aHeightRate > 1))
267 {
268 theFrameWidth = (Standard_Integer)(theFrameWidth /aHeightRate);
269 theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
270 }
271}
272// ---------------------------------------------------------------
273// Function: initBufferTiling
274// Purpose: calculate initialization sizes for frame buffer
275// when the tile algorithm is selected
276// ---------------------------------------------------------------
277static void initBufferTiling (Standard_Integer& theFrameWidth,
278 Standard_Integer &theFrameHeight,
279 const int theViewWidth,
280 const int theViewHeight)
281{
282 // fit framebuffer into the printing area
283 if (theFrameWidth > theViewWidth)
284 theFrameWidth = theViewWidth;
285
286 if (theFrameHeight > theViewHeight)
287 theFrameHeight = theViewHeight;
288}
7edf74fd 289#endif
7fd59977 290
7edf74fd 291// ---------------------------------------------------------------
7edf74fd 292// ---------------------------------------------------------------
7fd59977 293
2166f0fa 294//call_togl_print
47afc367 295
2166f0fa 296Standard_Boolean OpenGl_Workspace::Print
a174a3c5 297 (const Handle(OpenGl_PrinterContext)& thePrintContext,
298 const Graphic3d_CView& ACView,
4fe56619 299 const Aspect_CLayer2d& ACUnderLayer,
2166f0fa
SK
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)
306{
a174a3c5 307 if (thePrintContext.IsNull())
308 {
309 return Standard_False;
310 }
311
47afc367 312#ifdef _WIN32
7fd59977 313
2166f0fa 314 if (!Activate())
7edf74fd 315 {
2166f0fa
SK
316 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
317 // "The operation couldn't be completed.", MB_OK);
7edf74fd
A
318 return Standard_False;
319 }
7fd59977 320
7edf74fd 321 // printer page dimensions
2166f0fa 322 HDC hPrnDC = (HDC) hPrintDC;
7edf74fd
A
323 int devWidth = GetDeviceCaps (hPrnDC, HORZRES);
324 int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
7fd59977 325
7edf74fd
A
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)
329 {
330 // memory dc dimensions
331 BITMAP aBitmapInfo;
332 HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
333 if (aMemoryBitmap)
334 if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
335 {
336 devWidth = aBitmapInfo.bmWidth;
337 devHeight = aBitmapInfo.bmHeight;
338 }
339 }
7fd59977 340
7edf74fd
A
341 Standard_Integer tempWidth = (Standard_Integer) devWidth;
342 Standard_Integer tempHeight = (Standard_Integer) devHeight;
7fd59977 343
7edf74fd 344 // view dimensions
2166f0fa
SK
345 int viewWidth = myWidth;
346 int viewHeight = myHeight;
7edf74fd 347 if (viewWidth == 0 || viewHeight == 0)
7fd59977 348 {
2166f0fa
SK
349 //MessageBox (NULL, "Print failed: can't setup the view for printing.",
350 // "The operation couldn't be completed.", MB_OK);
7edf74fd
A
351 return Standard_False;
352 }
353
354 // calculate correct width/height ratio
355 Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
356 fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
357
358 // width and height for printing area
359 int width = (int) (tempWidth * theScaleFactor);
360 int height = (int) (tempHeight * theScaleFactor);
361
362 // device independent bitmap for the whole view
363#ifdef HAVE_FREEIMAGE
364 FipHandle aViewImage = NULL;
365 BYTE* aViewBuffer = NULL;
7fd59977 366#else
7edf74fd
A
367 HDC hMemDC = CreateCompatibleDC (hPrnDC);
368 HBITMAP hViewBitmap = NULL;
369 HGDIOBJ hViewBitmapOld = NULL;
370 VOID* aViewBuffer = NULL;
7fd59977 371#endif
372
7edf74fd
A
373 // Frame buffer initialization
374 OpenGl_FrameBuffer* aFrameBuffer = NULL;
2166f0fa 375 OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) ACView.ptrFBO;
7edf74fd
A
376 Standard_Integer aFrameWidth (0), aFrameHeight (0),
377 aPrevBufferX (0), aPrevBufferY (0);
7fd59977 378
2166f0fa
SK
379 bool IsTiling = (printAlgorithm == 1);
380
7edf74fd
A
381 // try to use existing frame buffer
382 if (aPrevBuffer)
383 {
384 GLsizei aPrevWidth = aPrevBuffer->GetSizeX();
385 GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
386 bool isUsable = false;
387
388 // check if its possible to use previous frame buffer
389 if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
7fd59977 390 {
7edf74fd
A
391 aFrameWidth = (Standard_Integer) width;
392 aFrameHeight = (Standard_Integer) height;
393 isUsable = true;
7fd59977 394 }
7edf74fd 395 else if (IsTiling)
7fd59977 396 {
7edf74fd
A
397 getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
398 if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
399 isUsable = true;
7fd59977 400 }
401
7edf74fd
A
402 // if it is enough memory for image paste dc operation
403 if (isUsable)
7fd59977 404 {
7edf74fd
A
405#ifdef HAVE_FREEIMAGE
406 // try to allocate fipImage and necessary resources
407 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
408 aFrameHeight, 24);
409
410 // if allocated succesfully
411 if (anImagePtr->isValid())
412 {
413 aViewImage = anImagePtr;
414 aViewBuffer = aViewImage->accessPixels ();
415 }
416 else
417 delete anImagePtr;
418
419 if (!aViewBuffer)
420 {
421 isUsable = false;
422 aViewBuffer = NULL;
423 aViewImage = NULL;
424 }
7fd59977 425#else
7edf74fd 426 // try to allocate compatible bitmap and necessary resources
4fe56619 427 initBitmapBuffer (hMemDC, hViewBitmap,
7edf74fd
A
428 aFrameWidth, aFrameHeight, aViewBuffer);
429 if (!aViewBuffer)
430 {
431 isUsable = false;
432 if (hViewBitmap)
433 DeleteObject (hViewBitmap);
434 hViewBitmap = NULL;
435 }
436 else
437 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
438#endif
7fd59977 439 }
440
7edf74fd
A
441 // use previous frame buffer
442 if (isUsable)
7fd59977 443 {
7edf74fd
A
444 aPrevBufferX = aPrevWidth;
445 aPrevBufferY = aPrevHeight;
446 aFrameBuffer = aPrevBuffer;
447 aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
7fd59977 448 }
7edf74fd 449 }
7fd59977 450
7edf74fd
A
451 // if previous buffer cannot be used, try to init a new one
452 if (!aFrameBuffer)
453 {
454 aFrameBuffer = new OpenGl_FrameBuffer();
7fd59977 455
7edf74fd
A
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)
7fd59977 460 {
7edf74fd
A
461 aFrameWidth = aMaxWidth;
462 aFrameHeight = aMaxHeight;
463
464 // calculate dimensions for different printing algorithms
465 if (!IsTiling)
466 initBufferStretch (aFrameWidth, aFrameHeight, width, height);
467 else
468 initBufferTiling (aFrameWidth, aFrameHeight, width, height);
469
470 // try to initialize framebuffer
2166f0fa 471 if (aFrameBuffer->Init (GetGlContext(), aFrameWidth, aFrameHeight))
7edf74fd
A
472 {
473#ifdef HAVE_FREEIMAGE
474 // try to allocate fipImage and necessary resources
475 fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
476 aFrameHeight, 24);
477
478 // if allocated succesfully
479 if (anImagePtr->isValid())
480 {
481 aViewImage = anImagePtr;
482 aViewBuffer = aViewImage->accessPixels ();
483 }
484 else
485 delete anImagePtr;
486
487 if (!aViewBuffer)
488 {
fd4a6963 489 aFrameBuffer->Release (GetGlContext().operator->());
7edf74fd
A
490 aViewBuffer = NULL;
491 aViewImage = NULL;
492 }
493 else
494 break;
495#else
496 // try to allocate compatible bitmap and necessary resources
4fe56619 497 initBitmapBuffer (hMemDC, hViewBitmap,
7edf74fd
A
498 aFrameWidth, aFrameHeight, aViewBuffer);
499 if (!aViewBuffer)
500 {
501 if (hViewBitmap)
502 DeleteObject (hViewBitmap);
fd4a6963 503 aFrameBuffer->Release (GetGlContext().operator->());
7edf74fd
A
504 hViewBitmap = NULL;
505 }
506 else
507 {
508 hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
509 break;
510 }
7fd59977 511#endif
7edf74fd 512 }
7fd59977 513
7edf74fd
A
514 // not initialized, decrease dimensions
515 aMaxWidth = aMaxWidth >> 1;
516 aMaxHeight = aMaxHeight >> 1;
7fd59977 517 }
518
4fe56619 519 // check if there are proper dimensions
7edf74fd
A
520 if (aMaxWidth <= 1 || aMaxHeight <= 1)
521 {
522 MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
523 "The operation couldn't be completed.", MB_OK);
524
525 if (aFrameBuffer)
526 delete aFrameBuffer;
527#ifndef HAVE_FREEIMAGE
528 if (hMemDC)
529 DeleteDC (hMemDC);
7fd59977 530#endif
531
7edf74fd
A
532 return Standard_False;
533 }
534 }
7fd59977 535
7edf74fd 536 // setup printing context and viewport
a174a3c5 537 myPrintContext = thePrintContext;
4fe56619 538 GLint aViewPortBack[4];
5e27df78 539 GLint anAlignBack = 1;
a174a3c5 540 myPrintContext->SetLayerViewport ((GLsizei )aFrameWidth,
541 (GLsizei )aFrameHeight);
7edf74fd
A
542 glGetIntegerv (GL_VIEWPORT, aViewPortBack);
543 glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
544 glPixelStorei (GL_PACK_ALIGNMENT, 4);
545
546 // start document if the printer context is not actually a memory dc
547 // (memory dc could be used for testing purposes)
2166f0fa 548 DOCINFO di;
7edf74fd
A
549 if (GetObjectType (hPrnDC) == OBJ_DC)
550 {
551 // Initalize printing procedure
7fd59977 552 di.cbSize = sizeof(DOCINFO);
7edf74fd 553 di.lpszDocName = "Open Cascade Document - print v3d view";
7fd59977 554 di.lpszOutput = filename;
555
7edf74fd
A
556 // if can't print the document
557 if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
558 {
559 MessageBox (NULL, "Print failed: printer can't start operation.",
560 "The operation couldn't be completed.", MB_OK);
561#ifndef HAVE_FREEIMAGE
562 if (hViewBitmap)
563 {
564 SelectObject (hMemDC, hViewBitmapOld);
565 DeleteObject (hViewBitmap);
566 }
567 DeleteDC (hMemDC);
568#endif
7fd59977 569
a174a3c5 570 myPrintContext.Nullify();
7edf74fd
A
571 return Standard_False;
572 }
573 }
7fd59977 574
7edf74fd 575 // activate the offscreen buffer
2166f0fa 576 aFrameBuffer->BindBuffer (GetGlContext());
7fd59977 577
7edf74fd
A
578 // calculate offset for centered printing
579 int aDevOffx = (int)(devWidth - width) /2;
580 int aDevOffy = (int)(devHeight - height)/2;
7fd59977 581
7edf74fd
A
582 // operation complete flag
583 bool isDone = true;
2166f0fa
SK
584
585 // Set up status for printing
2166f0fa
SK
586 if (!showBackground)
587 NamedStatus |= OPENGL_NS_WHITEBACK;
588
7edf74fd
A
589 if (!IsTiling)
590 {
a174a3c5 591 myPrintContext->SetScale ((GLfloat )aFrameWidth /viewWidth,
592 (GLfloat )aFrameHeight/viewHeight);
fd4a6963 593 aFrameBuffer->SetupViewport (GetGlContext());
2166f0fa 594 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
1981cb22 595 if (!myTransientDrawToFront)
596 {
597 // render to FBO only if allowed to render to back buffer
598 RedrawImmediatMode();
599 }
7edf74fd
A
600 glReadPixels (0, 0, aFrameWidth, aFrameHeight,
601 GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
602
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,
608 width, height);
7fd59977 609#else
7edf74fd 610 if (width > aFrameWidth && height > aFrameHeight)
7fd59977 611 {
7edf74fd 612 SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
6de552e6 613 isDone = (StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
614 hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY) != 0); // to avoid warning C4800
7fd59977 615 }
7edf74fd 616 else
7fd59977 617 {
6de552e6 618 isDone = (BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
619 hMemDC, 0, 0, SRCCOPY) != 0); // to avoid warning C4800
7fd59977 620 }
7edf74fd
A
621#endif
622 }
623 else
624 {
625 // calculate total count of frames and cropping size
626 Standard_Integer aPxCropx = 0;
627 Standard_Integer aPxCropy = 0;
4fe56619 628 Standard_Integer aTotalx =
7edf74fd 629 (Standard_Integer)floor ((float)width /aFrameWidth);
4fe56619 630 Standard_Integer aTotaly =
7edf74fd
A
631 (Standard_Integer)floor ((float)height/aFrameHeight);
632 if (width %aFrameWidth != 0)
7fd59977 633 {
7edf74fd
A
634 aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
635 aTotalx++;
7fd59977 636 }
7edf74fd 637 if (height%aFrameHeight != 0)
7fd59977 638 {
7edf74fd
A
639 aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
640 aTotaly++;
7fd59977 641 }
7edf74fd
A
642
643 int anOddPixelx = (width %aFrameWidth) %2;
644 int anOddPixely = (height%aFrameHeight)%2;
645
646 // calculate scale factor for full frames
647 Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
648 Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
649
650 // calculate and set the text scaling factor for printing context
651 GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
652 GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
a174a3c5 653 myPrintContext->SetScale (aScaleRatex * (GLfloat )aScalex,
654 aScaleRatey * (GLfloat )aScaley);
7edf74fd
A
655
656 // initialize projection matrix for printer context
657 TColStd_Array2OfReal aProj (0, 3, 0, 3);
658 Standard_Real aDef = 0;
659 aProj.Init (aDef);
660 aProj(2,2) = 1.0;
661 aProj(3,3) = 1.0;
662
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);
668
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;
674
675 // draw sequence of full frames
676 for (int i = 0; i < aTotalx; i++)
7fd59977 677 {
7edf74fd
A
678 // offsets are even numbers
679 aOffsety = -(aTotaly-1);
680 aSubTop = (Standard_Integer)aDevOffy;
681
682 // calculate cropped frame rect
683 aLeft = (i == 0) ? aPxCropx : 0;
684 aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
685 aFrameWidth;
686
687 for (int j = 0; j < aTotaly; j++)
688 {
689 // no offset for single frames
690 aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
691 aProj(3,1) = (aTotaly == 1) ? 0 : aOffsety;
692
693 // set projection matrix
694 aProj(0,0) = aScalex;
695 aProj(1,1) = aScaley;
a174a3c5 696 myPrintContext->SetProjTransformation (aProj);
7edf74fd
A
697
698 // calculate cropped frame rect
699 aTop = (j == 0) ? aPxCropy : 0;
700 aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
701 aFrameHeight;
702
703 // draw to the offscreen buffer and capture the result
fd4a6963 704 aFrameBuffer->SetupViewport (GetGlContext());
2166f0fa 705 Redraw1(ACView, ACUnderLayer, ACOverLayer, 0);
1981cb22 706 if (!myTransientDrawToFront)
707 {
708 // render to FBO only if forces to render to back buffer
709 RedrawImmediatMode();
710 }
7edf74fd
A
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);
717#else
6de552e6 718 isDone = (BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
719 hMemDC, aLeft, aTop, SRCCOPY) != 0); // to avoid warning C4800
7edf74fd
A
720#endif
721
722 // stop operation if errors
723 if (!isDone)
724 break;
725
726 // calculate new view offset for y-coordinate
727 aOffsety += 2.0;
728 aSubTop += aBottom-aTop;
729 }
730
731 // stop operation if errors
732 if (!isDone)
733 break;
4fe56619 734
7edf74fd
A
735 // calculate new view offset for x-coordinate
736 aOffsetx += 2.0;
737 aSubLeft += aRight-aLeft;
7fd59977 738 }
7edf74fd 739 }
7fd59977 740
7edf74fd
A
741 // complete printing or indicate an error
742 if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
743 {
744 EndPage (hPrnDC);
745 EndDoc (hPrnDC);
7fd59977 746 }
7edf74fd
A
747 else if (isDone == false)
748 {
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)
752 AbortDoc (hPrnDC);
753 }
4fe56619 754
7edf74fd 755 // return OpenGl to the previous state
7edf74fd 756 glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
2166f0fa 757 aFrameBuffer->UnbindBuffer (GetGlContext());
4fe56619 758 glViewport (aViewPortBack[0], aViewPortBack[1],
7edf74fd
A
759 aViewPortBack[2], aViewPortBack[3]);
760 if (aPrevBuffer)
96352003 761 {
7edf74fd 762 aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
96352003 763 }
7edf74fd 764 else
96352003 765 {
fd4a6963 766 aFrameBuffer->Release (GetGlContext().operator->());
7edf74fd 767 delete aFrameBuffer;
96352003 768 }
7edf74fd
A
769
770 // delete resources
771#ifndef HAVE_FREEIMAGE
772 if (hViewBitmap)
773 {
774 SelectObject (hMemDC, hViewBitmapOld);
775 DeleteObject (hViewBitmap);
776 }
777 DeleteDC (hMemDC);
778#endif
779
2166f0fa 780 // Reset status after printing
529afc1a 781 NamedStatus &= ~OPENGL_NS_WHITEBACK;
2166f0fa 782
a174a3c5 783 myPrintContext.Nullify();
7edf74fd 784 return (Standard_Boolean) isDone;
7fd59977 785
47afc367 786#else // not _WIN32
a174a3c5 787 myPrintContext.Nullify();
7edf74fd 788 return Standard_False;
4fe56619 789#endif
7fd59977 790}
7edf74fd 791
2166f0fa
SK
792/*----------------------------------------------------------------------*/
793
794//redrawView
4fe56619 795void OpenGl_Workspace::Redraw1 (const Graphic3d_CView& ACView,
a174a3c5 796 const Aspect_CLayer2d& ACUnderLayer,
797 const Aspect_CLayer2d& ACOverLayer,
798 const int aswap)
2166f0fa
SK
799{
800 if (myDisplay.IsNull() || myView.IsNull())
801 return;
802
2166f0fa
SK
803 // Request reset of material
804 NamedStatus |= OPENGL_NS_RESMAT;
805
806 /* GL_DITHER on/off pour le background */
807 if (myBackDither)
808 glEnable (GL_DITHER);
809 else
810 glDisable (GL_DITHER);
811
812 GLbitfield toClear = GL_COLOR_BUFFER_BIT;
813 if ( myUseZBuffer )
814 {
815 glDepthFunc(GL_LEQUAL);
816 glDepthMask(GL_TRUE);
817
818 // SAV checking if depth test was deprecated somewhere outside
819 if ( myUseDepthTest )
820 glEnable(GL_DEPTH_TEST);
821 else
822 glDisable(GL_DEPTH_TEST);
823
824 glClearDepth(1.0);
5e27df78 825 toClear |= GL_DEPTH_BUFFER_BIT;
2166f0fa
SK
826 }
827 else
828 {
829 glDisable(GL_DEPTH_TEST);
830 }
831
832 if ( NamedStatus & OPENGL_NS_WHITEBACK )
833 {
834 // Set background to white
835 glClearColor (1.F, 1.F, 1.F, 1.F);
5e27df78 836 toClear |= GL_DEPTH_BUFFER_BIT;
2166f0fa
SK
837 }
838 else
839 {
840 glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.F);
841 }
842 glClear (toClear);
843
844 Handle(OpenGl_Workspace) aWS(this);
a174a3c5 845 myView->Render (myPrintContext, aWS, ACView, ACUnderLayer, ACOverLayer);
2166f0fa
SK
846
847 // Swap the buffers
848 if ( aswap )
849 {
5e27df78 850 GetGlContext()->SwapBuffers();
2166f0fa
SK
851 myBackBufferRestored = Standard_False;
852 }
853 else
854 glFlush();
2166f0fa
SK
855}
856
857/*----------------------------------------------------------------------*/
858
859//TelCopyBuffers
1981cb22 860void OpenGl_Workspace::CopyBuffers (const Standard_Boolean theFrontToBack)
2166f0fa 861{
1981cb22 862 if (theFrontToBack)
863 {
864 myBackBufferRestored = Standard_False;
865 }
2166f0fa
SK
866
867 glMatrixMode (GL_PROJECTION);
868 glPushMatrix ();
869 glLoadIdentity ();
870 gluOrtho2D ((GLdouble) 0., (GLdouble) myWidth, 0., (GLdouble) myHeight);
871 glMatrixMode (GL_MODELVIEW);
872 glPushMatrix ();
873 glLoadIdentity ();
874
875 DisableFeatures();
876
1981cb22 877 glDrawBuffer (theFrontToBack ? GL_BACK : GL_FRONT);
878 glReadBuffer (theFrontToBack ? GL_FRONT : GL_BACK);
2166f0fa 879
1981cb22 880 glRasterPos2i (0, 0);
881 glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
2166f0fa
SK
882
883 EnableFeatures();
884
885 glMatrixMode (GL_PROJECTION);
886 glPopMatrix ();
887 glMatrixMode (GL_MODELVIEW);
888 glPopMatrix ();
889
890 glDrawBuffer (GL_BACK);
891}
892
893/*----------------------------------------------------------------------*/
894
895//call_subr_displayCB
5e27df78 896void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
897 int theReason)
2166f0fa 898{
5e27df78 899 if (theCView.GDisplayCB == NULL)
2166f0fa 900 {
5e27df78 901 return;
2166f0fa 902 }
5e27df78 903
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);
2166f0fa
SK
910}
911
912/*----------------------------------------------------------------------*/