[Libreoffice-commits] core.git: vcl/inc vcl/source vcl/unx

Radek Doulik rodo at novell.com
Thu Mar 7 04:37:49 PST 2013


 vcl/inc/salbmp.hxx              |    2 
 vcl/inc/unx/salbmp.h            |    3 
 vcl/inc/unx/salgdi.h            |    5 +
 vcl/source/gdi/gdimtf.cxx       |   10 --
 vcl/unx/generic/gdi/salbmp.cxx  |    2 
 vcl/unx/generic/gdi/salgdi2.cxx |  147 ++++++++++++++++++++++------------------
 6 files changed, 97 insertions(+), 72 deletions(-)

New commits:
commit 46e53913e9dcc84ffed8fb5f1b4959c70c7e5649
Author: Radek Doulik <rodo at novell.com>
Date:   Thu Mar 7 13:31:34 2013 +0100

    fix canvas bitmap rendering (argb32 pixmaps) fixes color issue in n#780830
    
    Change-Id: I5242bbb171ba21da43e535255b7e9dd73c1d4930

diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx
index 99b5e6a..03f9af9 100644
--- a/vcl/inc/salbmp.hxx
+++ b/vcl/inc/salbmp.hxx
@@ -47,6 +47,8 @@ public:
     virtual bool            Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas,
                                     Size& rSize,
                                     bool bMask = false ) = 0;
+    virtual bool            HasAlpha() const { return false; }
+    virtual void            SetHasAlpha( bool ) { }
     virtual void            Destroy() = 0;
     virtual Size            GetSize() const = 0;
     virtual sal_uInt16          GetBitCount() const = 0;
diff --git a/vcl/inc/unx/salbmp.h b/vcl/inc/unx/salbmp.h
index 866412d..6973507 100644
--- a/vcl/inc/unx/salbmp.h
+++ b/vcl/inc/unx/salbmp.h
@@ -74,6 +74,7 @@ private:
     BitmapBuffer*   mpDIB;
     ImplSalDDB*     mpDDB;
     bool            mbGrey;
+    bool            mbHasAlpha;
 
 public:
 
@@ -148,6 +149,8 @@ public:
     virtual BitmapBuffer*       AcquireBuffer( bool bReadOnly );
     virtual void                ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly );
     virtual bool                GetSystemData( BitmapSystemData& rData );
+    virtual bool                HasAlpha() const { return mbHasAlpha; }
+    virtual void                SetHasAlpha( bool bHasAlpha ) { mbHasAlpha = bHasAlpha; }
 };
 
 // --------------
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index f1039e9..3684dd0 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -324,6 +324,11 @@ public:
                                              const SalBitmap& rSourceBitmap,
                                              const SalBitmap& rAlphaBitmap );
 
+    bool                    drawAlphaBitmapOpt( const SalTwoRect&,
+                                                const SalBitmap& rSourceBitmap,
+                                                const SalBitmap& rAlphaBitmap,
+                                                bool bUseAlphaBitmap = true );
+
     virtual bool            drawAlphaRect( long nX, long nY, long nWidth,
                                            long nHeight, sal_uInt8 nTransparency );
 
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
index bf19753..a561d64 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -496,20 +496,16 @@ bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, S
                     }
 
                     SalBitmap* pSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
-                    SalBitmap* pSalMask = ImplGetSVData()->mpDefInst->CreateSalBitmap();
+                    pSalBmp->SetHasAlpha( true );
 
-                    if( pSalBmp->Create( xBitmapCanvas, aSize ) && pSalMask->Create( xBitmapCanvas, aSize, true ) )
+                    if( pSalBmp->Create( xBitmapCanvas, aSize ) )
                     {
                         Bitmap aBitmap( pSalBmp );
-                        Bitmap aMask( pSalMask );
-                        AlphaMask aAlphaMask( aMask );
-                        BitmapEx aBitmapEx( aBitmap, aAlphaMask );
-                        pOut->DrawBitmapEx( rPos, aBitmapEx );
+                        pOut->DrawBitmap( rPos, aBitmap );
                         return true;
                     }
 
                     delete pSalBmp;
-                    delete pSalMask;
                 }
             }
         }
