ooo33gsl12: #i115107# do not call getNativeControlRegion during paint on gtk
[LibreOffice.git] / vcl / source / helper / canvastools.cxx
blob71c306ff9bbb336841b6dbb3ec1f08d9d340775f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <rtl/logfile.hxx>
32 #include <cppuhelper/compbase1.hxx>
34 #include <com/sun/star/geometry/RealSize2D.hpp>
35 #include <com/sun/star/geometry/RealPoint2D.hpp>
36 #include <com/sun/star/geometry/RealRectangle2D.hpp>
37 #include <com/sun/star/geometry/IntegerSize2D.hpp>
38 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
39 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
40 #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
42 #include <com/sun/star/rendering/ColorSpaceType.hpp>
43 #include <com/sun/star/rendering/RenderingIntent.hpp>
44 #include <com/sun/star/rendering/XGraphicDevice.hpp>
45 #include <com/sun/star/rendering/XBitmap.hpp>
46 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
47 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
48 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
49 #include <com/sun/star/rendering/ColorComponentTag.hpp>
51 #include <basegfx/matrix/b2dhommatrix.hxx>
52 #include <basegfx/vector/b2dsize.hxx>
53 #include <basegfx/point/b2dpoint.hxx>
54 #include <basegfx/range/b2drectangle.hxx>
55 #include <basegfx/vector/b2isize.hxx>
56 #include <basegfx/point/b2ipoint.hxx>
57 #include <basegfx/range/b2irectangle.hxx>
59 // #i79917#
60 #include <basegfx/polygon/b2dpolygon.hxx>
61 #include <basegfx/tools/canvastools.hxx>
62 #include <basegfx/polygon/b2dpolypolygon.hxx>
64 #include <tools/poly.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <rtl/uuid.h>
68 #include <vcl/salbtype.hxx>
69 #include <vcl/bmpacc.hxx>
70 #include <vcl/bitmapex.hxx>
72 #include <vcl/canvasbitmap.hxx>
73 #include <vcl/canvastools.hxx>
74 #include <hash_map>
77 using namespace ::com::sun::star;
79 namespace vcl
81 namespace unotools
83 // #i79917# removed helpers bezierSequenceFromPolygon and
84 // pointSequenceFromPolygon here
85 // Also all helpers using tools Polygon and PolyPolygon will get mapped to the
86 // B2DPolygon helpers for these cases, see comments with the same TaskID below.
87 // TODO: Remove those wrapped methods
89 //---------------------------------------------------------------------------------------
91 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
92 const ::Polygon& inputPolygon )
94 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" );
96 // #i79917# map to basegfx
97 const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon());
98 return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon);
101 //---------------------------------------------------------------------------------------
103 uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
104 const ::PolyPolygon& inputPolyPolygon )
106 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" );
108 // #i79917# map to basegfx
109 const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon());
110 return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon);
113 //---------------------------------------------------------------------------------------
115 ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points )
117 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" );
119 const USHORT nCurrSize( sal::static_int_cast<USHORT>(points.getLength()) );
121 ::Polygon aPoly( nCurrSize );
123 USHORT nCurrPoint;
124 for( nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint )
125 aPoly[nCurrPoint] = pointFromRealPoint2D( points[nCurrPoint] );
127 return aPoly;
130 //---------------------------------------------------------------------------------------
132 ::PolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
134 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" );
136 ::PolyPolygon aRes;
138 int nCurrPoly;
139 for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
141 aRes.Insert( polygonFromPoint2DSequence( points[nCurrPoly] ) );
144 return aRes;
147 //---------------------------------------------------------------------------------------
149 ::Polygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves )
151 // #i79917# map to basegfx
152 const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves));
153 return ::Polygon(aB2DPolygon);
156 //---------------------------------------------------------------------------------------
158 ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves )
160 // #i79917# map to basegfx
161 const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves));
162 return ::PolyPolygon(aB2DPolyPolygon);
165 //---------------------------------------------------------------------------------------
167 uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
168 const ::Bitmap& inputBitmap )
170 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" );
172 return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) );
175 //---------------------------------------------------------------------------------------
177 uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
178 const ::BitmapEx& inputBitmap )
180 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" );
182 return new vcl::unotools::VclCanvasBitmap( inputBitmap );
185 //---------------------------------------------------------------------------------------
187 const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType )
189 static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds;
190 std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it =
191 aIds.find( eType );
192 if( it == aIds.end() )
194 uno::Sequence< sal_Int8 > aNewId( 16 );
195 rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True );
196 aIds[ eType ] = aNewId;
197 it = aIds.find( eType );
199 return it->second;
202 //---------------------------------------------------------------------------------------
204 namespace
206 inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
207 const rendering::IntegerBitmapLayout& rRHS )
209 return
210 rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
211 rLHS.ScanLineStride == rRHS.ScanLineStride &&
212 rLHS.PlaneStride == rRHS.PlaneStride &&
213 rLHS.ColorSpace == rRHS.ColorSpace &&
214 rLHS.Palette == rRHS.Palette &&
215 rLHS.IsMsbFirst == rRHS.IsMsbFirst;
218 bool readBmp( sal_Int32 nWidth,
219 sal_Int32 nHeight,
220 const rendering::IntegerBitmapLayout& rLayout,
221 const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
222 ScopedBitmapWriteAccess& rWriteAcc,
223 ScopedBitmapWriteAccess& rAlphaAcc )
225 rendering::IntegerBitmapLayout aCurrLayout;
226 geometry::IntegerRectangle2D aRect;
227 uno::Sequence<sal_Int8> aPixelData;
228 uno::Sequence<rendering::RGBColor> aRGBColors;
229 uno::Sequence<rendering::ARGBColor> aARGBColors;
231 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
233 aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
236 aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
238 catch( rendering::VolatileContentDestroyedException& )
240 // re-read bmp from the start
241 return false;
243 if( !(aCurrLayout == rLayout) )
244 return false; // re-read bmp from the start
246 if( rAlphaAcc.get() )
248 // read ARGB color
249 aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
251 if( rWriteAcc->HasPalette() )
253 for( sal_Int32 x=0; x<nWidth; ++x )
255 const rendering::ARGBColor& rColor=aARGBColors[x];
256 rWriteAcc->SetPixel( aRect.Y1, x,
257 (BYTE)rWriteAcc->GetBestPaletteIndex(
258 BitmapColor( toByteColor(rColor.Red),
259 toByteColor(rColor.Green),
260 toByteColor(rColor.Blue))) );
261 rAlphaAcc->SetPixel( aRect.Y1, x,
262 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
265 else
267 for( sal_Int32 x=0; x<nWidth; ++x )
269 const rendering::ARGBColor& rColor=aARGBColors[x];
270 rWriteAcc->SetPixel( aRect.Y1, x,
271 BitmapColor( toByteColor(rColor.Red),
272 toByteColor(rColor.Green),
273 toByteColor(rColor.Blue) ));
274 rAlphaAcc->SetPixel( aRect.Y1, x,
275 BitmapColor( 255 - toByteColor(rColor.Alpha) ));
279 else
281 // read RGB color
282 aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
283 if( rWriteAcc->HasPalette() )
285 for( sal_Int32 x=0; x<nWidth; ++x )
287 const rendering::RGBColor& rColor=aRGBColors[x];
288 rWriteAcc->SetPixel( aRect.Y1, x,
289 (BYTE)rWriteAcc->GetBestPaletteIndex(
290 BitmapColor( toByteColor(rColor.Red),
291 toByteColor(rColor.Green),
292 toByteColor(rColor.Blue))) );
295 else
297 for( sal_Int32 x=0; x<nWidth; ++x )
299 const rendering::RGBColor& rColor=aRGBColors[x];
300 rWriteAcc->SetPixel( aRect.Y1, x,
301 BitmapColor( toByteColor(rColor.Red),
302 toByteColor(rColor.Green),
303 toByteColor(rColor.Blue) ));
309 return true;
313 ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
315 RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
317 if( !xInputBitmap.is() )
318 return ::BitmapEx();
320 // tunnel directly for known implementation
321 // ----------------------------------------------------------------
322 VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
323 if( pImplBitmap )
324 return pImplBitmap->getBitmapEx();
326 // retrieve data via UNO interface
327 // ----------------------------------------------------------------
329 // volatile bitmaps are a bit more complicated to read
330 // from..
331 uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
332 xInputBitmap, uno::UNO_QUERY);
334 // loop a few times, until successfully read (for XVolatileBitmap)
335 for( int i=0; i<10; ++i )
337 sal_Int32 nDepth=0;
338 sal_Int32 nAlphaDepth=0;
339 const rendering::IntegerBitmapLayout aLayout(
340 xInputBitmap->getMemoryLayout());
342 OSL_ENSURE(aLayout.ColorSpace.is(),
343 "Cannot convert image without color space!");
344 if( !aLayout.ColorSpace.is() )
345 return ::BitmapEx();
347 nDepth = aLayout.ColorSpace->getBitsPerPixel();
349 if( xInputBitmap->hasAlpha() )
351 // determine alpha channel depth
352 const uno::Sequence<sal_Int8> aTags(
353 aLayout.ColorSpace->getComponentTags() );
354 const uno::Sequence<sal_Int32> aDepths(
355 aLayout.ColorSpace->getComponentBitCounts() );
356 const sal_Int8* pStart(aTags.getConstArray());
357 const sal_Size nLen(aTags.getLength());
358 const sal_Int8* pEnd(pStart+nLen);
360 const std::ptrdiff_t nAlphaIndex =
361 std::find(pStart,pEnd,
362 rendering::ColorComponentTag::ALPHA) - pStart;
364 if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
366 nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
367 nDepth -= nAlphaDepth;
371 BitmapPalette aPalette;
372 if( aLayout.Palette.is() )
374 uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
375 aLayout.Palette->getColorSpace());
376 ENSURE_OR_THROW(xPaletteColorSpace.is(),
377 "Palette without color space");
379 const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
380 if( nEntryCount <= 256 )
382 if( nEntryCount <= 2 )
383 nDepth = 1;
384 else
385 nDepth = 8;
387 const USHORT nPaletteEntries(
388 sal::static_int_cast<USHORT>(
389 std::min(sal_Int32(255), nEntryCount)));
391 // copy palette entries
392 aPalette.SetEntryCount(nPaletteEntries);
393 uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
394 uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
396 uno::Sequence<double> aPaletteEntry;
397 for( USHORT j=0; j<nPaletteEntries; ++j )
399 if( !xPalette->getIndex(aPaletteEntry,j) &&
400 nAlphaDepth == 0 )
402 nAlphaDepth = 1;
404 uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
405 ENSURE_OR_THROW(aColors.getLength() == 1,
406 "Palette returned more or less than one entry");
407 const rendering::RGBColor& rColor=aColors[0];
408 aPalette[j] = BitmapColor(toByteColor(rColor.Red),
409 toByteColor(rColor.Green),
410 toByteColor(rColor.Blue));
415 const ::Size aPixelSize(
416 sizeFromIntegerSize2D(xInputBitmap->getSize()));
418 // normalize bitcount
419 nDepth =
420 ( nDepth <= 1 ) ? 1 :
421 ( nDepth <= 4 ) ? 4 :
422 ( nDepth <= 8 ) ? 8 : 24;
424 ::Bitmap aBitmap( aPixelSize,
425 sal::static_int_cast<USHORT>(nDepth),
426 aLayout.Palette.is() ? &aPalette : NULL );
427 ::Bitmap aAlpha;
428 if( nAlphaDepth )
429 aAlpha = ::Bitmap( aPixelSize,
430 sal::static_int_cast<USHORT>(nAlphaDepth),
431 &::Bitmap::GetGreyPalette(
432 sal::static_int_cast<USHORT>(1L << nAlphaDepth)) );
434 { // limit scoped access
435 ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
436 aBitmap );
437 ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL,
438 aAlpha );
440 ENSURE_OR_THROW(pWriteAccess.get() != NULL,
441 "Cannot get write access to bitmap");
443 const sal_Int32 nWidth(aPixelSize.Width());
444 const sal_Int32 nHeight(aPixelSize.Height());
446 if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
447 pWriteAccess,pAlphaWriteAccess) )
448 continue;
449 } // limit scoped access
451 if( nAlphaDepth )
452 return ::BitmapEx( aBitmap,
453 AlphaMask( aAlpha ) );
454 else
455 return ::BitmapEx( aBitmap );
458 // failed to read data 10 times - bail out
459 return ::BitmapEx();
462 //---------------------------------------------------------------------------------------
464 geometry::RealSize2D size2DFromSize( const Size& rSize )
466 return geometry::RealSize2D( rSize.Width(),
467 rSize.Height() );
470 geometry::RealPoint2D point2DFromPoint( const Point& rPoint )
472 return geometry::RealPoint2D( rPoint.X(),
473 rPoint.Y() );
476 geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect )
478 return geometry::RealRectangle2D( rRect.Left(), rRect.Top(),
479 rRect.Right(), rRect.Bottom() );
482 Size sizeFromRealSize2D( const geometry::RealSize2D& rSize )
484 return Size( static_cast<long>(rSize.Width + .5),
485 static_cast<long>(rSize.Height + .5) );
488 Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint )
490 return Point( static_cast<long>(rPoint.X + .5),
491 static_cast<long>(rPoint.Y + .5) );
494 Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect )
496 return Rectangle( static_cast<long>(rRect.X1 + .5),
497 static_cast<long>(rRect.Y1 + .5),
498 static_cast<long>(rRect.X2 + .5),
499 static_cast<long>(rRect.Y2 + .5) );
502 ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec )
504 return ::Size( FRound( rVec.getX() ),
505 FRound( rVec.getY() ) );
508 ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
510 return ::Point( FRound( rPoint.getX() ),
511 FRound( rPoint.getY() ) );
514 ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect )
516 return ::Rectangle( FRound( rRect.getMinX() ),
517 FRound( rRect.getMinY() ),
518 FRound( rRect.getMaxX() ),
519 FRound( rRect.getMaxY() ) );
522 Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec )
524 return ::Size( rVec.getX(),
525 rVec.getY() );
528 Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint )
530 return ::Point( rPoint.getX(),
531 rPoint.getY() );
534 Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect )
536 return ::Rectangle( rRect.getMinX(),
537 rRect.getMinY(),
538 rRect.getMaxX(),
539 rRect.getMaxY() );
542 ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize )
544 return ::basegfx::B2DVector( rSize.Width(),
545 rSize.Height() );
548 ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint )
550 return ::basegfx::B2DPoint( rPoint.X(),
551 rPoint.Y() );
554 ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect )
556 return ::basegfx::B2DRange( rRect.Left(),
557 rRect.Top(),
558 rRect.Right(),
559 rRect.Bottom() );
562 basegfx::B2IVector b2ISizeFromSize( const Size& rSize )
564 return ::basegfx::B2IVector( rSize.Width(),
565 rSize.Height() );
568 basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint )
570 return ::basegfx::B2IPoint( rPoint.X(),
571 rPoint.Y() );
574 basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect )
576 return ::basegfx::B2IRange( rRect.Left(),
577 rRect.Top(),
578 rRect.Right(),
579 rRect.Bottom() );
582 geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize )
584 return geometry::IntegerSize2D( rSize.Width(),
585 rSize.Height() );
588 geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint )
590 return geometry::IntegerPoint2D( rPoint.X(),
591 rPoint.Y() );
594 geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle )
596 return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(),
597 rRectangle.Right(), rRectangle.Bottom() );
600 Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
602 return Size( rSize.Width,
603 rSize.Height );
606 Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint )
608 return Point( rPoint.X,
609 rPoint.Y );
612 Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
614 return Rectangle( rRectangle.X1, rRectangle.Y1,
615 rRectangle.X2, rRectangle.Y2 );
618 namespace
620 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
622 private:
623 uno::Sequence< sal_Int8 > m_aComponentTags;
625 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
627 return rendering::ColorSpaceType::RGB;
629 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
631 return m_aComponentTags;
633 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
635 return rendering::RenderingIntent::PERCEPTUAL;
637 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
639 return uno::Sequence< beans::PropertyValue >();
641 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
642 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
643 uno::RuntimeException)
645 // TODO(P3): if we know anything about target
646 // colorspace, this can be greatly sped up
647 uno::Sequence<rendering::ARGBColor> aIntermediate(
648 convertToARGB(deviceColor));
649 return targetColorSpace->convertFromARGB(aIntermediate);
651 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
653 const double* pIn( deviceColor.getConstArray() );
654 const sal_Size nLen( deviceColor.getLength() );
655 ENSURE_ARG_OR_THROW2(nLen%4==0,
656 "number of channels no multiple of 4",
657 static_cast<rendering::XColorSpace*>(this), 0);
659 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
660 rendering::RGBColor* pOut( aRes.getArray() );
661 for( sal_Size i=0; i<nLen; i+=4 )
663 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
664 pIn += 4;
666 return aRes;
668 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
670 const double* pIn( deviceColor.getConstArray() );
671 const sal_Size nLen( deviceColor.getLength() );
672 ENSURE_ARG_OR_THROW2(nLen%4==0,
673 "number of channels no multiple of 4",
674 static_cast<rendering::XColorSpace*>(this), 0);
676 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
677 rendering::ARGBColor* pOut( aRes.getArray() );
678 for( sal_Size i=0; i<nLen; i+=4 )
680 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
681 pIn += 4;
683 return aRes;
685 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
687 const double* pIn( deviceColor.getConstArray() );
688 const sal_Size nLen( deviceColor.getLength() );
689 ENSURE_ARG_OR_THROW2(nLen%4==0,
690 "number of channels no multiple of 4",
691 static_cast<rendering::XColorSpace*>(this), 0);
693 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
694 rendering::ARGBColor* pOut( aRes.getArray() );
695 for( sal_Size i=0; i<nLen; i+=4 )
697 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
698 pIn += 4;
700 return aRes;
702 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
704 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
705 const sal_Size nLen( rgbColor.getLength() );
707 uno::Sequence< double > aRes(nLen*4);
708 double* pColors=aRes.getArray();
709 for( sal_Size i=0; i<nLen; ++i )
711 *pColors++ = pIn->Red;
712 *pColors++ = pIn->Green;
713 *pColors++ = pIn->Blue;
714 *pColors++ = 1.0;
715 ++pIn;
717 return aRes;
719 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
721 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
722 const sal_Size nLen( rgbColor.getLength() );
724 uno::Sequence< double > aRes(nLen*4);
725 double* pColors=aRes.getArray();
726 for( sal_Size i=0; i<nLen; ++i )
728 *pColors++ = pIn->Red;
729 *pColors++ = pIn->Green;
730 *pColors++ = pIn->Blue;
731 *pColors++ = pIn->Alpha;
732 ++pIn;
734 return aRes;
736 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
738 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
739 const sal_Size nLen( rgbColor.getLength() );
741 uno::Sequence< double > aRes(nLen*4);
742 double* pColors=aRes.getArray();
743 for( sal_Size i=0; i<nLen; ++i )
745 *pColors++ = pIn->Red/pIn->Alpha;
746 *pColors++ = pIn->Green/pIn->Alpha;
747 *pColors++ = pIn->Blue/pIn->Alpha;
748 *pColors++ = pIn->Alpha;
749 ++pIn;
751 return aRes;
754 public:
755 StandardColorSpace() : m_aComponentTags(4)
757 sal_Int8* pTags = m_aComponentTags.getArray();
758 pTags[0] = rendering::ColorComponentTag::RGB_RED;
759 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
760 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
761 pTags[3] = rendering::ColorComponentTag::ALPHA;
766 uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace()
768 return new StandardColorSpace();
771 //---------------------------------------------------------------------------------------
773 uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor )
775 uno::Sequence< double > aRet(4);
776 double* pRet = aRet.getArray();
778 pRet[0] = toDoubleColor(rColor.GetRed());
779 pRet[1] = toDoubleColor(rColor.GetGreen());
780 pRet[2] = toDoubleColor(rColor.GetBlue());
782 // VCL's notion of alpha is different from the rest of the world's
783 pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency());
785 return aRet;
788 Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor )
790 ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
791 "color must have 4 channels" );
793 Color aColor;
795 aColor.SetRed ( toByteColor(rColor[0]) );
796 aColor.SetGreen( toByteColor(rColor[1]) );
797 aColor.SetBlue ( toByteColor(rColor[2]) );
798 // VCL's notion of alpha is different from the rest of the world's
799 aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
801 return aColor;
804 uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence(
805 const Color& rColor,
806 const uno::Reference< rendering::XColorSpace >& xColorSpace )
808 uno::Sequence<rendering::ARGBColor> aSeq(1);
809 aSeq[0] = rendering::ARGBColor(
810 1.0-toDoubleColor(rColor.GetTransparency()),
811 toDoubleColor(rColor.GetRed()),
812 toDoubleColor(rColor.GetGreen()),
813 toDoubleColor(rColor.GetBlue()) );
815 return xColorSpace->convertFromARGB(aSeq);
818 Color VCL_DLLPUBLIC doubleSequenceToColor(
819 const uno::Sequence< double > rColor,
820 const uno::Reference< rendering::XColorSpace >& xColorSpace )
822 const rendering::ARGBColor& rARGBColor(
823 xColorSpace->convertToARGB(rColor)[0]);
825 return Color( 255-toByteColor(rARGBColor.Alpha),
826 toByteColor(rARGBColor.Red),
827 toByteColor(rARGBColor.Green),
828 toByteColor(rARGBColor.Blue) );
831 //---------------------------------------------------------------------------------------
833 } // namespace vcltools
835 } // namespace canvas
837 // eof