xref: /aoo41x/main/vcl/source/helper/canvastools.cxx (revision 87bc88d3)
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 <rtl/logfile.hxx>
28cdf0e10cSrcweir #include <cppuhelper/compbase1.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <com/sun/star/geometry/RealSize2D.hpp>
31cdf0e10cSrcweir #include <com/sun/star/geometry/RealPoint2D.hpp>
32cdf0e10cSrcweir #include <com/sun/star/geometry/RealRectangle2D.hpp>
33cdf0e10cSrcweir #include <com/sun/star/geometry/IntegerSize2D.hpp>
34cdf0e10cSrcweir #include <com/sun/star/geometry/IntegerPoint2D.hpp>
35cdf0e10cSrcweir #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
36cdf0e10cSrcweir #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <com/sun/star/rendering/ColorSpaceType.hpp>
39cdf0e10cSrcweir #include <com/sun/star/rendering/RenderingIntent.hpp>
40cdf0e10cSrcweir #include <com/sun/star/rendering/XGraphicDevice.hpp>
41cdf0e10cSrcweir #include <com/sun/star/rendering/XBitmap.hpp>
42cdf0e10cSrcweir #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
43cdf0e10cSrcweir #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
44cdf0e10cSrcweir #include <com/sun/star/rendering/XIntegerBitmap.hpp>
45cdf0e10cSrcweir #include <com/sun/star/rendering/ColorComponentTag.hpp>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
48cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx>
49cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
50cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
51cdf0e10cSrcweir #include <basegfx/vector/b2isize.hxx>
52cdf0e10cSrcweir #include <basegfx/point/b2ipoint.hxx>
53cdf0e10cSrcweir #include <basegfx/range/b2irectangle.hxx>
54cdf0e10cSrcweir 
55cdf0e10cSrcweir // #i79917#
56cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
57cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
58cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
59cdf0e10cSrcweir 
60cdf0e10cSrcweir #include <tools/poly.hxx>
61cdf0e10cSrcweir #include <tools/diagnose_ex.h>
62cdf0e10cSrcweir #include <rtl/uuid.h>
63cdf0e10cSrcweir 
64cdf0e10cSrcweir #include <vcl/salbtype.hxx>
65cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
66cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
67cdf0e10cSrcweir 
68cdf0e10cSrcweir #include <canvasbitmap.hxx>
69cdf0e10cSrcweir #include <vcl/canvastools.hxx>
70cdf0e10cSrcweir #include <hash_map>
71cdf0e10cSrcweir 
72cdf0e10cSrcweir 
73cdf0e10cSrcweir using namespace ::com::sun::star;
74cdf0e10cSrcweir 
75cdf0e10cSrcweir namespace vcl
76cdf0e10cSrcweir {
77cdf0e10cSrcweir     namespace unotools
78cdf0e10cSrcweir     {
79cdf0e10cSrcweir         // #i79917# removed helpers bezierSequenceFromPolygon and
80cdf0e10cSrcweir 		// pointSequenceFromPolygon here
81cdf0e10cSrcweir 		// Also all helpers using tools Polygon and PolyPolygon will get mapped to the
82cdf0e10cSrcweir 		// B2DPolygon helpers for these cases, see comments with the same TaskID below.
83cdf0e10cSrcweir 		// TODO: Remove those wrapped methods
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
86cdf0e10cSrcweir 
xPolyPolygonFromPolygon(const uno::Reference<rendering::XGraphicDevice> & xGraphicDevice,const::Polygon & inputPolygon)87cdf0e10cSrcweir         uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& 	xGraphicDevice,
88cdf0e10cSrcweir                                                                              const ::Polygon&										inputPolygon )
89cdf0e10cSrcweir         {
90cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" );
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 			// #i79917# map to basegfx
93cdf0e10cSrcweir 			const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon());
94cdf0e10cSrcweir 			return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon);
95cdf0e10cSrcweir         }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
98cdf0e10cSrcweir 
xPolyPolygonFromPolyPolygon(const uno::Reference<rendering::XGraphicDevice> & xGraphicDevice,const::PolyPolygon & inputPolyPolygon)99cdf0e10cSrcweir         uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
100cdf0e10cSrcweir                                                                                  const ::PolyPolygon&								inputPolyPolygon )
101cdf0e10cSrcweir         {
102cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" );
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 			// #i79917# map to basegfx
105cdf0e10cSrcweir 			const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon());
106cdf0e10cSrcweir 	        return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon);
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir 
109cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
110cdf0e10cSrcweir 
polygonFromPoint2DSequence(const uno::Sequence<geometry::RealPoint2D> & points)111cdf0e10cSrcweir         ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points )
112cdf0e10cSrcweir         {
113cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" );
114cdf0e10cSrcweir 
115cdf0e10cSrcweir             const sal_uInt16 nCurrSize( sal::static_int_cast<sal_uInt16>(points.getLength()) );
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             ::Polygon aPoly( nCurrSize );
118cdf0e10cSrcweir 
119cdf0e10cSrcweir             sal_uInt16 nCurrPoint;
120cdf0e10cSrcweir             for( nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint )
121cdf0e10cSrcweir                 aPoly[nCurrPoint] = pointFromRealPoint2D( points[nCurrPoint] );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir             return aPoly;
124cdf0e10cSrcweir         }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
127cdf0e10cSrcweir 
polyPolygonFromPoint2DSequenceSequence(const uno::Sequence<uno::Sequence<geometry::RealPoint2D>> & points)128cdf0e10cSrcweir         ::PolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
129cdf0e10cSrcweir         {
130cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir             ::PolyPolygon aRes;
133cdf0e10cSrcweir 
134cdf0e10cSrcweir             int nCurrPoly;
135cdf0e10cSrcweir             for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
136cdf0e10cSrcweir             {
137cdf0e10cSrcweir                 aRes.Insert( polygonFromPoint2DSequence( points[nCurrPoly] ) );
138cdf0e10cSrcweir             }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir             return aRes;
141cdf0e10cSrcweir         }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
144cdf0e10cSrcweir 
polygonFromBezier2DSequence(const uno::Sequence<geometry::RealBezierSegment2D> & curves)145cdf0e10cSrcweir         ::Polygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves )
146cdf0e10cSrcweir         {
147cdf0e10cSrcweir 			// #i79917# map to basegfx
148cdf0e10cSrcweir 			const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves));
149cdf0e10cSrcweir 			return ::Polygon(aB2DPolygon);
150cdf0e10cSrcweir         }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
153cdf0e10cSrcweir 
polyPolygonFromBezier2DSequenceSequence(const uno::Sequence<uno::Sequence<geometry::RealBezierSegment2D>> & curves)154cdf0e10cSrcweir         ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves )
155cdf0e10cSrcweir         {
156cdf0e10cSrcweir 			// #i79917# map to basegfx
157cdf0e10cSrcweir 	        const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves));
158cdf0e10cSrcweir 			return ::PolyPolygon(aB2DPolyPolygon);
159cdf0e10cSrcweir         }
160cdf0e10cSrcweir 
161cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
162cdf0e10cSrcweir 
xBitmapFromBitmap(const uno::Reference<rendering::XGraphicDevice> &,const::Bitmap & inputBitmap)163cdf0e10cSrcweir         uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& 	/*xGraphicDevice*/,
164cdf0e10cSrcweir                                                                 const ::Bitmap&										inputBitmap )
165cdf0e10cSrcweir         {
166cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" );
167cdf0e10cSrcweir 
168cdf0e10cSrcweir             return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) );
169cdf0e10cSrcweir         }
170cdf0e10cSrcweir 
171cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
172cdf0e10cSrcweir 
xBitmapFromBitmapEx(const uno::Reference<rendering::XGraphicDevice> &,const::BitmapEx & inputBitmap)173cdf0e10cSrcweir         uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& 	/*xGraphicDevice*/,
174cdf0e10cSrcweir                                                                   const ::BitmapEx&										inputBitmap )
175cdf0e10cSrcweir         {
176cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" );
177cdf0e10cSrcweir 
178cdf0e10cSrcweir             return new vcl::unotools::VclCanvasBitmap( inputBitmap );
179cdf0e10cSrcweir         }
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
182cdf0e10cSrcweir 
getTunnelIdentifier(TunnelIdentifierType eType)183cdf0e10cSrcweir         const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType )
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir             static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds;
186cdf0e10cSrcweir             std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it =
187cdf0e10cSrcweir                 aIds.find( eType );
188cdf0e10cSrcweir             if( it == aIds.end() )
189cdf0e10cSrcweir             {
190cdf0e10cSrcweir                 uno::Sequence< sal_Int8 > aNewId( 16 );
191cdf0e10cSrcweir                 rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True );
192cdf0e10cSrcweir                 aIds[ eType ] = aNewId;
193cdf0e10cSrcweir                 it = aIds.find( eType );
194cdf0e10cSrcweir             }
195cdf0e10cSrcweir             return it->second;
196cdf0e10cSrcweir         }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         namespace
201cdf0e10cSrcweir         {
operator ==(const rendering::IntegerBitmapLayout & rLHS,const rendering::IntegerBitmapLayout & rRHS)202cdf0e10cSrcweir             inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
203cdf0e10cSrcweir                                     const rendering::IntegerBitmapLayout& rRHS )
204cdf0e10cSrcweir             {
205cdf0e10cSrcweir                 return
206cdf0e10cSrcweir                     rLHS.ScanLineBytes       == rRHS.ScanLineBytes &&
207cdf0e10cSrcweir                     rLHS.ScanLineStride      == rRHS.ScanLineStride &&
208cdf0e10cSrcweir                     rLHS.PlaneStride         == rRHS.PlaneStride &&
209cdf0e10cSrcweir                     rLHS.ColorSpace          == rRHS.ColorSpace &&
210cdf0e10cSrcweir                     rLHS.Palette             == rRHS.Palette &&
211cdf0e10cSrcweir                     rLHS.IsMsbFirst          == rRHS.IsMsbFirst;
212cdf0e10cSrcweir             }
213cdf0e10cSrcweir 
readBmp(sal_Int32 nWidth,sal_Int32 nHeight,const rendering::IntegerBitmapLayout & rLayout,const uno::Reference<rendering::XIntegerReadOnlyBitmap> & xInputBitmap,ScopedBitmapWriteAccess & rWriteAcc,ScopedBitmapWriteAccess & rAlphaAcc)214cdf0e10cSrcweir             bool readBmp( sal_Int32                                                  nWidth,
215cdf0e10cSrcweir                           sal_Int32                                                  nHeight,
216cdf0e10cSrcweir                           const rendering::IntegerBitmapLayout&                      rLayout,
217cdf0e10cSrcweir                           const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
218cdf0e10cSrcweir                           ScopedBitmapWriteAccess&                                   rWriteAcc,
219cdf0e10cSrcweir                           ScopedBitmapWriteAccess&                                   rAlphaAcc )
220cdf0e10cSrcweir             {
221cdf0e10cSrcweir                 rendering::IntegerBitmapLayout      aCurrLayout;
222cdf0e10cSrcweir                 geometry::IntegerRectangle2D        aRect;
223cdf0e10cSrcweir                 uno::Sequence<sal_Int8>             aPixelData;
224cdf0e10cSrcweir                 uno::Sequence<rendering::RGBColor>  aRGBColors;
225cdf0e10cSrcweir                 uno::Sequence<rendering::ARGBColor> aARGBColors;
226cdf0e10cSrcweir 
227cdf0e10cSrcweir                 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
228cdf0e10cSrcweir                 {
229cdf0e10cSrcweir                     aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
230cdf0e10cSrcweir                     try
231cdf0e10cSrcweir                     {
232cdf0e10cSrcweir                         aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
233cdf0e10cSrcweir                     }
234cdf0e10cSrcweir                     catch( rendering::VolatileContentDestroyedException& )
235cdf0e10cSrcweir                     {
236cdf0e10cSrcweir                         // re-read bmp from the start
237cdf0e10cSrcweir                         return false;
238cdf0e10cSrcweir                     }
239cdf0e10cSrcweir                     if( !(aCurrLayout == rLayout) )
240cdf0e10cSrcweir                         return false; // re-read bmp from the start
241cdf0e10cSrcweir 
242cdf0e10cSrcweir                     if( rAlphaAcc.get() )
243cdf0e10cSrcweir                     {
244cdf0e10cSrcweir                         // read ARGB color
245cdf0e10cSrcweir                         aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
246cdf0e10cSrcweir 
247cdf0e10cSrcweir                         if( rWriteAcc->HasPalette() )
248cdf0e10cSrcweir                         {
249cdf0e10cSrcweir                             for( sal_Int32 x=0; x<nWidth; ++x )
250cdf0e10cSrcweir                             {
251cdf0e10cSrcweir                                 const rendering::ARGBColor& rColor=aARGBColors[x];
252*87bc88d3SHerbert Dürr                                 rWriteAcc->SetPixelIndex( aRect.Y1, x,
253*87bc88d3SHerbert Dürr                                                      (sal_uInt8) rWriteAcc->GetBestPaletteIndex(
254cdf0e10cSrcweir                                                          BitmapColor( toByteColor(rColor.Red),
255cdf0e10cSrcweir                                                                       toByteColor(rColor.Green),
256cdf0e10cSrcweir                                                                       toByteColor(rColor.Blue))) );
257cdf0e10cSrcweir                                 rAlphaAcc->SetPixel( aRect.Y1, x,
258cdf0e10cSrcweir                                                      BitmapColor( 255 - toByteColor(rColor.Alpha) ));
259cdf0e10cSrcweir                             }
260cdf0e10cSrcweir                         }
261cdf0e10cSrcweir                         else
262cdf0e10cSrcweir                         {
263cdf0e10cSrcweir                             for( sal_Int32 x=0; x<nWidth; ++x )
264cdf0e10cSrcweir                             {
265cdf0e10cSrcweir                                 const rendering::ARGBColor& rColor=aARGBColors[x];
266cdf0e10cSrcweir                                 rWriteAcc->SetPixel( aRect.Y1, x,
267cdf0e10cSrcweir                                                      BitmapColor( toByteColor(rColor.Red),
268cdf0e10cSrcweir                                                                   toByteColor(rColor.Green),
269cdf0e10cSrcweir                                                                   toByteColor(rColor.Blue) ));
270cdf0e10cSrcweir                                 rAlphaAcc->SetPixel( aRect.Y1, x,
271cdf0e10cSrcweir                                                      BitmapColor( 255 - toByteColor(rColor.Alpha) ));
272cdf0e10cSrcweir                             }
273cdf0e10cSrcweir                         }
274cdf0e10cSrcweir                     }
275cdf0e10cSrcweir                     else
276cdf0e10cSrcweir                     {
277cdf0e10cSrcweir                         // read RGB color
278cdf0e10cSrcweir                         aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
279cdf0e10cSrcweir                         if( rWriteAcc->HasPalette() )
280cdf0e10cSrcweir                         {
281cdf0e10cSrcweir                             for( sal_Int32 x=0; x<nWidth; ++x )
282cdf0e10cSrcweir                             {
283cdf0e10cSrcweir                                 const rendering::RGBColor& rColor=aRGBColors[x];
284*87bc88d3SHerbert Dürr                                 rWriteAcc->SetPixelIndex( aRect.Y1, x,
285*87bc88d3SHerbert Dürr                                                      (sal_uInt8) rWriteAcc->GetBestPaletteIndex(
286cdf0e10cSrcweir                                                          BitmapColor( toByteColor(rColor.Red),
287cdf0e10cSrcweir                                                                       toByteColor(rColor.Green),
288cdf0e10cSrcweir                                                                       toByteColor(rColor.Blue))) );
289cdf0e10cSrcweir                             }
290cdf0e10cSrcweir                         }
291cdf0e10cSrcweir                         else
292cdf0e10cSrcweir                         {
293cdf0e10cSrcweir                             for( sal_Int32 x=0; x<nWidth; ++x )
294cdf0e10cSrcweir                             {
295cdf0e10cSrcweir                                 const rendering::RGBColor& rColor=aRGBColors[x];
296cdf0e10cSrcweir                                 rWriteAcc->SetPixel( aRect.Y1, x,
297cdf0e10cSrcweir                                                      BitmapColor( toByteColor(rColor.Red),
298cdf0e10cSrcweir                                                                   toByteColor(rColor.Green),
299cdf0e10cSrcweir                                                                   toByteColor(rColor.Blue) ));
300cdf0e10cSrcweir                             }
301cdf0e10cSrcweir                         }
302cdf0e10cSrcweir                     }
303cdf0e10cSrcweir                 }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir                 return true;
306cdf0e10cSrcweir             }
307cdf0e10cSrcweir         }
308cdf0e10cSrcweir 
bitmapExFromXBitmap(const uno::Reference<rendering::XIntegerReadOnlyBitmap> & xInputBitmap)309cdf0e10cSrcweir         ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
310cdf0e10cSrcweir         {
311cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
312cdf0e10cSrcweir 
313cdf0e10cSrcweir             if( !xInputBitmap.is() )
314cdf0e10cSrcweir                 return ::BitmapEx();
315cdf0e10cSrcweir 
316cdf0e10cSrcweir             // tunnel directly for known implementation
317cdf0e10cSrcweir             // ----------------------------------------------------------------
318cdf0e10cSrcweir             VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
319cdf0e10cSrcweir             if( pImplBitmap )
320cdf0e10cSrcweir                 return pImplBitmap->getBitmapEx();
321cdf0e10cSrcweir 
322cdf0e10cSrcweir             // retrieve data via UNO interface
323cdf0e10cSrcweir             // ----------------------------------------------------------------
324cdf0e10cSrcweir 
325cdf0e10cSrcweir             // volatile bitmaps are a bit more complicated to read
326cdf0e10cSrcweir             // from..
327cdf0e10cSrcweir             uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
328cdf0e10cSrcweir                 xInputBitmap, uno::UNO_QUERY);
329cdf0e10cSrcweir 
330cdf0e10cSrcweir             // loop a few times, until successfully read (for XVolatileBitmap)
331cdf0e10cSrcweir             for( int i=0; i<10; ++i )
332cdf0e10cSrcweir             {
333cdf0e10cSrcweir                 sal_Int32 nDepth=0;
334cdf0e10cSrcweir                 sal_Int32 nAlphaDepth=0;
335cdf0e10cSrcweir                 const rendering::IntegerBitmapLayout aLayout(
336cdf0e10cSrcweir                     xInputBitmap->getMemoryLayout());
337cdf0e10cSrcweir 
338cdf0e10cSrcweir                 OSL_ENSURE(aLayout.ColorSpace.is(),
339cdf0e10cSrcweir                            "Cannot convert image without color space!");
340cdf0e10cSrcweir                 if( !aLayout.ColorSpace.is() )
341cdf0e10cSrcweir                     return ::BitmapEx();
342cdf0e10cSrcweir 
343cdf0e10cSrcweir                 nDepth = aLayout.ColorSpace->getBitsPerPixel();
344cdf0e10cSrcweir 
345cdf0e10cSrcweir                 if( xInputBitmap->hasAlpha() )
346cdf0e10cSrcweir                 {
347cdf0e10cSrcweir                     // determine alpha channel depth
348cdf0e10cSrcweir                     const uno::Sequence<sal_Int8> aTags(
349cdf0e10cSrcweir                         aLayout.ColorSpace->getComponentTags() );
350cdf0e10cSrcweir                     const uno::Sequence<sal_Int32> aDepths(
351cdf0e10cSrcweir                         aLayout.ColorSpace->getComponentBitCounts() );
352cdf0e10cSrcweir                     const sal_Int8* pStart(aTags.getConstArray());
353cdf0e10cSrcweir                     const sal_Size  nLen(aTags.getLength());
354cdf0e10cSrcweir                     const sal_Int8* pEnd(pStart+nLen);
355cdf0e10cSrcweir 
356cdf0e10cSrcweir                     const std::ptrdiff_t nAlphaIndex =
357cdf0e10cSrcweir                         std::find(pStart,pEnd,
358cdf0e10cSrcweir                                   rendering::ColorComponentTag::ALPHA) - pStart;
359cdf0e10cSrcweir 
360cdf0e10cSrcweir                     if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
361cdf0e10cSrcweir                     {
362cdf0e10cSrcweir                         nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
363cdf0e10cSrcweir                         nDepth -= nAlphaDepth;
364cdf0e10cSrcweir                     }
365cdf0e10cSrcweir                 }
366cdf0e10cSrcweir 
367cdf0e10cSrcweir                 BitmapPalette aPalette;
368cdf0e10cSrcweir                 if( aLayout.Palette.is() )
369cdf0e10cSrcweir                 {
370cdf0e10cSrcweir                     uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
371cdf0e10cSrcweir                         aLayout.Palette->getColorSpace());
372cdf0e10cSrcweir                     ENSURE_OR_THROW(xPaletteColorSpace.is(),
373cdf0e10cSrcweir                                     "Palette without color space");
374cdf0e10cSrcweir 
375cdf0e10cSrcweir                     const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
376cdf0e10cSrcweir                     if( nEntryCount <= 256 )
377cdf0e10cSrcweir                     {
378cdf0e10cSrcweir                         if( nEntryCount <= 2 )
379cdf0e10cSrcweir                             nDepth = 1;
380cdf0e10cSrcweir                         else
381cdf0e10cSrcweir                             nDepth = 8;
382cdf0e10cSrcweir 
383cdf0e10cSrcweir                         const sal_uInt16 nPaletteEntries(
384cdf0e10cSrcweir                             sal::static_int_cast<sal_uInt16>(
385cdf0e10cSrcweir                                 std::min(sal_Int32(255), nEntryCount)));
386cdf0e10cSrcweir 
387cdf0e10cSrcweir                         // copy palette entries
388cdf0e10cSrcweir                         aPalette.SetEntryCount(nPaletteEntries);
389cdf0e10cSrcweir                         uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
390cdf0e10cSrcweir                         uno::Reference<rendering::XColorSpace>    xPalColorSpace( xPalette->getColorSpace() );
391cdf0e10cSrcweir 
392cdf0e10cSrcweir                         uno::Sequence<double> aPaletteEntry;
393cdf0e10cSrcweir                         for( sal_uInt16 j=0; j<nPaletteEntries; ++j )
394cdf0e10cSrcweir                         {
395cdf0e10cSrcweir                             if( !xPalette->getIndex(aPaletteEntry,j) &&
396cdf0e10cSrcweir                                 nAlphaDepth == 0 )
397cdf0e10cSrcweir                             {
398cdf0e10cSrcweir                                 nAlphaDepth = 1;
399cdf0e10cSrcweir                             }
400cdf0e10cSrcweir                             uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
401cdf0e10cSrcweir                             ENSURE_OR_THROW(aColors.getLength() == 1,
402cdf0e10cSrcweir                                             "Palette returned more or less than one entry");
403cdf0e10cSrcweir                             const rendering::RGBColor& rColor=aColors[0];
404cdf0e10cSrcweir                             aPalette[j] = BitmapColor(toByteColor(rColor.Red),
405cdf0e10cSrcweir                                                       toByteColor(rColor.Green),
406cdf0e10cSrcweir                                                       toByteColor(rColor.Blue));
407cdf0e10cSrcweir                         }
408cdf0e10cSrcweir                     }
409cdf0e10cSrcweir                 }
410cdf0e10cSrcweir 
411cdf0e10cSrcweir                 const ::Size aPixelSize(
412cdf0e10cSrcweir                     sizeFromIntegerSize2D(xInputBitmap->getSize()));
413cdf0e10cSrcweir 
414cdf0e10cSrcweir                 // normalize bitcount
415cdf0e10cSrcweir                 nDepth =
416cdf0e10cSrcweir                     ( nDepth <= 1 ) ? 1 :
417cdf0e10cSrcweir                     ( nDepth <= 4 ) ? 4 :
418cdf0e10cSrcweir                     ( nDepth <= 8 ) ? 8 : 24;
419cdf0e10cSrcweir 
420cdf0e10cSrcweir                 ::Bitmap aBitmap( aPixelSize,
421cdf0e10cSrcweir                                   sal::static_int_cast<sal_uInt16>(nDepth),
422cdf0e10cSrcweir                                   aLayout.Palette.is() ? &aPalette : NULL );
423cdf0e10cSrcweir                 ::Bitmap aAlpha;
424cdf0e10cSrcweir                 if( nAlphaDepth )
425cdf0e10cSrcweir                     aAlpha = ::Bitmap( aPixelSize,
426cdf0e10cSrcweir                                        sal::static_int_cast<sal_uInt16>(nAlphaDepth),
427cdf0e10cSrcweir                                        &::Bitmap::GetGreyPalette(
428cdf0e10cSrcweir                                            sal::static_int_cast<sal_uInt16>(1L << nAlphaDepth)) );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir                 { // limit scoped access
431cdf0e10cSrcweir                     ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
432cdf0e10cSrcweir                                                           aBitmap );
433cdf0e10cSrcweir                     ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL,
434cdf0e10cSrcweir                                                                aAlpha );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir                     ENSURE_OR_THROW(pWriteAccess.get() != NULL,
437cdf0e10cSrcweir                                     "Cannot get write access to bitmap");
438cdf0e10cSrcweir 
439cdf0e10cSrcweir                     const sal_Int32 nWidth(aPixelSize.Width());
440cdf0e10cSrcweir                     const sal_Int32 nHeight(aPixelSize.Height());
441cdf0e10cSrcweir 
442cdf0e10cSrcweir                     if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
443cdf0e10cSrcweir                                  pWriteAccess,pAlphaWriteAccess) )
444cdf0e10cSrcweir                         continue;
445cdf0e10cSrcweir                 } // limit scoped access
446cdf0e10cSrcweir 
447cdf0e10cSrcweir                 if( nAlphaDepth )
448cdf0e10cSrcweir                     return ::BitmapEx( aBitmap,
449cdf0e10cSrcweir                                        AlphaMask( aAlpha ) );
450cdf0e10cSrcweir                 else
451cdf0e10cSrcweir                     return ::BitmapEx( aBitmap );
452cdf0e10cSrcweir             }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir             // failed to read data 10 times - bail out
455cdf0e10cSrcweir             return ::BitmapEx();
456cdf0e10cSrcweir         }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
459cdf0e10cSrcweir 
size2DFromSize(const Size & rSize)460cdf0e10cSrcweir         geometry::RealSize2D size2DFromSize( const Size& rSize )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir             return geometry::RealSize2D( rSize.Width(),
463cdf0e10cSrcweir                                          rSize.Height() );
464cdf0e10cSrcweir         }
465cdf0e10cSrcweir 
point2DFromPoint(const Point & rPoint)466cdf0e10cSrcweir         geometry::RealPoint2D point2DFromPoint( const Point& rPoint )
467cdf0e10cSrcweir         {
468cdf0e10cSrcweir             return geometry::RealPoint2D( rPoint.X(),
469cdf0e10cSrcweir                                           rPoint.Y() );
470cdf0e10cSrcweir         }
471cdf0e10cSrcweir 
rectangle2DFromRectangle(const Rectangle & rRect)472cdf0e10cSrcweir         geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect )
473cdf0e10cSrcweir         {
474cdf0e10cSrcweir             return geometry::RealRectangle2D( rRect.Left(), rRect.Top(),
475cdf0e10cSrcweir                                               rRect.Right(), rRect.Bottom() );
476cdf0e10cSrcweir         }
477cdf0e10cSrcweir 
sizeFromRealSize2D(const geometry::RealSize2D & rSize)478cdf0e10cSrcweir         Size sizeFromRealSize2D( const geometry::RealSize2D& rSize )
479cdf0e10cSrcweir         {
480cdf0e10cSrcweir             return Size( static_cast<long>(rSize.Width + .5),
481cdf0e10cSrcweir                          static_cast<long>(rSize.Height + .5) );
482cdf0e10cSrcweir         }
483cdf0e10cSrcweir 
pointFromRealPoint2D(const geometry::RealPoint2D & rPoint)484cdf0e10cSrcweir         Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint )
485cdf0e10cSrcweir         {
486cdf0e10cSrcweir             return Point( static_cast<long>(rPoint.X + .5),
487cdf0e10cSrcweir                           static_cast<long>(rPoint.Y + .5) );
488cdf0e10cSrcweir         }
489cdf0e10cSrcweir 
rectangleFromRealRectangle2D(const geometry::RealRectangle2D & rRect)490cdf0e10cSrcweir         Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect )
491cdf0e10cSrcweir         {
492cdf0e10cSrcweir             return Rectangle( static_cast<long>(rRect.X1 + .5),
493cdf0e10cSrcweir                               static_cast<long>(rRect.Y1 + .5),
494cdf0e10cSrcweir                               static_cast<long>(rRect.X2 + .5),
495cdf0e10cSrcweir                               static_cast<long>(rRect.Y2 + .5) );
496cdf0e10cSrcweir         }
497cdf0e10cSrcweir 
sizeFromB2DSize(const::basegfx::B2DVector & rVec)498cdf0e10cSrcweir         ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec )
499cdf0e10cSrcweir         {
500cdf0e10cSrcweir             return ::Size( FRound( rVec.getX() ),
501cdf0e10cSrcweir                            FRound( rVec.getY() ) );
502cdf0e10cSrcweir         }
503cdf0e10cSrcweir 
pointFromB2DPoint(const::basegfx::B2DPoint & rPoint)504cdf0e10cSrcweir         ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
505cdf0e10cSrcweir         {
506cdf0e10cSrcweir             return ::Point( FRound( rPoint.getX() ),
507cdf0e10cSrcweir                             FRound( rPoint.getY() ) );
508cdf0e10cSrcweir         }
509cdf0e10cSrcweir 
rectangleFromB2DRectangle(const::basegfx::B2DRange & rRect)510cdf0e10cSrcweir         ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect )
511cdf0e10cSrcweir         {
512cdf0e10cSrcweir             return ::Rectangle( FRound( rRect.getMinX() ),
513cdf0e10cSrcweir                                 FRound( rRect.getMinY() ),
514cdf0e10cSrcweir                                 FRound( rRect.getMaxX() ),
515cdf0e10cSrcweir                                 FRound( rRect.getMaxY() ) );
516cdf0e10cSrcweir         }
517cdf0e10cSrcweir 
sizeFromB2ISize(const::basegfx::B2IVector & rVec)518cdf0e10cSrcweir         Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec )
519cdf0e10cSrcweir         {
520cdf0e10cSrcweir             return ::Size( rVec.getX(),
521cdf0e10cSrcweir                            rVec.getY() );
522cdf0e10cSrcweir         }
523cdf0e10cSrcweir 
pointFromB2IPoint(const::basegfx::B2IPoint & rPoint)524cdf0e10cSrcweir         Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint )
525cdf0e10cSrcweir         {
526cdf0e10cSrcweir             return ::Point( rPoint.getX(),
527cdf0e10cSrcweir                             rPoint.getY() );
528cdf0e10cSrcweir         }
529cdf0e10cSrcweir 
rectangleFromB2IRectangle(const::basegfx::B2IRange & rRect)530cdf0e10cSrcweir         Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect )
531cdf0e10cSrcweir         {
532cdf0e10cSrcweir             return ::Rectangle( rRect.getMinX(),
533cdf0e10cSrcweir                                 rRect.getMinY(),
534cdf0e10cSrcweir                                 rRect.getMaxX(),
535cdf0e10cSrcweir                                 rRect.getMaxY() );
536cdf0e10cSrcweir         }
537cdf0e10cSrcweir 
b2DSizeFromSize(const::Size & rSize)538cdf0e10cSrcweir         ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize )
539cdf0e10cSrcweir         {
540cdf0e10cSrcweir             return ::basegfx::B2DVector( rSize.Width(),
541cdf0e10cSrcweir                                          rSize.Height() );
542cdf0e10cSrcweir         }
543cdf0e10cSrcweir 
b2DPointFromPoint(const::Point & rPoint)544cdf0e10cSrcweir         ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint )
545cdf0e10cSrcweir         {
546cdf0e10cSrcweir             return ::basegfx::B2DPoint( rPoint.X(),
547cdf0e10cSrcweir                                         rPoint.Y() );
548cdf0e10cSrcweir         }
549cdf0e10cSrcweir 
b2DRectangleFromRectangle(const::Rectangle & rRect)550cdf0e10cSrcweir         ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect )
551cdf0e10cSrcweir         {
552cdf0e10cSrcweir             return ::basegfx::B2DRange( rRect.Left(),
553cdf0e10cSrcweir                                         rRect.Top(),
554cdf0e10cSrcweir                                         rRect.Right(),
555cdf0e10cSrcweir                                         rRect.Bottom() );
556cdf0e10cSrcweir         }
557cdf0e10cSrcweir 
b2ISizeFromSize(const Size & rSize)558cdf0e10cSrcweir         basegfx::B2IVector b2ISizeFromSize( const Size& rSize )
559cdf0e10cSrcweir         {
560cdf0e10cSrcweir             return ::basegfx::B2IVector( rSize.Width(),
561cdf0e10cSrcweir                                          rSize.Height() );
562cdf0e10cSrcweir         }
563cdf0e10cSrcweir 
b2IPointFromPoint(const Point & rPoint)564cdf0e10cSrcweir         basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint )
565cdf0e10cSrcweir         {
566cdf0e10cSrcweir             return ::basegfx::B2IPoint( rPoint.X(),
567cdf0e10cSrcweir                                         rPoint.Y() );
568cdf0e10cSrcweir         }
569cdf0e10cSrcweir 
b2IRectangleFromRectangle(const Rectangle & rRect)570cdf0e10cSrcweir         basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect )
571cdf0e10cSrcweir         {
572cdf0e10cSrcweir             return ::basegfx::B2IRange( rRect.Left(),
573cdf0e10cSrcweir                                         rRect.Top(),
574cdf0e10cSrcweir                                         rRect.Right(),
575cdf0e10cSrcweir                                         rRect.Bottom() );
576cdf0e10cSrcweir         }
577cdf0e10cSrcweir 
integerSize2DFromSize(const Size & rSize)578cdf0e10cSrcweir         geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize )
579cdf0e10cSrcweir         {
580cdf0e10cSrcweir             return geometry::IntegerSize2D( rSize.Width(),
581cdf0e10cSrcweir                                             rSize.Height() );
582cdf0e10cSrcweir         }
583cdf0e10cSrcweir 
integerPoint2DFromPoint(const Point & rPoint)584cdf0e10cSrcweir         geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint )
585cdf0e10cSrcweir         {
586cdf0e10cSrcweir             return geometry::IntegerPoint2D( rPoint.X(),
587cdf0e10cSrcweir                                              rPoint.Y() );
588cdf0e10cSrcweir         }
589cdf0e10cSrcweir 
integerRectangle2DFromRectangle(const Rectangle & rRectangle)590cdf0e10cSrcweir         geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle )
591cdf0e10cSrcweir         {
592cdf0e10cSrcweir             return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(),
593cdf0e10cSrcweir                                                  rRectangle.Right(), rRectangle.Bottom() );
594cdf0e10cSrcweir         }
595cdf0e10cSrcweir 
sizeFromIntegerSize2D(const geometry::IntegerSize2D & rSize)596cdf0e10cSrcweir         Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
597cdf0e10cSrcweir         {
598cdf0e10cSrcweir             return Size( rSize.Width,
599cdf0e10cSrcweir                          rSize.Height );
600cdf0e10cSrcweir         }
601cdf0e10cSrcweir 
pointFromIntegerPoint2D(const geometry::IntegerPoint2D & rPoint)602cdf0e10cSrcweir         Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint )
603cdf0e10cSrcweir         {
604cdf0e10cSrcweir             return Point( rPoint.X,
605cdf0e10cSrcweir                           rPoint.Y );
606cdf0e10cSrcweir         }
607cdf0e10cSrcweir 
rectangleFromIntegerRectangle2D(const geometry::IntegerRectangle2D & rRectangle)608cdf0e10cSrcweir         Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
609cdf0e10cSrcweir         {
610cdf0e10cSrcweir             return Rectangle( rRectangle.X1, rRectangle.Y1,
611cdf0e10cSrcweir                               rRectangle.X2, rRectangle.Y2 );
612cdf0e10cSrcweir         }
613cdf0e10cSrcweir 
614cdf0e10cSrcweir         namespace
615cdf0e10cSrcweir         {
616cdf0e10cSrcweir             class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
617cdf0e10cSrcweir             {
618cdf0e10cSrcweir             private:
619cdf0e10cSrcweir                 uno::Sequence< sal_Int8 > m_aComponentTags;
620cdf0e10cSrcweir 
getType()621cdf0e10cSrcweir                 virtual ::sal_Int8 SAL_CALL getType(  ) throw (uno::RuntimeException)
622cdf0e10cSrcweir                 {
623cdf0e10cSrcweir                     return rendering::ColorSpaceType::RGB;
624cdf0e10cSrcweir                 }
getComponentTags()625cdf0e10cSrcweir                 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags(  ) throw (uno::RuntimeException)
626cdf0e10cSrcweir                 {
627cdf0e10cSrcweir                     return m_aComponentTags;
628cdf0e10cSrcweir                 }
getRenderingIntent()629cdf0e10cSrcweir                 virtual ::sal_Int8 SAL_CALL getRenderingIntent(  ) throw (uno::RuntimeException)
630cdf0e10cSrcweir                 {
631cdf0e10cSrcweir                     return rendering::RenderingIntent::PERCEPTUAL;
632cdf0e10cSrcweir                 }
getProperties()633cdf0e10cSrcweir                 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties(  ) throw (uno::RuntimeException)
634cdf0e10cSrcweir                 {
635cdf0e10cSrcweir                     return uno::Sequence< beans::PropertyValue >();
636cdf0e10cSrcweir                 }
convertColorSpace(const uno::Sequence<double> & deviceColor,const uno::Reference<rendering::XColorSpace> & targetColorSpace)637cdf0e10cSrcweir                 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
638cdf0e10cSrcweir                                                                             const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
639cdf0e10cSrcweir                                                                                                                                                       uno::RuntimeException)
640cdf0e10cSrcweir                 {
641cdf0e10cSrcweir                     // TODO(P3): if we know anything about target
642cdf0e10cSrcweir                     // colorspace, this can be greatly sped up
643cdf0e10cSrcweir                     uno::Sequence<rendering::ARGBColor> aIntermediate(
644cdf0e10cSrcweir                         convertToARGB(deviceColor));
645cdf0e10cSrcweir                     return targetColorSpace->convertFromARGB(aIntermediate);
646cdf0e10cSrcweir                 }
convertToRGB(const uno::Sequence<double> & deviceColor)647cdf0e10cSrcweir                 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
648cdf0e10cSrcweir                 {
649cdf0e10cSrcweir                     const double*  pIn( deviceColor.getConstArray() );
650cdf0e10cSrcweir                     const sal_Size nLen( deviceColor.getLength() );
651cdf0e10cSrcweir                     ENSURE_ARG_OR_THROW2(nLen%4==0,
652cdf0e10cSrcweir                                          "number of channels no multiple of 4",
653cdf0e10cSrcweir                                          static_cast<rendering::XColorSpace*>(this), 0);
654cdf0e10cSrcweir 
655cdf0e10cSrcweir                     uno::Sequence< rendering::RGBColor > aRes(nLen/4);
656cdf0e10cSrcweir                     rendering::RGBColor* pOut( aRes.getArray() );
657cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; i+=4 )
658cdf0e10cSrcweir                     {
659cdf0e10cSrcweir                         *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
660cdf0e10cSrcweir                         pIn += 4;
661cdf0e10cSrcweir                     }
662cdf0e10cSrcweir                     return aRes;
663cdf0e10cSrcweir                 }
convertToARGB(const uno::Sequence<double> & deviceColor)664cdf0e10cSrcweir                 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
665cdf0e10cSrcweir                 {
666cdf0e10cSrcweir                     const double*  pIn( deviceColor.getConstArray() );
667cdf0e10cSrcweir                     const sal_Size nLen( deviceColor.getLength() );
668cdf0e10cSrcweir                     ENSURE_ARG_OR_THROW2(nLen%4==0,
669cdf0e10cSrcweir                                          "number of channels no multiple of 4",
670cdf0e10cSrcweir                                          static_cast<rendering::XColorSpace*>(this), 0);
671cdf0e10cSrcweir 
672cdf0e10cSrcweir                     uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
673cdf0e10cSrcweir                     rendering::ARGBColor* pOut( aRes.getArray() );
674cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; i+=4 )
675cdf0e10cSrcweir                     {
676cdf0e10cSrcweir                         *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
677cdf0e10cSrcweir                         pIn += 4;
678cdf0e10cSrcweir                     }
679cdf0e10cSrcweir                     return aRes;
680cdf0e10cSrcweir                 }
convertToPARGB(const uno::Sequence<double> & deviceColor)681cdf0e10cSrcweir                 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
682cdf0e10cSrcweir                 {
683cdf0e10cSrcweir                     const double*  pIn( deviceColor.getConstArray() );
684cdf0e10cSrcweir                     const sal_Size nLen( deviceColor.getLength() );
685cdf0e10cSrcweir                     ENSURE_ARG_OR_THROW2(nLen%4==0,
686cdf0e10cSrcweir                                          "number of channels no multiple of 4",
687cdf0e10cSrcweir                                          static_cast<rendering::XColorSpace*>(this), 0);
688cdf0e10cSrcweir 
689cdf0e10cSrcweir                     uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
690cdf0e10cSrcweir                     rendering::ARGBColor* pOut( aRes.getArray() );
691cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; i+=4 )
692cdf0e10cSrcweir                     {
693cdf0e10cSrcweir                         *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
694cdf0e10cSrcweir                         pIn += 4;
695cdf0e10cSrcweir                     }
696cdf0e10cSrcweir                     return aRes;
697cdf0e10cSrcweir                 }
convertFromRGB(const uno::Sequence<rendering::RGBColor> & rgbColor)698cdf0e10cSrcweir                 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
699cdf0e10cSrcweir                 {
700cdf0e10cSrcweir                     const rendering::RGBColor* pIn( rgbColor.getConstArray() );
701cdf0e10cSrcweir                     const sal_Size             nLen( rgbColor.getLength() );
702cdf0e10cSrcweir 
703cdf0e10cSrcweir                     uno::Sequence< double > aRes(nLen*4);
704cdf0e10cSrcweir                     double* pColors=aRes.getArray();
705cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; ++i )
706cdf0e10cSrcweir                     {
707cdf0e10cSrcweir                         *pColors++ = pIn->Red;
708cdf0e10cSrcweir                         *pColors++ = pIn->Green;
709cdf0e10cSrcweir                         *pColors++ = pIn->Blue;
710cdf0e10cSrcweir                         *pColors++ = 1.0;
711cdf0e10cSrcweir                         ++pIn;
712cdf0e10cSrcweir                     }
713cdf0e10cSrcweir                     return aRes;
714cdf0e10cSrcweir                 }
convertFromARGB(const uno::Sequence<rendering::ARGBColor> & rgbColor)715cdf0e10cSrcweir                 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
716cdf0e10cSrcweir                 {
717cdf0e10cSrcweir                     const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
718cdf0e10cSrcweir                     const sal_Size              nLen( rgbColor.getLength() );
719cdf0e10cSrcweir 
720cdf0e10cSrcweir                     uno::Sequence< double > aRes(nLen*4);
721cdf0e10cSrcweir                     double* pColors=aRes.getArray();
722cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; ++i )
723cdf0e10cSrcweir                     {
724cdf0e10cSrcweir                         *pColors++ = pIn->Red;
725cdf0e10cSrcweir                         *pColors++ = pIn->Green;
726cdf0e10cSrcweir                         *pColors++ = pIn->Blue;
727cdf0e10cSrcweir                         *pColors++ = pIn->Alpha;
728cdf0e10cSrcweir                         ++pIn;
729cdf0e10cSrcweir                     }
730cdf0e10cSrcweir                     return aRes;
731cdf0e10cSrcweir                 }
convertFromPARGB(const uno::Sequence<rendering::ARGBColor> & rgbColor)732cdf0e10cSrcweir                 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
733cdf0e10cSrcweir                 {
734cdf0e10cSrcweir                     const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
735cdf0e10cSrcweir                     const sal_Size              nLen( rgbColor.getLength() );
736cdf0e10cSrcweir 
737cdf0e10cSrcweir                     uno::Sequence< double > aRes(nLen*4);
738cdf0e10cSrcweir                     double* pColors=aRes.getArray();
739cdf0e10cSrcweir                     for( sal_Size i=0; i<nLen; ++i )
740cdf0e10cSrcweir                     {
741cdf0e10cSrcweir                         *pColors++ = pIn->Red/pIn->Alpha;
742cdf0e10cSrcweir                         *pColors++ = pIn->Green/pIn->Alpha;
743cdf0e10cSrcweir                         *pColors++ = pIn->Blue/pIn->Alpha;
744cdf0e10cSrcweir                         *pColors++ = pIn->Alpha;
745cdf0e10cSrcweir                         ++pIn;
746cdf0e10cSrcweir                     }
747cdf0e10cSrcweir                     return aRes;
748cdf0e10cSrcweir                 }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir             public:
StandardColorSpace()751cdf0e10cSrcweir                 StandardColorSpace() : m_aComponentTags(4)
752cdf0e10cSrcweir                 {
753cdf0e10cSrcweir                     sal_Int8* pTags = m_aComponentTags.getArray();
754cdf0e10cSrcweir                     pTags[0] = rendering::ColorComponentTag::RGB_RED;
755cdf0e10cSrcweir                     pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
756cdf0e10cSrcweir                     pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
757cdf0e10cSrcweir                     pTags[3] = rendering::ColorComponentTag::ALPHA;
758cdf0e10cSrcweir                 }
759cdf0e10cSrcweir             };
760cdf0e10cSrcweir         }
761cdf0e10cSrcweir 
createStandardColorSpace()762cdf0e10cSrcweir         uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace()
763cdf0e10cSrcweir         {
764cdf0e10cSrcweir             return new StandardColorSpace();
765cdf0e10cSrcweir         }
766cdf0e10cSrcweir 
767cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
768cdf0e10cSrcweir 
colorToStdColorSpaceSequence(const Color & rColor)769cdf0e10cSrcweir         uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor )
770cdf0e10cSrcweir         {
771cdf0e10cSrcweir             uno::Sequence< double > aRet(4);
772cdf0e10cSrcweir             double* pRet = aRet.getArray();
773cdf0e10cSrcweir 
774cdf0e10cSrcweir             pRet[0] = toDoubleColor(rColor.GetRed());
775cdf0e10cSrcweir             pRet[1] = toDoubleColor(rColor.GetGreen());
776cdf0e10cSrcweir             pRet[2] = toDoubleColor(rColor.GetBlue());
777cdf0e10cSrcweir 
778cdf0e10cSrcweir             // VCL's notion of alpha is different from the rest of the world's
779cdf0e10cSrcweir             pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency());
780cdf0e10cSrcweir 
781cdf0e10cSrcweir             return aRet;
782cdf0e10cSrcweir         }
783cdf0e10cSrcweir 
stdColorSpaceSequenceToColor(const uno::Sequence<double> & rColor)784cdf0e10cSrcweir         Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor		 )
785cdf0e10cSrcweir         {
786cdf0e10cSrcweir             ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
787cdf0e10cSrcweir                                  "color must have 4 channels" );
788cdf0e10cSrcweir 
789cdf0e10cSrcweir             Color aColor;
790cdf0e10cSrcweir 
791cdf0e10cSrcweir             aColor.SetRed  ( toByteColor(rColor[0]) );
792cdf0e10cSrcweir             aColor.SetGreen( toByteColor(rColor[1]) );
793cdf0e10cSrcweir             aColor.SetBlue ( toByteColor(rColor[2]) );
794cdf0e10cSrcweir             // VCL's notion of alpha is different from the rest of the world's
795cdf0e10cSrcweir             aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
796cdf0e10cSrcweir 
797cdf0e10cSrcweir             return aColor;
798cdf0e10cSrcweir         }
799cdf0e10cSrcweir 
colorToDoubleSequence(const Color & rColor,const uno::Reference<rendering::XColorSpace> & xColorSpace)800cdf0e10cSrcweir         uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence(
801cdf0e10cSrcweir             const Color&                                    rColor,
802cdf0e10cSrcweir             const uno::Reference< rendering::XColorSpace >& xColorSpace )
803cdf0e10cSrcweir         {
804cdf0e10cSrcweir             uno::Sequence<rendering::ARGBColor> aSeq(1);
805cdf0e10cSrcweir             aSeq[0] = rendering::ARGBColor(
806cdf0e10cSrcweir                     1.0-toDoubleColor(rColor.GetTransparency()),
807cdf0e10cSrcweir                     toDoubleColor(rColor.GetRed()),
808cdf0e10cSrcweir                     toDoubleColor(rColor.GetGreen()),
809cdf0e10cSrcweir                     toDoubleColor(rColor.GetBlue()) );
810cdf0e10cSrcweir 
811cdf0e10cSrcweir             return xColorSpace->convertFromARGB(aSeq);
812cdf0e10cSrcweir         }
813cdf0e10cSrcweir 
doubleSequenceToColor(const uno::Sequence<double> rColor,const uno::Reference<rendering::XColorSpace> & xColorSpace)814cdf0e10cSrcweir         Color VCL_DLLPUBLIC doubleSequenceToColor(
815cdf0e10cSrcweir             const uno::Sequence< double >                   rColor,
816cdf0e10cSrcweir             const uno::Reference< rendering::XColorSpace >& xColorSpace )
817cdf0e10cSrcweir         {
818cdf0e10cSrcweir             const rendering::ARGBColor& rARGBColor(
819cdf0e10cSrcweir                 xColorSpace->convertToARGB(rColor)[0]);
820cdf0e10cSrcweir 
821cdf0e10cSrcweir             return Color( 255-toByteColor(rARGBColor.Alpha),
822cdf0e10cSrcweir                           toByteColor(rARGBColor.Red),
823cdf0e10cSrcweir                           toByteColor(rARGBColor.Green),
824cdf0e10cSrcweir                           toByteColor(rARGBColor.Blue) );
825cdf0e10cSrcweir         }
826cdf0e10cSrcweir 
827cdf0e10cSrcweir         //---------------------------------------------------------------------------------------
828cdf0e10cSrcweir 
829cdf0e10cSrcweir     } // namespace vcltools
830cdf0e10cSrcweir 
831cdf0e10cSrcweir } // namespace canvas
832cdf0e10cSrcweir 
833cdf0e10cSrcweir // eof
834