diff --git a/vcl/unx/generic/gdi/salbmp.cxx b/vcl/unx/generic/gdi/salbmp.cxx
index aee24dd..faa04c7 100644
--- a/vcl/unx/generic/gdi/salbmp.cxx
+++ b/vcl/unx/generic/gdi/salbmp.cxx
@@ -42,6 +42,7 @@
 #include <unx/salbmp.h>
 #include <unx/salinst.h>
 #include <unx/x11/xlimits.hxx>
+#include "xrender_peer.hxx"
 
 #if defined HAVE_VALGRIND_HEADERS
 #include <valgrind/memcheck.h>
@@ -65,6 +66,7 @@ X11SalBitmap::X11SalBitmap()
     : mpDIB( NULL )
     , mpDDB( NULL )
     , mbGrey( false )
+    , mbHasAlpha( false )
 {
 }
 
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index 97d1924..4684842 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -495,7 +495,10 @@ void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSa
         XChangeGC( pXDisp, aGC, nValues, &aNewVal );
     }
 
-    static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nXScreen, nDepth, *pPosAry, aGC );
+    if ( rSalBitmap.GetBitCount() == 32 && rSalBitmap.HasAlpha() )
+        drawAlphaBitmapOpt( *pPosAry, rSalBitmap, rSalBitmap, false );
+    else
+        static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nXScreen, nDepth, *pPosAry, aGC );
 
     if( rSalBitmap.GetBitCount() == 1 )
         XChangeGC( pXDisp, aGC, nValues, &aOldVal );
@@ -623,10 +626,17 @@ void X11SalGraphics::drawMaskedBitmap( const SalTwoRect* pPosAry,
 
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
-    const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
+                                      const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
+{
+    return drawAlphaBitmapOpt( rTR, rSrcBitmap, rAlphaBmp );
+}
+
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+bool X11SalGraphics::drawAlphaBitmapOpt( const SalTwoRect& rTR,
+                                         const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp, bool bUseAlphaBitmap )
 {
     // non 8-bit alpha not implemented yet
-    if( rAlphaBmp.GetBitCount() != 8 )
+    if( bUseAlphaBitmap && rAlphaBmp.GetBitCount() != 8 )
         return false;
 
     // horizontal mirroring not implemented yet
@@ -648,10 +658,12 @@ bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
     const SalVisual& rSalVis = pSalDisp->GetVisual( m_nXScreen );
     Display* pXDisplay = pSalDisp->GetDisplay();
 
+    Picture aAlphaPic;
+    Pixmap aAlphaPM;
     // create source Picture
     int nDepth = m_pVDev ? m_pVDev->GetDepth() : rSalVis.GetDepth();
     const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
-    ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nXScreen, nDepth, rTR );
+    ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nXScreen, bUseAlphaBitmap ? nDepth : 32, rTR );
     if( !pSrcDDB )
         return false;
 
@@ -659,7 +671,7 @@ bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
     // we requested. E.g. mask pixmaps are always compatible with the drawable
     // TODO: find an appropriate picture format for these cases
     //       then remove the workaround below and the one for #i75531#
-    if( nDepth != pSrcDDB->ImplGetDepth() )
+    if( bUseAlphaBitmap && nDepth != pSrcDDB->ImplGetDepth() )
         return false;
 
     Pixmap aSrcPM = pSrcDDB->ImplGetPixmap();
@@ -670,81 +682,86 @@ bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
     // TODO: use scoped picture
     Visual* pSrcXVisual = rSalVis.GetVisual();
     XRenderPeer& rPeer = XRenderPeer::GetInstance();
-    XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual );
+    XRenderPictFormat* pSrcVisFmt = bUseAlphaBitmap ? rPeer.FindVisualFormat( pSrcXVisual ) : rPeer.FindStandardFormat( PictStandardARGB32 );
     if( !pSrcVisFmt )
         return false;
     Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL );
     if( !aSrcPic )
         return false;
 
