Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / helper / canvastools.cxx
blobf8dbf63ad84177da9979c31d58abf9f698f99827
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppuhelper/compbase1.hxx>
22 #include <com/sun/star/geometry/RealSize2D.hpp>
23 #include <com/sun/star/geometry/RealPoint2D.hpp>
24 #include <com/sun/star/geometry/RealRectangle2D.hpp>
25 #include <com/sun/star/geometry/IntegerSize2D.hpp>
26 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
27 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
28 #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
30 #include <com/sun/star/rendering/ColorSpaceType.hpp>
31 #include <com/sun/star/rendering/RenderingIntent.hpp>
32 #include <com/sun/star/rendering/XGraphicDevice.hpp>
33 #include <com/sun/star/rendering/XBitmap.hpp>
34 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
35 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
37 #include <com/sun/star/rendering/ColorComponentTag.hpp>
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <basegfx/vector/b2dsize.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/range/b2drectangle.hxx>
43 #include <basegfx/vector/b2isize.hxx>
44 #include <basegfx/point/b2ipoint.hxx>
45 #include <basegfx/range/b2irectangle.hxx>
46 #include <basegfx/polygon/b2dpolygon.hxx>
47 #include <basegfx/tools/canvastools.hxx>
48 #include <basegfx/polygon/b2dpolypolygon.hxx>
50 #include <tools/poly.hxx>
51 #include <tools/diagnose_ex.h>
52 #include <rtl/uuid.h>
54 #include <vcl/salbtype.hxx>
55 #include <vcl/bmpacc.hxx>
56 #include <vcl/bitmapex.hxx>
58 #include <canvasbitmap.hxx>
59 #include <vcl/canvastools.hxx>
61 using namespace ::com::sun::star;
63 namespace vcl
65 namespace unotools
67 uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
68 const ::BitmapEx& inputBitmap )
70 SAL_INFO( "vcl.helper", "vcl::unotools::xBitmapFromBitmapEx()" );
72 return new vcl::unotools::VclCanvasBitmap( inputBitmap );
75 namespace
77 inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
78 const rendering::IntegerBitmapLayout& rRHS )
80 return
81 rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
82 rLHS.ScanLineStride == rRHS.ScanLineStride &&
83 rLHS.PlaneStride == rRHS.PlaneStride &&
84 rLHS.ColorSpace == rRHS.ColorSpace &&
85 rLHS.Palette == rRHS.Palette &&
86 rLHS.IsMsbFirst == rRHS.IsMsbFirst;
89 bool readBmp( sal_Int32 nWidth,
90 sal_Int32 nHeight,
91 const rendering::IntegerBitmapLayout& rLayout,
92 const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
93 Bitmap::ScopedWriteAccess& rWriteAcc,
94 Bitmap::ScopedWriteAccess& rAlphaAcc )
96 rendering::IntegerBitmapLayout aCurrLayout;
97 geometry::IntegerRectangle2D aRect;
98 uno::Sequence<sal_Int8> aPixelData;
99 uno::Sequence<rendering::RGBColor> aRGBColors;
100 uno::Sequence<rendering::ARGBColor> aARGBColors;
102 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
104 aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
107 aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
109 catch( rendering::VolatileContentDestroyedException& )
111 // re-read bmp from the start
112 return false;
114 if( !(aCurrLayout == rLayout) )
115 return false; // re-read bmp from the start
117 if( rAlphaAcc.get() )
119 // read ARGB color
120 aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
122 if( rWriteAcc->HasPalette() )
124 for( sal_Int32 x=0; x<nWidth; ++x )
126 const rendering::ARGBColor& rColor=aARGBColors[x];
127 rWriteAcc->SetPixelIndex( aRect.Y1, x,
128 (sal_uInt8) rWriteAcc->GetBestPaletteIndex(
129 BitmapColor( toByteColor(rColor.Red),
130 toByteColor(rColor.Green),
131 toByteColor(rColor.Blue))) );
132 rAlphaAcc->SetPixel( aRect.Y1, x,
133 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
136 else
138 for( sal_Int32 x=0; x<nWidth; ++x )
140 const rendering::ARGBColor& rColor=aARGBColors[x];
141 rWriteAcc->SetPixel( aRect.Y1, x,
142 BitmapColor( toByteColor(rColor.Red),
143 toByteColor(rColor.Green),
144 toByteColor(rColor.Blue) ));
145 rAlphaAcc->SetPixel( aRect.Y1, x,
146 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
150 else
152 // read RGB color
153 aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
154 if( rWriteAcc->HasPalette() )
156 for( sal_Int32 x=0; x<nWidth; ++x )
158 const rendering::RGBColor& rColor=aRGBColors[x];
159 rWriteAcc->SetPixelIndex( aRect.Y1, x,
160 (sal_uInt8) rWriteAcc->GetBestPaletteIndex(
161 BitmapColor( toByteColor(rColor.Red),
162 toByteColor(rColor.Green),
163 toByteColor(rColor.Blue))) );
166 else
168 for( sal_Int32 x=0; x<nWidth; ++x )
170 const rendering::RGBColor& rColor=aRGBColors[x];
171 rWriteAcc->SetPixel( aRect.Y1, x,
172 BitmapColor( toByteColor(rColor.Red),
173 toByteColor(rColor.Green),
174 toByteColor(rColor.Blue) ));
180 return true;
184 ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
186 SAL_INFO( "vcl.helper", "vcl::unotools::bitmapExFromXBitmap()" );
188 if( !xInputBitmap.is() )
189 return ::BitmapEx();
191 // tunnel directly for known implementation
192 VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
193 if( pImplBitmap )
194 return pImplBitmap->getBitmapEx();
196 // retrieve data via UNO interface
198 // volatile bitmaps are a bit more complicated to read
199 // from..
200 uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
201 xInputBitmap, uno::UNO_QUERY);
203 // loop a few times, until successfully read (for XVolatileBitmap)
204 for( int i=0; i<10; ++i )
206 sal_Int32 nDepth=0;
207 sal_Int32 nAlphaDepth=0;
208 const rendering::IntegerBitmapLayout aLayout(
209 xInputBitmap->getMemoryLayout());
211 OSL_ENSURE(aLayout.ColorSpace.is(),
212 "Cannot convert image without color space!");
213 if( !aLayout.ColorSpace.is() )
214 return ::BitmapEx();
216 nDepth = aLayout.ColorSpace->getBitsPerPixel();
218 if( xInputBitmap->hasAlpha() )
220 // determine alpha channel depth
221 const uno::Sequence<sal_Int8> aTags(
222 aLayout.ColorSpace->getComponentTags() );
223 const sal_Int8* pStart(aTags.getConstArray());
224 const sal_Size nLen(aTags.getLength());
225 const sal_Int8* pEnd(pStart+nLen);
227 const std::ptrdiff_t nAlphaIndex =
228 std::find(pStart,pEnd,
229 rendering::ColorComponentTag::ALPHA) - pStart;
231 if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
233 nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
234 nDepth -= nAlphaDepth;
238 BitmapPalette aPalette;
239 if( aLayout.Palette.is() )
241 uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
242 aLayout.Palette->getColorSpace());
243 ENSURE_OR_THROW(xPaletteColorSpace.is(),
244 "Palette without color space");
246 const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
247 if( nEntryCount <= 256 )
249 if( nEntryCount <= 2 )
250 nDepth = 1;
251 else
252 nDepth = 8;
254 const sal_uInt16 nPaletteEntries(
255 sal::static_int_cast<sal_uInt16>(
256 std::min(sal_Int32(255), nEntryCount)));
258 // copy palette entries
259 aPalette.SetEntryCount(nPaletteEntries);
260 uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
261 uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
263 uno::Sequence<double> aPaletteEntry;
264 for( sal_uInt16 j=0; j<nPaletteEntries; ++j )
266 if( !xPalette->getIndex(aPaletteEntry,j) &&
267 nAlphaDepth == 0 )
269 nAlphaDepth = 1;
271 uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
272 ENSURE_OR_THROW(aColors.getLength() == 1,
273 "Palette returned more or less than one entry");
274 const rendering::RGBColor& rColor=aColors[0];
275 aPalette[j] = BitmapColor(toByteColor(rColor.Red),
276 toByteColor(rColor.Green),
277 toByteColor(rColor.Blue));
282 const ::Size aPixelSize(
283 sizeFromIntegerSize2D(xInputBitmap->getSize()));
285 // normalize bitcount
286 nDepth =
287 ( nDepth <= 1 ) ? 1 :
288 ( nDepth <= 4 ) ? 4 :
289 ( nDepth <= 8 ) ? 8 : 24;
291 ::Bitmap aBitmap( aPixelSize,
292 sal::static_int_cast<sal_uInt16>(nDepth),
293 aLayout.Palette.is() ? &aPalette : NULL );
294 ::Bitmap aAlpha;
295 if( nAlphaDepth )
296 aAlpha = ::Bitmap( aPixelSize,
297 sal::static_int_cast<sal_uInt16>(nAlphaDepth),
298 &::Bitmap::GetGreyPalette(
299 sal::static_int_cast<sal_uInt16>(1L << nAlphaDepth)) );
301 { // limit scoped access
302 Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
303 Bitmap::ScopedWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL,
304 aAlpha );
306 ENSURE_OR_THROW(pWriteAccess.get() != NULL,
307 "Cannot get write access to bitmap");
309 const sal_Int32 nWidth(aPixelSize.Width());
310 const sal_Int32 nHeight(aPixelSize.Height());
312 if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
313 pWriteAccess,pAlphaWriteAccess) )
314 continue;
315 } // limit scoped access
317 if( nAlphaDepth )
318 return ::BitmapEx( aBitmap,
319 AlphaMask( aAlpha ) );
320 else
321 return ::BitmapEx( aBitmap );
324 // failed to read data 10 times - bail out
325 return ::BitmapEx();
328 geometry::RealSize2D size2DFromSize( const Size& rSize )
330 return geometry::RealSize2D( rSize.Width(),
331 rSize.Height() );
334 Size sizeFromRealSize2D( const geometry::RealSize2D& rSize )
336 return Size( static_cast<long>(rSize.Width + .5),
337 static_cast<long>(rSize.Height + .5) );
340 ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec )
342 return ::Size( FRound( rVec.getX() ),
343 FRound( rVec.getY() ) );
346 ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
348 return ::Point( FRound( rPoint.getX() ),
349 FRound( rPoint.getY() ) );
352 ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect )
354 return ::Rectangle( FRound( rRect.getMinX() ),
355 FRound( rRect.getMinY() ),
356 FRound( rRect.getMaxX() ),
357 FRound( rRect.getMaxY() ) );
360 Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint )
362 return ::Point( rPoint.getX(),
363 rPoint.getY() );
366 Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect )
368 return ::Rectangle( rRect.getMinX(),
369 rRect.getMinY(),
370 rRect.getMaxX(),
371 rRect.getMaxY() );
374 ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize )
376 return ::basegfx::B2DVector( rSize.Width(),
377 rSize.Height() );
380 ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint )
382 return ::basegfx::B2DPoint( rPoint.X(),
383 rPoint.Y() );
386 ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect )
388 return ::basegfx::B2DRange( rRect.Left(),
389 rRect.Top(),
390 rRect.Right(),
391 rRect.Bottom() );
394 geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize )
396 return geometry::IntegerSize2D( rSize.Width(),
397 rSize.Height() );
400 Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
402 return Size( rSize.Width,
403 rSize.Height );
406 Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint )
408 return Point( rPoint.X,
409 rPoint.Y );
412 Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
414 return Rectangle( rRectangle.X1, rRectangle.Y1,
415 rRectangle.X2, rRectangle.Y2 );
418 namespace
420 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
422 private:
423 uno::Sequence< sal_Int8 > m_aComponentTags;
425 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
427 return rendering::ColorSpaceType::RGB;
429 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
431 return m_aComponentTags;
433 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
435 return rendering::RenderingIntent::PERCEPTUAL;
437 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
439 return uno::Sequence< beans::PropertyValue >();
441 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
442 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
443 uno::RuntimeException, std::exception) SAL_OVERRIDE
445 // TODO(P3): if we know anything about target
446 // colorspace, this can be greatly sped up
447 uno::Sequence<rendering::ARGBColor> aIntermediate(
448 convertToARGB(deviceColor));
449 return targetColorSpace->convertFromARGB(aIntermediate);
451 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
453 const double* pIn( deviceColor.getConstArray() );
454 const sal_Size nLen( deviceColor.getLength() );
455 ENSURE_ARG_OR_THROW2(nLen%4==0,
456 "number of channels no multiple of 4",
457 static_cast<rendering::XColorSpace*>(this), 0);
459 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
460 rendering::RGBColor* pOut( aRes.getArray() );
461 for( sal_Size i=0; i<nLen; i+=4 )
463 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
464 pIn += 4;
466 return aRes;
468 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
470 const double* pIn( deviceColor.getConstArray() );
471 const sal_Size nLen( deviceColor.getLength() );
472 ENSURE_ARG_OR_THROW2(nLen%4==0,
473 "number of channels no multiple of 4",
474 static_cast<rendering::XColorSpace*>(this), 0);
476 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
477 rendering::ARGBColor* pOut( aRes.getArray() );
478 for( sal_Size i=0; i<nLen; i+=4 )
480 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
481 pIn += 4;
483 return aRes;
485 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
487 const double* pIn( deviceColor.getConstArray() );
488 const sal_Size nLen( deviceColor.getLength() );
489 ENSURE_ARG_OR_THROW2(nLen%4==0,
490 "number of channels no multiple of 4",
491 static_cast<rendering::XColorSpace*>(this), 0);
493 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
494 rendering::ARGBColor* pOut( aRes.getArray() );
495 for( sal_Size i=0; i<nLen; i+=4 )
497 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
498 pIn += 4;
500 return aRes;
502 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
504 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
505 const sal_Size nLen( rgbColor.getLength() );
507 uno::Sequence< double > aRes(nLen*4);
508 double* pColors=aRes.getArray();
509 for( sal_Size i=0; i<nLen; ++i )
511 *pColors++ = pIn->Red;
512 *pColors++ = pIn->Green;
513 *pColors++ = pIn->Blue;
514 *pColors++ = 1.0;
515 ++pIn;
517 return aRes;
519 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
521 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
522 const sal_Size nLen( rgbColor.getLength() );
524 uno::Sequence< double > aRes(nLen*4);
525 double* pColors=aRes.getArray();
526 for( sal_Size i=0; i<nLen; ++i )
528 *pColors++ = pIn->Red;
529 *pColors++ = pIn->Green;
530 *pColors++ = pIn->Blue;
531 *pColors++ = pIn->Alpha;
532 ++pIn;
534 return aRes;
536 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
538 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
539 const sal_Size nLen( rgbColor.getLength() );
541 uno::Sequence< double > aRes(nLen*4);
542 double* pColors=aRes.getArray();
543 for( sal_Size i=0; i<nLen; ++i )
545 *pColors++ = pIn->Red/pIn->Alpha;
546 *pColors++ = pIn->Green/pIn->Alpha;
547 *pColors++ = pIn->Blue/pIn->Alpha;
548 *pColors++ = pIn->Alpha;
549 ++pIn;
551 return aRes;
554 public:
555 StandardColorSpace() : m_aComponentTags(4)
557 sal_Int8* pTags = m_aComponentTags.getArray();
558 pTags[0] = rendering::ColorComponentTag::RGB_RED;
559 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
560 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
561 pTags[3] = rendering::ColorComponentTag::ALPHA;
566 uno::Reference<rendering::XColorSpace> createStandardColorSpace()
568 return new StandardColorSpace();
571 uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor )
573 uno::Sequence< double > aRet(4);
574 double* pRet = aRet.getArray();
576 pRet[0] = toDoubleColor(rColor.GetRed());
577 pRet[1] = toDoubleColor(rColor.GetGreen());
578 pRet[2] = toDoubleColor(rColor.GetBlue());
580 // VCL's notion of alpha is different from the rest of the world's
581 pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency());
583 return aRet;
586 Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor )
588 ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
589 "color must have 4 channels" );
591 Color aColor;
593 aColor.SetRed ( toByteColor(rColor[0]) );
594 aColor.SetGreen( toByteColor(rColor[1]) );
595 aColor.SetBlue ( toByteColor(rColor[2]) );
596 // VCL's notion of alpha is different from the rest of the world's
597 aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
599 return aColor;
602 uno::Sequence< double > colorToDoubleSequence(
603 const Color& rColor,
604 const uno::Reference< rendering::XColorSpace >& xColorSpace )
606 uno::Sequence<rendering::ARGBColor> aSeq(1);
607 aSeq[0] = rendering::ARGBColor(
608 1.0-toDoubleColor(rColor.GetTransparency()),
609 toDoubleColor(rColor.GetRed()),
610 toDoubleColor(rColor.GetGreen()),
611 toDoubleColor(rColor.GetBlue()) );
613 return xColorSpace->convertFromARGB(aSeq);
616 Color doubleSequenceToColor(
617 const uno::Sequence< double >& rColor,
618 const uno::Reference< rendering::XColorSpace >& xColorSpace )
620 const rendering::ARGBColor aARGBColor(
621 xColorSpace->convertToARGB(rColor)[0]);
623 return Color( 255-toByteColor(aARGBColor.Alpha),
624 toByteColor(aARGBColor.Red),
625 toByteColor(aARGBColor.Green),
626 toByteColor(aARGBColor.Blue) );
629 } // namespace vcltools
631 } // namespace canvas
633 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */