[Libreoffice-commits] .: Branch 'feature/gtk3' - vcl/inc vcl/source vcl/unx

Michael Meeks michael at kemper.freedesktop.org
Wed Jul 6 10:57:14 PDT 2011


 vcl/inc/unx/headless/svpgdi.hxx |   17 +++
 vcl/source/window/window.cxx    |    5 +
 vcl/unx/headless/svpgdi.cxx     |  174 ++++++++++++++++++++++++++++++++++------
 vcl/unx/headless/svptext.cxx    |    2 
 4 files changed, 169 insertions(+), 29 deletions(-)

New commits:
commit 8b86bdf73d2a0241000c10ba2634959fc603ecf6
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue Jul 5 21:58:04 2011 +0100

    do more intelligent clipping, that doesn't allocate huge masks constantly

diff --git a/vcl/inc/unx/headless/svpgdi.hxx b/vcl/inc/unx/headless/svpgdi.hxx
index 3dbb325..0113d34 100644
--- a/vcl/inc/unx/headless/svpgdi.hxx
+++ b/vcl/inc/unx/headless/svpgdi.hxx
@@ -41,7 +41,6 @@ class SvpSalGraphics : public SalGraphics
 {
     basebmp::BitmapDeviceSharedPtr       m_aDevice;
     basebmp::BitmapDeviceSharedPtr       m_aOrigDevice;
-    basebmp::BitmapDeviceSharedPtr       m_aClipMap;
 
     bool                                 m_bUseLineColor;
     basebmp::Color                       m_aLineColor;
@@ -54,6 +53,19 @@ class SvpSalGraphics : public SalGraphics
     ServerFont*                          m_pServerFont[ MAX_FALLBACK ];
     sal_uInt32                           m_eTextFmt;
 
+    basebmp::BitmapDeviceSharedPtr       m_aClipMap;
+
+    Region                               m_aClipRegion;
+    bool                                 m_bClipSetup;
+    struct ClipUndoHandle {
+        SvpSalGraphics                &m_rGfx;
+        basebmp::BitmapDeviceSharedPtr m_aDevice;
+        ClipUndoHandle( SvpSalGraphics *pGfx ) : m_rGfx( *pGfx ) {}
+        ~ClipUndoHandle();
+    };
+    ClipUndoHandle  ensureClipFor( const basegfx::B2IRange &aRange );
+    void            ensureClip();
+
 protected:
     virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap );
     virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency );
@@ -76,8 +88,7 @@ public:
     virtual void			SetLineColor();
     virtual void			SetLineColor( SalColor nSalColor );
     virtual void			SetFillColor();
