19f62ea84SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 59f62ea84SAndrew Rist * distributed with this work for additional information 69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 109f62ea84SAndrew Rist * 119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 129f62ea84SAndrew Rist * 139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 149f62ea84SAndrew Rist * software distributed under the License is distributed on an 159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 179f62ea84SAndrew Rist * specific language governing permissions and limitations 189f62ea84SAndrew Rist * under the License. 199f62ea84SAndrew Rist * 209f62ea84SAndrew Rist *************************************************************/ 219f62ea84SAndrew Rist 229f62ea84SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <boost/bind.hpp> 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include "basebmp/scanlineformats.hxx" 30cdf0e10cSrcweir #include "basebmp/color.hxx" 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include "basegfx/vector/b2ivector.hxx" 33cdf0e10cSrcweir 34cdf0e10cSrcweir #include "tools/color.hxx" 35cdf0e10cSrcweir 36cdf0e10cSrcweir #include "vcl/bitmap.hxx" // for BitmapSystemData 37cdf0e10cSrcweir #include "vcl/salbtype.hxx" 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "aqua/salbmp.h" 40cdf0e10cSrcweir #include "aqua/salinst.h" 41cdf0e10cSrcweir 42cdf0e10cSrcweir #include "bmpfast.hxx" 43cdf0e10cSrcweir 44cdf0e10cSrcweir // ======================================================================= 45cdf0e10cSrcweir 46cdf0e10cSrcweir static bool isValidBitCount( sal_uInt16 nBitCount ) 47cdf0e10cSrcweir { 48cdf0e10cSrcweir return (nBitCount == 1) || (nBitCount == 4) || (nBitCount == 8) || (nBitCount == 16) || (nBitCount == 24) || (nBitCount == 32); 49cdf0e10cSrcweir } 50cdf0e10cSrcweir 51cdf0e10cSrcweir // ======================================================================= 52cdf0e10cSrcweir 53cdf0e10cSrcweir AquaSalBitmap::AquaSalBitmap() 54cdf0e10cSrcweir : mxGraphicContext( NULL ) 55cdf0e10cSrcweir , mxCachedImage( NULL ) 56cdf0e10cSrcweir , mnBits(0) 57cdf0e10cSrcweir , mnWidth(0) 58cdf0e10cSrcweir , mnHeight(0) 59cdf0e10cSrcweir , mnBytesPerRow(0) 60cdf0e10cSrcweir { 61cdf0e10cSrcweir } 62cdf0e10cSrcweir 63cdf0e10cSrcweir // ------------------------------------------------------------------ 64cdf0e10cSrcweir 65cdf0e10cSrcweir AquaSalBitmap::~AquaSalBitmap() 66cdf0e10cSrcweir { 67cdf0e10cSrcweir Destroy(); 68cdf0e10cSrcweir } 69cdf0e10cSrcweir 70cdf0e10cSrcweir // ------------------------------------------------------------------ 71cdf0e10cSrcweir 72cdf0e10cSrcweir bool AquaSalBitmap::Create( CGLayerRef xLayer, int nBitmapBits, 73cdf0e10cSrcweir int nX, int nY, int nWidth, int nHeight, bool /*bMirrorVert*/ ) 74cdf0e10cSrcweir { 75cdf0e10cSrcweir DBG_ASSERT( xLayer, "AquaSalBitmap::Create() from non-layered context" ); 76cdf0e10cSrcweir 77cdf0e10cSrcweir // sanitize input parameters 78cdf0e10cSrcweir if( nX < 0 ) 79cdf0e10cSrcweir nWidth += nX, nX = 0; 80cdf0e10cSrcweir if( nY < 0 ) 81cdf0e10cSrcweir nHeight += nY, nY = 0; 82cdf0e10cSrcweir const CGSize aLayerSize = CGLayerGetSize( xLayer ); 83cdf0e10cSrcweir if( nWidth >= (int)aLayerSize.width - nX ) 84cdf0e10cSrcweir nWidth = (int)aLayerSize.width - nX; 85cdf0e10cSrcweir if( nHeight >= (int)aLayerSize.height - nY ) 86cdf0e10cSrcweir nHeight = (int)aLayerSize.height - nY; 87cdf0e10cSrcweir if( (nWidth < 0) || (nHeight < 0) ) 88cdf0e10cSrcweir nWidth = nHeight = 0; 89cdf0e10cSrcweir 90cdf0e10cSrcweir // initialize properties 91cdf0e10cSrcweir mnWidth = nWidth; 92cdf0e10cSrcweir mnHeight = nHeight; 93cdf0e10cSrcweir mnBits = nBitmapBits ? nBitmapBits : 32; 94cdf0e10cSrcweir 95cdf0e10cSrcweir // initialize drawing context 96cdf0e10cSrcweir CreateContext(); 97cdf0e10cSrcweir 98cdf0e10cSrcweir // copy layer content into the bitmap buffer 99*cd426cceSHerbert Dürr const CGPoint aSrcPoint = CGPointMake( -nX, -nY); 100cdf0e10cSrcweir ::CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer ); 101cdf0e10cSrcweir return true; 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir // ------------------------------------------------------------------ 105cdf0e10cSrcweir 106cdf0e10cSrcweir bool AquaSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette ) 107cdf0e10cSrcweir { 108cdf0e10cSrcweir if( !isValidBitCount( nBits ) ) 109cdf0e10cSrcweir return false; 110cdf0e10cSrcweir maPalette = rBitmapPalette; 111cdf0e10cSrcweir mnBits = nBits; 112cdf0e10cSrcweir mnWidth = rSize.Width(); 113cdf0e10cSrcweir mnHeight = rSize.Height(); 114cdf0e10cSrcweir return AllocateUserData(); 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir // ------------------------------------------------------------------ 118cdf0e10cSrcweir 119cdf0e10cSrcweir bool AquaSalBitmap::Create( const SalBitmap& rSalBmp ) 120cdf0e10cSrcweir { 121cdf0e10cSrcweir return Create( rSalBmp, rSalBmp.GetBitCount() ); 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir // ------------------------------------------------------------------ 125cdf0e10cSrcweir 126cdf0e10cSrcweir bool AquaSalBitmap::Create( const SalBitmap& rSalBmp, SalGraphics* pGraphics ) 127cdf0e10cSrcweir { 128cdf0e10cSrcweir return Create( rSalBmp, pGraphics ? pGraphics->GetBitCount() : rSalBmp.GetBitCount() ); 129cdf0e10cSrcweir } 130cdf0e10cSrcweir 131cdf0e10cSrcweir // ------------------------------------------------------------------ 132cdf0e10cSrcweir 133cdf0e10cSrcweir bool AquaSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount ) 134cdf0e10cSrcweir { 135cdf0e10cSrcweir const AquaSalBitmap& rSourceBitmap = static_cast<const AquaSalBitmap&>(rSalBmp); 136cdf0e10cSrcweir 137cdf0e10cSrcweir if( isValidBitCount( nNewBitCount ) && rSourceBitmap.maUserBuffer.get() ) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir mnBits = nNewBitCount; 140cdf0e10cSrcweir mnWidth = rSourceBitmap.mnWidth; 141cdf0e10cSrcweir mnHeight = rSourceBitmap.mnHeight; 142cdf0e10cSrcweir maPalette = rSourceBitmap.maPalette; 143cdf0e10cSrcweir 144cdf0e10cSrcweir if( AllocateUserData() ) 145cdf0e10cSrcweir { 146cdf0e10cSrcweir ConvertBitmapData( mnWidth, mnHeight, mnBits, mnBytesPerRow, maPalette, maUserBuffer.get(), rSourceBitmap.mnBits, rSourceBitmap.mnBytesPerRow, rSourceBitmap.maPalette, rSourceBitmap.maUserBuffer.get() ); 147cdf0e10cSrcweir return true; 148cdf0e10cSrcweir } 149cdf0e10cSrcweir } 150cdf0e10cSrcweir return false; 151cdf0e10cSrcweir } 152cdf0e10cSrcweir 153cdf0e10cSrcweir // ------------------------------------------------------------------ 154cdf0e10cSrcweir 155cdf0e10cSrcweir void AquaSalBitmap::Destroy() 156cdf0e10cSrcweir { 157cdf0e10cSrcweir DestroyContext(); 158cdf0e10cSrcweir maUserBuffer.reset(); 159cdf0e10cSrcweir } 160cdf0e10cSrcweir 161cdf0e10cSrcweir // ------------------------------------------------------------------ 162cdf0e10cSrcweir 163cdf0e10cSrcweir void AquaSalBitmap::DestroyContext() 164cdf0e10cSrcweir { 165cdf0e10cSrcweir CGImageRelease( mxCachedImage ); 166cdf0e10cSrcweir mxCachedImage = NULL; 167cdf0e10cSrcweir 168cdf0e10cSrcweir if( mxGraphicContext ) 169cdf0e10cSrcweir { 170cdf0e10cSrcweir CGContextRelease( mxGraphicContext ); 171cdf0e10cSrcweir mxGraphicContext = NULL; 172cdf0e10cSrcweir maContextBuffer.reset(); 173cdf0e10cSrcweir } 174cdf0e10cSrcweir } 175cdf0e10cSrcweir 176cdf0e10cSrcweir // ------------------------------------------------------------------ 177cdf0e10cSrcweir 178cdf0e10cSrcweir bool AquaSalBitmap::CreateContext() 179cdf0e10cSrcweir { 180cdf0e10cSrcweir DestroyContext(); 181cdf0e10cSrcweir 182cdf0e10cSrcweir // prepare graphics context 183cdf0e10cSrcweir // convert image from user input if available 184cdf0e10cSrcweir const bool bSkipConversion = !maUserBuffer; 185cdf0e10cSrcweir if( bSkipConversion ) 186cdf0e10cSrcweir AllocateUserData(); 187cdf0e10cSrcweir 188cdf0e10cSrcweir // default to RGBA color space 189cdf0e10cSrcweir CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; 190cdf0e10cSrcweir CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; 191cdf0e10cSrcweir 192cdf0e10cSrcweir // convert data into something accepted by CGBitmapContextCreate() 193cdf0e10cSrcweir size_t bitsPerComponent = (mnBits == 16) ? 5 : 8; 194cdf0e10cSrcweir sal_uInt32 nContextBytesPerRow = mnBytesPerRow; 195cdf0e10cSrcweir if( (mnBits == 16) || (mnBits == 32) ) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir // no conversion needed for truecolor 198cdf0e10cSrcweir maContextBuffer = maUserBuffer; 199cdf0e10cSrcweir } 200cdf0e10cSrcweir else if( (mnBits == 8) && maPalette.IsGreyPalette() ) 201cdf0e10cSrcweir { 202cdf0e10cSrcweir // no conversion needed for grayscale 203cdf0e10cSrcweir maContextBuffer = maUserBuffer; 204cdf0e10cSrcweir aCGColorSpace = GetSalData()->mxGraySpace; 205cdf0e10cSrcweir aCGBmpInfo = kCGImageAlphaNone; 206cdf0e10cSrcweir bitsPerComponent = mnBits; 207cdf0e10cSrcweir } 208cdf0e10cSrcweir // TODO: is special handling for 1bit input buffers worth it? 209cdf0e10cSrcweir else 210cdf0e10cSrcweir { 211cdf0e10cSrcweir // convert user data to 32 bit 212cdf0e10cSrcweir nContextBytesPerRow = mnWidth << 2; 213cdf0e10cSrcweir try 214cdf0e10cSrcweir { 215cdf0e10cSrcweir maContextBuffer.reset( new sal_uInt8[ mnHeight * nContextBytesPerRow ] ); 216cdf0e10cSrcweir 217cdf0e10cSrcweir if( !bSkipConversion ) 218cdf0e10cSrcweir ConvertBitmapData( mnWidth, mnHeight, 219cdf0e10cSrcweir 32, nContextBytesPerRow, maPalette, maContextBuffer.get(), 220cdf0e10cSrcweir mnBits, mnBytesPerRow, maPalette, maUserBuffer.get() ); 221cdf0e10cSrcweir } 222cdf0e10cSrcweir catch( std::bad_alloc ) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir mxGraphicContext = 0; 225cdf0e10cSrcweir } 226cdf0e10cSrcweir } 227cdf0e10cSrcweir 228cdf0e10cSrcweir if( maContextBuffer.get() ) 229cdf0e10cSrcweir { 230cdf0e10cSrcweir mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight, 231cdf0e10cSrcweir bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo ); 232cdf0e10cSrcweir } 233cdf0e10cSrcweir 234cdf0e10cSrcweir if( !mxGraphicContext ) 235cdf0e10cSrcweir maContextBuffer.reset(); 236cdf0e10cSrcweir 237cdf0e10cSrcweir return mxGraphicContext != NULL; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir 240cdf0e10cSrcweir // ------------------------------------------------------------------ 241cdf0e10cSrcweir 242cdf0e10cSrcweir bool AquaSalBitmap::AllocateUserData() 243cdf0e10cSrcweir { 244cdf0e10cSrcweir Destroy(); 245cdf0e10cSrcweir 246cdf0e10cSrcweir if( mnWidth && mnHeight ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir mnBytesPerRow = 0; 249cdf0e10cSrcweir 250cdf0e10cSrcweir switch( mnBits ) 251cdf0e10cSrcweir { 252cdf0e10cSrcweir case 1: mnBytesPerRow = (mnWidth + 7) >> 3; break; 253cdf0e10cSrcweir case 4: mnBytesPerRow = (mnWidth + 1) >> 1; break; 254cdf0e10cSrcweir case 8: mnBytesPerRow = mnWidth; break; 255cdf0e10cSrcweir case 16: mnBytesPerRow = mnWidth << 1; break; 256cdf0e10cSrcweir case 24: mnBytesPerRow = (mnWidth << 1) + mnWidth; break; 257cdf0e10cSrcweir case 32: mnBytesPerRow = mnWidth << 2; break; 258cdf0e10cSrcweir default: 259cdf0e10cSrcweir DBG_ERROR("vcl::AquaSalBitmap::AllocateUserData(), illegal bitcount!"); 260cdf0e10cSrcweir } 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir try 264cdf0e10cSrcweir { 265cdf0e10cSrcweir if( mnBytesPerRow ) 266cdf0e10cSrcweir maUserBuffer.reset( new sal_uInt8[mnBytesPerRow * mnHeight] ); 267cdf0e10cSrcweir } 268cdf0e10cSrcweir catch( const std::bad_alloc& ) 269cdf0e10cSrcweir { 270cdf0e10cSrcweir DBG_ERROR( "vcl::AquaSalBitmap::AllocateUserData: bad alloc" ); 271cdf0e10cSrcweir maUserBuffer.reset( NULL ); 272cdf0e10cSrcweir mnBytesPerRow = 0; 273cdf0e10cSrcweir } 274cdf0e10cSrcweir 275cdf0e10cSrcweir return maUserBuffer.get() != 0; 276cdf0e10cSrcweir } 277cdf0e10cSrcweir 278cdf0e10cSrcweir // ------------------------------------------------------------------ 279cdf0e10cSrcweir 280cdf0e10cSrcweir class ImplPixelFormat 281cdf0e10cSrcweir { 282cdf0e10cSrcweir protected: 283cdf0e10cSrcweir sal_uInt8* pData; 284cdf0e10cSrcweir public: 285cdf0e10cSrcweir static ImplPixelFormat* GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette ); 286cdf0e10cSrcweir 287cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine ) { pData = pLine; } 288cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) = 0; 289cdf0e10cSrcweir virtual ColorData ReadPixel() = 0; 290cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) = 0; 291cdf0e10cSrcweir }; 292cdf0e10cSrcweir 293cdf0e10cSrcweir class ImplPixelFormat32 : public ImplPixelFormat 294cdf0e10cSrcweir // currently ARGB-format for 32bit depth 295cdf0e10cSrcweir { 296cdf0e10cSrcweir public: 297cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir pData += nPixel << 2; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir virtual ColorData ReadPixel() 302cdf0e10cSrcweir { 303cdf0e10cSrcweir const ColorData c = RGB_COLORDATA( pData[1], pData[2], pData[3] ); 304cdf0e10cSrcweir pData += 4; 305cdf0e10cSrcweir return c; 306cdf0e10cSrcweir } 307cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 308cdf0e10cSrcweir { 309cdf0e10cSrcweir *pData++ = 0; 310cdf0e10cSrcweir *pData++ = COLORDATA_RED( nColor ); 311cdf0e10cSrcweir *pData++ = COLORDATA_GREEN( nColor ); 312cdf0e10cSrcweir *pData++ = COLORDATA_BLUE( nColor ); 313cdf0e10cSrcweir } 314cdf0e10cSrcweir }; 315cdf0e10cSrcweir 316cdf0e10cSrcweir class ImplPixelFormat24 : public ImplPixelFormat 317cdf0e10cSrcweir // currently BGR-format for 24bit depth 318cdf0e10cSrcweir { 319cdf0e10cSrcweir public: 320cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 321cdf0e10cSrcweir { 322cdf0e10cSrcweir pData += (nPixel << 1) + nPixel; 323cdf0e10cSrcweir } 324cdf0e10cSrcweir virtual ColorData ReadPixel() 325cdf0e10cSrcweir { 326cdf0e10cSrcweir const ColorData c = RGB_COLORDATA( pData[2], pData[1], pData[0] ); 327cdf0e10cSrcweir pData += 3; 328cdf0e10cSrcweir return c; 329cdf0e10cSrcweir } 330cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 331cdf0e10cSrcweir { 332cdf0e10cSrcweir *pData++ = COLORDATA_BLUE( nColor ); 333cdf0e10cSrcweir *pData++ = COLORDATA_GREEN( nColor ); 334cdf0e10cSrcweir *pData++ = COLORDATA_RED( nColor ); 335cdf0e10cSrcweir } 336cdf0e10cSrcweir }; 337cdf0e10cSrcweir 338cdf0e10cSrcweir class ImplPixelFormat16 : public ImplPixelFormat 339cdf0e10cSrcweir // currently R5G6B5-format for 16bit depth 340cdf0e10cSrcweir { 341cdf0e10cSrcweir protected: 342cdf0e10cSrcweir sal_uInt16* pData16; 343cdf0e10cSrcweir public: 344cdf0e10cSrcweir 345cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir pData16 = (sal_uInt16*)pLine; 348cdf0e10cSrcweir } 349cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 350cdf0e10cSrcweir { 351cdf0e10cSrcweir pData += nPixel; 352cdf0e10cSrcweir } 353cdf0e10cSrcweir virtual ColorData ReadPixel() 354cdf0e10cSrcweir { 355cdf0e10cSrcweir const ColorData c = RGB_COLORDATA( (*pData & 0x7c00) >> 7, (*pData & 0x03e0) >> 2 , (*pData & 0x001f) << 3 ); 356cdf0e10cSrcweir pData++; 357cdf0e10cSrcweir return c; 358cdf0e10cSrcweir } 359cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 360cdf0e10cSrcweir { 361cdf0e10cSrcweir *pData++ = ((COLORDATA_RED( nColor ) & 0xf8 ) << 7 ) || 362cdf0e10cSrcweir ((COLORDATA_GREEN( nColor ) & 0xf8 ) << 2 ) || 363cdf0e10cSrcweir ((COLORDATA_BLUE( nColor ) & 0xf8 ) >> 3 ); 364cdf0e10cSrcweir } 365cdf0e10cSrcweir }; 366cdf0e10cSrcweir 367cdf0e10cSrcweir class ImplPixelFormat8 : public ImplPixelFormat 368cdf0e10cSrcweir { 369cdf0e10cSrcweir private: 370cdf0e10cSrcweir const BitmapPalette& mrPalette; 371cdf0e10cSrcweir 372cdf0e10cSrcweir public: 373cdf0e10cSrcweir ImplPixelFormat8( const BitmapPalette& rPalette ) 374cdf0e10cSrcweir : mrPalette( rPalette ) 375cdf0e10cSrcweir { 376cdf0e10cSrcweir } 377cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 378cdf0e10cSrcweir { 379cdf0e10cSrcweir pData += nPixel; 380cdf0e10cSrcweir } 381cdf0e10cSrcweir virtual ColorData ReadPixel() 382cdf0e10cSrcweir { 383cdf0e10cSrcweir return mrPalette[ *pData++ ].operator Color().GetColor(); 384cdf0e10cSrcweir } 385cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 386cdf0e10cSrcweir { 387cdf0e10cSrcweir const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); 388cdf0e10cSrcweir *pData++ = static_cast< sal_uInt8 >( mrPalette.GetBestIndex( aColor ) ); 389cdf0e10cSrcweir } 390cdf0e10cSrcweir }; 391cdf0e10cSrcweir 392cdf0e10cSrcweir class ImplPixelFormat4 : public ImplPixelFormat 393cdf0e10cSrcweir { 394cdf0e10cSrcweir private: 395cdf0e10cSrcweir const BitmapPalette& mrPalette; 396cdf0e10cSrcweir sal_uInt32 mnX; 397cdf0e10cSrcweir sal_uInt32 mnShift; 398cdf0e10cSrcweir 399cdf0e10cSrcweir public: 400cdf0e10cSrcweir ImplPixelFormat4( const BitmapPalette& rPalette ) 401cdf0e10cSrcweir : mrPalette( rPalette ) 402cdf0e10cSrcweir { 403cdf0e10cSrcweir } 404cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 405cdf0e10cSrcweir { 406cdf0e10cSrcweir mnX += nPixel; 407cdf0e10cSrcweir if( (nPixel & 1) ) 408cdf0e10cSrcweir mnShift ^= 4; 409cdf0e10cSrcweir } 410cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine ) 411cdf0e10cSrcweir { 412cdf0e10cSrcweir pData = pLine; 413cdf0e10cSrcweir mnX = 0; 414cdf0e10cSrcweir mnShift = 4; 415cdf0e10cSrcweir } 416cdf0e10cSrcweir virtual ColorData ReadPixel() 417cdf0e10cSrcweir { 418cdf0e10cSrcweir const BitmapColor& rColor = mrPalette[( pData[mnX >> 1] >> mnShift) & 0x0f]; 419cdf0e10cSrcweir mnX++; 420cdf0e10cSrcweir mnShift ^= 4; 421cdf0e10cSrcweir return rColor.operator Color().GetColor(); 422cdf0e10cSrcweir } 423cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 424cdf0e10cSrcweir { 425cdf0e10cSrcweir const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); 426cdf0e10cSrcweir pData[mnX>>1] &= (0xf0 >> mnShift); 427cdf0e10cSrcweir pData[mnX>>1] |= (static_cast< sal_uInt8 >( mrPalette.GetBestIndex( aColor ) ) & 0x0f); 428cdf0e10cSrcweir mnX++; 429cdf0e10cSrcweir mnShift ^= 4; 430cdf0e10cSrcweir } 431cdf0e10cSrcweir }; 432cdf0e10cSrcweir 433cdf0e10cSrcweir class ImplPixelFormat1 : public ImplPixelFormat 434cdf0e10cSrcweir { 435cdf0e10cSrcweir private: 436cdf0e10cSrcweir const BitmapPalette& mrPalette; 437cdf0e10cSrcweir sal_uInt32 mnX; 438cdf0e10cSrcweir 439cdf0e10cSrcweir public: 440cdf0e10cSrcweir ImplPixelFormat1( const BitmapPalette& rPalette ) 441cdf0e10cSrcweir : mrPalette( rPalette ) 442cdf0e10cSrcweir { 443cdf0e10cSrcweir } 444cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel ) 445cdf0e10cSrcweir { 446cdf0e10cSrcweir mnX += nPixel; 447cdf0e10cSrcweir } 448cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine ) 449cdf0e10cSrcweir { 450cdf0e10cSrcweir pData = pLine; 451cdf0e10cSrcweir mnX = 0; 452cdf0e10cSrcweir } 453cdf0e10cSrcweir virtual ColorData ReadPixel() 454cdf0e10cSrcweir { 455cdf0e10cSrcweir const BitmapColor& rColor = mrPalette[ (pData[mnX >> 3 ] >> ( 7 - ( mnX & 7 ) )) & 1]; 456cdf0e10cSrcweir mnX++; 457cdf0e10cSrcweir return rColor.operator Color().GetColor(); 458cdf0e10cSrcweir } 459cdf0e10cSrcweir virtual void WritePixel( ColorData nColor ) 460cdf0e10cSrcweir { 461cdf0e10cSrcweir const BitmapColor aColor( COLORDATA_RED( nColor ), COLORDATA_GREEN( nColor ), COLORDATA_BLUE( nColor ) ); 462cdf0e10cSrcweir if( mrPalette.GetBestIndex( aColor ) & 1 ) 463cdf0e10cSrcweir pData[ mnX >> 3 ] |= 1 << ( 7 - ( mnX & 7 ) ); 464cdf0e10cSrcweir else 465cdf0e10cSrcweir pData[ mnX >> 3 ] &= ~( 1 << ( 7 - ( mnX & 7 ) ) ); 466cdf0e10cSrcweir mnX++; 467cdf0e10cSrcweir } 468cdf0e10cSrcweir }; 469cdf0e10cSrcweir 470cdf0e10cSrcweir ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalette& rPalette ) 471cdf0e10cSrcweir { 472cdf0e10cSrcweir switch( nBits ) 473cdf0e10cSrcweir { 474cdf0e10cSrcweir case 1: return new ImplPixelFormat1( rPalette ); 475cdf0e10cSrcweir case 4: return new ImplPixelFormat4( rPalette ); 476cdf0e10cSrcweir case 8: return new ImplPixelFormat8( rPalette ); 477cdf0e10cSrcweir case 16: return new ImplPixelFormat16; 478cdf0e10cSrcweir case 24: return new ImplPixelFormat24; 479cdf0e10cSrcweir case 32: return new ImplPixelFormat32; 480cdf0e10cSrcweir } 481cdf0e10cSrcweir 482cdf0e10cSrcweir return 0; 483cdf0e10cSrcweir } 484cdf0e10cSrcweir 485cdf0e10cSrcweir void AquaSalBitmap::ConvertBitmapData( sal_uInt32 nWidth, sal_uInt32 nHeight, 486cdf0e10cSrcweir sal_uInt16 nDestBits, sal_uInt32 nDestBytesPerRow, const BitmapPalette& rDestPalette, sal_uInt8* pDestData, 487cdf0e10cSrcweir sal_uInt16 nSrcBits, sal_uInt32 nSrcBytesPerRow, const BitmapPalette& rSrcPalette, sal_uInt8* pSrcData ) 488cdf0e10cSrcweir 489cdf0e10cSrcweir { 490cdf0e10cSrcweir if( (nDestBytesPerRow == nSrcBytesPerRow) && (nDestBits == nSrcBits) && ((nSrcBits != 8) || (rDestPalette.operator==( rSrcPalette ))) ) 491cdf0e10cSrcweir { 492cdf0e10cSrcweir // simple case, same format, so just copy 493cdf0e10cSrcweir memcpy( pDestData, pSrcData, nHeight * nDestBytesPerRow ); 494cdf0e10cSrcweir return; 495cdf0e10cSrcweir } 496cdf0e10cSrcweir 497cdf0e10cSrcweir // try accelerated conversion if possible 498cdf0e10cSrcweir // TODO: are other truecolor conversions except BGR->ARGB worth it? 499cdf0e10cSrcweir bool bConverted = false; 500cdf0e10cSrcweir if( (nSrcBits == 24) && (nDestBits == 32) ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir // TODO: extend bmpfast.cxx with a method that can be directly used here 503cdf0e10cSrcweir BitmapBuffer aSrcBuf; 504cdf0e10cSrcweir aSrcBuf.mnFormat = BMP_FORMAT_24BIT_TC_BGR; 505cdf0e10cSrcweir aSrcBuf.mpBits = pSrcData; 506cdf0e10cSrcweir aSrcBuf.mnBitCount = nSrcBits; 507cdf0e10cSrcweir aSrcBuf.mnScanlineSize = nSrcBytesPerRow; 508cdf0e10cSrcweir BitmapBuffer aDstBuf; 509cdf0e10cSrcweir aDstBuf.mnFormat = BMP_FORMAT_32BIT_TC_ARGB; 510cdf0e10cSrcweir aDstBuf.mpBits = pDestData; 511cdf0e10cSrcweir aSrcBuf.mnBitCount = nDestBits; 512cdf0e10cSrcweir aDstBuf.mnScanlineSize = nDestBytesPerRow; 513cdf0e10cSrcweir 514cdf0e10cSrcweir aSrcBuf.mnWidth = aDstBuf.mnWidth = nWidth; 515cdf0e10cSrcweir aSrcBuf.mnHeight = aDstBuf.mnHeight = nHeight; 516cdf0e10cSrcweir 517cdf0e10cSrcweir SalTwoRect aTwoRects; 518cdf0e10cSrcweir aTwoRects.mnSrcX = aTwoRects.mnDestX = 0; 519cdf0e10cSrcweir aTwoRects.mnSrcY = aTwoRects.mnDestY = 0; 520cdf0e10cSrcweir aTwoRects.mnSrcWidth = aTwoRects.mnDestWidth = mnWidth; 521cdf0e10cSrcweir aTwoRects.mnSrcHeight = aTwoRects.mnDestHeight = mnHeight; 522cdf0e10cSrcweir bConverted = ::ImplFastBitmapConversion( aDstBuf, aSrcBuf, aTwoRects ); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir 525cdf0e10cSrcweir if( !bConverted ) 526cdf0e10cSrcweir { 527cdf0e10cSrcweir // TODO: this implementation is for clarety, not for speed 528cdf0e10cSrcweir 529cdf0e10cSrcweir ImplPixelFormat* pD = ImplPixelFormat::GetFormat( nDestBits, rDestPalette ); 530cdf0e10cSrcweir ImplPixelFormat* pS = ImplPixelFormat::GetFormat( nSrcBits, rSrcPalette ); 531cdf0e10cSrcweir 532cdf0e10cSrcweir if( pD && pS ) 533cdf0e10cSrcweir { 534cdf0e10cSrcweir sal_uInt32 nY = nHeight; 535cdf0e10cSrcweir while( nY-- ) 536cdf0e10cSrcweir { 537cdf0e10cSrcweir pD->StartLine( pDestData ); 538cdf0e10cSrcweir pS->StartLine( pSrcData ); 539cdf0e10cSrcweir 540cdf0e10cSrcweir sal_uInt32 nX = nWidth; 541cdf0e10cSrcweir while( nX-- ) 542cdf0e10cSrcweir pD->WritePixel( pS->ReadPixel() ); 543cdf0e10cSrcweir 544cdf0e10cSrcweir pSrcData += nSrcBytesPerRow; 545cdf0e10cSrcweir pDestData += nDestBytesPerRow; 546cdf0e10cSrcweir } 547cdf0e10cSrcweir } 548cdf0e10cSrcweir delete pS; 549cdf0e10cSrcweir delete pD; 550cdf0e10cSrcweir } 551cdf0e10cSrcweir } 552cdf0e10cSrcweir 553cdf0e10cSrcweir // ------------------------------------------------------------------ 554cdf0e10cSrcweir 555cdf0e10cSrcweir Size AquaSalBitmap::GetSize() const 556cdf0e10cSrcweir { 557cdf0e10cSrcweir return Size( mnWidth, mnHeight ); 558cdf0e10cSrcweir } 559cdf0e10cSrcweir 560cdf0e10cSrcweir // ------------------------------------------------------------------ 561cdf0e10cSrcweir 562cdf0e10cSrcweir sal_uInt16 AquaSalBitmap::GetBitCount() const 563cdf0e10cSrcweir { 564cdf0e10cSrcweir return mnBits; 565cdf0e10cSrcweir } 566cdf0e10cSrcweir 567cdf0e10cSrcweir // ------------------------------------------------------------------ 568cdf0e10cSrcweir 569cdf0e10cSrcweir static struct pal_entry 570cdf0e10cSrcweir { 571cdf0e10cSrcweir sal_uInt8 mnRed; 572cdf0e10cSrcweir sal_uInt8 mnGreen; 573cdf0e10cSrcweir sal_uInt8 mnBlue; 574cdf0e10cSrcweir } 575cdf0e10cSrcweir const aImplSalSysPalEntryAry[ 16 ] = 576cdf0e10cSrcweir { 577cdf0e10cSrcweir { 0, 0, 0 }, 578cdf0e10cSrcweir { 0, 0, 0x80 }, 579cdf0e10cSrcweir { 0, 0x80, 0 }, 580cdf0e10cSrcweir { 0, 0x80, 0x80 }, 581cdf0e10cSrcweir { 0x80, 0, 0 }, 582cdf0e10cSrcweir { 0x80, 0, 0x80 }, 583cdf0e10cSrcweir { 0x80, 0x80, 0 }, 584cdf0e10cSrcweir { 0x80, 0x80, 0x80 }, 585cdf0e10cSrcweir { 0xC0, 0xC0, 0xC0 }, 586cdf0e10cSrcweir { 0, 0, 0xFF }, 587cdf0e10cSrcweir { 0, 0xFF, 0 }, 588cdf0e10cSrcweir { 0, 0xFF, 0xFF }, 589cdf0e10cSrcweir { 0xFF, 0, 0 }, 590cdf0e10cSrcweir { 0xFF, 0, 0xFF }, 591cdf0e10cSrcweir { 0xFF, 0xFF, 0 }, 592cdf0e10cSrcweir { 0xFF, 0xFF, 0xFF } 593cdf0e10cSrcweir }; 594cdf0e10cSrcweir 595cdf0e10cSrcweir const BitmapPalette& GetDefaultPalette( int mnBits, bool bMonochrome ) 596cdf0e10cSrcweir { 597cdf0e10cSrcweir if( bMonochrome ) 598cdf0e10cSrcweir return Bitmap::GetGreyPalette( 1U << mnBits ); 599cdf0e10cSrcweir 600cdf0e10cSrcweir // at this point we should provide some kind of default palette 601cdf0e10cSrcweir // since all other platforms do so, too. 602cdf0e10cSrcweir static bool bDefPalInit = false; 603cdf0e10cSrcweir static BitmapPalette aDefPalette256; 604cdf0e10cSrcweir static BitmapPalette aDefPalette16; 605cdf0e10cSrcweir static BitmapPalette aDefPalette2; 606cdf0e10cSrcweir if( ! bDefPalInit ) 607cdf0e10cSrcweir { 608cdf0e10cSrcweir bDefPalInit = true; 609cdf0e10cSrcweir aDefPalette256.SetEntryCount( 256 ); 610cdf0e10cSrcweir aDefPalette16.SetEntryCount( 16 ); 611cdf0e10cSrcweir aDefPalette2.SetEntryCount( 2 ); 612cdf0e10cSrcweir 613cdf0e10cSrcweir // Standard colors 614cdf0e10cSrcweir unsigned int i; 615cdf0e10cSrcweir for( i = 0; i < 16; i++ ) 616cdf0e10cSrcweir { 617cdf0e10cSrcweir aDefPalette16[i] = 618cdf0e10cSrcweir aDefPalette256[i] = BitmapColor( aImplSalSysPalEntryAry[i].mnRed, 619cdf0e10cSrcweir aImplSalSysPalEntryAry[i].mnGreen, 620cdf0e10cSrcweir aImplSalSysPalEntryAry[i].mnBlue ); 621cdf0e10cSrcweir } 622cdf0e10cSrcweir 623cdf0e10cSrcweir aDefPalette2[0] = BitmapColor( 0, 0, 0 ); 624cdf0e10cSrcweir aDefPalette2[1] = BitmapColor( 0xff, 0xff, 0xff ); 625cdf0e10cSrcweir 626cdf0e10cSrcweir // own palette (6/6/6) 627cdf0e10cSrcweir const int DITHER_PAL_STEPS = 6; 628cdf0e10cSrcweir const sal_uInt8 DITHER_PAL_DELTA = 51; 629cdf0e10cSrcweir int nB, nG, nR; 630cdf0e10cSrcweir sal_uInt8 nRed, nGreen, nBlue; 631cdf0e10cSrcweir for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA ) 632cdf0e10cSrcweir { 633cdf0e10cSrcweir for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA ) 634cdf0e10cSrcweir { 635cdf0e10cSrcweir for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA ) 636cdf0e10cSrcweir { 637cdf0e10cSrcweir aDefPalette256[ i ] = BitmapColor( nRed, nGreen, nBlue ); 638cdf0e10cSrcweir i++; 639cdf0e10cSrcweir } 640cdf0e10cSrcweir } 641cdf0e10cSrcweir } 642cdf0e10cSrcweir } 643cdf0e10cSrcweir 644cdf0e10cSrcweir // now fill in appropriate palette 645cdf0e10cSrcweir switch( mnBits ) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir case 1: return aDefPalette2; 648cdf0e10cSrcweir case 4: return aDefPalette16; 649cdf0e10cSrcweir case 8: return aDefPalette256; 650cdf0e10cSrcweir default: break; 651cdf0e10cSrcweir } 652cdf0e10cSrcweir 653cdf0e10cSrcweir const static BitmapPalette aEmptyPalette; 654cdf0e10cSrcweir return aEmptyPalette; 655cdf0e10cSrcweir } 656cdf0e10cSrcweir 657cdf0e10cSrcweir BitmapBuffer* AquaSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) 658cdf0e10cSrcweir { 659cdf0e10cSrcweir if( !maUserBuffer.get() ) 660cdf0e10cSrcweir // || maContextBuffer.get() && (maUserBuffer.get() != maContextBuffer.get()) ) 661cdf0e10cSrcweir { 662cdf0e10cSrcweir fprintf(stderr,"ASB::Acq(%dx%d,d=%d)\n",mnWidth,mnHeight,mnBits); 663cdf0e10cSrcweir // TODO: AllocateUserData(); 664cdf0e10cSrcweir return NULL; 665cdf0e10cSrcweir } 666cdf0e10cSrcweir 667cdf0e10cSrcweir BitmapBuffer* pBuffer = new BitmapBuffer; 668cdf0e10cSrcweir pBuffer->mnWidth = mnWidth; 669cdf0e10cSrcweir pBuffer->mnHeight = mnHeight; 670cdf0e10cSrcweir pBuffer->maPalette = maPalette; 671cdf0e10cSrcweir pBuffer->mnScanlineSize = mnBytesPerRow; 672cdf0e10cSrcweir pBuffer->mpBits = maUserBuffer.get(); 673cdf0e10cSrcweir pBuffer->mnBitCount = mnBits; 674cdf0e10cSrcweir switch( mnBits ) 675cdf0e10cSrcweir { 676cdf0e10cSrcweir case 1: pBuffer->mnFormat = BMP_FORMAT_1BIT_MSB_PAL; break; 677cdf0e10cSrcweir case 4: pBuffer->mnFormat = BMP_FORMAT_4BIT_MSN_PAL; break; 678cdf0e10cSrcweir case 8: pBuffer->mnFormat = BMP_FORMAT_8BIT_PAL; break; 679cdf0e10cSrcweir case 16: pBuffer->mnFormat = BMP_FORMAT_16BIT_TC_MSB_MASK; 680cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( k16BitRedColorMask, k16BitGreenColorMask, k16BitBlueColorMask ); 681cdf0e10cSrcweir break; 682cdf0e10cSrcweir case 24: pBuffer->mnFormat = BMP_FORMAT_24BIT_TC_BGR; break; 683cdf0e10cSrcweir case 32: pBuffer->mnFormat = BMP_FORMAT_32BIT_TC_ARGB; 684cdf0e10cSrcweir pBuffer->maColorMask = ColorMask( k32BitRedColorMask, k32BitGreenColorMask, k32BitBlueColorMask ); 685cdf0e10cSrcweir break; 686cdf0e10cSrcweir } 687cdf0e10cSrcweir pBuffer->mnFormat |= BMP_FORMAT_BOTTOM_UP; 688cdf0e10cSrcweir 689cdf0e10cSrcweir // some BitmapBuffer users depend on a complete palette 690cdf0e10cSrcweir if( (mnBits <= 8) && !maPalette ) 691cdf0e10cSrcweir pBuffer->maPalette = GetDefaultPalette( mnBits, true ); 692cdf0e10cSrcweir 693cdf0e10cSrcweir return pBuffer; 694cdf0e10cSrcweir } 695cdf0e10cSrcweir 696cdf0e10cSrcweir // ------------------------------------------------------------------ 697cdf0e10cSrcweir 698cdf0e10cSrcweir void AquaSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) 699cdf0e10cSrcweir { 700cdf0e10cSrcweir // invalidate graphic context if we have different data 701cdf0e10cSrcweir if( !bReadOnly ) 702cdf0e10cSrcweir { 703cdf0e10cSrcweir maPalette = pBuffer->maPalette; 704cdf0e10cSrcweir if( mxGraphicContext ) 705cdf0e10cSrcweir DestroyContext(); 706cdf0e10cSrcweir } 707cdf0e10cSrcweir 708cdf0e10cSrcweir delete pBuffer; 709cdf0e10cSrcweir } 710cdf0e10cSrcweir 711cdf0e10cSrcweir // ------------------------------------------------------------------ 712cdf0e10cSrcweir 713cdf0e10cSrcweir CGImageRef AquaSalBitmap::CreateCroppedImage( int nX, int nY, int nNewWidth, int nNewHeight ) const 714cdf0e10cSrcweir { 715cdf0e10cSrcweir if( !mxCachedImage ) 716cdf0e10cSrcweir { 717cdf0e10cSrcweir if( !mxGraphicContext ) 718cdf0e10cSrcweir if( !const_cast<AquaSalBitmap*>(this)->CreateContext() ) 719cdf0e10cSrcweir return NULL; 720cdf0e10cSrcweir 721cdf0e10cSrcweir mxCachedImage = CGBitmapContextCreateImage( mxGraphicContext ); 722cdf0e10cSrcweir } 723cdf0e10cSrcweir 724cdf0e10cSrcweir CGImageRef xCroppedImage = NULL; 725cdf0e10cSrcweir // short circuit if there is nothing to crop 726cdf0e10cSrcweir if( !nX && !nY && (mnWidth == nNewWidth) && (mnHeight == nNewHeight) ) 727cdf0e10cSrcweir { 728cdf0e10cSrcweir xCroppedImage = mxCachedImage; 729cdf0e10cSrcweir CFRetain( xCroppedImage ); 730cdf0e10cSrcweir } 731cdf0e10cSrcweir else 732cdf0e10cSrcweir { 733cdf0e10cSrcweir nY = mnHeight - (nY + nNewHeight); // adjust for y-mirrored context 734*cd426cceSHerbert Dürr const CGRect aCropRect = CGRectMake( nX, nY, nNewWidth, nNewHeight); 735cdf0e10cSrcweir xCroppedImage = CGImageCreateWithImageInRect( mxCachedImage, aCropRect ); 736cdf0e10cSrcweir } 737cdf0e10cSrcweir 738cdf0e10cSrcweir return xCroppedImage; 739cdf0e10cSrcweir } 740cdf0e10cSrcweir 741cdf0e10cSrcweir // ------------------------------------------------------------------ 742cdf0e10cSrcweir 743cdf0e10cSrcweir static void CFRTLFree(void* /*info*/, const void* data, size_t /*size*/) 744cdf0e10cSrcweir { 745cdf0e10cSrcweir rtl_freeMemory( const_cast<void*>(data) ); 746cdf0e10cSrcweir } 747cdf0e10cSrcweir 748cdf0e10cSrcweir CGImageRef AquaSalBitmap::CreateWithMask( const AquaSalBitmap& rMask, 749cdf0e10cSrcweir int nX, int nY, int nWidth, int nHeight ) const 750cdf0e10cSrcweir { 751cdf0e10cSrcweir CGImageRef xImage( CreateCroppedImage( nX, nY, nWidth, nHeight ) ); 752cdf0e10cSrcweir if( !xImage ) 753cdf0e10cSrcweir return NULL; 754cdf0e10cSrcweir 755cdf0e10cSrcweir CGImageRef xMask = rMask.CreateCroppedImage( nX, nY, nWidth, nHeight ); 756cdf0e10cSrcweir if( !xMask ) 757cdf0e10cSrcweir return xImage; 758cdf0e10cSrcweir 759cdf0e10cSrcweir // CGImageCreateWithMask() only likes masks or greyscale images => convert if needed 760cdf0e10cSrcweir // TODO: isolate in an extra method? 761cdf0e10cSrcweir if( !CGImageIsMask(xMask) || (CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace) ) 762cdf0e10cSrcweir { 763cdf0e10cSrcweir const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the rect has no offset 764cdf0e10cSrcweir 765cdf0e10cSrcweir // create the alpha mask image fitting our image 766cdf0e10cSrcweir // TODO: is caching the full mask or the subimage mask worth it? 767cdf0e10cSrcweir int nMaskBytesPerRow = ((nWidth + 3) & ~3); 768cdf0e10cSrcweir void* pMaskMem = rtl_allocateMemory( nMaskBytesPerRow * nHeight ); 769cdf0e10cSrcweir CGContextRef xMaskContext = CGBitmapContextCreate( pMaskMem, 770cdf0e10cSrcweir nWidth, nHeight, 8, nMaskBytesPerRow, GetSalData()->mxGraySpace, kCGImageAlphaNone ); 771cdf0e10cSrcweir CGContextDrawImage( xMaskContext, xImageRect, xMask ); 772cdf0e10cSrcweir CFRelease( xMask ); 773cdf0e10cSrcweir CGDataProviderRef xDataProvider( CGDataProviderCreateWithData( NULL, 774cdf0e10cSrcweir pMaskMem, nHeight * nMaskBytesPerRow, &CFRTLFree ) ); 775cdf0e10cSrcweir static const float* pDecode = NULL; 776cdf0e10cSrcweir xMask = CGImageMaskCreate( nWidth, nHeight, 8, 8, nMaskBytesPerRow, xDataProvider, pDecode, false ); 777cdf0e10cSrcweir CFRelease( xDataProvider ); 778cdf0e10cSrcweir CFRelease( xMaskContext ); 779cdf0e10cSrcweir } 780cdf0e10cSrcweir 781cdf0e10cSrcweir if( !xMask ) 782cdf0e10cSrcweir return xImage; 783cdf0e10cSrcweir 784cdf0e10cSrcweir // combine image and alpha mask 785cdf0e10cSrcweir CGImageRef xMaskedImage = CGImageCreateWithMask( xImage, xMask ); 786cdf0e10cSrcweir CFRelease( xMask ); 787cdf0e10cSrcweir CFRelease( xImage ); 788cdf0e10cSrcweir return xMaskedImage; 789cdf0e10cSrcweir } 790cdf0e10cSrcweir 791cdf0e10cSrcweir // ------------------------------------------------------------------ 792cdf0e10cSrcweir 793cdf0e10cSrcweir /** creates an image from the given rectangle, replacing all black pixels with nMaskColor and make all other full transparent */ 794cdf0e10cSrcweir CGImageRef AquaSalBitmap::CreateColorMask( int nX, int nY, int nWidth, int nHeight, SalColor nMaskColor ) const 795cdf0e10cSrcweir { 796cdf0e10cSrcweir CGImageRef xMask = 0; 797cdf0e10cSrcweir if( maUserBuffer.get() && (nX + nWidth <= mnWidth) && (nY + nHeight <= mnHeight) ) 798cdf0e10cSrcweir { 799cdf0e10cSrcweir const sal_uInt32 nDestBytesPerRow = nWidth << 2; 800cdf0e10cSrcweir sal_uInt32* pMaskBuffer = static_cast<sal_uInt32*>( rtl_allocateMemory( nHeight * nDestBytesPerRow ) ); 801cdf0e10cSrcweir sal_uInt32* pDest = pMaskBuffer; 802cdf0e10cSrcweir 803cdf0e10cSrcweir ImplPixelFormat* pSourcePixels = ImplPixelFormat::GetFormat( mnBits, maPalette ); 804cdf0e10cSrcweir 805cdf0e10cSrcweir if( pMaskBuffer && pSourcePixels ) 806cdf0e10cSrcweir { 807cdf0e10cSrcweir sal_uInt32 nColor; 808cdf0e10cSrcweir reinterpret_cast<sal_uInt8*>(&nColor)[0] = 0xff; 809cdf0e10cSrcweir reinterpret_cast<sal_uInt8*>(&nColor)[1] = SALCOLOR_RED( nMaskColor ); 810cdf0e10cSrcweir reinterpret_cast<sal_uInt8*>(&nColor)[2] = SALCOLOR_GREEN( nMaskColor ); 811cdf0e10cSrcweir reinterpret_cast<sal_uInt8*>(&nColor)[3] = SALCOLOR_BLUE( nMaskColor ); 812cdf0e10cSrcweir 813cdf0e10cSrcweir sal_uInt8* pSource = maUserBuffer.get(); 814cdf0e10cSrcweir if( nY ) 815cdf0e10cSrcweir pSource += nY * mnBytesPerRow; 816cdf0e10cSrcweir 817cdf0e10cSrcweir int y = nHeight; 818cdf0e10cSrcweir while( y-- ) 819cdf0e10cSrcweir { 820cdf0e10cSrcweir pSourcePixels->StartLine( pSource ); 821cdf0e10cSrcweir pSourcePixels->SkipPixel(nX); 822cdf0e10cSrcweir sal_uInt32 x = nWidth; 823cdf0e10cSrcweir while( x-- ) 824cdf0e10cSrcweir { 825cdf0e10cSrcweir *pDest++ = ( pSourcePixels->ReadPixel() == 0 ) ? nColor : 0; 826cdf0e10cSrcweir } 827cdf0e10cSrcweir pSource += mnBytesPerRow; 828cdf0e10cSrcweir } 829cdf0e10cSrcweir 830cdf0e10cSrcweir CGDataProviderRef xDataProvider( CGDataProviderCreateWithData(NULL, pMaskBuffer, nHeight * nDestBytesPerRow, &CFRTLFree) ); 831cdf0e10cSrcweir xMask = CGImageCreate(nWidth, nHeight, 8, 32, nDestBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaPremultipliedFirst, xDataProvider, NULL, true, kCGRenderingIntentDefault); 832cdf0e10cSrcweir CFRelease(xDataProvider); 833cdf0e10cSrcweir } 834cdf0e10cSrcweir else 835cdf0e10cSrcweir { 836cdf0e10cSrcweir free(pMaskBuffer); 837cdf0e10cSrcweir } 838cdf0e10cSrcweir 839cdf0e10cSrcweir delete pSourcePixels; 840cdf0e10cSrcweir } 841cdf0e10cSrcweir return xMask; 842cdf0e10cSrcweir } 843cdf0e10cSrcweir 844cdf0e10cSrcweir // ======================================================================= 845cdf0e10cSrcweir 846cdf0e10cSrcweir /** AquaSalBitmap::GetSystemData Get platform native image data from existing image 847cdf0e10cSrcweir * 848cdf0e10cSrcweir * @param rData struct BitmapSystemData, defined in vcl/inc/bitmap.hxx 849cdf0e10cSrcweir * @return true if successful 850cdf0e10cSrcweir **/ 851cdf0e10cSrcweir bool AquaSalBitmap::GetSystemData( BitmapSystemData& rData ) 852cdf0e10cSrcweir { 853cdf0e10cSrcweir bool bRet = false; 854cdf0e10cSrcweir 855cdf0e10cSrcweir if( !mxGraphicContext ) 856cdf0e10cSrcweir CreateContext(); 857cdf0e10cSrcweir 858cdf0e10cSrcweir if ( mxGraphicContext ) 859cdf0e10cSrcweir { 860cdf0e10cSrcweir bRet = true; 861cdf0e10cSrcweir 862cdf0e10cSrcweir #ifdef CAIRO 863cdf0e10cSrcweir if ((CGBitmapContextGetBitsPerPixel(mxGraphicContext) == 32) && 864cdf0e10cSrcweir (CGBitmapContextGetBitmapInfo(mxGraphicContext) & kCGBitmapByteOrderMask) != kCGBitmapByteOrder32Host) { 865cdf0e10cSrcweir /** 866cdf0e10cSrcweir * We need to hack things because VCL does not use kCGBitmapByteOrder32Host, while Cairo requires it. 867cdf0e10cSrcweir */ 868cdf0e10cSrcweir OSL_TRACE("AquaSalBitmap::%s(): kCGBitmapByteOrder32Host not found => inserting it.",__func__); 869cdf0e10cSrcweir 870cdf0e10cSrcweir CGImageRef xImage = CGBitmapContextCreateImage (mxGraphicContext); 871cdf0e10cSrcweir 872cdf0e10cSrcweir // re-create the context with single change: include kCGBitmapByteOrder32Host flag. 873cdf0e10cSrcweir CGContextRef mxGraphicContextNew = CGBitmapContextCreate( CGBitmapContextGetData(mxGraphicContext), 874cdf0e10cSrcweir CGBitmapContextGetWidth(mxGraphicContext), 875cdf0e10cSrcweir CGBitmapContextGetHeight(mxGraphicContext), 876cdf0e10cSrcweir CGBitmapContextGetBitsPerComponent(mxGraphicContext), 877cdf0e10cSrcweir CGBitmapContextGetBytesPerRow(mxGraphicContext), 878cdf0e10cSrcweir CGBitmapContextGetColorSpace(mxGraphicContext), 879cdf0e10cSrcweir CGBitmapContextGetBitmapInfo(mxGraphicContext) | kCGBitmapByteOrder32Host); 880cdf0e10cSrcweir CFRelease(mxGraphicContext); 881cdf0e10cSrcweir 882cdf0e10cSrcweir // Needs to be flipped 883cdf0e10cSrcweir CGContextSaveGState( mxGraphicContextNew ); 884cdf0e10cSrcweir CGContextTranslateCTM (mxGraphicContextNew, 0, CGBitmapContextGetHeight(mxGraphicContextNew)); 885cdf0e10cSrcweir CGContextScaleCTM (mxGraphicContextNew, 1.0, -1.0); 886cdf0e10cSrcweir 887cdf0e10cSrcweir CGContextDrawImage(mxGraphicContextNew, CGRectMake( 0, 0, CGImageGetWidth(xImage), CGImageGetHeight(xImage)), xImage); 888cdf0e10cSrcweir 889cdf0e10cSrcweir // Flip back 890cdf0e10cSrcweir CGContextRestoreGState( mxGraphicContextNew ); 891cdf0e10cSrcweir 892cdf0e10cSrcweir CGImageRelease( xImage ); 893cdf0e10cSrcweir mxGraphicContext = mxGraphicContextNew; 894cdf0e10cSrcweir } 895cdf0e10cSrcweir #endif 896cdf0e10cSrcweir 897cdf0e10cSrcweir rData.rImageContext = (void *) mxGraphicContext; 898cdf0e10cSrcweir rData.mnWidth = mnWidth; 899cdf0e10cSrcweir rData.mnHeight = mnHeight; 900cdf0e10cSrcweir } 901cdf0e10cSrcweir 902cdf0e10cSrcweir return bRet; 903cdf0e10cSrcweir } 904