diff options
author | tsahi glik <tsahi.glik@cloudon.com> | 2014-01-16 12:51:44 -0800 |
---|---|---|
committer | tsahi glik <tsahi.glik@cloudon.com> | 2014-01-16 12:55:57 -0800 |
commit | a5351434fbea1126961f5dbaa986e7c9e686c24e (patch) | |
tree | 25dc716144a7e9414c1bfc5fa754bdf2fcea65f1 /vcl | |
parent | 2646b1594de2c156571e66e9f7eb1afbde863a3b (diff) |
fix rendering issues in iOS with aqua
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/quartz/salbmp.h | 4 | ||||
-rw-r--r-- | vcl/quartz/salbmp.cxx | 101 | ||||
-rw-r--r-- | vcl/quartz/salgdi.cxx | 24 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 90 |
4 files changed, 169 insertions, 50 deletions
diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h index 510c64faa38c..7d3d7df63efe 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 d3246df5d134..66576d31c5cc 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 9f07939ef828..252a025edf56 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 c2b1c8e6519f..0224f5860ea9 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 |