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