Salome HOME
d0cfa2d555bbfce8aaea3e91b0f9b61ac1e1bc8b
[modules/shaper.git] / src / XGUI / XGUI_ViewPort.cpp
1 #ifdef WIN32
2 # include <windows.h>
3 # include <wingdi.h>
4 #endif
5
6 #include "XGUI_ViewPort.h"
7 #include "XGUI_ViewWindow.h"
8 #include "XGUI_Viewer.h"
9 #include "XGUI_Constants.h"
10
11 #include <QPaintEvent>
12 #include <QPainter>
13 #include <QFileInfo>
14 #include <QApplication>
15
16 #include <V3d_OrthographicView.hxx>
17 #include <V3d_PerspectiveView.hxx>
18 #include <Visual3d_View.hxx>
19 #include <Graphic3d_GraphicDriver.hxx>
20
21 #ifdef WIN32
22 #include <WNT_Window.hxx>
23 #else
24 #include <Xw_Window.hxx>
25 #endif
26
27 #include <GL/gl.h>
28 //qmetatype.h must be included before any header file that defines Bool
29 //see /QtCore/qmetatype.h:53 for more info
30 #ifndef WIN32
31 # ifndef GLX_GLXEXT_LEGACY
32 #  define GLX_GLXEXT_LEGACY
33 # endif
34 # include <GL/glx.h>
35 # include <dlfcn.h>
36 #endif
37
38 static double rx = 0.;
39 static double ry = 0.;
40 static int sx = 0;
41 static int sy = 0;
42 static Standard_Boolean zRotation = Standard_False;
43
44 /*!
45  Create native view window for CasCade view [ static ]
46  */
47 Handle(Aspect_Window) CreateCasWindow(const Handle(V3d_View)& view, WId winId)
48 {
49   Aspect_Handle aWindowHandle = (Aspect_Handle) winId;
50 #ifdef WIN32
51   Handle(WNT_Window) viewWindow = new WNT_Window(aWindowHandle);
52 #else
53   Handle(Aspect_DisplayConnection) aDispConnection = view->Viewer()->Driver()->GetDisplayConnection();
54   Handle(Xw_Window) viewWindow = new Xw_Window( aDispConnection, aWindowHandle );
55 #endif
56   return viewWindow;
57 }
58
59 class OpenGLUtils_FrameBuffer
60 {
61 public:
62   OpenGLUtils_FrameBuffer();
63   ~OpenGLUtils_FrameBuffer();
64
65   bool init(const GLsizei&, const GLsizei&);
66   void release();
67
68   void bind();
69   void unbind();
70
71 private:
72   GLuint textureId;
73   GLuint fboId;
74   GLuint rboId;
75 };
76
77 #ifndef APIENTRY
78 #define APIENTRY
79 #endif
80 #ifndef APIENTRYP
81 #define APIENTRYP APIENTRY *
82 #endif
83
84 #ifndef GL_FRAMEBUFFER_EXT
85 #define GL_FRAMEBUFFER_EXT                0x8D40
86 #endif
87
88 #ifndef GL_RENDERBUFFER_EXT
89 #define GL_RENDERBUFFER_EXT               0x8D41
90 #endif
91
92 #ifndef GL_COLOR_ATTACHMENT0_EXT
93 #define GL_COLOR_ATTACHMENT0_EXT          0x8CE0
94 #endif
95
96 #ifndef GL_DEPTH_ATTACHMENT_EXT
97 #define GL_DEPTH_ATTACHMENT_EXT           0x8D00
98 #endif
99
100 #ifndef GL_FRAMEBUFFER_COMPLETE_EXT
101 #define GL_FRAMEBUFFER_COMPLETE_EXT       0x8CD5
102 #endif
103
104 typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers);
105 typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
106 typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment,
107                                                           GLenum textarget, GLuint texture,
108                                                           GLint level);
109 typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
110 typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint *framebuffers);
111 typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers);
112 typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
113 typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat,
114                                                          GLsizei width, GLsizei height);
115 typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment,
116                                                              GLenum renderbuffertarget,
117                                                              GLuint renderbuffer);
118 typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint *renderbuffers);
119
120 static PFNGLGENFRAMEBUFFERSEXTPROC vglGenFramebuffersEXT = NULL;
121 static PFNGLBINDFRAMEBUFFEREXTPROC vglBindFramebufferEXT = NULL;
122 static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC vglFramebufferTexture2DEXT = NULL;
123 static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC vglCheckFramebufferStatusEXT = NULL;
124 static PFNGLDELETEFRAMEBUFFERSEXTPROC vglDeleteFramebuffersEXT = NULL;
125 static PFNGLGENRENDERBUFFERSEXTPROC vglGenRenderbuffersEXT = NULL;
126 static PFNGLBINDRENDERBUFFEREXTPROC vglBindRenderbufferEXT = NULL;
127 static PFNGLRENDERBUFFERSTORAGEEXTPROC vglRenderbufferStorageEXT = NULL;
128 static PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC vglFramebufferRenderbufferEXT = NULL;
129 static PFNGLDELETERENDERBUFFERSEXTPROC vglDeleteRenderbuffersEXT = NULL;
130
131 #ifndef WIN32
132 #define GL_GetProcAddress( x ) glXGetProcAddressARB( (const GLubyte*)x )
133 #else
134 #define GL_GetProcAddress( x ) wglGetProcAddress( (const LPCSTR)x )
135 #endif
136
137 bool InitializeEXT()
138 {
139   vglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) GL_GetProcAddress("glGenFramebuffersEXT");
140   vglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) GL_GetProcAddress("glBindFramebufferEXT");
141   vglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) GL_GetProcAddress(
142       "glFramebufferTexture2DEXT");
143   vglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) GL_GetProcAddress(
144       "glCheckFramebufferStatusEXT");
145   vglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) GL_GetProcAddress(
146       "glDeleteFramebuffersEXT");
147   vglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) GL_GetProcAddress(
148       "glGenRenderbuffersEXT");
149   vglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) GL_GetProcAddress(
150       "glBindRenderbufferEXT");
151   vglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) GL_GetProcAddress(
152       "glRenderbufferStorageEXT");
153   vglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) GL_GetProcAddress(
154       "glFramebufferRenderbufferEXT");
155   vglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) GL_GetProcAddress(
156       "glDeleteRenderbuffersEXT");
157
158   bool ok = vglGenFramebuffersEXT && vglBindFramebufferEXT && vglFramebufferTexture2DEXT
159       && vglCheckFramebufferStatusEXT && vglDeleteFramebuffersEXT && vglGenRenderbuffersEXT
160       && vglBindRenderbufferEXT && vglRenderbufferStorageEXT && vglFramebufferRenderbufferEXT
161       && vglDeleteRenderbuffersEXT;
162
163   return ok;
164 }
165
166 static bool IsEXTInitialized = InitializeEXT();
167
168 OpenGLUtils_FrameBuffer::OpenGLUtils_FrameBuffer()
169     : textureId(0), fboId(0), rboId(0)
170 {
171 }
172
173 OpenGLUtils_FrameBuffer::~OpenGLUtils_FrameBuffer()
174 {
175   release();
176 }
177
178 bool OpenGLUtils_FrameBuffer::init(const GLsizei& xSize, const GLsizei& ySize)
179 {
180   char* ext = (char*) glGetString(GL_EXTENSIONS);
181   if (!IsEXTInitialized || strstr(ext, "GL_EXT_framebuffer_object") == NULL) {
182     //qDebug( "Initializing OpenGL FrameBuffer extension failed");
183     return false;
184   }
185
186   // create a texture object
187   glEnable (GL_TEXTURE_2D);
188   glGenTextures(1, &textureId);
189   glBindTexture(GL_TEXTURE_2D, textureId);
190   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
191   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
192   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, xSize, ySize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
193   glBindTexture(GL_TEXTURE_2D, 0);
194
195   // create a renderbuffer object to store depth info
196   vglGenRenderbuffersEXT(1, &rboId);
197   vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rboId);
198   vglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, xSize, ySize);
199   vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0);
200
201   // create a framebuffer object
202   vglGenFramebuffersEXT(1, &fboId);
203   vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId);
204
205   // attach the texture to FBO color attachment point
206   vglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
207                              textureId, 0);
208
209   // attach the renderbuffer to depth attachment point
210   vglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
211   GL_RENDERBUFFER_EXT,
212                                 rboId);
213
214   // check FBO status
215   GLenum status = vglCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT);
216
217   // Unbind FBO
218   vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0);
219
220   return status == GL_FRAMEBUFFER_COMPLETE_EXT;
221 }
222
223 void OpenGLUtils_FrameBuffer::release()
224 {
225   if (!IsEXTInitialized)
226     return;
227
228   glDeleteTextures(1, &textureId);
229   textureId = 0;
230
231   vglDeleteFramebuffersEXT(1, &fboId);
232   fboId = 0;
233
234   vglDeleteRenderbuffersEXT(1, &rboId);
235   rboId = 0;
236 }
237
238 void OpenGLUtils_FrameBuffer::bind()
239 {
240   if (!IsEXTInitialized)
241     return;
242
243   vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId);
244 }
245
246 void OpenGLUtils_FrameBuffer::unbind()
247 {
248   if (!IsEXTInitialized)
249     return;
250
251   vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0);
252 }
253
254 //************************************************************************
255 //************************************************************************
256 //************************************************************************
257 XGUI_ViewPort::XGUI_ViewPort(XGUI_ViewWindow* theParent,
258                              const Handle(V3d_Viewer)& theViewer,
259                              V3d_TypeOfView theType)
260     : QWidget(theParent),
261       myPaintersRedrawing(false),
262       myScale(1.0),
263       myIsAdvancedZoomingEnabled(false),
264       myBgImgHeight(0),
265       myBgImgWidth(0)
266 {
267   setMouseTracking(true);
268   setBackgroundRole(QPalette::NoRole);
269
270   // set focus policy to threat QContextMenuEvent from keyboard  
271   setFocusPolicy(Qt::StrongFocus);
272   setAttribute(Qt::WA_PaintOnScreen);
273   setAttribute(Qt::WA_NoSystemBackground);
274   setAutoFillBackground(false);
275
276   if (theType == V3d_ORTHOGRAPHIC) {
277     myOrthoView = new V3d_OrthographicView(theViewer);
278     myActiveView = myOrthoView;
279     myPerspView = 0;
280   } else {
281     myPerspView = new V3d_PerspectiveView(theViewer);
282     myActiveView = myPerspView;
283   }
284   myActiveView->SetSurfaceDetail(V3d_TEX_ALL);
285 }
286
287 //***********************************************
288 XGUI_ViewPort::~XGUI_ViewPort()
289 {
290 }
291
292 //***********************************************
293 bool XGUI_ViewPort::mapView(const Handle(V3d_View)& theView)
294 {
295   if (!setWindow(theView))
296     return false;
297
298   if (!mapped(theView)) {
299     theView->SetWindow(myWindow);
300     //if (theView != activeView())
301       //theView->View()->Deactivate();
302   }
303
304   /* create static trihedron (16551: EDF PAL 501) */
305   //OCCViewer_ViewWindow* aVW = dynamic_cast<OCCViewer_ViewWindow*>( parentWidget()->parentWidget()->parentWidget() );
306   //if ( aVW ) {
307   //    OCCViewer_Viewer* aViewModel = dynamic_cast<OCCViewer_Viewer*>( aVW->getViewManager()->getViewModel() );
308   //    if ( aViewModel && aViewModel->isStaticTrihedronDisplayed() ){
309   //theView->ZBufferTriedronSetup();
310   theView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER);
311   //    }
312   //}
313
314   emit(vpMapped());
315
316   return true;
317 }
318
319 //***********************************************
320 bool XGUI_ViewPort::setWindow(const Handle(V3d_View)& theView)
321 {
322   if (!myWindow.IsNull())
323     return true;
324
325   if (theView.IsNull())
326     return false;
327
328   attachWindow(theView, CreateCasWindow(theView, winId()));
329
330   myWindow = theView->Window();
331   return !myWindow.IsNull();
332 }
333
334 //***********************************************
335 bool XGUI_ViewPort::mapped(const Handle(V3d_View)& theView) const
336 {
337   return (!theView.IsNull() && theView->View()->IsDefined());
338 }
339
340 //***********************************************
341 void XGUI_ViewPort::updateBackground()
342 {
343   if (activeView().IsNull())
344     return;
345   if (!myBackground.isValid())
346     return;
347
348   // VSR: Important note on below code.
349   // In OCCT (in version 6.5.2), things about the background drawing
350   // are not straightforward and not clearly understandable:
351   // - Horizontal gradient is drawn vertically (!), well ok, from top side to bottom one.
352   // - Vertical gradient is drawn horizontally (!), from right side to left one (!!!).
353   // - First and second diagonal gradients are confused.
354   // - Image texture, once set, can not be removed (!).
355   // - Texture image fill mode Aspect_FM_NONE is not taken into account (and means the same
356   //   as Aspect_FM_CENTERED).
357   // - The only way to cancel gradient background (and get back to single colored) is to
358   //   set gradient background style to Aspect_GFM_NONE while passing two colors is also needed
359   //   (see V3d_View::SetBgGradientColors() function).
360   // - Also, it is impossible to draw texture image above the gradiented background (only above
361   //   single-colored).
362   // In OCCT 6.5.3 all above mentioned problems are fixed; so, above comment should be removed as soon
363   // as SALOME is migrated to OCCT 6.5.3. The same concerns #ifdef statements in the below code
364   switch(myBackground.mode()) {
365   case XGUI::ColorBackground: {
366     QColor c = myBackground.color();
367     if (c.isValid()) {
368       // Unset texture should be done here
369       // ...
370       Quantity_Color qCol(c.red() / 255., c.green() / 255., c.blue() / 255., Quantity_TOC_RGB);
371       activeView()->SetBgGradientStyle(Aspect_GFM_NONE); // cancel gradient background
372       activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
373       // then change background color
374       activeView()->SetBackgroundColor(qCol);
375       // update viewer
376       activeView()->Update();
377     }
378     break;
379   }
380   case XGUI::SimpleGradientBackground: {
381     QColor c1, c2;
382     int type = myBackground.gradient(c1, c2);
383     if (c1.isValid() && type >= XGUI::HorizontalGradient && type <= XGUI::LastGradient) {
384       // Unset texture should be done here
385       // ...
386       // Get colors and set-up gradiented background
387       if (!c2.isValid())
388         c2 = c1;
389       Quantity_Color qCol1(c1.red() / 255., c1.green() / 255., c1.blue() / 255., Quantity_TOC_RGB);
390       Quantity_Color qCol2(c2.red() / 255., c2.green() / 255., c2.blue() / 255., Quantity_TOC_RGB);
391       activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
392       switch(type) {
393       case XGUI::HorizontalGradient:
394         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_HOR,
395         Standard_True);
396         break;
397       case XGUI::VerticalGradient:
398         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_VER,
399         Standard_True);
400         break;
401       case XGUI::Diagonal1Gradient:
402         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG1,
403         Standard_True);
404         break;
405       case XGUI::Diagonal2Gradient:
406         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG2,
407         Standard_True);
408         break;
409       case XGUI::Corner1Gradient:
410         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER1,
411         Standard_True);
412         break;
413       case XGUI::Corner2Gradient:
414         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER2,
415         Standard_True);
416         break;
417       case XGUI::Corner3Gradient:
418         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER3,
419         Standard_True);
420         break;
421       case XGUI::Corner4Gradient:
422         activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER4,
423         Standard_True);
424         break;
425       default:
426         break;
427       }
428     }
429     break;
430   }
431   case XGUI::CustomGradientBackground:
432     // NOT IMPLEMENTED YET
433     break;
434   default:
435     break;
436   }
437   // VSR: In OCCT before v6.5.3 below code can't be used because of very ugly bug - it has been impossible to
438   // clear the background texture image as soon as it was once set to the viewer.
439   if (myBackground.isTextureShown()) {
440     QString fileName;
441     int textureMode = myBackground.texture(fileName);
442     QFileInfo fi(fileName);
443     if (!fileName.isEmpty() && fi.exists()) {
444       // set texture image: file name and fill mode
445       switch(textureMode) {
446       case XGUI::CenterTexture:
447         activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
448                                          Aspect_FM_CENTERED);
449         break;
450       case XGUI::TileTexture:
451         activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
452                                          Aspect_FM_TILED);
453         break;
454       case XGUI::StretchTexture:
455         activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
456                                          Aspect_FM_STRETCH);
457         break;
458       default:
459         break;
460       }
461       activeView()->Update();
462     }
463   }
464 }
465
466 //***********************************************
467 void XGUI_ViewPort::attachWindow(const Handle(V3d_View)& theView,
468                                  const Handle(Aspect_Window)& theWnd)
469 {
470   if (!theView.IsNull()) {
471     theView->SetWindow(theWnd);
472     updateBackground();
473   }
474 }
475
476 //***********************************************
477 void XGUI_ViewPort::paintEvent(QPaintEvent* theEvent)
478 {
479 #ifndef WIN32
480   /* X11 : map before show doesn't work */
481   if ( !mapped( activeView() ) )
482   mapView( activeView() );
483 #endif
484   if (!myWindow.IsNull()) {
485     QApplication::syncX();
486     QRect rc = theEvent->rect();
487     //if ( !myPaintersRedrawing ) {
488     //activeView()->Redraw();
489     activeView()->Redraw(rc.x(), rc.y(), rc.width(), rc.height());
490     emit vpUpdated();
491     //}
492   }
493   //if ( myPaintersRedrawing ) {
494   //    QPainter p( this );
495   //    //emit vpDrawExternal( &p );
496   //    myPaintersRedrawing = false;
497   //}
498 }
499
500 //***********************************************
501 void XGUI_ViewPort::resizeEvent(QResizeEvent* theEvent)
502 {
503 #ifdef WIN32
504   /* Win32 : map before first show to avoid flicker */
505   if (!mapped(activeView()))
506     mapView(activeView());
507 #endif
508   QApplication::syncX();
509   if (!activeView().IsNull()) {
510     activeView()->MustBeResized();
511   }
512 }
513
514 //***********************************************
515 QImage XGUI_ViewPort::dumpView(QRect theRect, bool toUpdate)
516 {
517   Handle(V3d_View) view = getView();
518   if (view.IsNull())
519     return QImage();
520
521   int aWidth;
522   int aHeight;
523   if (theRect.isNull()) {
524     aWidth = width();
525     aHeight = height();
526   } else {
527     aWidth = theRect.width();
528     aHeight = theRect.height();
529   }
530   QApplication::syncX();
531
532   OpenGLUtils_FrameBuffer aFrameBuffer;
533   if (aFrameBuffer.init(aWidth, aHeight)) {
534     QImage anImage(aWidth, aHeight, QImage::Format_RGB32);
535
536     glPushAttrib (GL_VIEWPORT_BIT);
537     glViewport(0, 0, aWidth, aHeight);
538     aFrameBuffer.bind();
539
540     // draw scene
541     if (toUpdate) {
542       if (theRect.isNull())
543         view->Redraw();
544       else
545         view->Redraw(theRect.x(), theRect.y(), theRect.width(), theRect.height());
546     }
547     aFrameBuffer.unbind();
548     glPopAttrib();
549
550     aFrameBuffer.bind();
551     if (theRect.isNull())
552       glReadPixels(0, 0, aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, anImage.bits());
553     else
554       glReadPixels(theRect.x(), theRect.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE,
555                    anImage.bits());
556     aFrameBuffer.unbind();
557
558     anImage = anImage.rgbSwapped();
559     anImage = anImage.mirrored();
560     return anImage;
561   }
562   // if frame buffers are unsupported, use old functionality
563   unsigned char* data = new unsigned char[aWidth * aHeight * 4];
564
565   QPoint p;
566   if (theRect.isNull()) {
567     if (toUpdate)
568       view->Redraw();
569     p = mapFromParent(geometry().topLeft());
570   } else {
571     if (toUpdate)
572       view->Redraw(theRect.x(), theRect.y(), theRect.width(), theRect.height());
573     p = theRect.topLeft();
574   }
575   glReadPixels(p.x(), p.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
576
577   QImage anImage(data, aWidth, aHeight, QImage::Format_ARGB32);
578   anImage = anImage.mirrored();
579   anImage = anImage.rgbSwapped();
580   return anImage;
581 }
582
583 /*!
584  Inits 'rotation' transformation.
585  */
586 void XGUI_ViewPort::startRotation(int x, int y, int theRotationPointType,
587                                   const gp_Pnt& theSelectedPoint)
588 {
589   if (!activeView().IsNull()) {
590     switch(theRotationPointType) {
591     case XGUI::GRAVITY:
592       activeView()->StartRotation(x, y, 0.45);
593       break;
594     case XGUI::SELECTED:
595       sx = x;
596       sy = y;
597
598       double X, Y;
599       activeView()->Size(X, Y);
600       rx = Standard_Real(activeView()->Convert(X));
601       ry = Standard_Real(activeView()->Convert(Y));
602
603       activeView()->Rotate(0., 0., 0., theSelectedPoint.X(), theSelectedPoint.Y(),
604                            theSelectedPoint.Z(),
605                            Standard_True);
606
607       Quantity_Ratio zRotationThreshold;
608       zRotation = Standard_False;
609       zRotationThreshold = 0.45;
610       if (zRotationThreshold > 0.) {
611         Standard_Real dx = Abs(sx - rx / 2.);
612         Standard_Real dy = Abs(sy - ry / 2.);
613         Standard_Real dd = zRotationThreshold * (rx + ry) / 2.;
614         if (dx > dd || dy > dd)
615           zRotation = Standard_True;
616       }
617       break;
618     default:
619       break;
620     }
621     activeView()->DepthFitAll();
622   }
623 }
624
625 /*!
626  Rotates the viewport. 
627  */
628 void XGUI_ViewPort::rotate(int x, int y, int theRotationPointType, const gp_Pnt& theSelectedPoint)
629 {
630   if (!activeView().IsNull()) {
631     switch(theRotationPointType) {
632     case XGUI::GRAVITY:
633       activeView()->Rotation(x, y);
634       break;
635     case XGUI::SELECTED:
636       double dx, dy, dz;
637       if (zRotation) {
638         dz = atan2(Standard_Real(x) - rx / 2., ry / 2. - Standard_Real(y))
639             - atan2(sx - rx / 2., ry / 2. - sy);
640         dx = dy = 0.;
641       } else {
642         dx = (Standard_Real(x) - sx) * M_PI / rx;
643         dy = (sy - Standard_Real(y)) * M_PI / ry;
644         dz = 0.;
645       }
646
647       activeView()->Rotate(dx, dy, dz, theSelectedPoint.X(), theSelectedPoint.Y(),
648                            theSelectedPoint.Z(),
649                            Standard_False);
650       break;
651     default:
652       break;
653     }
654     emit vpTransformed();
655   }
656   //  setZSize( getZSize() );
657 }
658
659 /*!
660  Resets the viewport after 'rotation'. 
661  */
662 void XGUI_ViewPort::endRotation()
663 {
664   if (!activeView().IsNull()) {
665     activeView()->ZFitAll(1.);
666     activeView()->SetZSize(0.);
667     activeView()->Update();
668     emit vpTransformed();
669   }
670 }
671
672 /*!
673  Inits 'zoom' transformation.
674  */
675 void XGUI_ViewPort::startZoomAtPoint(int x, int y)
676 {
677   if (!activeView().IsNull()/* && isAdvancedZoomingEnabled() */)
678     activeView()->StartZoomAtPoint(x, y);
679 }
680
681 /*!
682  Centers the viewport. 
683  */
684 void XGUI_ViewPort::setCenter(int x, int y)
685 {
686   if (!activeView().IsNull()) {
687     activeView()->Place(x, y, myScale);
688     emit vpTransformed();
689   }
690 }
691
692 /*!
693  Called at 'pan' transformation. 
694  */
695 void XGUI_ViewPort::pan(int dx, int dy)
696 {
697   if (!activeView().IsNull()) {
698     activeView()->Pan(dx, dy, 1.0);
699     emit vpTransformed();
700   }
701 }
702
703 /*!
704  Called at 'window fit' transformation.
705  */
706 void XGUI_ViewPort::fitRect(const QRect& rect)
707 {
708   if (!activeView().IsNull()) {
709     activeView()->WindowFit(rect.left(), rect.top(), rect.right(), rect.bottom());
710     emit vpTransformed();
711   }
712 }
713
714 /*!
715  Called at 'zoom' transformation.
716  */
717 void XGUI_ViewPort::zoom(int x0, int y0, int x, int y)
718 {
719   if (!activeView().IsNull()) {
720     if (isAdvancedZoomingEnabled())
721       activeView()->ZoomAtPoint(x0, y0, x, y);
722     else
723       activeView()->Zoom(x0 + y0, 0, x + y, 0);
724     emit vpTransformed();
725   }
726 }
727
728 /*!
729  Sets the background data
730  */
731 void XGUI_ViewPort::setBackground(const XGUI_ViewBackground& bgData)
732 {
733   if (bgData.isValid()) {
734     myBackground = bgData;
735     updateBackground();
736     emit vpChangeBackground(myBackground);
737   }
738 }
739
740 void XGUI_ViewPort::fitAll(bool theKeepScale, bool theWithZ, bool theUpd)
741 {
742   if ( activeView().IsNull() )
743     return;
744
745   if ( theKeepScale )
746     myScale = activeView()->Scale();
747
748   Standard_Real aMargin = 0.01;
749   activeView()->FitAll( aMargin, theWithZ, theUpd );
750   activeView()->SetZSize(0.);
751   emit vpTransformed( );
752 }
753
754 void XGUI_ViewPort::syncronizeWith( const XGUI_ViewPort* ref )
755 {
756   Handle(V3d_View) refView = ref->getView();
757   Handle(V3d_View) tgtView = getView();
758
759   /*  The following params are copied:
760       - view type( ortho/persp )
761       - position of view point
762       - orientation of high point
763       - position of the eye
764       - projection vector
765       - view center ( 2D )
766       - view twist
767       - view scale
768   */
769
770   /* we'll update after setting all params */
771   tgtView->SetImmediateUpdate( Standard_False );
772
773   /* perspective */
774   if ( refView->Type() == V3d_PERSPECTIVE )
775     tgtView->SetFocale( refView->Focale() );
776
777   /* copy params */
778   Standard_Real x, y, z;
779   refView->At( x, y, z ); tgtView->SetAt( x, y, z );
780   refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
781   refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
782   refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
783   refView->Center( x, y ); tgtView->SetCenter( x, y );
784   tgtView->SetScale( refView->Scale() );
785   tgtView->SetTwist( refView->Twist() );
786
787   /* update */
788   tgtView->Update();
789   tgtView->SetImmediateUpdate( Standard_True );
790 }