-
-    virtual void                        SetFillColor( SalColor nSalColor );
+    virtual void            SetFillColor( SalColor nSalColor );
 
     virtual void			SetXORMode( bool bSet, bool );
 
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index bc9b070..37f3531 100755
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -2963,7 +2963,12 @@ void Window::ImplScroll( const Rectangle& rRect,
     if ( mpWindowImpl->mbWinRegion )
         aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
 
+    long before = aRegion.GetRectCount();
     aRegion.Exclude( aInvalidateRegion );
+    long after = aRegion.GetRectCount();
+    if (after != before)
+        fprintf (stderr, "invalidate region screwed with our rect count: %ld -> %ld\n",
+                 before, after);
 
     ImplClipBoundaries( aRegion, sal_False, sal_True );
     if ( !bScrollChilds )
diff --git a/vcl/unx/headless/svpgdi.cxx b/vcl/unx/headless/svpgdi.cxx
index 71e48cc..9bb5e21 100644
--- a/vcl/unx/headless/svpgdi.cxx
+++ b/vcl/unx/headless/svpgdi.cxx
@@ -94,7 +94,8 @@ SvpSalGraphics::SvpSalGraphics() :
     m_aFillColor( COL_WHITE ),
     m_aTextColor( COL_BLACK ),
     m_aDrawMode( DrawMode_PAINT ),
-    m_eTextFmt( Format::EIGHT_BIT_GREY )
+    m_eTextFmt( Format::EIGHT_BIT_GREY ),
+    m_bClipSetup( false )
 {
     for( int i = 0; i < MAX_FALLBACK; ++i )
         m_pServerFont[i] = NULL;
@@ -106,9 +107,8 @@ SvpSalGraphics::~SvpSalGraphics()
 
 void SvpSalGraphics::setDevice( BitmapDeviceSharedPtr& rDevice )
 {
-    m_aDevice = rDevice;
     m_aOrigDevice = rDevice;
-    m_aClipMap.reset();
+    ResetClipRegion();
 
     // determine matching bitmap format for masks
     sal_uInt32 nDeviceFmt = m_aDevice->getScanlineFormat();
@@ -142,7 +142,7 @@ long SvpSalGraphics::GetGraphicsWidth() const
 {
     if( m_aDevice.get() )
     {
-        B2IVector aSize = m_aDevice->getSize();
+        B2IVector aSize = m_aOrigDevice->getSize();
         return aSize.getX();
     }
     return 0;
@@ -152,39 +152,139 @@ void SvpSalGraphics::ResetClipRegion()
 {
     m_aDevice = m_aOrigDevice;
     m_aClipMap.reset();
+    m_bClipSetup = true;
+    m_aClipRegion.SetNull();
+    //    fprintf( stderr, "clip region reset\n" );
+}
+
+
+// verify clip for the whole area is setup
+void SvpSalGraphics::ensureClip()
+{
+    if (m_bClipSetup)
+        return;
+
+    m_aDevice = m_aOrigDevice;
+    B2IVector aSize = m_aDevice->getSize();
+    m_aClipMap = createBitmapDevice( aSize, false, Format::ONE_BIT_MSB_GREY );
+    m_aClipMap->clear( basebmp::Color(0xFFFFFFFF) );
+
+    fprintf( stderr, "non rect clip region set with %d rects:\n",
+             (int)m_aClipRegion.GetRectCount() );
+    ImplRegionInfo aInfo;
+    long nX, nY, nW, nH;
+    bool bRegionRect = m_aClipRegion.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+    while( bRegionRect )
+    {
+        if ( nW && nH )
+        {
+            B2DPolyPolygon aFull;
+            aFull.append( tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nW, nY+nH ) ) );
+            m_aClipMap->fillPolyPolygon( aFull, basebmp::Color(0), DrawMode_PAINT );
+        }
+        fprintf( stderr, "\t %ld,%ld %ldx%ld\n", nX, nY, nW, nH );
+        bRegionRect = m_aClipRegion.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+    }
+    m_bClipSetup = true;
+}
+
+SvpSalGraphics::ClipUndoHandle::~ClipUndoHandle()
+{
+    if( m_aDevice.get() )
+        m_rGfx.m_aDevice = m_aDevice;
 }
 
+// setup a clip rectangle -only- iff we have to; if aRange
+// is entirely contained inside an existing clip frame, we
+// will avoid setting up the clip bitmap.
+SvpSalGraphics::ClipUndoHandle SvpSalGraphics::ensureClipFor( const basegfx::B2IRange &aRange )
+{
+    ClipUndoHandle aRet(this);
+
+    if (m_bClipSetup)
+        return aRet;
+
+    fprintf( stderr, "ensureClipFor: %d, %d %dx%d\n",
+             aRange.getMinX(), aRange.getMinY(),
+             (int)aRange.getWidth(), (int)aRange.getHeight() );
+
+    // first see if aRange is purely internal to one of the clip regions
+    Rectangle aRect( Point( aRange.getMinX(), aRange.getMinY() ),
+                     Size( aRange.getWidth(), aRange.getHeight() ) );
+
+    // then see if we are overlapping with just one
+    int nHit = 0;
+    Rectangle aIterRect, aHitRect;
+    RegionHandle aHnd = m_aClipRegion.BeginEnumRects();
+    while( m_aClipRegion.GetNextEnumRect( aHnd, aIterRect ) )
+    {
+        if( aIterRect.IsOver( aRect ) )
+        {
+            aHitRect = aIterRect;
+            nHit++;
+        }
+    }
+    m_aClipRegion.EndEnumRects (aHnd);
+
+    if( nHit == 0 )
+    {
+        // degenerate case - we're all clipped ... hmm.
+    }
+    else if( nHit == 1 )
+    {
+        if( aIterRect.IsInside( aRect ) )
+        {
+            fprintf (stderr, " is inside ! avoid deeper clip ...\n");
+            return aRet;
+        }
+        fprintf (stderr, " operation only overlaps with a single clip zone\n" );
+        aRet.m_aDevice = m_aDevice;
+        m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
+                                                 basegfx::B2IRange (aHitRect.Left(),
+                                                                    aHitRect.Top(),
+                                                                    aHitRect.Right(),
+                                                                    aHitRect.Bottom()) );
+        return aRet;
+    }
+    else
+        fprintf (stderr, "URK: complex & slow clipping case\n" );
+
+    ensureClip();
+    return aRet;
+}
+
+
+// Clipping by creating unconditional mask bitmaps is horribly
+// slow so defer it, as much as possible. It is common to get
+// 3 rectangles pushed, and have to create a vast off-screen
+// mask only to destroy it shortly afterwards. That is
+// particularly galling if we render only to a small,
+// well defined rectangular area inside one of these clip
+// rectangles.
+//
+// ensureClipFor() or ensureClip() need to be called before
+// real rendering. FIXME: we should prolly push this down to
+// bitmapdevice instead.
 bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
 {
     if( i_rClip.IsEmpty() )
+    {
         m_aClipMap.reset();
+        m_bClipSetup = true;
+        fprintf( stderr, "clip region reset\n" );
+    }
     else if( i_rClip.GetRectCount() == 1 )
     {
         m_aClipMap.reset();
         Rectangle aBoundRect( i_rClip.GetBoundRect() );
         m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
                                                  basegfx::B2IRange(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right(),aBoundRect.Bottom()) );
+        m_bClipSetup = true;
     }
     else
     {
-        m_aDevice = m_aOrigDevice;
-        B2IVector aSize = m_aDevice->getSize();
-        m_aClipMap = createBitmapDevice( aSize, false, Format::ONE_BIT_MSB_GREY );
-        m_aClipMap->clear( basebmp::Color(0xFFFFFFFF) );
-
-        ImplRegionInfo aInfo;
-        long nX, nY, nW, nH;
-        bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
-        while( bRegionRect )
-        {
-            if ( nW && nH )
-            {
-                B2DPolyPolygon aFull;
-                aFull.append( tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nW, nY+nH ) ) ); 
-                m_aClipMap->fillPolyPolygon( aFull, basebmp::Color(0), DrawMode_PAINT );
-            }
-            bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
-        }
+        m_aClipRegion = i_rClip;
+        m_bClipSetup = false;
     }
     return true;
 }
