summaryrefslogtreecommitdiff
path: root/vcl/source/helper
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2008-06-24 10:41:34 +0000
committerKurt Zenker <kz@openoffice.org>2008-06-24 10:41:34 +0000
commit9d3e9d5f5da6baef8f3ea9deb17ef6b04f6b22b2 (patch)
treeb3bf9aa185c4390a8ba161835568ad18928a0699 /vcl/source/helper
parent7f6e151b25ca63e4eee637324bc2aeeae1b032c8 (diff)
INTEGRATION: CWS canvas05 (1.13.56); FILE MERGED
2008/04/21 07:47:36 thb 1.13.56.5: RESYNC: (1.13-1.14); FILE MERGED 2008/04/04 22:06:55 thb 1.13.56.4: Fixed typo in alpha channel sequence index 2008/03/13 16:56:55 thb 1.13.56.3: Adapting VCL ColorSpace impls to API change; implementing some cheap paths for color space conversions 2007/10/02 11:03:26 thb 1.13.56.2: #i10000# WaE fix for Solaris 2007/10/01 13:40:13 thb 1.13.56.1: #i78888# #i78925# #i79258# #i79437# #i79846# Merge from CWS picom
Diffstat (limited to 'vcl/source/helper')
-rw-r--r--vcl/source/helper/canvastools.cxx521
1 files changed, 384 insertions, 137 deletions
diff --git a/vcl/source/helper/canvastools.cxx b/vcl/source/helper/canvastools.cxx
index cf6abc986eb1..3a239d7c3b3c 100644
--- a/vcl/source/helper/canvastools.cxx
+++ b/vcl/source/helper/canvastools.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: canvastools.cxx,v $
- * $Revision: 1.14 $
+ * $Revision: 1.15 $
*
* This file is part of OpenOffice.org.
*
@@ -30,51 +30,27 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
+
#include <rtl/logfile.hxx>
+#include <cppuhelper/compbase1.hxx>
-#ifndef _COM_SUN_STAR_GEOMETRY_REALSIZE2D_HPP__
#include <com/sun/star/geometry/RealSize2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_REALPOINT2D_HPP__
#include <com/sun/star/geometry/RealPoint2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_REALRECTANGLE2D_HPP__
#include <com/sun/star/geometry/RealRectangle2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_INTEGERSIZE2D_HPP__
#include <com/sun/star/geometry/IntegerSize2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_INTEGERPOINT2D_HPP__
#include <com/sun/star/geometry/IntegerPoint2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_INTEGERRECTANGLE2D_HPP__
#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
-#endif
+#include <com/sun/star/geometry/RealBezierSegment2D.hpp>
-#ifndef _COM_SUN_STAR_RENDERING_XGRAPHICDEVICE_HPP__
+#include <com/sun/star/rendering/ColorSpaceType.hpp>
+#include <com/sun/star/rendering/RenderingIntent.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_XBITMAP_HPP__
#include <com/sun/star/rendering/XBitmap.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_XPOLYPOLYGON2D_HPP__
#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_GEOMETRY_REALBEZIERSEGMENT2D_HPP__
-#include <com/sun/star/geometry/RealBezierSegment2D.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_INTEGERBITMAPFORMAT_HPP__
-#include <com/sun/star/rendering/IntegerBitmapFormat.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_INTEGERBITMAPLAYOUT_HPP__
#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_ENDIANNESS_HPP__
-#include <com/sun/star/rendering/Endianness.hpp>
-#endif
-#ifndef _COM_SUN_STAR_RENDERING_XINTEGERBITMAP_HPP__
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
-#endif
+#include <com/sun/star/rendering/ColorComponentTag.hpp>
+
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/point/b2dpoint.hxx>
@@ -89,6 +65,7 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <tools/poly.hxx>
+#include <tools/diagnose_ex.h>
#include <rtl/uuid.h>
#include <vcl/salbtype.hxx>
@@ -227,140 +204,229 @@ namespace vcl
//---------------------------------------------------------------------------------------
- ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
- const uno::Reference< rendering::XIntegerBitmap >& xInputBitmap )
+ namespace
{
- RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
-
- if( !xGraphicDevice.is() || !xInputBitmap.is() )
- return ::BitmapEx();
-
- uno::Reference< lang::XUnoTunnel > xTunnel( xInputBitmap, uno::UNO_QUERY );
- if( xTunnel.is() )
+ inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
+ const rendering::IntegerBitmapLayout& rRHS )
{
- const uno::Sequence< sal_Int8 >& rTest = getTunnelIdentifier( Id_BitmapEx );
- sal_Int64 nPtr = xTunnel->getSomething( rTest );
- if( nPtr != 0 )
- {
- return BitmapEx( *(BitmapEx*)sal_IntPtr(nPtr) );
- }
+ return
+ rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
+ rLHS.ScanLineStride == rRHS.ScanLineStride &&
+ rLHS.PlaneStride == rRHS.PlaneStride &&
+ rLHS.ColorSpace == rRHS.ColorSpace &&
+ rLHS.Palette == rRHS.Palette &&
+ rLHS.IsMsbFirst == rRHS.IsMsbFirst;
}
- rendering::IntegerBitmapLayout aFormat;
- const Size aPixelSize( sizeFromIntegerSize2D( xInputBitmap->getSize() ) );
- const uno::Sequence< sal_Int8 > data( xInputBitmap->getData(
- aFormat,
- geometry::IntegerRectangle2D(0,0,aPixelSize.Width(),aPixelSize.Height()) ) );
-
- ::Bitmap aBitmap( aPixelSize, 24 ); // create 24bpp Bitmap
- ::Bitmap aAlpha( aPixelSize, 8 ); // create 8bpp alpha Bitmap
-
+ bool readBmp( sal_Int32 nWidth,
+ sal_Int32 nHeight,
+ const rendering::IntegerBitmapLayout& rLayout,
+ const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
+ ScopedBitmapWriteAccess& rWriteAcc,
+ ScopedBitmapWriteAccess& rAlphaAcc )
{
- ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
- aBitmap );
- ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.AcquireWriteAccess(),
- aAlpha );
+ rendering::IntegerBitmapLayout aCurrLayout;
+ geometry::IntegerRectangle2D aRect;
+ uno::Sequence<sal_Int8> aPixelData;
+ uno::Sequence<rendering::RGBColor> aRGBColors;
+ uno::Sequence<rendering::ARGBColor> aARGBColors;
- if( pWriteAccess.get() != NULL &&
- pAlphaWriteAccess.get() != NULL )
+ for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
{
- // for the time being, always read as BGRA
- int nCurrPos(0);
- for( int y=0; y<aPixelSize.Height(); ++y )
+ aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
+ try
{
- for( int x=0; x<aPixelSize.Width(); ++x )
- {
- pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos+2 ],
- data[ nCurrPos+1 ],
- data[ nCurrPos ] ) );
- nCurrPos += 3;
+ aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
+ }
+ catch( rendering::VolatileContentDestroyedException& )
+ {
+ // re-read bmp from the start
+ return false;
+ }
+ if( !(aCurrLayout == rLayout) )
+ return false; // re-read bmp from the start
- pAlphaWriteAccess->SetPixel( y, x, BitmapColor( 255 - data[ nCurrPos++ ] ) );
+ if( rAlphaAcc.get() )
+ {
+ // read ARGB color
+ aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
+ for( sal_Int32 x=0; x<nWidth; ++x )
+ {
+ const rendering::ARGBColor& rColor=aARGBColors[x];
+ rWriteAcc->SetPixel( aRect.Y1, x,
+ BitmapColor( toByteColor(rColor.Red),
+ toByteColor(rColor.Green),
+ toByteColor(rColor.Blue) ));
+ rAlphaAcc->SetPixel( aRect.Y1, x,
+ BitmapColor( 255 - toByteColor(rColor.Alpha) ));
+ }
+ }
+ else
+ {
+ // read RGB color
+ aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
+ for( sal_Int32 x=0; x<nWidth; ++x )
+ {
+ const rendering::RGBColor& rColor=aRGBColors[x];
+ rWriteAcc->SetPixel( aRect.Y1, x,
+ BitmapColor( toByteColor(rColor.Red),
+ toByteColor(rColor.Green),
+ toByteColor(rColor.Blue) ));
}
}
}
- }
-
- return ::BitmapEx( aBitmap,
- AlphaMask( aAlpha ) );
- }
-
- //---------------------------------------------------------------------------------------
-
- uno::Sequence< double > colorToDoubleSequence( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
- const Color& rColor )
- {
- // TODO: handle color space conversions, when defined on canvas/graphicDevice
- uno::Sequence< double > aRet(4);
- double* pRet = aRet.getArray();
-
- pRet[0] = rColor.GetRed() / 255.0;
- pRet[1] = rColor.GetGreen() / 255.0;
- pRet[2] = rColor.GetBlue() / 255.0;
-
- // out notion of alpha is different from the rest of the world's
- pRet[3] = 1.0 - rColor.GetTransparency() / 255.0;
- return aRet;
+ return true;
+ }
}
- uno::Sequence< sal_Int8 > colorToIntSequence( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
- const Color& rColor )
+ ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
{
- // TODO: handle color space conversions, when defined on canvas/graphicDevice
- uno::Sequence< sal_Int8 > aRet(4);
- sal_Int8* pRet = aRet.getArray();
-
- pRet[0] = rColor.GetRed();
- pRet[1] = rColor.GetGreen();
- pRet[2] = rColor.GetBlue();
-
- // out notion of alpha is different from the rest of the world's
- pRet[3] = 255 - rColor.GetTransparency();
+ RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
- return aRet;
- }
+ if( !xInputBitmap.is() )
+ return ::BitmapEx();
- Color sequenceToColor( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
- const uno::Sequence< sal_Int8 >& rColor )
- {
- OSL_ENSURE( rColor.getLength() > 2, "sequenceToColor: need at least three channels" );
+ // tunnel directly for known implementation
+ // ----------------------------------------------------------------
+ VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
+ if( pImplBitmap )
+ return pImplBitmap->getBitmapEx();
- // TODO: handle color space conversions, when defined on canvas/graphicDevice
- Color aColor;
+ // retrieve data via UNO interface
+ // ----------------------------------------------------------------
- aColor.SetRed ( rColor[0] );
- aColor.SetGreen( rColor[1] );
- aColor.SetBlue ( rColor[2] );
+ // volatile bitmaps are a bit more complicated to read
+ // from..
+ uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
+ xInputBitmap, uno::UNO_QUERY);
- if( rColor.getLength() > 3 )
+ // loop a few times, until successfully read (for XVolatileBitmap)
+ for( int i=0; i<10; ++i )
{
- // out notion of alpha is different from the rest of the world's
- aColor.SetTransparency( 255 - rColor[3] );
- }
+ sal_Int32 nDepth=0;
+ sal_Int32 nAlphaDepth=0;
+ const rendering::IntegerBitmapLayout aLayout(
+ xInputBitmap->getMemoryLayout());
- return aColor;
- }
+ OSL_ENSURE(aLayout.ColorSpace.is(),
+ "Cannot convert image without color space!");
+ if( !aLayout.ColorSpace.is() )
+ return ::BitmapEx();
- Color sequenceToColor( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
- const uno::Sequence< double >& rColor )
- {
- OSL_ENSURE( rColor.getLength() > 2, "sequenceToColor: need at least three channels" );
+ nDepth = aLayout.ColorSpace->getBitsPerPixel();
- // TODO: handle color space conversions, when defined on canvas/graphicDevice
- Color aColor;
+ if( xInputBitmap->hasAlpha() )
+ {
+ // determine alpha channel depth
+ const uno::Sequence<sal_Int8> aTags(
+ aLayout.ColorSpace->getComponentTags() );
+ const uno::Sequence<sal_Int32> aDepths(
+ aLayout.ColorSpace->getComponentBitCounts() );
+ const sal_Int8* pStart(aTags.getConstArray());
+ const sal_Size nLen(aTags.getLength());
+ const sal_Int8* pEnd(pStart+nLen);
+
+ const std::ptrdiff_t nAlphaIndex =
+ std::find(pStart,pEnd,
+ rendering::ColorComponentTag::ALPHA) - pStart;
+
+ if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
+ {
+ nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
+ nDepth -= nAlphaDepth;
+ }
+ }
- aColor.SetRed ( static_cast<UINT8>( 255*rColor[0] + .5 ) );
- aColor.SetGreen( static_cast<UINT8>( 255*rColor[1] + .5 ) );
- aColor.SetBlue ( static_cast<UINT8>( 255*rColor[2] + .5 ) );
+ BitmapPalette aPalette;
+ if( aLayout.Palette.is() )
+ {
+ uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
+ aLayout.Palette->getColorSpace());
+ ENSURE_OR_THROW(xPaletteColorSpace.is(),
+ "Palette without color space");
- if( rColor.getLength() > 3 )
- {
- // out notion of alpha is different from the rest of the world's
- aColor.SetTransparency( static_cast<UINT8>( 255 - 255*rColor[3] + .5 ) );
+ const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
+ if( nEntryCount <= 256 )
+ {
+ if( nEntryCount <= 2 )
+ nDepth = 1;
+ else
+ nDepth = 8;
+
+ const USHORT nPaletteEntries(
+ sal::static_int_cast<USHORT>(
+ std::min(sal_Int32(255), nEntryCount)));
+
+ // copy palette entries
+ aPalette.SetEntryCount(nPaletteEntries);
+ uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
+ uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
+
+ uno::Sequence<double> aPaletteEntry;
+ for( USHORT j=0; j<nPaletteEntries; ++j )
+ {
+ if( !xPalette->getIndex(aPaletteEntry,j) &&
+ nAlphaDepth == 0 )
+ {
+ nAlphaDepth = 1;
+ }
+ uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
+ ENSURE_OR_THROW(aColors.getLength() == 1,
+ "Palette returned more or less than one entry");
+ const rendering::RGBColor& rColor=aColors[0];
+ aPalette[j] = BitmapColor(toByteColor(rColor.Red),
+ toByteColor(rColor.Green),
+ toByteColor(rColor.Blue));
+ }
+ }
+ }
+
+ const ::Size aPixelSize(
+ sizeFromIntegerSize2D(xInputBitmap->getSize()));
+
+ // normalize bitcount
+ nDepth =
+ ( nDepth <= 1 ) ? 1 :
+ ( nDepth <= 4 ) ? 4 :
+ ( nDepth <= 8 ) ? 8 : 24;
+
+ ::Bitmap aBitmap( aPixelSize,
+ sal::static_int_cast<USHORT>(nDepth),
+ aLayout.Palette.is() ? &aPalette : NULL );
+ ::Bitmap aAlpha;
+ if( nAlphaDepth )
+ aAlpha = ::Bitmap( aPixelSize,
+ sal::static_int_cast<USHORT>(nAlphaDepth),
+ &::Bitmap::GetGreyPalette(
+ sal::static_int_cast<USHORT>(1L << nAlphaDepth)) );
+
+ { // limit scoped access
+ ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
+ aBitmap );
+ ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.AcquireWriteAccess(),
+ aAlpha );
+
+ ENSURE_OR_THROW(pWriteAccess.get() != NULL,
+ "Cannot get write access to bitmap");
+
+ const sal_Int32 nWidth(aPixelSize.Width());
+ const sal_Int32 nHeight(aPixelSize.Height());
+
+ if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
+ pWriteAccess,pAlphaWriteAccess) )
+ continue;
+ } // limit scoped access
+
+ if( nAlphaDepth )
+ return ::BitmapEx( aBitmap,
+ AlphaMask( aAlpha ) );
+ else
+ return ::BitmapEx( aBitmap );
}
- return aColor;
+ // failed to read data 10 times - bail out
+ return ::BitmapEx();
}
//---------------------------------------------------------------------------------------
@@ -519,6 +585,187 @@ namespace vcl
rRectangle.X2, rRectangle.Y2 );
}
+ namespace
+ {
+ class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
+ {
+ private:
+ uno::Sequence< sal_Int8 > m_aComponentTags;
+
+ virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
+ {
+ return rendering::ColorSpaceType::RGB;
+ }
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
+ {
+ return m_aComponentTags;
+ }
+ virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
+ {
+ return rendering::RenderingIntent::PERCEPTUAL;
+ }
+ virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
+ {
+ return uno::Sequence< beans::PropertyValue >();
+ }
+ virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
+ const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+ {
+ // TODO(P3): if we know anything about target
+ // colorspace, this can be greatly sped up
+ uno::Sequence<rendering::ARGBColor> aIntermediate(
+ convertToARGB(deviceColor));
+ return targetColorSpace->convertFromARGB(aIntermediate);
+ }
+ virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const double* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::RGBColor > aRes(nLen/4);
+ rendering::RGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const double* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::RGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< double > aRes(nLen*4);
+ double* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = pIn->Red;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Blue;
+ *pColors++ = 1.0;
+ ++pIn;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< double > aRes(nLen*4);
+ double* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = pIn->Red;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Blue;
+ *pColors++ = pIn->Alpha;
+ ++pIn;
+ }
+ return aRes;
+ }
+
+ public:
+ StandardColorSpace() : m_aComponentTags(4)
+ {
+ sal_Int8* pTags = m_aComponentTags.getArray();
+ pTags[0] = rendering::ColorComponentTag::RGB_RED;
+ pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
+ pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
+ pTags[3] = rendering::ColorComponentTag::ALPHA;
+ }
+ };
+ }
+
+ uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace()
+ {
+ return new StandardColorSpace();
+ }
+
+ //---------------------------------------------------------------------------------------
+
+ uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor )
+ {
+ uno::Sequence< double > aRet(4);
+ double* pRet = aRet.getArray();
+
+ pRet[0] = toDoubleColor(rColor.GetRed());
+ pRet[1] = toDoubleColor(rColor.GetGreen());
+ pRet[2] = toDoubleColor(rColor.GetBlue());
+
+ // VCL's notion of alpha is different from the rest of the world's
+ pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency());
+
+ return aRet;
+ }
+
+ Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor )
+ {
+ ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
+ "color must have 4 channels" );
+
+ Color aColor;
+
+ aColor.SetRed ( toByteColor(rColor[0]) );
+ aColor.SetGreen( toByteColor(rColor[1]) );
+ aColor.SetBlue ( toByteColor(rColor[2]) );
+ // VCL's notion of alpha is different from the rest of the world's
+ aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
+
+ return aColor;
+ }
+
+ uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence(
+ const Color& rColor,
+ const uno::Reference< rendering::XColorSpace >& xColorSpace )
+ {
+ uno::Sequence<rendering::ARGBColor> aSeq(1);
+ aSeq[0] = rendering::ARGBColor(
+ 1.0-toDoubleColor(rColor.GetTransparency()),
+ toDoubleColor(rColor.GetRed()),
+ toDoubleColor(rColor.GetGreen()),
+ toDoubleColor(rColor.GetBlue()) );
+
+ return xColorSpace->convertFromARGB(aSeq);
+ }
+
+ Color VCL_DLLPUBLIC doubleSequenceToColor(
+ const uno::Sequence< double > rColor,
+ const uno::Reference< rendering::XColorSpace >& xColorSpace )
+ {
+ const rendering::ARGBColor& rARGBColor(
+ xColorSpace->convertToARGB(rColor)[0]);
+
+ return Color( 255-toByteColor(rARGBColor.Alpha),
+ toByteColor(rARGBColor.Red),
+ toByteColor(rARGBColor.Green),
+ toByteColor(rARGBColor.Blue) );
+ }
+
+ //---------------------------------------------------------------------------------------
+
} // namespace vcltools
} // namespace canvas