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