@@ -258,33 +358,40 @@ void SvpSalGraphics::SetTextColor( SalColor nSalColor )
 void SvpSalGraphics::drawPixel( long nX, long nY )
 {
     if( m_bUseLineColor )
+    {
+        ensureClip();
         m_aDevice->setPixel( B2IPoint( nX, nY ),
                              m_aLineColor,
                              m_aDrawMode,
                              m_aClipMap
                              );
+    }
     dbgOut( m_aDevice );
 }
 
 void SvpSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
 {
     basebmp::Color aColor( nSalColor );
+    ensureClip();
     m_aDevice->setPixel( B2IPoint( nX, nY ),
                          aColor,
                          m_aDrawMode,
                          m_aClipMap
-                         ); 
+                         );
     dbgOut( m_aDevice );
 }
 
 void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
 {
     if( m_bUseLineColor )
+    {
+        ensureClip(); // FIXME: for ...
         m_aDevice->drawLine( B2IPoint( nX1, nY1 ),
                              B2IPoint( nX2, nY2 ),
                              m_aLineColor,
                              m_aDrawMode,
                              m_aClipMap );
+    }
     dbgOut( m_aDevice );
 }
 
@@ -293,6 +400,7 @@ void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
     if( m_bUseLineColor || m_bUseFillColor )
     {
         B2DPolygon aRect = tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
+        ensureClip(); // FIXME: for ...
         if( m_bUseFillColor )
         {
             B2DPolyPolygon aPolyPoly( aRect );
@@ -313,6 +421,7 @@ void SvpSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry )
         for( sal_uLong i = 1; i < nPoints; i++ )
             aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
         aPoly.setClosed( false );
+        ensureClip(); // FIXME: for ...
         m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap );
     }
     dbgOut( m_aDevice );
