[Libreoffice-commits] .: 2 commits - vcl/unx

Lubos Lunak llunak at kemper.freedesktop.org
Tue Dec 14 10:01:12 PST 2010


 vcl/unx/kde4/KDESalGraphics.cxx |   97 ++++++++++++++++++++++++++++------------
 1 file changed, 69 insertions(+), 28 deletions(-)

New commits:
commit 06a5f348170691e9b3aa4ccf3c8c5d07889e3774
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Tue Dec 14 18:59:36 2010 +0100

    simply use QRegion in Qt code instead of messing with Xlib
    
    It's also optimizing for the common path (IMAGE_BASED_PAINTING).

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index d3cc804..bdfd0e2 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -305,7 +305,7 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
     m_image->fill(KApplication::palette().color(QPalette::Window).rgb());
     
     
-    XLIB_Region pTempClipRegion = 0;
+    QRegion* clipRegion = NULL;
 
     if (type == CTRL_PUSHBUTTON)
     {
@@ -532,28 +532,8 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
                        vclStateValue2StateFlag(nControlState, value) );
         
         // draw just the border, see http://qa.openoffice.org/issues/show_bug.cgi?id=107945
-        int nFrameWidth = getFrameWidth();
-        pTempClipRegion = XCreateRegion();
-        XRectangle xRect;
-        xRect.x = widgetRect.left();
-        xRect.y = widgetRect.top();
-        xRect.width = widgetRect.width();
-        xRect.height = widgetRect.height();
-        XUnionRectWithRegion( &xRect, pTempClipRegion, pTempClipRegion );
-        xRect.x += nFrameWidth;
-        xRect.y += nFrameWidth;
-
-        // do not crash for too small widgets, see http://qa.openoffice.org/issues/show_bug.cgi?id=112102
-        if( xRect.width > 2*nFrameWidth && xRect.height > 2*nFrameWidth )
-        {
-            xRect.width -= 2*nFrameWidth;
-            xRect.height -= 2*nFrameWidth;
-            
-            XLIB_Region pSubtract = XCreateRegion();
-            XUnionRectWithRegion( &xRect, pSubtract, pSubtract );
-            XSubtractRegion( pTempClipRegion, pSubtract, pTempClipRegion );
-            XDestroyRegion( pSubtract );
-        }
+        int fw = getFrameWidth();
+        clipRegion = new QRegion( QRegion( widgetRect ).subtracted( widgetRect.adjusted( fw, fw, -fw, -fw )));
     }
     else if (type == CTRL_FIXEDBORDER)
     {
@@ -603,11 +583,10 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
         // See XRegionToQRegion() comment for a small catch (although not real hopefully).
         QPixmap destPixmap = QPixmap::fromX11Pixmap( GetDrawable(), QPixmap::ExplicitlyShared );
         QPainter paint( &destPixmap );
-        if( pTempClipRegion && pClipRegion_ )
-            paint.setClipRegion( XRegionToQRegion( pTempClipRegion )
-                .intersected( XRegionToQRegion( pClipRegion_ )));
-        else if( pTempClipRegion )
-            paint.setClipRegion( XRegionToQRegion( pTempClipRegion ));
+        if( clipRegion && pClipRegion_ )
+            paint.setClipRegion( clipRegion->intersected( XRegionToQRegion( pClipRegion_ )));
+        else if( clipRegion )
+            paint.setClipRegion( *clipRegion );
         else if( pClipRegion_ )
             paint.setClipRegion( XRegionToQRegion( pClipRegion_ ));
         paint.drawImage( widgetRect.left(), widgetRect.top(), *m_image,
@@ -615,11 +594,21 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
             Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither );
 #else
         GC gc = SelectFont();
-        
         if( gc )
         {
-            if( pTempClipRegion )
+            XLIB_Region pTempClipRegion = NULL;
+            if( clipRegion )
             {
+                pTempClipRegion = XCreateRegion();
+                foreach( const QRect& r, clipRegion->rects())
+                {
+                    XRectangle xr;
+                    xr.x = r.x();
+                    xr.y = r.y();
+                    xr.width = r.width();
+                    xr.height = r.height();
+                    XUnionRectWithRegion( &xr, pTempClipRegion, pTempClipRegion );
+                }
                 if( pClipRegion_ )
                     XIntersectRegion( pTempClipRegion, pClipRegion_, pTempClipRegion );
                 XSetRegion( GetXDisplay(), gc, pTempClipRegion );
@@ -636,15 +625,14 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
                     XSetRegion( GetXDisplay(), gc, pClipRegion_ );
                 else
                     XSetClipMask( GetXDisplay(), gc, None );
+                XDestroyRegion( pTempClipRegion );
             }
         }
         else
             returnVal = false;
 #endif
     }
