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

tsahi glik tsahi.glik at cloudon.com
Thu Jan 16 12:56:41 PST 2014


 drawinglayer/source/processor2d/vclhelperbufferdevice.cxx |   14 -
 vcl/inc/quartz/salbmp.h                                   |    4 
 vcl/quartz/salbmp.cxx                                     |  101 ++++++++++++--
 vcl/quartz/salgdi.cxx                                     |   24 ---
 vcl/quartz/salgdicommon.cxx                               |   90 +++++++++---
 5 files changed, 176 insertions(+), 57 deletions(-)

New commits:
commit a5351434fbea1126961f5dbaa986e7c9e686c24e
Author: tsahi glik <tsahi.glik at cloudon.com>
Date:   Thu Jan 16 12:51:44 2014 -0800

    fix rendering issues in iOS with aqua

diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index 46ad65b..176d7a4 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -47,7 +47,7 @@ namespace
         VDevBuffer();
         virtual ~VDevBuffer();
 
-        VirtualDevice* alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono);
+        VirtualDevice* alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, sal_Int32 nBits);
         void free(VirtualDevice& rDevice);
 
         // Timer virtuals
@@ -80,7 +80,7 @@ namespace
         }
     }
 
-    VirtualDevice* VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, bool bMono)
+    VirtualDevice* VDevBuffer::alloc(OutputDevice& rOutDev, const Size& rSizePixel, bool bClear, sal_Int32 nBits)
     {
         ::osl::MutexGuard aGuard(m_aMutex);
         VirtualDevice* pRetval = 0;
@@ -94,7 +94,7 @@ namespace
             {
                 OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)");
 
-                if((bMono && 1 == (*a)->GetBitCount()) || (!bMono && (*a)->GetBitCount() > 1))
+                if(nBits == (*a)->GetBitCount())
                 {
                     // candidate is valid due to bit depth
                     if(aFound != maFreeBuffers.end())
@@ -160,7 +160,7 @@ namespace
         // no success yet, create new buffer
         if(!pRetval)
         {
-            pRetval = (bMono) ? new VirtualDevice(rOutDev, 1) : new VirtualDevice(rOutDev);
+            pRetval = new VirtualDevice(rOutDev, nBits);
             pRetval->SetOutputSizePixel(rSizePixel, bClear);
         }
         else
@@ -233,7 +233,7 @@ namespace drawinglayer
 
         if(isVisible())
         {
-            mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false);
+            mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, 0);
 
             // #i93485# assert when copying from window to VDev is used
             OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW,
@@ -348,7 +348,7 @@ namespace drawinglayer
         OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
         if(!mpMask)
         {
-            mpMask = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, true);
+            mpMask = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, 1);
             mpMask->SetMapMode(mpContent->GetMapMode());
 
             // do NOT copy AA flag for mask!
@@ -362,7 +362,7 @@ namespace drawinglayer
         OSL_ENSURE(mpContent, "impBufferDevice: No content, check isVisible() before accessing (!)");
         if(!mpAlpha)
         {
-            mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false);
+            mpAlpha = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, 8);
             mpAlpha->SetMapMode(mpContent->GetMapMode());
 
             // copy AA flag for new target; masking needs to be smooth
diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h
index 510c64f..7d3d7df 100644
--- a/vcl/inc/quartz/salbmp.h
+++ b/vcl/inc/quartz/salbmp.h
@@ -55,6 +55,7 @@ public:
     int                             mnWidth;
     int                             mnHeight;
     sal_uInt32                      mnBytesPerRow;
+    void*                           maExternalData;
 
 public:
     QuartzSalBitmap();
@@ -70,6 +71,8 @@ public:
     virtual bool    Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas,
                             Size& rSize,
                             bool bMask = false );
+    // creating quartz wrapper from existing buffer
+    bool            Create( BitmapBuffer& buffer);
 
     void            Destroy();
 
@@ -93,6 +96,7 @@ private:
 
 public:
     bool            Create( CGLayerRef xLayer, int nBitCount, int nX, int nY, int nWidth, int nHeight );
+    bool            Create( CGImageRef xImage, int nBitCount, int nX, int nY, int nWidth, int nHeight );
 
 public:
     CGImageRef      CreateWithMask( const QuartzSalBitmap& rMask, int nX, int nY, int nWidth, int nHeight ) const;
diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx
index d3246df..66576d3 100644
--- a/vcl/quartz/salbmp.cxx
+++ b/vcl/quartz/salbmp.cxx
@@ -62,6 +62,7 @@ QuartzSalBitmap::QuartzSalBitmap()
 , mnWidth(0)
 , mnHeight(0)
 , mnBytesPerRow(0)
+, maExternalData(NULL)
 {
 }
 
@@ -102,7 +103,63 @@ bool QuartzSalBitmap::Create( CGLayerRef xLayer, int nBitmapBits,
 
     // copy layer content into the bitmap buffer
     const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX), static_cast<CGFloat>(-nY) };
-    CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer );
+    if(mxGraphicContext) // remove warning
+        CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer );
+    return true;
+}
+
+// ------------------------------------------------------------------
+
+bool QuartzSalBitmap::Create( CGImageRef xImage, int nBitmapBits,
+                             int nX, int nY, int nWidth, int nHeight )
+{
+    DBG_ASSERT( xImage, "QuartzSalBitmap::Create() from null image" );
+
+    // sanitize input parameters
+    if( nX < 0 )
+        nWidth += nX, nX = 0;
+    if( nY < 0 )
+        nHeight += nY, nY = 0;
+    const CGSize aLayerSize = CGSizeMake(CGImageGetWidth(xImage), CGImageGetHeight(xImage));
+    if( nWidth >= (int)aLayerSize.width - nX )
+        nWidth = (int)aLayerSize.width - nX;
+    if( nHeight >= (int)aLayerSize.height - nY )
+        nHeight = (int)aLayerSize.height - nY;
+    if( (nWidth < 0) || (nHeight < 0) )
+        nWidth = nHeight = 0;
+
+    // initialize properties
+    mnWidth  = nWidth;
+    mnHeight = nHeight;
+    mnBits   = nBitmapBits ? nBitmapBits : 32;
+
+    // initialize drawing context
+    CreateContext();
+
+    // copy layer content into the bitmap buffer
+    if(mxGraphicContext) // remove warning
+        CGContextDrawImage( mxGraphicContext,
+                           CGRectMake(static_cast<CGFloat>(-nX),
+                                      static_cast<CGFloat>(-nY),
+                                      aLayerSize.width,
+                                      aLayerSize.height),
+                           xImage );
+    return true;
+}
+
+bool QuartzSalBitmap::Create( BitmapBuffer& buffer)
+{
+    // initialize properties
+    mnWidth  = buffer.mnWidth;
+    mnHeight = buffer.mnHeight;
+    mnBits   = buffer.mnBitCount;
+    mnBytesPerRow = buffer.mnScanlineSize;
+    maExternalData = buffer.mpBits;
+    maPalette = buffer.maPalette;
+
+    // initialize drawing context
+    CreateContext();
+
     return true;
 }
 
@@ -168,6 +225,7 @@ void QuartzSalBitmap::Destroy()
 {
     DestroyContext();
     maUserBuffer.reset();
+    maExternalData = NULL;
 }
 
 // ------------------------------------------------------------------
@@ -193,12 +251,16 @@ bool QuartzSalBitmap::CreateContext()
 
     // prepare graphics context
     // convert image from user input if available
-    const bool bSkipConversion = !maUserBuffer;
+    const bool bSkipConversion = !maUserBuffer && !maExternalData;
     if( bSkipConversion )
         AllocateUserData();
 
     // default to RGBA color space
+#ifdef IOS
+    CGColorSpaceRef aCGColorSpace = CGColorSpaceCreateDeviceRGB();
+#else
     CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
+#endif
     CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst;
 
     // convert data into something accepted by CGBitmapContextCreate()
@@ -206,14 +268,28 @@ bool QuartzSalBitmap::CreateContext()
     sal_uInt32 nContextBytesPerRow = mnBytesPerRow;
     if( (mnBits == 16) || (mnBits == 32) )
     {
-        // no conversion needed for truecolor
-        maContextBuffer = maUserBuffer;
+        if (!maExternalData)
+        {
+            // no conversion needed for truecolor
+            maContextBuffer = maUserBuffer;
+        }
     }
-    else if( (mnBits == 8) && maPalette.IsGreyPalette() )
+    else if( mnBits == 8
+#ifndef IOS
+            && maPalette.IsGreyPalette()
+#endif
+            )
     {
         // no conversion needed for grayscale
-        maContextBuffer = maUserBuffer;
+        if (!maExternalData)
+        {
+            maContextBuffer = maUserBuffer;
+        }
+#ifdef IOS
+        aCGColorSpace = CGColorSpaceCreateDeviceGray();
+#else
         aCGColorSpace = GetSalData()->mxGraySpace;
+#endif
         aCGBmpInfo = kCGImageAlphaNone;
         bitsPerComponent = mnBits;
     }
