summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authortsahi glik <tsahi.glik@cloudon.com>2014-01-16 12:51:44 -0800
committertsahi glik <tsahi.glik@cloudon.com>2014-01-16 12:55:57 -0800
commita5351434fbea1126961f5dbaa986e7c9e686c24e (patch)
tree25dc716144a7e9414c1bfc5fa754bdf2fcea65f1 /vcl
parent2646b1594de2c156571e66e9f7eb1afbde863a3b (diff)
fix rendering issues in iOS with aqua
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/quartz/salbmp.h4
-rw-r--r--vcl/quartz/salbmp.cxx101
-rw-r--r--vcl/quartz/salgdi.cxx24
-rw-r--r--vcl/quartz/salgdicommon.cxx90
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