xref: /AOO41X/main/vcl/source/helper/canvasbitmap.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <com/sun/star/util/Endianness.hpp>
32*cdf0e10cSrcweir #include <com/sun/star/rendering/ColorComponentTag.hpp>
33*cdf0e10cSrcweir #include <com/sun/star/rendering/ColorSpaceType.hpp>
34*cdf0e10cSrcweir #include <com/sun/star/rendering/RenderingIntent.hpp>
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include <rtl/instance.hxx>
37*cdf0e10cSrcweir #include <vos/mutex.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
40*cdf0e10cSrcweir #include <canvasbitmap.hxx>
41*cdf0e10cSrcweir #include <vcl/canvastools.hxx>
42*cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
43*cdf0e10cSrcweir #include <vcl/svapp.hxx>
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include <algorithm>
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir using namespace ::vcl::unotools;
49*cdf0e10cSrcweir using namespace ::com::sun::star;
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir namespace
52*cdf0e10cSrcweir {
53*cdf0e10cSrcweir     // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir     // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word,
56*cdf0e10cSrcweir     // unrolled loop. See e.g. Hackers Delight, p. 66
57*cdf0e10cSrcweir     inline sal_Int32 bitcount( sal_uInt32 val )
58*cdf0e10cSrcweir     {
59*cdf0e10cSrcweir         val = val - ((val >> 1) & 0x55555555);
60*cdf0e10cSrcweir         val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
61*cdf0e10cSrcweir         val = (val + (val >> 4)) & 0x0F0F0F0F;
62*cdf0e10cSrcweir         val = val + (val >> 8);
63*cdf0e10cSrcweir         val = val + (val >> 16);
64*cdf0e10cSrcweir         return sal_Int32(val & 0x0000003F);
65*cdf0e10cSrcweir     }
66*cdf0e10cSrcweir }
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir void VclCanvasBitmap::setComponentInfo( sal_uLong redShift, sal_uLong greenShift, sal_uLong blueShift )
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir     // sort channels in increasing order of appearance in the pixel
71*cdf0e10cSrcweir     // (starting with the least significant bits)
72*cdf0e10cSrcweir     sal_Int8 redPos(0);
73*cdf0e10cSrcweir     sal_Int8 greenPos(1);
74*cdf0e10cSrcweir     sal_Int8 bluePos(2);
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir     if( redShift > greenShift )
77*cdf0e10cSrcweir     {
78*cdf0e10cSrcweir         std::swap(redPos,greenPos);
79*cdf0e10cSrcweir         if( redShift > blueShift )
80*cdf0e10cSrcweir         {
81*cdf0e10cSrcweir             std::swap(redPos,bluePos);
82*cdf0e10cSrcweir             if( greenShift > blueShift )
83*cdf0e10cSrcweir                 std::swap(greenPos,bluePos);
84*cdf0e10cSrcweir         }
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir     else
87*cdf0e10cSrcweir     {
88*cdf0e10cSrcweir         if( greenShift > blueShift )
89*cdf0e10cSrcweir         {
90*cdf0e10cSrcweir             std::swap(greenPos,bluePos);
91*cdf0e10cSrcweir             if( redShift > blueShift )
92*cdf0e10cSrcweir                 std::swap(redPos,bluePos);
93*cdf0e10cSrcweir         }
94*cdf0e10cSrcweir     }
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir     m_aComponentTags.realloc(3);
97*cdf0e10cSrcweir     sal_Int8* pTags = m_aComponentTags.getArray();
98*cdf0e10cSrcweir     pTags[redPos]   = rendering::ColorComponentTag::RGB_RED;
99*cdf0e10cSrcweir     pTags[greenPos] = rendering::ColorComponentTag::RGB_GREEN;
100*cdf0e10cSrcweir     pTags[bluePos]  = rendering::ColorComponentTag::RGB_BLUE;
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir     m_aComponentBitCounts.realloc(3);
103*cdf0e10cSrcweir     sal_Int32* pCounts = m_aComponentBitCounts.getArray();
104*cdf0e10cSrcweir     pCounts[redPos]    = bitcount(sal::static_int_cast<sal_uInt32>(redShift));
105*cdf0e10cSrcweir     pCounts[greenPos]  = bitcount(sal::static_int_cast<sal_uInt32>(greenShift));
106*cdf0e10cSrcweir     pCounts[bluePos]   = bitcount(sal::static_int_cast<sal_uInt32>(blueShift));
107*cdf0e10cSrcweir }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
110*cdf0e10cSrcweir     m_aBmpEx( rBitmap ),
111*cdf0e10cSrcweir     m_aBitmap( rBitmap.GetBitmap() ),
112*cdf0e10cSrcweir     m_aAlpha(),
113*cdf0e10cSrcweir     m_pBmpAcc( m_aBitmap.AcquireReadAccess() ),
114*cdf0e10cSrcweir     m_pAlphaAcc( NULL ),
115*cdf0e10cSrcweir     m_aComponentTags(),
116*cdf0e10cSrcweir     m_aComponentBitCounts(),
117*cdf0e10cSrcweir     m_aLayout(),
118*cdf0e10cSrcweir     m_nBitsPerInputPixel(0),
119*cdf0e10cSrcweir     m_nBitsPerOutputPixel(0),
120*cdf0e10cSrcweir     m_nRedIndex(-1),
121*cdf0e10cSrcweir     m_nGreenIndex(-1),
122*cdf0e10cSrcweir     m_nBlueIndex(-1),
123*cdf0e10cSrcweir     m_nAlphaIndex(-1),
124*cdf0e10cSrcweir     m_nIndexIndex(-1),
125*cdf0e10cSrcweir     m_nEndianness(0),
126*cdf0e10cSrcweir     m_bSwap(false),
127*cdf0e10cSrcweir     m_bPalette(false)
128*cdf0e10cSrcweir {
129*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
130*cdf0e10cSrcweir     {
131*cdf0e10cSrcweir         m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
132*cdf0e10cSrcweir         m_pAlphaAcc = m_aAlpha.AcquireReadAccess();
133*cdf0e10cSrcweir     }
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir     m_aLayout.ScanLines      = 0;
136*cdf0e10cSrcweir     m_aLayout.ScanLineBytes  = 0;
137*cdf0e10cSrcweir     m_aLayout.ScanLineStride = 0;
138*cdf0e10cSrcweir     m_aLayout.PlaneStride    = 0;
139*cdf0e10cSrcweir     m_aLayout.ColorSpace.clear();
140*cdf0e10cSrcweir     m_aLayout.Palette.clear();
141*cdf0e10cSrcweir     m_aLayout.IsMsbFirst     = sal_False;
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir     if( m_pBmpAcc )
144*cdf0e10cSrcweir     {
145*cdf0e10cSrcweir         m_aLayout.ScanLines      = m_pBmpAcc->Height();
146*cdf0e10cSrcweir         m_aLayout.ScanLineBytes  = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
147*cdf0e10cSrcweir         m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
148*cdf0e10cSrcweir         m_aLayout.PlaneStride    = 0;
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir         switch( m_pBmpAcc->GetScanlineFormat() )
151*cdf0e10cSrcweir         {
152*cdf0e10cSrcweir             case BMP_FORMAT_1BIT_MSB_PAL:
153*cdf0e10cSrcweir                 m_bPalette           = true;
154*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 1;
155*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
156*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_True;
157*cdf0e10cSrcweir                 break;
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir             case BMP_FORMAT_1BIT_LSB_PAL:
160*cdf0e10cSrcweir                 m_bPalette           = true;
161*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 1;
162*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
163*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False;
164*cdf0e10cSrcweir                 break;
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir             case BMP_FORMAT_4BIT_MSN_PAL:
167*cdf0e10cSrcweir                 m_bPalette           = true;
168*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 4;
169*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
170*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_True;
171*cdf0e10cSrcweir                 break;
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir             case BMP_FORMAT_4BIT_LSN_PAL:
174*cdf0e10cSrcweir                 m_bPalette           = true;
175*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 4;
176*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
177*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False;
178*cdf0e10cSrcweir                 break;
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir             case BMP_FORMAT_8BIT_PAL:
181*cdf0e10cSrcweir                 m_bPalette           = true;
182*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 8;
183*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
184*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
185*cdf0e10cSrcweir                 break;
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir             case BMP_FORMAT_8BIT_TC_MASK:
188*cdf0e10cSrcweir                 m_bPalette           = false;
189*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 8;
190*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE; // doesn't matter
191*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
192*cdf0e10cSrcweir                 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
193*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetGreenMask(),
194*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetBlueMask() );
195*cdf0e10cSrcweir                 break;
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir             case BMP_FORMAT_16BIT_TC_MSB_MASK:
198*cdf0e10cSrcweir                 m_bPalette           = false;
199*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 16;
200*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::BIG;
201*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
202*cdf0e10cSrcweir                 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
203*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetGreenMask(),
204*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetBlueMask() );
205*cdf0e10cSrcweir                 break;
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir             case BMP_FORMAT_16BIT_TC_LSB_MASK:
208*cdf0e10cSrcweir                 m_bPalette           = false;
209*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 16;
210*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
211*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
212*cdf0e10cSrcweir                 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
213*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetGreenMask(),
214*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetBlueMask() );
215*cdf0e10cSrcweir                 break;
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir             case BMP_FORMAT_24BIT_TC_BGR:
218*cdf0e10cSrcweir                 m_bPalette           = false;
219*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 24;
220*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
221*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
222*cdf0e10cSrcweir                 setComponentInfo( 0xff0000LL,
223*cdf0e10cSrcweir                                   0x00ff00LL,
224*cdf0e10cSrcweir                                   0x0000ffLL );
225*cdf0e10cSrcweir                 break;
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir             case BMP_FORMAT_24BIT_TC_RGB:
228*cdf0e10cSrcweir                 m_bPalette           = false;
229*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 24;
230*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
231*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
232*cdf0e10cSrcweir                 setComponentInfo( 0x0000ffLL,
233*cdf0e10cSrcweir                                   0x00ff00LL,
234*cdf0e10cSrcweir                                   0xff0000LL );
235*cdf0e10cSrcweir                 break;
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir             case BMP_FORMAT_24BIT_TC_MASK:
238*cdf0e10cSrcweir                 m_bPalette           = false;
239*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 24;
240*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
241*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
242*cdf0e10cSrcweir                 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
243*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetGreenMask(),
244*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetBlueMask() );
245*cdf0e10cSrcweir                 break;
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir             case BMP_FORMAT_32BIT_TC_ABGR:
248*cdf0e10cSrcweir             {
249*cdf0e10cSrcweir                 m_bPalette           = false;
250*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 32;
251*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
252*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir                 m_aComponentTags.realloc(4);
255*cdf0e10cSrcweir                 sal_Int8* pTags = m_aComponentTags.getArray();
256*cdf0e10cSrcweir                 pTags[0]        = rendering::ColorComponentTag::ALPHA;
257*cdf0e10cSrcweir                 pTags[1]        = rendering::ColorComponentTag::RGB_BLUE;
258*cdf0e10cSrcweir                 pTags[2]        = rendering::ColorComponentTag::RGB_GREEN;
259*cdf0e10cSrcweir                 pTags[3]        = rendering::ColorComponentTag::RGB_RED;
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir                 m_aComponentBitCounts.realloc(4);
262*cdf0e10cSrcweir                 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
263*cdf0e10cSrcweir                 pCounts[0]         = 8;
264*cdf0e10cSrcweir                 pCounts[1]         = 8;
265*cdf0e10cSrcweir                 pCounts[2]         = 8;
266*cdf0e10cSrcweir                 pCounts[3]         = 8;
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir                 m_nRedIndex   = 3;
269*cdf0e10cSrcweir                 m_nGreenIndex = 2;
270*cdf0e10cSrcweir                 m_nBlueIndex  = 1;
271*cdf0e10cSrcweir                 m_nAlphaIndex = 0;
272*cdf0e10cSrcweir             }
273*cdf0e10cSrcweir             break;
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir             case BMP_FORMAT_32BIT_TC_ARGB:
276*cdf0e10cSrcweir             {
277*cdf0e10cSrcweir                 m_bPalette           = false;
278*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 32;
279*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
280*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
281*cdf0e10cSrcweir 
282*cdf0e10cSrcweir                 m_aComponentTags.realloc(4);
283*cdf0e10cSrcweir                 sal_Int8* pTags = m_aComponentTags.getArray();
284*cdf0e10cSrcweir                 pTags[0]        = rendering::ColorComponentTag::ALPHA;
285*cdf0e10cSrcweir                 pTags[1]        = rendering::ColorComponentTag::RGB_RED;
286*cdf0e10cSrcweir                 pTags[2]        = rendering::ColorComponentTag::RGB_GREEN;
287*cdf0e10cSrcweir                 pTags[3]        = rendering::ColorComponentTag::RGB_BLUE;
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir                 m_aComponentBitCounts.realloc(4);
290*cdf0e10cSrcweir                 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
291*cdf0e10cSrcweir                 pCounts[0]         = 8;
292*cdf0e10cSrcweir                 pCounts[1]         = 8;
293*cdf0e10cSrcweir                 pCounts[2]         = 8;
294*cdf0e10cSrcweir                 pCounts[3]         = 8;
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir                 m_nRedIndex   = 1;
297*cdf0e10cSrcweir                 m_nGreenIndex = 2;
298*cdf0e10cSrcweir                 m_nBlueIndex  = 3;
299*cdf0e10cSrcweir                 m_nAlphaIndex = 0;
300*cdf0e10cSrcweir             }
301*cdf0e10cSrcweir             break;
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir             case BMP_FORMAT_32BIT_TC_BGRA:
304*cdf0e10cSrcweir             {
305*cdf0e10cSrcweir                 m_bPalette           = false;
306*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 32;
307*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
308*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir                 m_aComponentTags.realloc(4);
311*cdf0e10cSrcweir                 sal_Int8* pTags = m_aComponentTags.getArray();
312*cdf0e10cSrcweir                 pTags[0]        = rendering::ColorComponentTag::RGB_BLUE;
313*cdf0e10cSrcweir                 pTags[1]        = rendering::ColorComponentTag::RGB_GREEN;
314*cdf0e10cSrcweir                 pTags[2]        = rendering::ColorComponentTag::RGB_RED;
315*cdf0e10cSrcweir                 pTags[3]        = rendering::ColorComponentTag::ALPHA;
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir                 m_aComponentBitCounts.realloc(4);
318*cdf0e10cSrcweir                 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
319*cdf0e10cSrcweir                 pCounts[0]         = 8;
320*cdf0e10cSrcweir                 pCounts[1]         = 8;
321*cdf0e10cSrcweir                 pCounts[2]         = 8;
322*cdf0e10cSrcweir                 pCounts[3]         = 8;
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir                 m_nRedIndex   = 2;
325*cdf0e10cSrcweir                 m_nGreenIndex = 1;
326*cdf0e10cSrcweir                 m_nBlueIndex  = 0;
327*cdf0e10cSrcweir                 m_nAlphaIndex = 3;
328*cdf0e10cSrcweir             }
329*cdf0e10cSrcweir             break;
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir             case BMP_FORMAT_32BIT_TC_RGBA:
332*cdf0e10cSrcweir             {
333*cdf0e10cSrcweir                 m_bPalette           = false;
334*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 32;
335*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
336*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
337*cdf0e10cSrcweir 
338*cdf0e10cSrcweir                 m_aComponentTags.realloc(4);
339*cdf0e10cSrcweir                 sal_Int8* pTags = m_aComponentTags.getArray();
340*cdf0e10cSrcweir                 pTags[0]        = rendering::ColorComponentTag::RGB_RED;
341*cdf0e10cSrcweir                 pTags[1]        = rendering::ColorComponentTag::RGB_GREEN;
342*cdf0e10cSrcweir                 pTags[2]        = rendering::ColorComponentTag::RGB_BLUE;
343*cdf0e10cSrcweir                 pTags[3]        = rendering::ColorComponentTag::ALPHA;
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir                 m_aComponentBitCounts.realloc(4);
346*cdf0e10cSrcweir                 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
347*cdf0e10cSrcweir                 pCounts[0]         = 8;
348*cdf0e10cSrcweir                 pCounts[1]         = 8;
349*cdf0e10cSrcweir                 pCounts[2]         = 8;
350*cdf0e10cSrcweir                 pCounts[3]         = 8;
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir                 m_nRedIndex   = 0;
353*cdf0e10cSrcweir                 m_nGreenIndex = 1;
354*cdf0e10cSrcweir                 m_nBlueIndex  = 2;
355*cdf0e10cSrcweir                 m_nAlphaIndex = 3;
356*cdf0e10cSrcweir             }
357*cdf0e10cSrcweir             break;
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir             case BMP_FORMAT_32BIT_TC_MASK:
360*cdf0e10cSrcweir                 m_bPalette           = false;
361*cdf0e10cSrcweir                 m_nBitsPerInputPixel = 32;
362*cdf0e10cSrcweir                 m_nEndianness        = util::Endianness::LITTLE;
363*cdf0e10cSrcweir                 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
364*cdf0e10cSrcweir                 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
365*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetGreenMask(),
366*cdf0e10cSrcweir                                   m_pBmpAcc->GetColorMask().GetBlueMask() );
367*cdf0e10cSrcweir                 break;
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir             default:
370*cdf0e10cSrcweir                 DBG_ERROR( "unsupported bitmap format" );
371*cdf0e10cSrcweir                 break;
372*cdf0e10cSrcweir         }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir         if( m_bPalette )
375*cdf0e10cSrcweir         {
376*cdf0e10cSrcweir             m_aComponentTags.realloc(1);
377*cdf0e10cSrcweir             m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir             m_aComponentBitCounts.realloc(1);
380*cdf0e10cSrcweir             m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
381*cdf0e10cSrcweir 
382*cdf0e10cSrcweir             m_nIndexIndex = 0;
383*cdf0e10cSrcweir         }
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir         m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
386*cdf0e10cSrcweir         if( m_aBmpEx.IsTransparent() )
387*cdf0e10cSrcweir         {
388*cdf0e10cSrcweir             // TODO(P1): need to interleave alpha with bitmap data -
389*cdf0e10cSrcweir             // won't fuss with less-than-8 bit for now
390*cdf0e10cSrcweir             m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir             // check whether alpha goes in front or behind the
393*cdf0e10cSrcweir             // bitcount sequence. If pixel format is little endian,
394*cdf0e10cSrcweir             // put it behind all the other channels. If it's big
395*cdf0e10cSrcweir             // endian, put it in front (because later, the actual data
396*cdf0e10cSrcweir             // always gets written after the pixel data)
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir             // TODO(Q1): slight catch - in the case of the
399*cdf0e10cSrcweir             // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
400*cdf0e10cSrcweir             // channels might happen!
401*cdf0e10cSrcweir             m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
402*cdf0e10cSrcweir             m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir             m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
405*cdf0e10cSrcweir             m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir             if( m_nEndianness == util::Endianness::BIG )
408*cdf0e10cSrcweir             {
409*cdf0e10cSrcweir                 // put alpha in front of all the color channels
410*cdf0e10cSrcweir                 sal_Int8*  pTags  =m_aComponentTags.getArray();
411*cdf0e10cSrcweir                 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
412*cdf0e10cSrcweir                 std::rotate(pTags,
413*cdf0e10cSrcweir                             pTags+m_aComponentTags.getLength()-1,
414*cdf0e10cSrcweir                             pTags+m_aComponentTags.getLength());
415*cdf0e10cSrcweir                 std::rotate(pCounts,
416*cdf0e10cSrcweir                             pCounts+m_aComponentBitCounts.getLength()-1,
417*cdf0e10cSrcweir                             pCounts+m_aComponentBitCounts.getLength());
418*cdf0e10cSrcweir                 ++m_nRedIndex;
419*cdf0e10cSrcweir                 ++m_nGreenIndex;
420*cdf0e10cSrcweir                 ++m_nBlueIndex;
421*cdf0e10cSrcweir                 ++m_nIndexIndex;
422*cdf0e10cSrcweir                 m_nAlphaIndex=0;
423*cdf0e10cSrcweir             }
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir             // always add a full byte to the pixel size, otherwise
426*cdf0e10cSrcweir             // pixel packing hell breaks loose.
427*cdf0e10cSrcweir             m_nBitsPerOutputPixel += 8;
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir             // adapt scanline parameters
430*cdf0e10cSrcweir             const Size aSize = m_aBitmap.GetSizePixel();
431*cdf0e10cSrcweir             m_aLayout.ScanLineBytes  =
432*cdf0e10cSrcweir             m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
433*cdf0e10cSrcweir         }
434*cdf0e10cSrcweir     }
435*cdf0e10cSrcweir }
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir VclCanvasBitmap::~VclCanvasBitmap()
438*cdf0e10cSrcweir {
439*cdf0e10cSrcweir     if( m_pAlphaAcc )
440*cdf0e10cSrcweir         m_aAlpha.ReleaseAccess(m_pAlphaAcc);
441*cdf0e10cSrcweir     if( m_pBmpAcc )
442*cdf0e10cSrcweir         m_aBitmap.ReleaseAccess(m_pBmpAcc);
443*cdf0e10cSrcweir }
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir // XBitmap
446*cdf0e10cSrcweir geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException)
447*cdf0e10cSrcweir {
448*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
449*cdf0e10cSrcweir     return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
450*cdf0e10cSrcweir }
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir ::sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException)
453*cdf0e10cSrcweir {
454*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
455*cdf0e10cSrcweir     return m_aBmpEx.IsTransparent();
456*cdf0e10cSrcweir }
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
459*cdf0e10cSrcweir                                                                                 sal_Bool beFast ) throw (uno::RuntimeException)
460*cdf0e10cSrcweir {
461*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir     BitmapEx aNewBmp( m_aBitmap );
464*cdf0e10cSrcweir     aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE );
465*cdf0e10cSrcweir     return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
466*cdf0e10cSrcweir }
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir // XIntegerReadOnlyBitmap
469*cdf0e10cSrcweir uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& 	 bitmapLayout,
470*cdf0e10cSrcweir                                                              const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException,
471*cdf0e10cSrcweir                                                                                                                rendering::VolatileContentDestroyedException,
472*cdf0e10cSrcweir                                                                                                                uno::RuntimeException)
473*cdf0e10cSrcweir {
474*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir     bitmapLayout = getMemoryLayout();
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir     const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
479*cdf0e10cSrcweir     if( aRequestedArea.IsEmpty() )
480*cdf0e10cSrcweir         return uno::Sequence< sal_Int8 >();
481*cdf0e10cSrcweir 
482*cdf0e10cSrcweir     // Invalid/empty bitmap: no data available
483*cdf0e10cSrcweir     if( !m_pBmpAcc )
484*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
485*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
486*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir     if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
489*cdf0e10cSrcweir         aRequestedArea.Right() > m_pBmpAcc->Width() ||
490*cdf0e10cSrcweir         aRequestedArea.Bottom() > m_pBmpAcc->Height() )
491*cdf0e10cSrcweir     {
492*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
493*cdf0e10cSrcweir     }
494*cdf0e10cSrcweir 
495*cdf0e10cSrcweir     uno::Sequence< sal_Int8 > aRet;
496*cdf0e10cSrcweir     Rectangle aRequestedBytes( aRequestedArea );
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir     // adapt to byte boundaries
499*cdf0e10cSrcweir     aRequestedBytes.Left()  = aRequestedArea.Left()*m_nBitsPerOutputPixel/8;
500*cdf0e10cSrcweir     aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8;
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir     // copy stuff to output sequence
503*cdf0e10cSrcweir     aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
504*cdf0e10cSrcweir     sal_Int8* pOutBuf = aRet.getArray();
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir     bitmapLayout.ScanLines     = aRequestedBytes.getHeight();
507*cdf0e10cSrcweir     bitmapLayout.ScanLineBytes =
508*cdf0e10cSrcweir     bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
509*cdf0e10cSrcweir 
510*cdf0e10cSrcweir     sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
511*cdf0e10cSrcweir     if( !(m_pBmpAcc->GetScanlineFormat() & BMP_FORMAT_TOP_DOWN) )
512*cdf0e10cSrcweir     {
513*cdf0e10cSrcweir         pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
514*cdf0e10cSrcweir         nScanlineStride *= -1;
515*cdf0e10cSrcweir     }
516*cdf0e10cSrcweir 
517*cdf0e10cSrcweir     if( !m_aBmpEx.IsTransparent() )
518*cdf0e10cSrcweir     {
519*cdf0e10cSrcweir         OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir         // can return bitmap data as-is
522*cdf0e10cSrcweir         for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
523*cdf0e10cSrcweir         {
524*cdf0e10cSrcweir             Scanline pScan = m_pBmpAcc->GetScanline(y);
525*cdf0e10cSrcweir             rtl_copyMemory(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
526*cdf0e10cSrcweir             pOutBuf += nScanlineStride;
527*cdf0e10cSrcweir         }
528*cdf0e10cSrcweir     }
529*cdf0e10cSrcweir     else
530*cdf0e10cSrcweir     {
531*cdf0e10cSrcweir         OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
532*cdf0e10cSrcweir         OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
533*cdf0e10cSrcweir 
534*cdf0e10cSrcweir         // interleave alpha with bitmap data - note, bitcount is
535*cdf0e10cSrcweir         // always integer multiple of 8
536*cdf0e10cSrcweir         OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
537*cdf0e10cSrcweir                    "Transparent bitmap bitcount not integer multiple of 8" );
538*cdf0e10cSrcweir 
539*cdf0e10cSrcweir         for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
540*cdf0e10cSrcweir         {
541*cdf0e10cSrcweir             sal_Int8* pOutScan = pOutBuf;
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir             if( m_nBitsPerInputPixel < 8 )
544*cdf0e10cSrcweir             {
545*cdf0e10cSrcweir                 // input less than a byte - copy via GetPixel()
546*cdf0e10cSrcweir                 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
547*cdf0e10cSrcweir                 {
548*cdf0e10cSrcweir                     *pOutScan++ = m_pBmpAcc->GetPixel(y,x);
549*cdf0e10cSrcweir                     *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
550*cdf0e10cSrcweir                 }
551*cdf0e10cSrcweir             }
552*cdf0e10cSrcweir             else
553*cdf0e10cSrcweir             {
554*cdf0e10cSrcweir                 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
555*cdf0e10cSrcweir                 const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
556*cdf0e10cSrcweir                 Scanline  pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir                 // input integer multiple of byte - copy directly
559*cdf0e10cSrcweir                 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
560*cdf0e10cSrcweir                 {
561*cdf0e10cSrcweir                     for( long i=0; i<nNonAlphaBytes; ++i )
562*cdf0e10cSrcweir                         *pOutScan++ = *pScan++;
563*cdf0e10cSrcweir                     *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
564*cdf0e10cSrcweir                 }
565*cdf0e10cSrcweir             }
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir             pOutBuf += nScanlineStride;
568*cdf0e10cSrcweir         }
569*cdf0e10cSrcweir     }
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir     return aRet;
572*cdf0e10cSrcweir }
573*cdf0e10cSrcweir 
574*cdf0e10cSrcweir uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout&	bitmapLayout,
575*cdf0e10cSrcweir                                                               const geometry::IntegerPoint2D&	pos ) throw (lang::IndexOutOfBoundsException,
576*cdf0e10cSrcweir                                                                                                              rendering::VolatileContentDestroyedException,
577*cdf0e10cSrcweir                                                                                                              uno::RuntimeException)
578*cdf0e10cSrcweir {
579*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir     bitmapLayout = getMemoryLayout();
582*cdf0e10cSrcweir 
583*cdf0e10cSrcweir     // Invalid/empty bitmap: no data available
584*cdf0e10cSrcweir     if( !m_pBmpAcc )
585*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
586*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
587*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir     if( pos.X < 0 || pos.Y < 0 ||
590*cdf0e10cSrcweir         pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
591*cdf0e10cSrcweir     {
592*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException();
593*cdf0e10cSrcweir     }
594*cdf0e10cSrcweir 
595*cdf0e10cSrcweir     uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
596*cdf0e10cSrcweir     sal_Int8* pOutBuf = aRet.getArray();
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir     // copy stuff to output sequence
599*cdf0e10cSrcweir     bitmapLayout.ScanLines     = 1;
600*cdf0e10cSrcweir     bitmapLayout.ScanLineBytes =
601*cdf0e10cSrcweir     bitmapLayout.ScanLineStride= aRet.getLength();
602*cdf0e10cSrcweir 
603*cdf0e10cSrcweir     const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
604*cdf0e10cSrcweir     if( !m_aBmpEx.IsTransparent() )
605*cdf0e10cSrcweir     {
606*cdf0e10cSrcweir         OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
607*cdf0e10cSrcweir 
608*cdf0e10cSrcweir         // can return bitmap data as-is
609*cdf0e10cSrcweir         Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
610*cdf0e10cSrcweir         rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
611*cdf0e10cSrcweir     }
612*cdf0e10cSrcweir     else
613*cdf0e10cSrcweir     {
614*cdf0e10cSrcweir         OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
615*cdf0e10cSrcweir         OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir         // interleave alpha with bitmap data - note, bitcount is
618*cdf0e10cSrcweir         // always integer multiple of 8
619*cdf0e10cSrcweir         OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
620*cdf0e10cSrcweir                    "Transparent bitmap bitcount not integer multiple of 8" );
621*cdf0e10cSrcweir 
622*cdf0e10cSrcweir         if( m_nBitsPerInputPixel < 8 )
623*cdf0e10cSrcweir         {
624*cdf0e10cSrcweir             // input less than a byte - copy via GetPixel()
625*cdf0e10cSrcweir             *pOutBuf++ = m_pBmpAcc->GetPixel(pos.Y,pos.X);
626*cdf0e10cSrcweir             *pOutBuf   = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
627*cdf0e10cSrcweir         }
628*cdf0e10cSrcweir         else
629*cdf0e10cSrcweir         {
630*cdf0e10cSrcweir             const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
631*cdf0e10cSrcweir             Scanline  pScan = m_pBmpAcc->GetScanline(pos.Y);
632*cdf0e10cSrcweir 
633*cdf0e10cSrcweir             // input integer multiple of byte - copy directly
634*cdf0e10cSrcweir             rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
635*cdf0e10cSrcweir             pOutBuf += nNonAlphaBytes;
636*cdf0e10cSrcweir             *pOutBuf++ = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
637*cdf0e10cSrcweir         }
638*cdf0e10cSrcweir     }
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir     return aRet;
641*cdf0e10cSrcweir }
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException)
644*cdf0e10cSrcweir {
645*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
646*cdf0e10cSrcweir 
647*cdf0e10cSrcweir     uno::Reference< XBitmapPalette > aRet;
648*cdf0e10cSrcweir     if( m_bPalette )
649*cdf0e10cSrcweir         aRet.set(this);
650*cdf0e10cSrcweir 
651*cdf0e10cSrcweir     return aRet;
652*cdf0e10cSrcweir }
653*cdf0e10cSrcweir 
654*cdf0e10cSrcweir rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException)
655*cdf0e10cSrcweir {
656*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir     rendering::IntegerBitmapLayout aLayout( m_aLayout );
659*cdf0e10cSrcweir 
660*cdf0e10cSrcweir     // only set references to self on separate copy of
661*cdf0e10cSrcweir     // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
662*cdf0e10cSrcweir     // a circular reference!
663*cdf0e10cSrcweir     if( m_bPalette )
664*cdf0e10cSrcweir         aLayout.Palette.set( this );
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir     aLayout.ColorSpace.set( this );
667*cdf0e10cSrcweir 
668*cdf0e10cSrcweir     return aLayout;
669*cdf0e10cSrcweir }
670*cdf0e10cSrcweir 
671*cdf0e10cSrcweir sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException)
672*cdf0e10cSrcweir {
673*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
674*cdf0e10cSrcweir 
675*cdf0e10cSrcweir     if( !m_pBmpAcc )
676*cdf0e10cSrcweir         return 0;
677*cdf0e10cSrcweir 
678*cdf0e10cSrcweir     return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
679*cdf0e10cSrcweir }
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
682*cdf0e10cSrcweir {
683*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
684*cdf0e10cSrcweir 
685*cdf0e10cSrcweir     const sal_uInt16 nCount( m_pBmpAcc ?
686*cdf0e10cSrcweir                          (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
687*cdf0e10cSrcweir     OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
688*cdf0e10cSrcweir     if( nIndex < 0 || nIndex >= nCount )
689*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"),
690*cdf0e10cSrcweir                                               static_cast<rendering::XBitmapPalette*>(this));
691*cdf0e10cSrcweir 
692*cdf0e10cSrcweir     const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
693*cdf0e10cSrcweir     o_entry.realloc(3);
694*cdf0e10cSrcweir     double* pColor=o_entry.getArray();
695*cdf0e10cSrcweir     pColor[0] = aCol.GetRed();
696*cdf0e10cSrcweir     pColor[1] = aCol.GetGreen();
697*cdf0e10cSrcweir     pColor[2] = aCol.GetBlue();
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir     return sal_True; // no palette transparency here.
700*cdf0e10cSrcweir }
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
703*cdf0e10cSrcweir {
704*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir     const sal_uInt16 nCount( m_pBmpAcc ?
707*cdf0e10cSrcweir                          (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
708*cdf0e10cSrcweir 
709*cdf0e10cSrcweir     OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
710*cdf0e10cSrcweir     if( nIndex < 0 || nIndex >= nCount )
711*cdf0e10cSrcweir         throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"),
712*cdf0e10cSrcweir                                               static_cast<rendering::XBitmapPalette*>(this));
713*cdf0e10cSrcweir 
714*cdf0e10cSrcweir     return sal_False; // read-only implementation
715*cdf0e10cSrcweir }
716*cdf0e10cSrcweir 
717*cdf0e10cSrcweir namespace
718*cdf0e10cSrcweir {
719*cdf0e10cSrcweir     struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
720*cdf0e10cSrcweir                                                                PaletteColorSpaceHolder>
721*cdf0e10cSrcweir     {
722*cdf0e10cSrcweir         uno::Reference<rendering::XColorSpace> operator()()
723*cdf0e10cSrcweir         {
724*cdf0e10cSrcweir             return vcl::unotools::createStandardColorSpace();
725*cdf0e10cSrcweir         }
726*cdf0e10cSrcweir     };
727*cdf0e10cSrcweir }
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace(  ) throw (uno::RuntimeException)
730*cdf0e10cSrcweir {
731*cdf0e10cSrcweir     // this is the method from XBitmapPalette. Return palette color
732*cdf0e10cSrcweir     // space here
733*cdf0e10cSrcweir     return PaletteColorSpaceHolder::get();
734*cdf0e10cSrcweir }
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir sal_Int8 SAL_CALL VclCanvasBitmap::getType(  ) throw (uno::RuntimeException)
737*cdf0e10cSrcweir {
738*cdf0e10cSrcweir     return rendering::ColorSpaceType::RGB;
739*cdf0e10cSrcweir }
740*cdf0e10cSrcweir 
741*cdf0e10cSrcweir uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags(  ) throw (uno::RuntimeException)
742*cdf0e10cSrcweir {
743*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
744*cdf0e10cSrcweir     return m_aComponentTags;
745*cdf0e10cSrcweir }
746*cdf0e10cSrcweir 
747*cdf0e10cSrcweir sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent(  ) throw (uno::RuntimeException)
748*cdf0e10cSrcweir {
749*cdf0e10cSrcweir     return rendering::RenderingIntent::PERCEPTUAL;
750*cdf0e10cSrcweir }
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties(  ) throw (uno::RuntimeException)
753*cdf0e10cSrcweir {
754*cdf0e10cSrcweir     return uno::Sequence< ::beans::PropertyValue >();
755*cdf0e10cSrcweir }
756*cdf0e10cSrcweir 
757*cdf0e10cSrcweir uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
758*cdf0e10cSrcweir                                                                      const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException)
759*cdf0e10cSrcweir {
760*cdf0e10cSrcweir     // TODO(P3): if we know anything about target
761*cdf0e10cSrcweir     // colorspace, this can be greatly sped up
762*cdf0e10cSrcweir     uno::Sequence<rendering::ARGBColor> aIntermediate(
763*cdf0e10cSrcweir         convertToARGB(deviceColor));
764*cdf0e10cSrcweir     return targetColorSpace->convertFromARGB(aIntermediate);
765*cdf0e10cSrcweir }
766*cdf0e10cSrcweir 
767*cdf0e10cSrcweir uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
768*cdf0e10cSrcweir {
769*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
770*cdf0e10cSrcweir 
771*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
772*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
773*cdf0e10cSrcweir     ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
774*cdf0e10cSrcweir                          "number of channels no multiple of pixel element count",
775*cdf0e10cSrcweir                          static_cast<rendering::XBitmapPalette*>(this), 01);
776*cdf0e10cSrcweir 
777*cdf0e10cSrcweir     uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
778*cdf0e10cSrcweir     rendering::RGBColor* pOut( aRes.getArray() );
779*cdf0e10cSrcweir 
780*cdf0e10cSrcweir     if( m_bPalette )
781*cdf0e10cSrcweir     {
782*cdf0e10cSrcweir         OSL_ENSURE(m_nIndexIndex != -1,
783*cdf0e10cSrcweir                    "Invalid color channel indices");
784*cdf0e10cSrcweir         ENSURE_OR_THROW(m_pBmpAcc,
785*cdf0e10cSrcweir                         "Unable to get BitmapAccess");
786*cdf0e10cSrcweir 
787*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
788*cdf0e10cSrcweir         {
789*cdf0e10cSrcweir             const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
790*cdf0e10cSrcweir                 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
793*cdf0e10cSrcweir             *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
794*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetGreen()),
795*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetBlue()));
796*cdf0e10cSrcweir         }
797*cdf0e10cSrcweir     }
798*cdf0e10cSrcweir     else
799*cdf0e10cSrcweir     {
800*cdf0e10cSrcweir         OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
801*cdf0e10cSrcweir                    "Invalid color channel indices");
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
804*cdf0e10cSrcweir         {
805*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
806*cdf0e10cSrcweir             *pOut++ = rendering::RGBColor(
807*cdf0e10cSrcweir                 deviceColor[i+m_nRedIndex],
808*cdf0e10cSrcweir                 deviceColor[i+m_nGreenIndex],
809*cdf0e10cSrcweir                 deviceColor[i+m_nBlueIndex]);
810*cdf0e10cSrcweir         }
811*cdf0e10cSrcweir     }
812*cdf0e10cSrcweir 
813*cdf0e10cSrcweir     return aRes;
814*cdf0e10cSrcweir }
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
817*cdf0e10cSrcweir {
818*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
821*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
822*cdf0e10cSrcweir     ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
823*cdf0e10cSrcweir                          "number of channels no multiple of pixel element count",
824*cdf0e10cSrcweir                          static_cast<rendering::XBitmapPalette*>(this), 01);
825*cdf0e10cSrcweir 
826*cdf0e10cSrcweir     uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
827*cdf0e10cSrcweir     rendering::ARGBColor* pOut( aRes.getArray() );
828*cdf0e10cSrcweir 
829*cdf0e10cSrcweir     if( m_bPalette )
830*cdf0e10cSrcweir     {
831*cdf0e10cSrcweir         OSL_ENSURE(m_nIndexIndex != -1,
832*cdf0e10cSrcweir                    "Invalid color channel indices");
833*cdf0e10cSrcweir         ENSURE_OR_THROW(m_pBmpAcc,
834*cdf0e10cSrcweir                         "Unable to get BitmapAccess");
835*cdf0e10cSrcweir 
836*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
837*cdf0e10cSrcweir         {
838*cdf0e10cSrcweir             const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
839*cdf0e10cSrcweir                 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
842*cdf0e10cSrcweir             const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
843*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(nAlpha,
844*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetRed()),
845*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetGreen()),
846*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetBlue()));
847*cdf0e10cSrcweir         }
848*cdf0e10cSrcweir     }
849*cdf0e10cSrcweir     else
850*cdf0e10cSrcweir     {
851*cdf0e10cSrcweir         OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
852*cdf0e10cSrcweir                    "Invalid color channel indices");
853*cdf0e10cSrcweir 
854*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
855*cdf0e10cSrcweir         {
856*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
857*cdf0e10cSrcweir             const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
858*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(
859*cdf0e10cSrcweir                 nAlpha,
860*cdf0e10cSrcweir                 deviceColor[i+m_nRedIndex],
861*cdf0e10cSrcweir                 deviceColor[i+m_nGreenIndex],
862*cdf0e10cSrcweir                 deviceColor[i+m_nBlueIndex]);
863*cdf0e10cSrcweir         }
864*cdf0e10cSrcweir     }
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir     return aRes;
867*cdf0e10cSrcweir }
868*cdf0e10cSrcweir 
869*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
870*cdf0e10cSrcweir {
871*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
874*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
875*cdf0e10cSrcweir     ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
876*cdf0e10cSrcweir                          "number of channels no multiple of pixel element count",
877*cdf0e10cSrcweir                          static_cast<rendering::XBitmapPalette*>(this), 01);
878*cdf0e10cSrcweir 
879*cdf0e10cSrcweir     uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
880*cdf0e10cSrcweir     rendering::ARGBColor* pOut( aRes.getArray() );
881*cdf0e10cSrcweir 
882*cdf0e10cSrcweir     if( m_bPalette )
883*cdf0e10cSrcweir     {
884*cdf0e10cSrcweir         OSL_ENSURE(m_nIndexIndex != -1,
885*cdf0e10cSrcweir                    "Invalid color channel indices");
886*cdf0e10cSrcweir         ENSURE_OR_THROW(m_pBmpAcc,
887*cdf0e10cSrcweir                         "Unable to get BitmapAccess");
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
890*cdf0e10cSrcweir         {
891*cdf0e10cSrcweir             const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
892*cdf0e10cSrcweir                 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
893*cdf0e10cSrcweir 
894*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
895*cdf0e10cSrcweir             const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
896*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(nAlpha,
897*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetRed()),
898*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetGreen()),
899*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetBlue()));
900*cdf0e10cSrcweir         }
901*cdf0e10cSrcweir     }
902*cdf0e10cSrcweir     else
903*cdf0e10cSrcweir     {
904*cdf0e10cSrcweir         OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
905*cdf0e10cSrcweir                    "Invalid color channel indices");
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
908*cdf0e10cSrcweir         {
909*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
910*cdf0e10cSrcweir             const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
911*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(
912*cdf0e10cSrcweir                 nAlpha,
913*cdf0e10cSrcweir                 nAlpha*deviceColor[i+m_nRedIndex],
914*cdf0e10cSrcweir                 nAlpha*deviceColor[i+m_nGreenIndex],
915*cdf0e10cSrcweir                 nAlpha*deviceColor[i+m_nBlueIndex]);
916*cdf0e10cSrcweir         }
917*cdf0e10cSrcweir     }
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir     return aRes;
920*cdf0e10cSrcweir }
921*cdf0e10cSrcweir 
922*cdf0e10cSrcweir uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
923*cdf0e10cSrcweir {
924*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
925*cdf0e10cSrcweir 
926*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
927*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir     uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
930*cdf0e10cSrcweir     double* pColors=aRes.getArray();
931*cdf0e10cSrcweir 
932*cdf0e10cSrcweir     if( m_bPalette )
933*cdf0e10cSrcweir     {
934*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
935*cdf0e10cSrcweir         {
936*cdf0e10cSrcweir             pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
937*cdf0e10cSrcweir                     BitmapColor(toByteColor(rgbColor[i].Red),
938*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Green),
939*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Blue)));
940*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
941*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = 1.0;
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
944*cdf0e10cSrcweir         }
945*cdf0e10cSrcweir     }
946*cdf0e10cSrcweir     else
947*cdf0e10cSrcweir     {
948*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
949*cdf0e10cSrcweir         {
950*cdf0e10cSrcweir             pColors[m_nRedIndex]   = rgbColor[i].Red;
951*cdf0e10cSrcweir             pColors[m_nGreenIndex] = rgbColor[i].Green;
952*cdf0e10cSrcweir             pColors[m_nBlueIndex]  = rgbColor[i].Blue;
953*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
954*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = 1.0;
955*cdf0e10cSrcweir 
956*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
957*cdf0e10cSrcweir         }
958*cdf0e10cSrcweir     }
959*cdf0e10cSrcweir     return aRes;
960*cdf0e10cSrcweir }
961*cdf0e10cSrcweir 
962*cdf0e10cSrcweir uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
963*cdf0e10cSrcweir {
964*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
967*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
968*cdf0e10cSrcweir 
969*cdf0e10cSrcweir     uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
970*cdf0e10cSrcweir     double* pColors=aRes.getArray();
971*cdf0e10cSrcweir 
972*cdf0e10cSrcweir     if( m_bPalette )
973*cdf0e10cSrcweir     {
974*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
975*cdf0e10cSrcweir         {
976*cdf0e10cSrcweir             pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
977*cdf0e10cSrcweir                     BitmapColor(toByteColor(rgbColor[i].Red),
978*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Green),
979*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Blue)));
980*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
981*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
982*cdf0e10cSrcweir 
983*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
984*cdf0e10cSrcweir         }
985*cdf0e10cSrcweir     }
986*cdf0e10cSrcweir     else
987*cdf0e10cSrcweir     {
988*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
989*cdf0e10cSrcweir         {
990*cdf0e10cSrcweir             pColors[m_nRedIndex]   = rgbColor[i].Red;
991*cdf0e10cSrcweir             pColors[m_nGreenIndex] = rgbColor[i].Green;
992*cdf0e10cSrcweir             pColors[m_nBlueIndex]  = rgbColor[i].Blue;
993*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
994*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
995*cdf0e10cSrcweir 
996*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
997*cdf0e10cSrcweir         }
998*cdf0e10cSrcweir     }
999*cdf0e10cSrcweir     return aRes;
1000*cdf0e10cSrcweir }
1001*cdf0e10cSrcweir 
1002*cdf0e10cSrcweir uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1003*cdf0e10cSrcweir {
1004*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1005*cdf0e10cSrcweir 
1006*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
1007*cdf0e10cSrcweir     const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1008*cdf0e10cSrcweir 
1009*cdf0e10cSrcweir     uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
1010*cdf0e10cSrcweir     double* pColors=aRes.getArray();
1011*cdf0e10cSrcweir 
1012*cdf0e10cSrcweir     if( m_bPalette )
1013*cdf0e10cSrcweir     {
1014*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1015*cdf0e10cSrcweir         {
1016*cdf0e10cSrcweir             const double nAlpha( rgbColor[i].Alpha );
1017*cdf0e10cSrcweir             pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
1018*cdf0e10cSrcweir                     BitmapColor(toByteColor(rgbColor[i].Red / nAlpha),
1019*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Green / nAlpha),
1020*cdf0e10cSrcweir                                 toByteColor(rgbColor[i].Blue / nAlpha)));
1021*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
1022*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = nAlpha;
1023*cdf0e10cSrcweir 
1024*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
1025*cdf0e10cSrcweir         }
1026*cdf0e10cSrcweir     }
1027*cdf0e10cSrcweir     else
1028*cdf0e10cSrcweir     {
1029*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1030*cdf0e10cSrcweir         {
1031*cdf0e10cSrcweir             const double nAlpha( rgbColor[i].Alpha );
1032*cdf0e10cSrcweir             pColors[m_nRedIndex]   = rgbColor[i].Red / nAlpha;
1033*cdf0e10cSrcweir             pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha;
1034*cdf0e10cSrcweir             pColors[m_nBlueIndex]  = rgbColor[i].Blue / nAlpha;
1035*cdf0e10cSrcweir             if( m_nAlphaIndex != -1 )
1036*cdf0e10cSrcweir                 pColors[m_nAlphaIndex] = nAlpha;
1037*cdf0e10cSrcweir 
1038*cdf0e10cSrcweir             pColors += nComponentsPerPixel;
1039*cdf0e10cSrcweir         }
1040*cdf0e10cSrcweir     }
1041*cdf0e10cSrcweir     return aRes;
1042*cdf0e10cSrcweir }
1043*cdf0e10cSrcweir 
1044*cdf0e10cSrcweir sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel(  ) throw (uno::RuntimeException)
1045*cdf0e10cSrcweir {
1046*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1047*cdf0e10cSrcweir     return m_nBitsPerOutputPixel;
1048*cdf0e10cSrcweir }
1049*cdf0e10cSrcweir 
1050*cdf0e10cSrcweir uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts(  ) throw (uno::RuntimeException)
1051*cdf0e10cSrcweir {
1052*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1053*cdf0e10cSrcweir     return m_aComponentBitCounts;
1054*cdf0e10cSrcweir }
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness(  ) throw (uno::RuntimeException)
1057*cdf0e10cSrcweir {
1058*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1059*cdf0e10cSrcweir     return m_nEndianness;
1060*cdf0e10cSrcweir }
1061*cdf0e10cSrcweir 
1062*cdf0e10cSrcweir uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1063*cdf0e10cSrcweir                                                                               const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1064*cdf0e10cSrcweir {
1065*cdf0e10cSrcweir     if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1066*cdf0e10cSrcweir     {
1067*cdf0e10cSrcweir         vos::OGuard aGuard( Application::GetSolarMutex() );
1068*cdf0e10cSrcweir 
1069*cdf0e10cSrcweir         const sal_Size  nLen( deviceColor.getLength() );
1070*cdf0e10cSrcweir         const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1071*cdf0e10cSrcweir         ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1072*cdf0e10cSrcweir                              "number of channels no multiple of pixel element count",
1073*cdf0e10cSrcweir                              static_cast<rendering::XBitmapPalette*>(this), 01);
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir         uno::Sequence<double> aRes(nLen);
1076*cdf0e10cSrcweir         double* pOut( aRes.getArray() );
1077*cdf0e10cSrcweir 
1078*cdf0e10cSrcweir         if( m_bPalette )
1079*cdf0e10cSrcweir         {
1080*cdf0e10cSrcweir             OSL_ENSURE(m_nIndexIndex != -1,
1081*cdf0e10cSrcweir                        "Invalid color channel indices");
1082*cdf0e10cSrcweir             ENSURE_OR_THROW(m_pBmpAcc,
1083*cdf0e10cSrcweir                             "Unable to get BitmapAccess");
1084*cdf0e10cSrcweir 
1085*cdf0e10cSrcweir             for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1086*cdf0e10cSrcweir             {
1087*cdf0e10cSrcweir                 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1088*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1089*cdf0e10cSrcweir 
1090*cdf0e10cSrcweir                 // TODO(F3): Convert result to sRGB color space
1091*cdf0e10cSrcweir                 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1092*cdf0e10cSrcweir                 *pOut++ = toDoubleColor(aCol.GetRed());
1093*cdf0e10cSrcweir                 *pOut++ = toDoubleColor(aCol.GetGreen());
1094*cdf0e10cSrcweir                 *pOut++ = toDoubleColor(aCol.GetBlue());
1095*cdf0e10cSrcweir                 *pOut++ = nAlpha;
1096*cdf0e10cSrcweir             }
1097*cdf0e10cSrcweir         }
1098*cdf0e10cSrcweir         else
1099*cdf0e10cSrcweir         {
1100*cdf0e10cSrcweir             OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1101*cdf0e10cSrcweir                        "Invalid color channel indices");
1102*cdf0e10cSrcweir 
1103*cdf0e10cSrcweir             for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1104*cdf0e10cSrcweir             {
1105*cdf0e10cSrcweir                 // TODO(F3): Convert result to sRGB color space
1106*cdf0e10cSrcweir                 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1107*cdf0e10cSrcweir                 *pOut++ = deviceColor[i+m_nRedIndex];
1108*cdf0e10cSrcweir                 *pOut++ = deviceColor[i+m_nGreenIndex];
1109*cdf0e10cSrcweir                 *pOut++ = deviceColor[i+m_nBlueIndex];
1110*cdf0e10cSrcweir                 *pOut++ = nAlpha;
1111*cdf0e10cSrcweir             }
1112*cdf0e10cSrcweir         }
1113*cdf0e10cSrcweir 
1114*cdf0e10cSrcweir         return aRes;
1115*cdf0e10cSrcweir     }
1116*cdf0e10cSrcweir     else
1117*cdf0e10cSrcweir     {
1118*cdf0e10cSrcweir         // TODO(P3): if we know anything about target
1119*cdf0e10cSrcweir         // colorspace, this can be greatly sped up
1120*cdf0e10cSrcweir         uno::Sequence<rendering::ARGBColor> aIntermediate(
1121*cdf0e10cSrcweir             convertIntegerToARGB(deviceColor));
1122*cdf0e10cSrcweir         return targetColorSpace->convertFromARGB(aIntermediate);
1123*cdf0e10cSrcweir     }
1124*cdf0e10cSrcweir }
1125*cdf0e10cSrcweir 
1126*cdf0e10cSrcweir uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1127*cdf0e10cSrcweir                                                                                   const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1128*cdf0e10cSrcweir {
1129*cdf0e10cSrcweir     if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1130*cdf0e10cSrcweir     {
1131*cdf0e10cSrcweir         // it's us, so simply pass-through the data
1132*cdf0e10cSrcweir         return deviceColor;
1133*cdf0e10cSrcweir     }
1134*cdf0e10cSrcweir     else
1135*cdf0e10cSrcweir     {
1136*cdf0e10cSrcweir         // TODO(P3): if we know anything about target
1137*cdf0e10cSrcweir         // colorspace, this can be greatly sped up
1138*cdf0e10cSrcweir         uno::Sequence<rendering::ARGBColor> aIntermediate(
1139*cdf0e10cSrcweir             convertIntegerToARGB(deviceColor));
1140*cdf0e10cSrcweir         return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1141*cdf0e10cSrcweir     }
1142*cdf0e10cSrcweir }
1143*cdf0e10cSrcweir 
1144*cdf0e10cSrcweir uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1145*cdf0e10cSrcweir {
1146*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1147*cdf0e10cSrcweir 
1148*cdf0e10cSrcweir     const sal_uInt8*     pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1149*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
1150*cdf0e10cSrcweir     const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1151*cdf0e10cSrcweir 
1152*cdf0e10cSrcweir     uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1153*cdf0e10cSrcweir     rendering::RGBColor* pOut( aRes.getArray() );
1154*cdf0e10cSrcweir 
1155*cdf0e10cSrcweir     ENSURE_OR_THROW(m_pBmpAcc,
1156*cdf0e10cSrcweir                     "Unable to get BitmapAccess");
1157*cdf0e10cSrcweir 
1158*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1159*cdf0e10cSrcweir     {
1160*cdf0e10cSrcweir         const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1161*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1162*cdf0e10cSrcweir         {
1163*cdf0e10cSrcweir             // if palette, index is guaranteed to be 8 bit
1164*cdf0e10cSrcweir             const BitmapColor aCol =
1165*cdf0e10cSrcweir                 m_bPalette ?
1166*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(*pIn) :
1167*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn,0);
1168*cdf0e10cSrcweir 
1169*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1170*cdf0e10cSrcweir             *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1171*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetGreen()),
1172*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetBlue()));
1173*cdf0e10cSrcweir             // skips alpha
1174*cdf0e10cSrcweir             pIn += nBytesPerPixel;
1175*cdf0e10cSrcweir         }
1176*cdf0e10cSrcweir     }
1177*cdf0e10cSrcweir     else
1178*cdf0e10cSrcweir     {
1179*cdf0e10cSrcweir         for( sal_Int32 i=0; i<nNumColors; ++i )
1180*cdf0e10cSrcweir         {
1181*cdf0e10cSrcweir             const BitmapColor aCol =
1182*cdf0e10cSrcweir                 m_bPalette ?
1183*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(
1184*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt16>(
1185*cdf0e10cSrcweir                         m_pBmpAcc->GetPixelFromData(
1186*cdf0e10cSrcweir                             pIn, i ))) :
1187*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn, i);
1188*cdf0e10cSrcweir 
1189*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1190*cdf0e10cSrcweir             *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1191*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetGreen()),
1192*cdf0e10cSrcweir                                           toDoubleColor(aCol.GetBlue()));
1193*cdf0e10cSrcweir         }
1194*cdf0e10cSrcweir     }
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir     return aRes;
1197*cdf0e10cSrcweir }
1198*cdf0e10cSrcweir 
1199*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1200*cdf0e10cSrcweir {
1201*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1202*cdf0e10cSrcweir 
1203*cdf0e10cSrcweir     const sal_uInt8*     pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1204*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
1205*cdf0e10cSrcweir     const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1206*cdf0e10cSrcweir 
1207*cdf0e10cSrcweir     uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1208*cdf0e10cSrcweir     rendering::ARGBColor* pOut( aRes.getArray() );
1209*cdf0e10cSrcweir 
1210*cdf0e10cSrcweir     ENSURE_OR_THROW(m_pBmpAcc,
1211*cdf0e10cSrcweir                     "Unable to get BitmapAccess");
1212*cdf0e10cSrcweir 
1213*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1214*cdf0e10cSrcweir     {
1215*cdf0e10cSrcweir         const long      nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1216*cdf0e10cSrcweir         const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1217*cdf0e10cSrcweir         const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1218*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1219*cdf0e10cSrcweir         {
1220*cdf0e10cSrcweir             // if palette, index is guaranteed to be 8 bit
1221*cdf0e10cSrcweir             const BitmapColor aCol =
1222*cdf0e10cSrcweir                 m_bPalette ?
1223*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(*pIn) :
1224*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn,0);
1225*cdf0e10cSrcweir 
1226*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1227*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1228*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetRed()),
1229*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetGreen()),
1230*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetBlue()));
1231*cdf0e10cSrcweir             pIn += nBytesPerPixel;
1232*cdf0e10cSrcweir         }
1233*cdf0e10cSrcweir     }
1234*cdf0e10cSrcweir     else
1235*cdf0e10cSrcweir     {
1236*cdf0e10cSrcweir         for( sal_Int32 i=0; i<nNumColors; ++i )
1237*cdf0e10cSrcweir         {
1238*cdf0e10cSrcweir             const BitmapColor aCol =
1239*cdf0e10cSrcweir                 m_bPalette ?
1240*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(
1241*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt16>(
1242*cdf0e10cSrcweir                         m_pBmpAcc->GetPixelFromData(
1243*cdf0e10cSrcweir                             pIn, i ))) :
1244*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn, i);
1245*cdf0e10cSrcweir 
1246*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1247*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(1.0,
1248*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetRed()),
1249*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetGreen()),
1250*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetBlue()));
1251*cdf0e10cSrcweir         }
1252*cdf0e10cSrcweir     }
1253*cdf0e10cSrcweir 
1254*cdf0e10cSrcweir     return aRes;
1255*cdf0e10cSrcweir }
1256*cdf0e10cSrcweir 
1257*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1258*cdf0e10cSrcweir {
1259*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1260*cdf0e10cSrcweir 
1261*cdf0e10cSrcweir     const sal_uInt8*     pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1262*cdf0e10cSrcweir     const sal_Size  nLen( deviceColor.getLength() );
1263*cdf0e10cSrcweir     const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1264*cdf0e10cSrcweir 
1265*cdf0e10cSrcweir     uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1266*cdf0e10cSrcweir     rendering::ARGBColor* pOut( aRes.getArray() );
1267*cdf0e10cSrcweir 
1268*cdf0e10cSrcweir     ENSURE_OR_THROW(m_pBmpAcc,
1269*cdf0e10cSrcweir                     "Unable to get BitmapAccess");
1270*cdf0e10cSrcweir 
1271*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1272*cdf0e10cSrcweir     {
1273*cdf0e10cSrcweir         const long      nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1274*cdf0e10cSrcweir         const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1275*cdf0e10cSrcweir         const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1276*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1277*cdf0e10cSrcweir         {
1278*cdf0e10cSrcweir             // if palette, index is guaranteed to be 8 bit
1279*cdf0e10cSrcweir             const BitmapColor aCol =
1280*cdf0e10cSrcweir                 m_bPalette ?
1281*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(*pIn) :
1282*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn,0);
1283*cdf0e10cSrcweir 
1284*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1285*cdf0e10cSrcweir             const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1286*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(nAlpha,
1287*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetRed()),
1288*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetGreen()),
1289*cdf0e10cSrcweir                                            nAlpha*toDoubleColor(aCol.GetBlue()));
1290*cdf0e10cSrcweir             pIn += nBytesPerPixel;
1291*cdf0e10cSrcweir         }
1292*cdf0e10cSrcweir     }
1293*cdf0e10cSrcweir     else
1294*cdf0e10cSrcweir     {
1295*cdf0e10cSrcweir         for( sal_Int32 i=0; i<nNumColors; ++i )
1296*cdf0e10cSrcweir         {
1297*cdf0e10cSrcweir             const BitmapColor aCol =
1298*cdf0e10cSrcweir                 m_bPalette ?
1299*cdf0e10cSrcweir                 m_pBmpAcc->GetPaletteColor(
1300*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt16>(
1301*cdf0e10cSrcweir                         m_pBmpAcc->GetPixelFromData(
1302*cdf0e10cSrcweir                             pIn, i ))) :
1303*cdf0e10cSrcweir                 m_pBmpAcc->GetPixelFromData(pIn, i);
1304*cdf0e10cSrcweir 
1305*cdf0e10cSrcweir             // TODO(F3): Convert result to sRGB color space
1306*cdf0e10cSrcweir             *pOut++ = rendering::ARGBColor(1.0,
1307*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetRed()),
1308*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetGreen()),
1309*cdf0e10cSrcweir                                            toDoubleColor(aCol.GetBlue()));
1310*cdf0e10cSrcweir         }
1311*cdf0e10cSrcweir     }
1312*cdf0e10cSrcweir 
1313*cdf0e10cSrcweir     return aRes;
1314*cdf0e10cSrcweir }
1315*cdf0e10cSrcweir 
1316*cdf0e10cSrcweir uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1317*cdf0e10cSrcweir {
1318*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1319*cdf0e10cSrcweir 
1320*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
1321*cdf0e10cSrcweir     const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1322*cdf0e10cSrcweir 
1323*cdf0e10cSrcweir     uno::Sequence< sal_Int8 > aRes(nNumBytes);
1324*cdf0e10cSrcweir     sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1325*cdf0e10cSrcweir 
1326*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1327*cdf0e10cSrcweir     {
1328*cdf0e10cSrcweir         const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1329*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1330*cdf0e10cSrcweir         {
1331*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1332*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green),
1333*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue));
1334*cdf0e10cSrcweir             const BitmapColor aCol2 =
1335*cdf0e10cSrcweir                 m_bPalette ?
1336*cdf0e10cSrcweir                 BitmapColor(
1337*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1338*cdf0e10cSrcweir                 aCol;
1339*cdf0e10cSrcweir 
1340*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1341*cdf0e10cSrcweir             pColors   += nNonAlphaBytes;
1342*cdf0e10cSrcweir             *pColors++ = sal_uInt8(255);
1343*cdf0e10cSrcweir         }
1344*cdf0e10cSrcweir     }
1345*cdf0e10cSrcweir     else
1346*cdf0e10cSrcweir     {
1347*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1348*cdf0e10cSrcweir         {
1349*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1350*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green),
1351*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue));
1352*cdf0e10cSrcweir             const BitmapColor aCol2 =
1353*cdf0e10cSrcweir                 m_bPalette ?
1354*cdf0e10cSrcweir                 BitmapColor(
1355*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1356*cdf0e10cSrcweir                 aCol;
1357*cdf0e10cSrcweir 
1358*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1359*cdf0e10cSrcweir         }
1360*cdf0e10cSrcweir     }
1361*cdf0e10cSrcweir 
1362*cdf0e10cSrcweir     return aRes;
1363*cdf0e10cSrcweir }
1364*cdf0e10cSrcweir 
1365*cdf0e10cSrcweir uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1366*cdf0e10cSrcweir {
1367*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1368*cdf0e10cSrcweir 
1369*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
1370*cdf0e10cSrcweir     const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1371*cdf0e10cSrcweir 
1372*cdf0e10cSrcweir     uno::Sequence< sal_Int8 > aRes(nNumBytes);
1373*cdf0e10cSrcweir     sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1374*cdf0e10cSrcweir 
1375*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1376*cdf0e10cSrcweir     {
1377*cdf0e10cSrcweir         const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1378*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1379*cdf0e10cSrcweir         {
1380*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1381*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green),
1382*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue));
1383*cdf0e10cSrcweir             const BitmapColor aCol2 =
1384*cdf0e10cSrcweir                 m_bPalette ?
1385*cdf0e10cSrcweir                 BitmapColor(
1386*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1387*cdf0e10cSrcweir                 aCol;
1388*cdf0e10cSrcweir 
1389*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1390*cdf0e10cSrcweir             pColors   += nNonAlphaBytes;
1391*cdf0e10cSrcweir             *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1392*cdf0e10cSrcweir         }
1393*cdf0e10cSrcweir     }
1394*cdf0e10cSrcweir     else
1395*cdf0e10cSrcweir     {
1396*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1397*cdf0e10cSrcweir         {
1398*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1399*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green),
1400*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue));
1401*cdf0e10cSrcweir             const BitmapColor aCol2 =
1402*cdf0e10cSrcweir                 m_bPalette ?
1403*cdf0e10cSrcweir                 BitmapColor(
1404*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1405*cdf0e10cSrcweir                 aCol;
1406*cdf0e10cSrcweir 
1407*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1408*cdf0e10cSrcweir         }
1409*cdf0e10cSrcweir     }
1410*cdf0e10cSrcweir 
1411*cdf0e10cSrcweir     return aRes;
1412*cdf0e10cSrcweir }
1413*cdf0e10cSrcweir 
1414*cdf0e10cSrcweir uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1415*cdf0e10cSrcweir {
1416*cdf0e10cSrcweir     vos::OGuard aGuard( Application::GetSolarMutex() );
1417*cdf0e10cSrcweir 
1418*cdf0e10cSrcweir     const sal_Size  nLen( rgbColor.getLength() );
1419*cdf0e10cSrcweir     const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1420*cdf0e10cSrcweir 
1421*cdf0e10cSrcweir     uno::Sequence< sal_Int8 > aRes(nNumBytes);
1422*cdf0e10cSrcweir     sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1423*cdf0e10cSrcweir 
1424*cdf0e10cSrcweir     if( m_aBmpEx.IsTransparent() )
1425*cdf0e10cSrcweir     {
1426*cdf0e10cSrcweir         const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1427*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1428*cdf0e10cSrcweir         {
1429*cdf0e10cSrcweir             const double nAlpha( rgbColor[i].Alpha );
1430*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1431*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green / nAlpha),
1432*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue / nAlpha));
1433*cdf0e10cSrcweir             const BitmapColor aCol2 =
1434*cdf0e10cSrcweir                 m_bPalette ?
1435*cdf0e10cSrcweir                 BitmapColor(
1436*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1437*cdf0e10cSrcweir                 aCol;
1438*cdf0e10cSrcweir 
1439*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1440*cdf0e10cSrcweir             pColors   += nNonAlphaBytes;
1441*cdf0e10cSrcweir             *pColors++ = 255 - toByteColor(nAlpha);
1442*cdf0e10cSrcweir         }
1443*cdf0e10cSrcweir     }
1444*cdf0e10cSrcweir     else
1445*cdf0e10cSrcweir     {
1446*cdf0e10cSrcweir         for( sal_Size i=0; i<nLen; ++i )
1447*cdf0e10cSrcweir         {
1448*cdf0e10cSrcweir             const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1449*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Green),
1450*cdf0e10cSrcweir                                    toByteColor(rgbColor[i].Blue));
1451*cdf0e10cSrcweir             const BitmapColor aCol2 =
1452*cdf0e10cSrcweir                 m_bPalette ?
1453*cdf0e10cSrcweir                 BitmapColor(
1454*cdf0e10cSrcweir                     sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1455*cdf0e10cSrcweir                 aCol;
1456*cdf0e10cSrcweir 
1457*cdf0e10cSrcweir             m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1458*cdf0e10cSrcweir         }
1459*cdf0e10cSrcweir     }
1460*cdf0e10cSrcweir 
1461*cdf0e10cSrcweir     return aRes;
1462*cdf0e10cSrcweir }
1463*cdf0e10cSrcweir 
1464*cdf0e10cSrcweir BitmapEx VclCanvasBitmap::getBitmapEx() const
1465*cdf0e10cSrcweir {
1466*cdf0e10cSrcweir     return m_aBmpEx;
1467*cdf0e10cSrcweir }
1468