-    // create alpha Picture
+    if ( bUseAlphaBitmap ) {
+        // create alpha Picture
 
-    // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
-    // problem is that they don't provide an 8bit Pixmap on a non-8bit display
-    BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( sal_True );
+        // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
+        // problem is that they don't provide an 8bit Pixmap on a non-8bit display
+        BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( sal_True );
 
-    // an XImage needs its data top_down
-    // TODO: avoid wrongly oriented images in upper layers!
-    const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
-    const char* pSrcBits = (char*)pAlphaBuffer->mpBits;
-    char* pAlphaBits = new char[ nImageSize ];
-    if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
-        memcpy( pAlphaBits, pSrcBits, nImageSize );
-    else
-    {
-        char* pDstBits = pAlphaBits + nImageSize;
-        const int nLineSize = pAlphaBuffer->mnScanlineSize;
-        for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
-            memcpy( pDstBits, pSrcBits, nLineSize );
-    }
-
-    // the alpha values need to be inverted for XRender
-    // TODO: make upper layers use standard alpha
-    long* pLDst = (long*)pAlphaBits;
-    for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
-        *pLDst = ~*pLDst;
-
-    char* pCDst = (char*)pLDst;
-    for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
-        *pCDst = ~*pCDst;
-
-    const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
-    XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
-        pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
-        pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
-
-    Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, hDrawable_,
-        rTR.mnDestWidth, rTR.mnDestHeight, 8 );
-
-    XGCValues aAlphaGCV;
-    aAlphaGCV.function = GXcopy;
-    GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
-    XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
-        rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
-    XFreeGC( pXDisplay, aAlphaGC );
-    XFree( pAlphaImg );
-    if( pAlphaBits != (char*)pAlphaBuffer->mpBits )
-        delete[] pAlphaBits;
-
-    const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, sal_True );
-
-    XRenderPictureAttributes aAttr;
-    aAttr.repeat = true;
-    Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
-    if( !aAlphaPic )
-        return false;
+        // an XImage needs its data top_down
+        // TODO: avoid wrongly oriented images in upper layers!
+        const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
+        const char* pSrcBits = (char*)pAlphaBuffer->mpBits;
+        char* pAlphaBits = new char[ nImageSize ];
+        if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
+            memcpy( pAlphaBits, pSrcBits, nImageSize );
+        else
+            {
+                char* pDstBits = pAlphaBits + nImageSize;
+                const int nLineSize = pAlphaBuffer->mnScanlineSize;
+                for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
+                    memcpy( pDstBits, pSrcBits, nLineSize );
+            }
+
+        // the alpha values need to be inverted for XRender
+        // TODO: make upper layers use standard alpha
+        long* pLDst = (long*)pAlphaBits;
+        for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
+            *pLDst = ~*pLDst;
+
+        char* pCDst = (char*)pLDst;
+        for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
+            *pCDst = ~*pCDst;
+
+        const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
+        XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
+                                          pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
+                                          pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
+
+        aAlphaPM = limitXCreatePixmap( pXDisplay, hDrawable_,
+                                       rTR.mnDestWidth, rTR.mnDestHeight, 8 );
+
+        XGCValues aAlphaGCV;
+        aAlphaGCV.function = GXcopy;
+        GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
+        XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
+                   rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
+        XFreeGC( pXDisplay, aAlphaGC );
+        XFree( pAlphaImg );
+        if( pAlphaBits != (char*)pAlphaBuffer->mpBits )
+            delete[] pAlphaBits;
+
+        const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, sal_True );
+
+        XRenderPictureAttributes aAttr;
+        aAttr.repeat = true;
+        aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
+        if( !aAlphaPic )
+            return false;
+    }
 
     // set clipping
     if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
         rPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
 
     // paint source * mask over destination picture
-    rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic,
-        rTR.mnSrcX, rTR.mnSrcY, 0, 0,
-        rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
+    rPeer.CompositePicture( PictOpOver, aSrcPic, bUseAlphaBitmap ? aAlphaPic : None, aDstPic,
+                            rTR.mnSrcX, rTR.mnSrcY, 0, 0,
+                            rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
 
-    rPeer.FreePicture( aAlphaPic );
-    XFreePixmap(pXDisplay, aAlphaPM);
+    if ( bUseAlphaBitmap )
+    {
+        rPeer.FreePicture( aAlphaPic );
+        XFreePixmap( pXDisplay, aAlphaPM);
+    }
     rPeer.FreePicture( aSrcPic );
     return true;
 }


More information about the Libreoffice-commits mailing list