Update ooo320-m1
[ooovba.git] / vcl / source / helper / canvastools.cxx
blobba66d16dbe80df24374321d5cb33809a32dc32cc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: canvastools.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <rtl/logfile.hxx>
35 #include <cppuhelper/compbase1.hxx>
37 #include <com/sun/star/geometry/RealSize2D.hpp>
38 #include <com/sun/star/geometry/RealPoint2D.hpp>
39 #include <com/sun/star/geometry/RealRectangle2D.hpp>
40 #include <com/sun/star/geometry/IntegerSize2D.hpp>
41 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
42 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
43 #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
45 #include <com/sun/star/rendering/ColorSpaceType.hpp>
46 #include <com/sun/star/rendering/RenderingIntent.hpp>
47 #include <com/sun/star/rendering/XGraphicDevice.hpp>
48 #include <com/sun/star/rendering/XBitmap.hpp>
49 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
50 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
51 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
52 #include <com/sun/star/rendering/ColorComponentTag.hpp>
54 #include <basegfx/matrix/b2dhommatrix.hxx>
55 #include <basegfx/vector/b2dsize.hxx>
56 #include <basegfx/point/b2dpoint.hxx>
57 #include <basegfx/range/b2drectangle.hxx>
58 #include <basegfx/vector/b2isize.hxx>
59 #include <basegfx/point/b2ipoint.hxx>
60 #include <basegfx/range/b2irectangle.hxx>
62 // #i79917#
63 #include <basegfx/polygon/b2dpolygon.hxx>
64 #include <basegfx/tools/canvastools.hxx>
65 #include <basegfx/polygon/b2dpolypolygon.hxx>
67 #include <tools/poly.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <rtl/uuid.h>
71 #include <vcl/salbtype.hxx>
72 #include <vcl/bmpacc.hxx>
73 #include <vcl/bitmapex.hxx>
75 #include <vcl/canvasbitmap.hxx>
76 #include <vcl/canvastools.hxx>
77 #include <hash_map>
80 using namespace ::com::sun::star;
82 namespace vcl
84 namespace unotools
86 // #i79917# removed helpers bezierSequenceFromPolygon and
87 // pointSequenceFromPolygon here
88 // Also all helpers using tools Polygon and PolyPolygon will get mapped to the
89 // B2DPolygon helpers for these cases, see comments with the same TaskID below.
90 // TODO: Remove those wrapped methods
92 //---------------------------------------------------------------------------------------
94 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
95 const ::Polygon& inputPolygon )
97 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" );
99 // #i79917# map to basegfx
100 const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon());
101 return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon);
104 //---------------------------------------------------------------------------------------
106 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
107 const ::PolyPolygon& inputPolyPolygon )
109 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" );
111 // #i79917# map to basegfx
112 const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon());
113 return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon);
116 //---------------------------------------------------------------------------------------
118 ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points )
120 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" );
122 const USHORT nCurrSize( sal::static_int_cast<USHORT>(points.getLength()) );
124 ::Polygon aPoly( nCurrSize );
126 USHORT nCurrPoint;
127 for( nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint )
128 aPoly[nCurrPoint] = pointFromRealPoint2D( points[nCurrPoint] );
130 return aPoly;
133 //---------------------------------------------------------------------------------------
135 ::PolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
137 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" );
139 ::PolyPolygon aRes;
141 int nCurrPoly;
142 for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
144 aRes.Insert( polygonFromPoint2DSequence( points[nCurrPoly] ) );
147 return aRes;
150 //---------------------------------------------------------------------------------------
152 ::Polygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves )
154 // #i79917# map to basegfx
155 const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves));
156 return ::Polygon(aB2DPolygon);
159 //---------------------------------------------------------------------------------------
161 ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves )
163 // #i79917# map to basegfx
164 const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves));
165 return ::PolyPolygon(aB2DPolyPolygon);
168 //---------------------------------------------------------------------------------------
170 uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
171 const ::Bitmap& inputBitmap )
173 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" );
175 return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) );
178 //---------------------------------------------------------------------------------------
180 uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
181 const ::BitmapEx& inputBitmap )
183 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" );
185 return new vcl::unotools::VclCanvasBitmap( inputBitmap );
188 //---------------------------------------------------------------------------------------
190 const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType )
192 static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds;
193 std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it =
194 aIds.find( eType );
195 if( it == aIds.end() )
197 uno::Sequence< sal_Int8 > aNewId( 16 );
198 rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True );
199 aIds[ eType ] = aNewId;
200 it = aIds.find( eType );
202 return it->second;
205 //---------------------------------------------------------------------------------------
207 namespace
209 inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
210 const rendering::IntegerBitmapLayout& rRHS )
212 return
213 rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
214 rLHS.ScanLineStride == rRHS.ScanLineStride &&
215 rLHS.PlaneStride == rRHS.PlaneStride &&
216 rLHS.ColorSpace == rRHS.ColorSpace &&
217 rLHS.Palette == rRHS.Palette &&
218 rLHS.IsMsbFirst == rRHS.IsMsbFirst;
221 bool readBmp( sal_Int32 nWidth,
222 sal_Int32 nHeight,
223 const rendering::IntegerBitmapLayout& rLayout,
224 const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
225 ScopedBitmapWriteAccess& rWriteAcc,
226 ScopedBitmapWriteAccess& rAlphaAcc )
228 rendering::IntegerBitmapLayout aCurrLayout;
229 geometry::IntegerRectangle2D aRect;
230 uno::Sequence<sal_Int8> aPixelData;
231 uno::Sequence<rendering::RGBColor> aRGBColors;
232 uno::Sequence<rendering::ARGBColor> aARGBColors;
234 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
236 aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
239 aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
241 catch( rendering::VolatileContentDestroyedException& )
243 // re-read bmp from the start
244 return false;
246 if( !(aCurrLayout == rLayout) )
247 return false; // re-read bmp from the start
249 if( rAlphaAcc.get() )
251 // read ARGB color
252 aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
254 if( rWriteAcc->HasPalette() )
256 for( sal_Int32 x=0; x<nWidth; ++x )
258 const rendering::ARGBColor& rColor=aARGBColors[x];
259 rWriteAcc->SetPixel( aRect.Y1, x,
260 (BYTE)rWriteAcc->GetBestPaletteIndex(
261 BitmapColor( toByteColor(rColor.Red),
262 toByteColor(rColor.Green),
263 toByteColor(rColor.Blue))) );
264 rAlphaAcc->SetPixel( aRect.Y1, x,
265 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
268 else
270 for( sal_Int32 x=0; x<nWidth; ++x )
272 const rendering::ARGBColor& rColor=aARGBColors[x];
273 rWriteAcc->SetPixel( aRect.Y1, x,
274 BitmapColor( toByteColor(rColor.Red),
275 toByteColor(rColor.Green),
276 toByteColor(rColor.Blue) ));
277 rAlphaAcc->SetPixel( aRect.Y1, x,
278 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
282 else
284 // read RGB color
285 aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
286 if( rWriteAcc->HasPalette() )
288 for( sal_Int32 x=0; x<nWidth; ++x )
290 const rendering::RGBColor& rColor=aRGBColors[x];
291 rWriteAcc->SetPixel( aRect.Y1, x,
292 (BYTE)rWriteAcc->GetBestPaletteIndex(
293 BitmapColor( toByteColor(rColor.Red),
294 toByteColor(rColor.Green),
295 toByteColor(rColor.Blue))) );
298 else
300 for( sal_Int32 x=0; x<nWidth; ++x )
302 const rendering::RGBColor& rColor=aRGBColors[x];
303 rWriteAcc->SetPixel( aRect.Y1, x,
304 BitmapColor( toByteColor(rColor.Red),
305 toByteColor(rColor.Green),
306 toByteColor(rColor.Blue) ));
312 return true;
316 ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
318 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
320 if( !xInputBitmap.is() )
321 return ::BitmapEx();
323 // tunnel directly for known implementation
324 // ----------------------------------------------------------------
325 VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
326 if( pImplBitmap )
327 return pImplBitmap->getBitmapEx();
329 // retrieve data via UNO interface
330 // ----------------------------------------------------------------
332 // volatile bitmaps are a bit more complicated to read
333 // from..
334 uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
335 xInputBitmap, uno::UNO_QUERY);
337 // loop a few times, until successfully read (for XVolatileBitmap)
338 for( int i=0; i<10; ++i )
340 sal_Int32 nDepth=0;
341 sal_Int32 nAlphaDepth=0;
342 const rendering::IntegerBitmapLayout aLayout(
343 xInputBitmap->getMemoryLayout());
345 OSL_ENSURE(aLayout.ColorSpace.is(),
346 "Cannot convert image without color space!");
347 if( !aLayout.ColorSpace.is() )
348 return ::BitmapEx();
350 nDepth = aLayout.ColorSpace->getBitsPerPixel();
352 if( xInputBitmap->hasAlpha() )
354 // determine alpha channel depth
355 const uno::Sequence<sal_Int8> aTags(
356 aLayout.ColorSpace->getComponentTags() );
357 const uno::Sequence<sal_Int32> aDepths(
358 aLayout.ColorSpace->getComponentBitCounts() );
359 const sal_Int8* pStart(aTags.getConstArray());
360 const sal_Size nLen(aTags.getLength());
361 const sal_Int8* pEnd(pStart+nLen);
363 const std::ptrdiff_t nAlphaIndex =
364 std::find(pStart,pEnd,
365 rendering::ColorComponentTag::ALPHA) - pStart;
367 if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
369 nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
370 nDepth -= nAlphaDepth;
374 BitmapPalette aPalette;
375 if( aLayout.Palette.is() )
377 uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
378 aLayout.Palette->getColorSpace());
379 ENSURE_OR_THROW(xPaletteColorSpace.is(),
380 "Palette without color space");
382 const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
383 if( nEntryCount <= 256 )
385 if( nEntryCount <= 2 )
386 nDepth = 1;
387 else
388 nDepth = 8;
390 const USHORT nPaletteEntries(
391 sal::static_int_cast<USHORT>(
392 std::min(sal_Int32(255), nEntryCount)));
394 // copy palette entries
395 aPalette.SetEntryCount(nPaletteEntries);
396 uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
397 uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
399 uno::Sequence<double> aPaletteEntry;
400 for( USHORT j=0; j<nPaletteEntries; ++j )
402 if( !xPalette->getIndex(aPaletteEntry,j) &&
403 nAlphaDepth == 0 )
405 nAlphaDepth = 1;
407 uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
408 ENSURE_OR_THROW(aColors.getLength() == 1,
409 "Palette returned more or less than one entry");
410 const rendering::RGBColor& rColor=aColors[0];
411 aPalette[j] = BitmapColor(toByteColor(rColor.Red),
412 toByteColor(rColor.Green),
413 toByteColor(rColor.Blue));
418 const ::Size aPixelSize(
419 sizeFromIntegerSize2D(xInputBitmap->getSize()));
421 // normalize bitcount
422 nDepth =
423 ( nDepth <= 1 ) ? 1 :
424 ( nDepth <= 4 ) ? 4 :
425 ( nDepth <= 8 ) ? 8 : 24;
427 ::Bitmap aBitmap( aPixelSize,
428 sal::static_int_cast<USHORT>(nDepth),
429 aLayout.Palette.is() ? &aPalette : NULL );
430 ::Bitmap aAlpha;
431 if( nAlphaDepth )
432 aAlpha = ::Bitmap( aPixelSize,
433 sal::static_int_cast<USHORT>(nAlphaDepth),
434 &::Bitmap::GetGreyPalette(
435 sal::static_int_cast<USHORT>(1L << nAlphaDepth)) );
437 { // limit scoped access
438 ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
439 aBitmap );
440 ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL,
441 aAlpha );
443 ENSURE_OR_THROW(pWriteAccess.get() != NULL,
444 "Cannot get write access to bitmap");
446 const sal_Int32 nWidth(aPixelSize.Width());
447 const sal_Int32 nHeight(aPixelSize.Height());
449 if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
450 pWriteAccess,pAlphaWriteAccess) )
451 continue;
452 } // limit scoped access
454 if( nAlphaDepth )
455 return ::BitmapEx( aBitmap,
456 AlphaMask( aAlpha ) );
457 else
458 return ::BitmapEx( aBitmap );
461 // failed to read data 10 times - bail out
462 return ::BitmapEx();
465 //---------------------------------------------------------------------------------------
467 geometry::RealSize2D size2DFromSize( const Size& rSize )
469 return geometry::RealSize2D( rSize.Width(),
470 rSize.Height() );
473 geometry::RealPoint2D point2DFromPoint( const Point& rPoint )
475 return geometry::RealPoint2D( rPoint.X(),
476 rPoint.Y() );
479 geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect )
481 return geometry::RealRectangle2D( rRect.Left(), rRect.Top(),
482 rRect.Right(), rRect.Bottom() );
485 Size sizeFromRealSize2D( const geometry::RealSize2D& rSize )
487 return Size( static_cast<long>(rSize.Width + .5),
488 static_cast<long>(rSize.Height + .5) );
491 Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint )
493 return Point( static_cast<long>(rPoint.X + .5),
494 static_cast<long>(rPoint.Y + .5) );
497 Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect )
499 return Rectangle( static_cast<long>(rRect.X1 + .5),
500 static_cast<long>(rRect.Y1 + .5),
501 static_cast<long>(rRect.X2 + .5),
502 static_cast<long>(rRect.Y2 + .5) );
505 ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec )
507 return ::Size( FRound( rVec.getX() ),
508 FRound( rVec.getY() ) );
511 ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
513 return ::Point( FRound( rPoint.getX() ),
514 FRound( rPoint.getY() ) );
517 ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect )
519 return ::Rectangle( FRound( rRect.getMinX() ),
520 FRound( rRect.getMinY() ),
521 FRound( rRect.getMaxX() ),
522 FRound( rRect.getMaxY() ) );
525 Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec )
527 return ::Size( rVec.getX(),
528 rVec.getY() );
531 Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint )
533 return ::Point( rPoint.getX(),
534 rPoint.getY() );
537 Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect )
539 return ::Rectangle( rRect.getMinX(),
540 rRect.getMinY(),
541 rRect.getMaxX(),
542 rRect.getMaxY() );
545 ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize )
547 return ::basegfx::B2DVector( rSize.Width(),
548 rSize.Height() );
551 ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint )
553 return ::basegfx::B2DPoint( rPoint.X(),
554 rPoint.Y() );
557 ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect )
559 return ::basegfx::B2DRange( rRect.Left(),
560 rRect.Top(),
561 rRect.Right(),
562 rRect.Bottom() );
565 basegfx::B2IVector b2ISizeFromSize( const Size& rSize )
567 return ::basegfx::B2IVector( rSize.Width(),
568 rSize.Height() );
571 basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint )
573 return ::basegfx::B2IPoint( rPoint.X(),
574 rPoint.Y() );
577 basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect )
579 return ::basegfx::B2IRange( rRect.Left(),
580 rRect.Top(),
581 rRect.Right(),
582 rRect.Bottom() );
585 geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize )
587 return geometry::IntegerSize2D( rSize.Width(),
588 rSize.Height() );
591 geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint )
593 return geometry::IntegerPoint2D( rPoint.X(),
594 rPoint.Y() );
597 geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle )
599 return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(),
600 rRectangle.Right(), rRectangle.Bottom() );
603 Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
605 return Size( rSize.Width,
606 rSize.Height );
609 Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint )
611 return Point( rPoint.X,
612 rPoint.Y );
615 Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
617 return Rectangle( rRectangle.X1, rRectangle.Y1,
618 rRectangle.X2, rRectangle.Y2 );
621 namespace
623 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
625 private:
626 uno::Sequence< sal_Int8 > m_aComponentTags;
628 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
630 return rendering::ColorSpaceType::RGB;
632 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
634 return m_aComponentTags;
636 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
638 return rendering::RenderingIntent::PERCEPTUAL;
640 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
642 return uno::Sequence< beans::PropertyValue >();
644 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
645 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
646 uno::RuntimeException)
648 // TODO(P3): if we know anything about target
649 // colorspace, this can be greatly sped up
650 uno::Sequence<rendering::ARGBColor> aIntermediate(
651 convertToARGB(deviceColor));
652 return targetColorSpace->convertFromARGB(aIntermediate);
654 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
656 const double* pIn( deviceColor.getConstArray() );
657 const sal_Size nLen( deviceColor.getLength() );
658 ENSURE_ARG_OR_THROW2(nLen%4==0,
659 "number of channels no multiple of 4",
660 static_cast<rendering::XColorSpace*>(this), 0);
662 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
663 rendering::RGBColor* pOut( aRes.getArray() );
664 for( sal_Size i=0; i<nLen; i+=4 )
666 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
667 pIn += 4;
669 return aRes;
671 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
673 const double* pIn( deviceColor.getConstArray() );
674 const sal_Size nLen( deviceColor.getLength() );
675 ENSURE_ARG_OR_THROW2(nLen%4==0,
676 "number of channels no multiple of 4",
677 static_cast<rendering::XColorSpace*>(this), 0);
679 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
680 rendering::ARGBColor* pOut( aRes.getArray() );
681 for( sal_Size i=0; i<nLen; i+=4 )
683 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
684 pIn += 4;
686 return aRes;
688 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
690 const double* pIn( deviceColor.getConstArray() );
691 const sal_Size nLen( deviceColor.getLength() );
692 ENSURE_ARG_OR_THROW2(nLen%4==0,
693 "number of channels no multiple of 4",
694 static_cast<rendering::XColorSpace*>(this), 0);
696 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
697 rendering::ARGBColor* pOut( aRes.getArray() );
698 for( sal_Size i=0; i<nLen; i+=4 )
700 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
701 pIn += 4;
703 return aRes;
705 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
707 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
708 const sal_Size nLen( rgbColor.getLength() );
710 uno::Sequence< double > aRes(nLen*4);
711 double* pColors=aRes.getArray();
712 for( sal_Size i=0; i<nLen; ++i )
714 *pColors++ = pIn->Red;
715 *pColors++ = pIn->Green;
716 *pColors++ = pIn->Blue;
717 *pColors++ = 1.0;
718 ++pIn;
720 return aRes;
722 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
724 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
725 const sal_Size nLen( rgbColor.getLength() );
727 uno::Sequence< double > aRes(nLen*4);
728 double* pColors=aRes.getArray();
729 for( sal_Size i=0; i<nLen; ++i )
731 *pColors++ = pIn->Red;
732 *pColors++ = pIn->Green;
733 *pColors++ = pIn->Blue;
734 *pColors++ = pIn->Alpha;
735 ++pIn;
737 return aRes;
739 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
741 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
742 const sal_Size nLen( rgbColor.getLength() );
744 uno::Sequence< double > aRes(nLen*4);
745 double* pColors=aRes.getArray();
746 for( sal_Size i=0; i<nLen; ++i )
748 *pColors++ = pIn->Red/pIn->Alpha;
749 *pColors++ = pIn->Green/pIn->Alpha;
750 *pColors++ = pIn->Blue/pIn->Alpha;
751 *pColors++ = pIn->Alpha;
752 ++pIn;
754 return aRes;
757 public:
758 StandardColorSpace() : m_aComponentTags(4)
760 sal_Int8* pTags = m_aComponentTags.getArray();
761 pTags[0] = rendering::ColorComponentTag::RGB_RED;
762 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
763 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
764 pTags[3] = rendering::ColorComponentTag::ALPHA;
769 uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace()
771 return new StandardColorSpace();
774 //---------------------------------------------------------------------------------------
776 uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor )
778 uno::Sequence< double > aRet(4);
779 double* pRet = aRet.getArray();
781 pRet[0] = toDoubleColor(rColor.GetRed());
782 pRet[1] = toDoubleColor(rColor.GetGreen());
783 pRet[2] = toDoubleColor(rColor.GetBlue());
785 // VCL's notion of alpha is different from the rest of the world's
786 pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency());
788 return aRet;
791 Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor )
793 ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
794 "color must have 4 channels" );
796 Color aColor;
798 aColor.SetRed ( toByteColor(rColor[0]) );
799 aColor.SetGreen( toByteColor(rColor[1]) );
800 aColor.SetBlue ( toByteColor(rColor[2]) );
801 // VCL's notion of alpha is different from the rest of the world's
802 aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
804 return aColor;
807 uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence(
808 const Color& rColor,
809 const uno::Reference< rendering::XColorSpace >& xColorSpace )
811 uno::Sequence<rendering::ARGBColor> aSeq(1);
812 aSeq[0] = rendering::ARGBColor(
813 1.0-toDoubleColor(rColor.GetTransparency()),
814 toDoubleColor(rColor.GetRed()),
815 toDoubleColor(rColor.GetGreen()),
816 toDoubleColor(rColor.GetBlue()) );
818 return xColorSpace->convertFromARGB(aSeq);
821 Color VCL_DLLPUBLIC doubleSequenceToColor(
822 const uno::Sequence< double > rColor,
823 const uno::Reference< rendering::XColorSpace >& xColorSpace )
825 const rendering::ARGBColor& rARGBColor(
826 xColorSpace->convertToARGB(rColor)[0]);
828 return Color( 255-toByteColor(rARGBColor.Alpha),
829 toByteColor(rARGBColor.Red),
830 toByteColor(rARGBColor.Green),
831 toByteColor(rARGBColor.Blue) );
834 //---------------------------------------------------------------------------------------
836 } // namespace vcltools
838 } // namespace canvas
840 // eof