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