@@ -237,9 +313,14 @@ bool QuartzSalBitmap::CreateContext()
         }
     }
 
-    if( maContextBuffer.get() )
+    if(maExternalData)
+    {
+        mxGraphicContext = ::CGBitmapContextCreate( maExternalData, mnWidth, mnHeight,
+                                                   bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo );
+    }
+    else if( maContextBuffer.get() )
     {
-        mxGraphicContext = CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight,
+        mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight,
             bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo );
     }
 
@@ -280,7 +361,7 @@ bool QuartzSalBitmap::AllocateUserData()
     catch( const std::bad_alloc& )
     {
         OSL_FAIL( "vcl::QuartzSalBitmap::AllocateUserData: bad alloc" );
-        maUserBuffer.reset();
+        maUserBuffer.reset( static_cast<sal_uInt8*>(NULL) );
         mnBytesPerRow = 0;
     }
 
@@ -771,7 +852,7 @@ CGImageRef QuartzSalBitmap::CreateWithMask( const QuartzSalBitmap& rMask,
 
     // CGImageCreateWithMask() only likes masks or greyscale images => convert if needed
     // TODO: isolate in an extra method?
-    if( !CGImageIsMask(xMask) || (CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace) )
+    if( !CGImageIsMask(xMask) || rMask.GetBitCount() != 8)//(CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace) )
     {
         const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the rect has no offset
 
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 9f07939..252a025 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -806,6 +806,8 @@ bool SvpSalGraphics::CheckContext()
 {
     if (mbForeignContext)
         return true;
+    if(m_aDevice == NULL) // fix tiledrendering crash when changing content size
+        return false;
 
     const basegfx::B2IVector size = m_aDevice->getSize();
     const basegfx::B2IVector bufferSize = m_aDevice->getBufferSize();
@@ -829,32 +831,14 @@ bool SvpSalGraphics::CheckContext()
                                           kCGImageAlphaNone);
         break;
     case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
-        mrContext = CGBitmapContextCreate(pixelBuffer.get(),
-                                          bufferSize.getX(), bufferSize.getY(),
-                                          8, scanlineStride,
-                                          CGColorSpaceCreateDeviceRGB(),
-                                          kCGImageAlphaNoneSkipLast);
-        break;
     case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB:
-        mrContext = CGBitmapContextCreate(pixelBuffer.get(),
-                                          bufferSize.getX(), bufferSize.getY(),
-                                          8, scanlineStride,
-                                          CGColorSpaceCreateDeviceRGB(),
-                                          kCGImageAlphaNoneSkipFirst);
-        break;
-    case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
-        mrContext = CGBitmapContextCreate(pixelBuffer.get(),
-                                          bufferSize.getX(), bufferSize.getY(),
-                                          8, scanlineStride,
-                                          CGColorSpaceCreateDeviceRGB(),
-                                          kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
-        break;
     case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR:
+    case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
         mrContext = CGBitmapContextCreate(pixelBuffer.get(),
                                           bufferSize.getX(), bufferSize.getY(),
                                           8, scanlineStride,
                                           CGColorSpaceCreateDeviceRGB(),
-                                          kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Little);
+                                          kCGImageAlphaNoneSkipFirst);//kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
         break;
     default:
         SAL_WARN( "vcl.ios", "CheckContext: unsupported color format " << basebmp::formatName( m_aDevice->getScanlineFormat() ) );
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index c2b1c8e..0224f58 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -35,6 +35,8 @@
 
 #ifdef IOS
 #include "saldatabasic.hxx"
+#include "headless/svpbmp.hxx"
+#include <basegfx/range/b2ibox.hxx>
 #endif
 
 using namespace vcl;
@@ -285,12 +287,6 @@ static inline void alignLinePoint( const SalPoint* i_pIn, float& o_fX, float& o_
 
 void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics )
 {
-#ifdef IOS
-    // Horrible horrible this is all crack, mxLayer is always NULL on iOS,
-    // all this stuff should be rewritten anyway for iOS
-    if( !mxLayer )
-        return;
-#endif
 
     if( !pSrcGraphics )
     {
@@ -335,12 +331,9 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
     const CGPoint aDstPoint = CGPointMake(+rPosAry.mnDestX - rPosAry.mnSrcX, rPosAry.mnDestY - rPosAry.mnSrcY);
     if( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth &&
          rPosAry.mnSrcHeight == rPosAry.mnDestHeight) &&
-        (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) ) // workaround a Quartz crasher
+        (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth)
+        && pSrc->mxLayer ) // workaround a Quartz crasher
     {
-#ifdef IOS
-        if( !CheckContext() )
-            return;
-#endif
         // in XOR mode the drawing context is redirected to the XOR mask
         // if source and target are identical then copyBits() paints onto the target context though
         CGContextRef xCopyContext = mrContext;
@@ -895,6 +888,25 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol
     // #i97317# workaround for Quartz having problems with drawing small polygons
     if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) )
     {
+        // prepare drawing mode
+        CGPathDrawingMode eMode;
+        if( IsBrushVisible() && IsPenVisible() )
+        {
+            eMode = kCGPathEOFillStroke;
+        }
+        else if( IsPenVisible() )
+        {
+            eMode = kCGPathStroke;
+        }
+        else if( IsBrushVisible() )
+        {
+            eMode = kCGPathEOFill;
+        }
+        else
+        {
+            return true;
+        }
+
         // use the path to prepare the graphics context
         CGContextSaveGState( mrContext );
         CGContextBeginPath( mrContext );
@@ -903,7 +915,7 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol
         // draw path with antialiased polygon
         CGContextSetShouldAntialias( mrContext, true );
         CGContextSetAlpha( mrContext, 1.0 - fTransparency );
-        CGContextDrawPath( mrContext, kCGPathEOFillStroke );
+        CGContextDrawPath( mrContext, eMode );
         CGContextRestoreGState( mrContext );
 
         // mark modified rectangle as updated
@@ -1145,18 +1157,56 @@ sal_uInt16 AquaSalGraphics::GetBitCount() const
 
 SalBitmap* AquaSalGraphics::getBitmap( long  nX, long  nY, long  nDX, long  nDY )
 {
-    DBG_ASSERT( mxLayer, "AquaSalGraphics::getBitmap() with no layer" );
-
-    ApplyXorContext();
+    if (!mbForeignContext && m_aDevice != NULL)
+    {
+        // on ios virtual device are Svp so use Svp bitmap to get the content
+        basegfx::B2IBox aRect( nX, nY, nX+nDX, nY+nDY );
+        basebmp::BitmapDeviceSharedPtr aSubSet = basebmp::subsetBitmapDevice(m_aDevice , aRect );
 
-    QuartzSalBitmap* pBitmap = new QuartzSalBitmap;
-    if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY) )
+        SvpSalBitmap* pSalBitmap = new SvpSalBitmap;
+        pSalBitmap->setBitmap(aSubSet);
+        BitmapBuffer* pBuffer = pSalBitmap->AcquireBuffer(true);
+        QuartzSalBitmap* pBitmap = new QuartzSalBitmap;
+        if( !pBitmap->Create(*pBuffer))
+        {
+            delete pBitmap;
+            pBitmap = NULL;
+        }
+        pSalBitmap->ReleaseBuffer(pBuffer, true);
+        delete pSalBitmap;
+        return pBitmap;
+    }
+    else if (mbForeignContext)
     {
-        delete pBitmap;
-        pBitmap = NULL;
+        //if using external context like on ios, check if we can get a backing image and copy it
+        CGImageRef backImage = CGBitmapContextCreateImage(mrContext);
+        if (backImage)
+        {
+            QuartzSalBitmap* pBitmap = new QuartzSalBitmap;
+            if( !pBitmap->Create(backImage, mnBitmapDepth, nX, nY, nDX, nDY))
+            {
+                delete pBitmap;
+                pBitmap = NULL;
+            }
+            CGImageRelease(backImage);
+            return pBitmap;
+        }
+        return NULL;
     }
+    else
+    {
+        DBG_ASSERT( mxLayer, "AquaSalGraphics::getBitmap() with no layer" );
+
+        ApplyXorContext();
 
-    return pBitmap;
+        QuartzSalBitmap* pBitmap = new QuartzSalBitmap;
+        if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY) )
+        {
+            delete pBitmap;
+            pBitmap = NULL;
+        }
+        return pBitmap;
+    }
 }
 
 #ifndef IOS


More information about the Libreoffice-commits mailing list