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
isValidBitCount(sal_uInt16 nBitCount)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
AquaSalBitmap()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
~AquaSalBitmap()65cdf0e10cSrcweir AquaSalBitmap::~AquaSalBitmap()
66cdf0e10cSrcweir {
67cdf0e10cSrcweir Destroy();
68cdf0e10cSrcweir }
69cdf0e10cSrcweir
70cdf0e10cSrcweir // ------------------------------------------------------------------
71cdf0e10cSrcweir
Create(CGLayerRef xLayer,int nBitmapBits,int nX,int nY,int nWidth,int nHeight,bool)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
99cd426cceSHerbert Dürr const CGPoint aSrcPoint = CGPointMake( -nX, -nY);
100cdf0e10cSrcweir ::CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer );
101cdf0e10cSrcweir return true;
102cdf0e10cSrcweir }
103cdf0e10cSrcweir
104cdf0e10cSrcweir // ------------------------------------------------------------------
105cdf0e10cSrcweir
Create(const Size & rSize,sal_uInt16 nBits,const BitmapPalette & rBitmapPalette)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
Create(const SalBitmap & rSalBmp)119cdf0e10cSrcweir bool AquaSalBitmap::Create( const SalBitmap& rSalBmp )
120cdf0e10cSrcweir {
121cdf0e10cSrcweir return Create( rSalBmp, rSalBmp.GetBitCount() );
122cdf0e10cSrcweir }
123cdf0e10cSrcweir
124cdf0e10cSrcweir // ------------------------------------------------------------------
125cdf0e10cSrcweir
Create(const SalBitmap & rSalBmp,SalGraphics * pGraphics)126cdf0e10cSrcweir bool AquaSalBitmap::Create( const SalBitmap& rSalBmp, SalGraphics* pGraphics )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir return Create( rSalBmp, pGraphics ? pGraphics->GetBitCount() : rSalBmp.GetBitCount() );
129cdf0e10cSrcweir }
130cdf0e10cSrcweir
131cdf0e10cSrcweir // ------------------------------------------------------------------
132cdf0e10cSrcweir
Create(const SalBitmap & rSalBmp,sal_uInt16 nNewBitCount)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
Destroy()155cdf0e10cSrcweir void AquaSalBitmap::Destroy()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir DestroyContext();
158cdf0e10cSrcweir maUserBuffer.reset();
159cdf0e10cSrcweir }
160cdf0e10cSrcweir
161cdf0e10cSrcweir // ------------------------------------------------------------------
162cdf0e10cSrcweir
DestroyContext()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
CreateContext()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
AllocateUserData()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" );
2713d762826SHerbert Dürr maUserBuffer.reset();
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
StartLine(sal_uInt8 * pLine)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:
SkipPixel(sal_uInt32 nPixel)297cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
298cdf0e10cSrcweir {
299cdf0e10cSrcweir pData += nPixel << 2;
300cdf0e10cSrcweir }
ReadPixel()301cdf0e10cSrcweir virtual ColorData ReadPixel()
302cdf0e10cSrcweir {
303cdf0e10cSrcweir const ColorData c = RGB_COLORDATA( pData[1], pData[2], pData[3] );
304cdf0e10cSrcweir pData += 4;
305cdf0e10cSrcweir return c;
306cdf0e10cSrcweir }
WritePixel(ColorData nColor)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:
SkipPixel(sal_uInt32 nPixel)320cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
321cdf0e10cSrcweir {
322cdf0e10cSrcweir pData += (nPixel << 1) + nPixel;
323cdf0e10cSrcweir }
ReadPixel()324cdf0e10cSrcweir virtual ColorData ReadPixel()
325cdf0e10cSrcweir {
326cdf0e10cSrcweir const ColorData c = RGB_COLORDATA( pData[2], pData[1], pData[0] );
327cdf0e10cSrcweir pData += 3;
328cdf0e10cSrcweir return c;
329cdf0e10cSrcweir }
WritePixel(ColorData nColor)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
StartLine(sal_uInt8 * pLine)345cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine )
346cdf0e10cSrcweir {
347cdf0e10cSrcweir pData16 = (sal_uInt16*)pLine;
348cdf0e10cSrcweir }
SkipPixel(sal_uInt32 nPixel)349cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
350cdf0e10cSrcweir {
351cdf0e10cSrcweir pData += nPixel;
352cdf0e10cSrcweir }
ReadPixel()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 }
WritePixel(ColorData nColor)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:
ImplPixelFormat8(const BitmapPalette & rPalette)373cdf0e10cSrcweir ImplPixelFormat8( const BitmapPalette& rPalette )
374cdf0e10cSrcweir : mrPalette( rPalette )
375cdf0e10cSrcweir {
376cdf0e10cSrcweir }
SkipPixel(sal_uInt32 nPixel)377cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir pData += nPixel;
380cdf0e10cSrcweir }
ReadPixel()381cdf0e10cSrcweir virtual ColorData ReadPixel()
382cdf0e10cSrcweir {
383cdf0e10cSrcweir return mrPalette[ *pData++ ].operator Color().GetColor();
384cdf0e10cSrcweir }
WritePixel(ColorData nColor)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:
ImplPixelFormat4(const BitmapPalette & rPalette)400cdf0e10cSrcweir ImplPixelFormat4( const BitmapPalette& rPalette )
401cdf0e10cSrcweir : mrPalette( rPalette )
402cdf0e10cSrcweir {
403cdf0e10cSrcweir }
SkipPixel(sal_uInt32 nPixel)404cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
405cdf0e10cSrcweir {
406cdf0e10cSrcweir mnX += nPixel;
407cdf0e10cSrcweir if( (nPixel & 1) )
408cdf0e10cSrcweir mnShift ^= 4;
409cdf0e10cSrcweir }
StartLine(sal_uInt8 * pLine)410cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine )
411cdf0e10cSrcweir {
412cdf0e10cSrcweir pData = pLine;
413cdf0e10cSrcweir mnX = 0;
414cdf0e10cSrcweir mnShift = 4;
415cdf0e10cSrcweir }
ReadPixel()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 }
WritePixel(ColorData nColor)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:
ImplPixelFormat1(const BitmapPalette & rPalette)440cdf0e10cSrcweir ImplPixelFormat1( const BitmapPalette& rPalette )
441cdf0e10cSrcweir : mrPalette( rPalette )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir }
SkipPixel(sal_uInt32 nPixel)444cdf0e10cSrcweir virtual void SkipPixel( sal_uInt32 nPixel )
445cdf0e10cSrcweir {
446cdf0e10cSrcweir mnX += nPixel;
447cdf0e10cSrcweir }
StartLine(sal_uInt8 * pLine)448cdf0e10cSrcweir virtual void StartLine( sal_uInt8* pLine )
449cdf0e10cSrcweir {
450cdf0e10cSrcweir pData = pLine;
451cdf0e10cSrcweir mnX = 0;
452cdf0e10cSrcweir }
ReadPixel()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 }
WritePixel(ColorData nColor)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
GetFormat(sal_uInt16 nBits,const BitmapPalette & rPalette)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
ConvertBitmapData(sal_uInt32 nWidth,sal_uInt32 nHeight,sal_uInt16 nDestBits,sal_uInt32 nDestBytesPerRow,const BitmapPalette & rDestPalette,sal_uInt8 * pDestData,sal_uInt16 nSrcBits,sal_uInt32 nSrcBytesPerRow,const BitmapPalette & rSrcPalette,sal_uInt8 * pSrcData)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
GetSize() const555cdf0e10cSrcweir Size AquaSalBitmap::GetSize() const
556cdf0e10cSrcweir {
557cdf0e10cSrcweir return Size( mnWidth, mnHeight );
558cdf0e10cSrcweir }
559cdf0e10cSrcweir
560cdf0e10cSrcweir // ------------------------------------------------------------------
561cdf0e10cSrcweir
GetBitCount() const562cdf0e10cSrcweir 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
GetDefaultPalette(int mnBits,bool bMonochrome)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
AcquireBuffer(bool)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
ReleaseBuffer(BitmapBuffer * pBuffer,bool bReadOnly)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
CreateCroppedImage(int nX,int nY,int nNewWidth,int nNewHeight) const713cdf0e10cSrcweir 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
734cd426cceSHerbert Dürr const CGRect aCropRect = CGRectMake( nX, nY, nNewWidth, nNewHeight);
735cdf0e10cSrcweir xCroppedImage = CGImageCreateWithImageInRect( mxCachedImage, aCropRect );
736cdf0e10cSrcweir }
737cdf0e10cSrcweir
738cdf0e10cSrcweir return xCroppedImage;
739cdf0e10cSrcweir }
740cdf0e10cSrcweir
741cdf0e10cSrcweir // ------------------------------------------------------------------
742cdf0e10cSrcweir
CFRTLFree(void *,const void * data,size_t)743cdf0e10cSrcweir static void CFRTLFree(void* /*info*/, const void* data, size_t /*size*/)
744cdf0e10cSrcweir {
745cdf0e10cSrcweir rtl_freeMemory( const_cast<void*>(data) );
746cdf0e10cSrcweir }
747cdf0e10cSrcweir
CreateWithMask(const AquaSalBitmap & rMask,int nX,int nY,int nWidth,int nHeight) const748cdf0e10cSrcweir 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 ) );
775*24a22e85SHerbert Dürr static const CGFloat* 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 */
CreateColorMask(int nX,int nY,int nWidth,int nHeight,SalColor nMaskColor) const794cdf0e10cSrcweir 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 **/
GetSystemData(BitmapSystemData & rData)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