-    if( pTempClipRegion )
-        XDestroyRegion( pTempClipRegion );
-
+    delete clipRegion;
     return returnVal;
 }
 
commit bf4b61c7b7f2ca1d9641ab0cf5f88a68bc3930d0
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Tue Dec 14 18:45:15 2010 +0100

    do not use QPixmap::handle(), as it may be 0
    
    See comments in code for details. The usage of Xlib's Region type
    internals is not nice, but seems to be ok in practice.

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index 26b65b7..d3cc804 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -233,6 +233,39 @@ namespace
     }
 }
 
+#if QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 )
+#define IMAGE_BASED_PAINTING
+#else
+#undef IMAGE_BASED_PAINTING
+#endif
+
+#ifdef IMAGE_BASED_PAINTING
+// There is a small catch with this function, although hopefully only philosophical.
+// Officially Xlib's Region is an opaque data type, with only functions for manipulating it.
+// However, whoever designed it apparently didn't give it that much thought, as it's impossible
+// to find out what exactly a region actually is (except for really weird ways like XClipBox()
+// and repeated XPointInRegion(), which would be awfully slow). Fortunately, the header file
+// describing the structure actually happens to be installed too, and there's at least one
+// widely used software using it (Compiz). So access the data directly too and assume that
+// everybody who compiles with Qt4 support has Xlib new enough and good enough to support this.
+// In case this doesn't work for somebody, try #include <X11/region.h> instead, or build
+// without IMAGE_BASED_PAINTING (in which case QApplication::setGraphicsSystem( "native" ) may
+// be needed too).
+#include <X11/Xregion.h>
+static QRegion XRegionToQRegion( XLIB_Region xr )
+{
+    QRegion qr;
+    for( int i = 0;
+         i < xr->numRects;
+         ++i )
+    {
+        BOX& b = xr->rects[ i ];
+        qr |= QRect( b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1 ); // x2,y2 is outside, not the bottom-right corner
+    }
+    return qr;
+}
+#endif
+
 BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
                                         const Rectangle& rControlRegion, ControlState nControlState,
                                         const ImplControlValue& value,
@@ -562,6 +595,25 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
     
     if (returnVal)
     {
+#ifdef IMAGE_BASED_PAINTING
+        // Create a wrapper QPixmap around the destination pixmap, allowing the use of QPainter.
+        // Using X11SalGraphics::CopyScreenArea() would require using QPixmap and if Qt uses
+        // other graphics system than native, QPixmap::handle() would be 0 (i.e. it wouldn't work),
+        // I have no idea how to create QPixmap with non-null handle() in such case, so go this way.
+        // See XRegionToQRegion() comment for a small catch (although not real hopefully).
+        QPixmap destPixmap = QPixmap::fromX11Pixmap( GetDrawable(), QPixmap::ExplicitlyShared );
+        QPainter paint( &destPixmap );
+        if( pTempClipRegion && pClipRegion_ )
+            paint.setClipRegion( XRegionToQRegion( pTempClipRegion )
+                .intersected( XRegionToQRegion( pClipRegion_ )));
+        else if( pTempClipRegion )
+            paint.setClipRegion( XRegionToQRegion( pTempClipRegion ));
+        else if( pClipRegion_ )
+            paint.setClipRegion( XRegionToQRegion( pClipRegion_ ));
+        paint.drawImage( widgetRect.left(), widgetRect.top(), *m_image,
+            0, 0, widgetRect.width(), widgetRect.height(),
+            Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither );
+#else
         GC gc = SelectFont();
         
         if( gc )
@@ -588,6 +640,7 @@ BOOL KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
         }
         else
             returnVal = false;
+#endif
     }
     if( pTempClipRegion )
         XDestroyRegion( pTempClipRegion );


More information about the Libreoffice-commits mailing list