/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #i79917# #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; namespace vcl { namespace unotools { // #i79917# removed helpers bezierSequenceFromPolygon and // pointSequenceFromPolygon here // Also all helpers using tools Polygon and PolyPolygon will get mapped to the // B2DPolygon helpers for these cases, see comments with the same TaskID below. // TODO: Remove those wrapped methods //--------------------------------------------------------------------------------------- uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, const ::Polygon& inputPolygon ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" ); // #i79917# map to basegfx const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon()); return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon); } //--------------------------------------------------------------------------------------- uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, const ::PolyPolygon& inputPolyPolygon ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" ); // #i79917# map to basegfx const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon()); return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon); } //--------------------------------------------------------------------------------------- ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" ); const sal_uInt16 nCurrSize( sal::static_int_cast(points.getLength()) ); ::Polygon aPoly( nCurrSize ); sal_uInt16 nCurrPoint; for( nCurrPoint=0; nCurrPoint >& points ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" ); ::PolyPolygon aRes; int nCurrPoly; for( nCurrPoly=0; nCurrPoly& curves ) { // #i79917# map to basegfx const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves)); return ::Polygon(aB2DPolygon); } //--------------------------------------------------------------------------------------- ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves ) { // #i79917# map to basegfx const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves)); return ::PolyPolygon(aB2DPolyPolygon); } //--------------------------------------------------------------------------------------- uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, const ::Bitmap& inputBitmap ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" ); return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) ); } //--------------------------------------------------------------------------------------- uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, const ::BitmapEx& inputBitmap ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" ); return new vcl::unotools::VclCanvasBitmap( inputBitmap ); } //--------------------------------------------------------------------------------------- const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType ) { static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds; std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it = aIds.find( eType ); if( it == aIds.end() ) { uno::Sequence< sal_Int8 > aNewId( 16 ); rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True ); aIds[ eType ] = aNewId; it = aIds.find( eType ); } return it->second; } //--------------------------------------------------------------------------------------- namespace { inline bool operator==( const rendering::IntegerBitmapLayout& rLHS, const rendering::IntegerBitmapLayout& rRHS ) { 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; } bool readBmp( sal_Int32 nWidth, sal_Int32 nHeight, const rendering::IntegerBitmapLayout& rLayout, const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap, ScopedBitmapWriteAccess& rWriteAcc, ScopedBitmapWriteAccess& rAlphaAcc ) { rendering::IntegerBitmapLayout aCurrLayout; geometry::IntegerRectangle2D aRect; uno::Sequence aPixelData; uno::Sequence aRGBColors; uno::Sequence aARGBColors; for( aRect.Y1=0; aRect.Y1getData(aCurrLayout,aRect); } catch( rendering::VolatileContentDestroyedException& ) { // re-read bmp from the start return false; } if( !(aCurrLayout == rLayout) ) return false; // re-read bmp from the start if( rAlphaAcc.get() ) { // read ARGB color aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData); if( rWriteAcc->HasPalette() ) { for( sal_Int32 x=0; xSetPixelIndex( aRect.Y1, x, (sal_uInt8) rWriteAcc->GetBestPaletteIndex( BitmapColor( toByteColor(rColor.Red), toByteColor(rColor.Green), toByteColor(rColor.Blue))) ); rAlphaAcc->SetPixel( aRect.Y1, x, BitmapColor( 255 - toByteColor(rColor.Alpha) )); } } else { for( sal_Int32 x=0; xSetPixel( 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); if( rWriteAcc->HasPalette() ) { for( sal_Int32 x=0; xSetPixelIndex( aRect.Y1, x, (sal_uInt8) rWriteAcc->GetBestPaletteIndex( BitmapColor( toByteColor(rColor.Red), toByteColor(rColor.Green), toByteColor(rColor.Blue))) ); } } else { for( sal_Int32 x=0; xSetPixel( aRect.Y1, x, BitmapColor( toByteColor(rColor.Red), toByteColor(rColor.Green), toByteColor(rColor.Blue) )); } } } } return true; } } ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap ) { RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" ); if( !xInputBitmap.is() ) return ::BitmapEx(); // tunnel directly for known implementation // ---------------------------------------------------------------- VclCanvasBitmap* pImplBitmap = dynamic_cast(xInputBitmap.get()); if( pImplBitmap ) return pImplBitmap->getBitmapEx(); // retrieve data via UNO interface // ---------------------------------------------------------------- // volatile bitmaps are a bit more complicated to read // from.. uno::Reference xVolatileBitmap( xInputBitmap, uno::UNO_QUERY); // loop a few times, until successfully read (for XVolatileBitmap) for( int i=0; i<10; ++i ) { sal_Int32 nDepth=0; sal_Int32 nAlphaDepth=0; const rendering::IntegerBitmapLayout aLayout( xInputBitmap->getMemoryLayout()); OSL_ENSURE(aLayout.ColorSpace.is(), "Cannot convert image without color space!"); if( !aLayout.ColorSpace.is() ) return ::BitmapEx(); nDepth = aLayout.ColorSpace->getBitsPerPixel(); if( xInputBitmap->hasAlpha() ) { // determine alpha channel depth const uno::Sequence aTags( aLayout.ColorSpace->getComponentTags() ); const uno::Sequence 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(nLen) ) { nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1; nDepth -= nAlphaDepth; } } BitmapPalette aPalette; if( aLayout.Palette.is() ) { uno::Reference< rendering::XColorSpace > xPaletteColorSpace( aLayout.Palette->getColorSpace()); ENSURE_OR_THROW(xPaletteColorSpace.is(), "Palette without color space"); const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() ); if( nEntryCount <= 256 ) { if( nEntryCount <= 2 ) nDepth = 1; else nDepth = 8; const sal_uInt16 nPaletteEntries( sal::static_int_cast( std::min(sal_Int32(255), nEntryCount))); // copy palette entries aPalette.SetEntryCount(nPaletteEntries); uno::Reference xPalette( aLayout.Palette ); uno::Reference xPalColorSpace( xPalette->getColorSpace() ); uno::Sequence aPaletteEntry; for( sal_uInt16 j=0; jgetIndex(aPaletteEntry,j) && nAlphaDepth == 0 ) { nAlphaDepth = 1; } uno::Sequence 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(nDepth), aLayout.Palette.is() ? &aPalette : NULL ); ::Bitmap aAlpha; if( nAlphaDepth ) aAlpha = ::Bitmap( aPixelSize, sal::static_int_cast(nAlphaDepth), &::Bitmap::GetGreyPalette( sal::static_int_cast(1L << nAlphaDepth)) ); { // limit scoped access ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), aBitmap ); ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL, 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 ); } // failed to read data 10 times - bail out return ::BitmapEx(); } //--------------------------------------------------------------------------------------- geometry::RealSize2D size2DFromSize( const Size& rSize ) { return geometry::RealSize2D( rSize.Width(), rSize.Height() ); } geometry::RealPoint2D point2DFromPoint( const Point& rPoint ) { return geometry::RealPoint2D( rPoint.X(), rPoint.Y() ); } geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect ) { return geometry::RealRectangle2D( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ); } Size sizeFromRealSize2D( const geometry::RealSize2D& rSize ) { return Size( static_cast(rSize.Width + .5), static_cast(rSize.Height + .5) ); } Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint ) { return Point( static_cast(rPoint.X + .5), static_cast(rPoint.Y + .5) ); } Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect ) { return Rectangle( static_cast(rRect.X1 + .5), static_cast(rRect.Y1 + .5), static_cast(rRect.X2 + .5), static_cast(rRect.Y2 + .5) ); } ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec ) { return ::Size( FRound( rVec.getX() ), FRound( rVec.getY() ) ); } ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint ) { return ::Point( FRound( rPoint.getX() ), FRound( rPoint.getY() ) ); } ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect ) { return ::Rectangle( FRound( rRect.getMinX() ), FRound( rRect.getMinY() ), FRound( rRect.getMaxX() ), FRound( rRect.getMaxY() ) ); } Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec ) { return ::Size( rVec.getX(), rVec.getY() ); } Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint ) { return ::Point( rPoint.getX(), rPoint.getY() ); } Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect ) { return ::Rectangle( rRect.getMinX(), rRect.getMinY(), rRect.getMaxX(), rRect.getMaxY() ); } ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize ) { return ::basegfx::B2DVector( rSize.Width(), rSize.Height() ); } ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint ) { return ::basegfx::B2DPoint( rPoint.X(), rPoint.Y() ); } ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect ) { return ::basegfx::B2DRange( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ); } basegfx::B2IVector b2ISizeFromSize( const Size& rSize ) { return ::basegfx::B2IVector( rSize.Width(), rSize.Height() ); } basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint ) { return ::basegfx::B2IPoint( rPoint.X(), rPoint.Y() ); } basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect ) { return ::basegfx::B2IRange( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ); } geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize ) { return geometry::IntegerSize2D( rSize.Width(), rSize.Height() ); } geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint ) { return geometry::IntegerPoint2D( rPoint.X(), rPoint.Y() ); } geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle ) { return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom() ); } Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize ) { return Size( rSize.Width, rSize.Height ); } Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint ) { return Point( rPoint.X, rPoint.Y ); } Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle ) { return Rectangle( rRectangle.X1, rRectangle.Y1, 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 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(this), 0); uno::Sequence< rendering::RGBColor > aRes(nLen/4); rendering::RGBColor* pOut( aRes.getArray() ); for( sal_Size i=0; i 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(this), 0); uno::Sequence< rendering::ARGBColor > aRes(nLen/4); rendering::ARGBColor* pOut( aRes.getArray() ); for( sal_Size i=0; i SAL_CALL convertToPARGB( 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(this), 0); uno::Sequence< rendering::ARGBColor > aRes(nLen/4); rendering::ARGBColor* pOut( aRes.getArray() ); for( sal_Size i=0; i 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; iRed; *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; iRed; *pColors++ = pIn->Green; *pColors++ = pIn->Blue; *pColors++ = pIn->Alpha; ++pIn; } return aRes; } virtual uno::Sequence< double > SAL_CALL convertFromPARGB( 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; iRed/pIn->Alpha; *pColors++ = pIn->Green/pIn->Alpha; *pColors++ = pIn->Blue/pIn->Alpha; *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 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 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 // eof