@@ -326,6 +435,7 @@ void SvpSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry )
         aPoly.append( B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
         for( sal_uLong i = 1; i < nPoints; i++ )
             aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
+        ensureClip(); // FIXME: for ...
         if( m_bUseFillColor )
         {
             aPoly.setClosed( true );
@@ -361,6 +471,7 @@ void SvpSalGraphics::drawPolyPolygon( sal_uInt32        nPoly,
                 aPolyPoly.append( aPoly );
             }
         }
+        ensureClip(); // FIXME: for ...
         if( m_bUseFillColor )
         {
             aPolyPoly.setClosed( true );
@@ -421,6 +532,9 @@ void SvpSalGraphics::copyArea( long nDestX,
 {
     B2IRange aSrcRect( nSrcX, nSrcY, nSrcX+nSrcWidth, nSrcY+nSrcHeight );
     B2IRange aDestRect( nDestX, nDestY, nDestX+nSrcWidth, nDestY+nSrcHeight );
+    fprintf( stderr, "copyArea %ld pixels - clip region %d\n",
+             (long)(nSrcWidth * nSrcHeight), m_aClipMap.get() != NULL );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
     m_aDevice->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
     dbgOut( m_aDevice );
 }
@@ -436,7 +550,8 @@ void SvpSalGraphics::copyBits( const SalTwoRect* pPosAry,
     B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
                         pPosAry->mnDestX+pPosAry->mnDestWidth,
                         pPosAry->mnDestY+pPosAry->mnDestHeight );
-    m_aDevice->drawBitmap( pSrc->m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );    
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawBitmap( pSrc->m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
     dbgOut( m_aDevice );
 }
 
@@ -450,7 +565,8 @@ void SvpSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
     B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
                         pPosAry->mnDestX+pPosAry->mnDestWidth,
                         pPosAry->mnDestY+pPosAry->mnDestHeight );
-    m_aDevice->drawBitmap( rSrc.getBitmap(), aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );    
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawBitmap( rSrc.getBitmap(), aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
     dbgOut( m_aDevice );
 }
 
@@ -473,6 +589,7 @@ void SvpSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
     B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
                         pPosAry->mnDestX+pPosAry->mnDestWidth,
                         pPosAry->mnDestY+pPosAry->mnDestHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
     m_aDevice->drawMaskedBitmap( rSrc.getBitmap(), rSrcTrans.getBitmap(), aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
     dbgOut( m_aDevice );
 }
@@ -500,6 +617,8 @@ void SvpSalGraphics::drawMask( const SalTwoRect* pPosAry,
 
     basebmp::Color aColor( nMaskColor );
     B2IRange aSrcRect2( 0, 0, pPosAry->mnSrcWidth, pPosAry->mnSrcHeight );
+    const B2IRange aClipRect( aDestPoint, B2ITuple( aSrcRect.getWidth(), aSrcRect.getHeight() ) );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aClipRect );
     m_aDevice->drawMaskedColor( aColor, aCopy, aSrcRect, aDestPoint, m_aClipMap );
     dbgOut( m_aDevice );
 }
@@ -511,6 +630,7 @@ SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeigh
                            m_aDevice );
     B2IRange aSrcRect( nX, nY, nX+nWidth, nY+nHeight );
     B2IRange aDestRect( 0, 0, nWidth, nHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
     aCopy->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT );
 
     SvpSalBitmap* pBitmap = new SvpSalBitmap();
@@ -520,7 +640,7 @@ SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeigh
 
 SalColor SvpSalGraphics::getPixel( long nX, long nY )
 {
-    basebmp::Color aColor( m_aDevice->getPixel( B2IPoint( nX, nY ) ) );
+    basebmp::Color aColor( m_aOrigDevice->getPixel( B2IPoint( nX, nY ) ) );
     return aColor.toInt32();
 }
 
@@ -529,6 +649,7 @@ void SvpSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInv
     // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
     B2DPolygon aRect = tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
     B2DPolyPolygon aPolyPoly( aRect );
+    ensureClip(); // FIXME for ...
     m_aDevice->fillPolyPolygon( aPolyPoly, basebmp::Color( 0xffffff ), DrawMode_XOR, m_aClipMap );
     dbgOut( m_aDevice );
 }
@@ -541,6 +662,7 @@ void SvpSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInver
     for( sal_uLong i = 1; i < nPoints; i++ )
         aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
     aPoly.setClosed( true );
+    ensureClip(); // FIXME for ...
     m_aDevice->fillPolyPolygon( B2DPolyPolygon(aPoly), basebmp::Color( 0xffffff ), DrawMode_XOR, m_aClipMap );
     dbgOut( m_aDevice );
 }
diff --git a/vcl/unx/headless/svptext.cxx b/vcl/unx/headless/svptext.cxx
index 7005aa4..02277aa 100644
--- a/vcl/unx/headless/svptext.cxx
+++ b/vcl/unx/headless/svptext.cxx
@@ -533,6 +533,8 @@ void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
 
         // blend text color into target using the glyph's mask
         const B2IRange aSrcRect( B2ITuple(0,0), aAlphaMask->getSize() );
+        const B2IRange aClipRect( aDstPoint, aAlphaMask->getSize() );
+        SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aClipRect );
         m_aDevice->drawMaskedColor( m_aTextColor, aAlphaMask, aSrcRect, aDstPoint, m_aClipMap );
     }
 }


More information about the Libreoffice-commits mailing list