1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppuhelper/compbase.hxx>
22 #include <com/sun/star/geometry/RealSize2D.hpp>
23 #include <com/sun/star/geometry/RealPoint2D.hpp>
24 #include <com/sun/star/geometry/RealRectangle2D.hpp>
25 #include <com/sun/star/geometry/IntegerSize2D.hpp>
26 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
27 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
28 #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
30 #include <com/sun/star/rendering/ColorSpaceType.hpp>
31 #include <com/sun/star/rendering/RenderingIntent.hpp>
32 #include <com/sun/star/rendering/XGraphicDevice.hpp>
33 #include <com/sun/star/rendering/XBitmap.hpp>
34 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
35 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
37 #include <com/sun/star/rendering/ColorComponentTag.hpp>
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <basegfx/vector/b2dsize.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/range/b2drectangle.hxx>
43 #include <basegfx/vector/b2isize.hxx>
44 #include <basegfx/point/b2ipoint.hxx>
45 #include <basegfx/range/b2irectangle.hxx>
46 #include <basegfx/polygon/b2dpolygon.hxx>
47 #include <basegfx/tools/canvastools.hxx>
48 #include <basegfx/polygon/b2dpolypolygon.hxx>
50 #include <tools/poly.hxx>
51 #include <tools/diagnose_ex.h>
54 #include <vcl/salbtype.hxx>
55 #include <vcl/bitmapaccess.hxx>
56 #include <vcl/bitmapex.hxx>
58 #include <canvasbitmap.hxx>
59 #include <vcl/canvastools.hxx>
61 using namespace ::com::sun::star
;
67 uno::Reference
< rendering::XBitmap
> xBitmapFromBitmapEx( const uno::Reference
< rendering::XGraphicDevice
>& /*xGraphicDevice*/,
68 const ::BitmapEx
& inputBitmap
)
70 SAL_INFO( "vcl.helper", "vcl::unotools::xBitmapFromBitmapEx()" );
72 return new vcl::unotools::VclCanvasBitmap( inputBitmap
);
77 inline bool equalsLayout( const rendering::IntegerBitmapLayout
& rLHS
,
78 const rendering::IntegerBitmapLayout
& rRHS
)
81 rLHS
.ScanLineBytes
== rRHS
.ScanLineBytes
&&
82 rLHS
.ScanLineStride
== rRHS
.ScanLineStride
&&
83 rLHS
.PlaneStride
== rRHS
.PlaneStride
&&
84 rLHS
.ColorSpace
== rRHS
.ColorSpace
&&
85 rLHS
.Palette
== rRHS
.Palette
&&
86 rLHS
.IsMsbFirst
== rRHS
.IsMsbFirst
;
88 bool readBmp( sal_Int32 nWidth
,
90 const rendering::IntegerBitmapLayout
& rLayout
,
91 const uno::Reference
< rendering::XIntegerReadOnlyBitmap
>& xInputBitmap
,
92 Bitmap::ScopedWriteAccess
& rWriteAcc
,
93 Bitmap::ScopedWriteAccess
& rAlphaAcc
)
95 rendering::IntegerBitmapLayout aCurrLayout
;
96 geometry::IntegerRectangle2D aRect
;
97 uno::Sequence
<sal_Int8
> aPixelData
;
98 uno::Sequence
<rendering::RGBColor
> aRGBColors
;
99 uno::Sequence
<rendering::ARGBColor
> aARGBColors
;
101 for( aRect
.Y1
=0; aRect
.Y1
<nHeight
; ++aRect
.Y1
)
103 aRect
.X1
= 0; aRect
.X2
= nWidth
; aRect
.Y2
= aRect
.Y1
+1;
106 aPixelData
= xInputBitmap
->getData(aCurrLayout
,aRect
);
108 catch( rendering::VolatileContentDestroyedException
& )
110 // re-read bmp from the start
113 if( !equalsLayout(aCurrLayout
, rLayout
) )
114 return false; // re-read bmp from the start
116 if( rAlphaAcc
.get() )
119 aARGBColors
= rLayout
.ColorSpace
->convertIntegerToARGB(aPixelData
);
121 if( rWriteAcc
->HasPalette() )
123 for( sal_Int32 x
=0; x
<nWidth
; ++x
)
125 const rendering::ARGBColor
& rColor
=aARGBColors
[x
];
126 rWriteAcc
->SetPixelIndex( aRect
.Y1
, x
,
127 (sal_uInt8
) rWriteAcc
->GetBestPaletteIndex(
128 BitmapColor( toByteColor(rColor
.Red
),
129 toByteColor(rColor
.Green
),
130 toByteColor(rColor
.Blue
))) );
131 rAlphaAcc
->SetPixel( aRect
.Y1
, x
,
132 BitmapColor( 255 - toByteColor(rColor
.Alpha
) ));
137 for( sal_Int32 x
=0; x
<nWidth
; ++x
)
139 const rendering::ARGBColor
& rColor
=aARGBColors
[x
];
140 rWriteAcc
->SetPixel( aRect
.Y1
, x
,
141 BitmapColor( toByteColor(rColor
.Red
),
142 toByteColor(rColor
.Green
),
143 toByteColor(rColor
.Blue
) ));
144 rAlphaAcc
->SetPixel( aRect
.Y1
, x
,
145 BitmapColor( 255 - toByteColor(rColor
.Alpha
) ));
152 aRGBColors
= rLayout
.ColorSpace
->convertIntegerToRGB(aPixelData
);
153 if( rWriteAcc
->HasPalette() )
155 for( sal_Int32 x
=0; x
<nWidth
; ++x
)
157 const rendering::RGBColor
& rColor
=aRGBColors
[x
];
158 rWriteAcc
->SetPixelIndex( aRect
.Y1
, x
,
159 (sal_uInt8
) rWriteAcc
->GetBestPaletteIndex(
160 BitmapColor( toByteColor(rColor
.Red
),
161 toByteColor(rColor
.Green
),
162 toByteColor(rColor
.Blue
))) );
167 for( sal_Int32 x
=0; x
<nWidth
; ++x
)
169 const rendering::RGBColor
& rColor
=aRGBColors
[x
];
170 rWriteAcc
->SetPixel( aRect
.Y1
, x
,
171 BitmapColor( toByteColor(rColor
.Red
),
172 toByteColor(rColor
.Green
),
173 toByteColor(rColor
.Blue
) ));
183 ::BitmapEx
bitmapExFromXBitmap( const uno::Reference
< rendering::XIntegerReadOnlyBitmap
>& xInputBitmap
)
185 SAL_INFO( "vcl.helper", "vcl::unotools::bitmapExFromXBitmap()" );
187 if( !xInputBitmap
.is() )
190 // tunnel directly for known implementation
191 VclCanvasBitmap
* pImplBitmap
= dynamic_cast<VclCanvasBitmap
*>(xInputBitmap
.get());
193 return pImplBitmap
->getBitmapEx();
195 // retrieve data via UNO interface
197 // volatile bitmaps are a bit more complicated to read
199 uno::Reference
<rendering::XVolatileBitmap
> xVolatileBitmap(
200 xInputBitmap
, uno::UNO_QUERY
);
202 // loop a few times, until successfully read (for XVolatileBitmap)
203 for( int i
=0; i
<10; ++i
)
206 sal_Int32 nAlphaDepth
=0;
207 const rendering::IntegerBitmapLayout
aLayout(
208 xInputBitmap
->getMemoryLayout());
210 OSL_ENSURE(aLayout
.ColorSpace
.is(),
211 "Cannot convert image without color space!");
212 if( !aLayout
.ColorSpace
.is() )
215 nDepth
= aLayout
.ColorSpace
->getBitsPerPixel();
217 if( xInputBitmap
->hasAlpha() )
219 // determine alpha channel depth
220 const uno::Sequence
<sal_Int8
> aTags(
221 aLayout
.ColorSpace
->getComponentTags() );
222 const sal_Int8
* pStart(aTags
.getConstArray());
223 const std::size_t nLen(aTags
.getLength());
224 const sal_Int8
* pEnd(pStart
+nLen
);
226 const std::ptrdiff_t nAlphaIndex
=
227 std::find(pStart
,pEnd
,
228 rendering::ColorComponentTag::ALPHA
) - pStart
;
230 if( nAlphaIndex
< sal::static_int_cast
<std::ptrdiff_t>(nLen
) )
232 nAlphaDepth
= aLayout
.ColorSpace
->getComponentBitCounts()[nAlphaIndex
] > 1 ? 8 : 1;
233 nDepth
-= nAlphaDepth
;
237 BitmapPalette aPalette
;
238 if( aLayout
.Palette
.is() )
240 uno::Reference
< rendering::XColorSpace
> xPaletteColorSpace(
241 aLayout
.Palette
->getColorSpace());
242 ENSURE_OR_THROW(xPaletteColorSpace
.is(),
243 "Palette without color space");
245 const sal_Int32
nEntryCount( aLayout
.Palette
->getNumberOfEntries() );
246 if( nEntryCount
<= 256 )
248 if( nEntryCount
<= 2 )
253 const sal_uInt16
nPaletteEntries(
254 sal::static_int_cast
<sal_uInt16
>(
255 std::min(sal_Int32(255), nEntryCount
)));
257 // copy palette entries
258 aPalette
.SetEntryCount(nPaletteEntries
);
259 uno::Reference
<rendering::XBitmapPalette
> xPalette( aLayout
.Palette
);
260 uno::Reference
<rendering::XColorSpace
> xPalColorSpace( xPalette
->getColorSpace() );
262 uno::Sequence
<double> aPaletteEntry
;
263 for( sal_uInt16 j
=0; j
<nPaletteEntries
; ++j
)
265 if( !xPalette
->getIndex(aPaletteEntry
,j
) &&
270 uno::Sequence
<rendering::RGBColor
> aColors
=xPalColorSpace
->convertToRGB(aPaletteEntry
);
271 ENSURE_OR_THROW(aColors
.getLength() == 1,
272 "Palette returned more or less than one entry");
273 const rendering::RGBColor
& rColor
=aColors
[0];
274 aPalette
[j
] = BitmapColor(toByteColor(rColor
.Red
),
275 toByteColor(rColor
.Green
),
276 toByteColor(rColor
.Blue
));
281 const ::Size
aPixelSize(
282 sizeFromIntegerSize2D(xInputBitmap
->getSize()));
284 // normalize bitcount
286 ( nDepth
<= 1 ) ? 1 :
287 ( nDepth
<= 4 ) ? 4 :
288 ( nDepth
<= 8 ) ? 8 : 24;
290 ::Bitmap
aBitmap( aPixelSize
,
291 sal::static_int_cast
<sal_uInt16
>(nDepth
),
292 aLayout
.Palette
.is() ? &aPalette
: nullptr );
295 aAlpha
= ::Bitmap( aPixelSize
,
296 sal::static_int_cast
<sal_uInt16
>(nAlphaDepth
),
297 &::Bitmap::GetGreyPalette(
298 sal::static_int_cast
<sal_uInt16
>(1L << nAlphaDepth
)) );
300 { // limit scoped access
301 Bitmap::ScopedWriteAccess
pWriteAccess( aBitmap
);
302 Bitmap::ScopedWriteAccess
pAlphaWriteAccess( nAlphaDepth
? aAlpha
.AcquireWriteAccess() : nullptr,
305 ENSURE_OR_THROW(pWriteAccess
.get() != nullptr,
306 "Cannot get write access to bitmap");
308 const sal_Int32
nWidth(aPixelSize
.Width());
309 const sal_Int32
nHeight(aPixelSize
.Height());
311 if( !readBmp(nWidth
,nHeight
,aLayout
,xInputBitmap
,
312 pWriteAccess
,pAlphaWriteAccess
) )
314 } // limit scoped access
317 return ::BitmapEx( aBitmap
,
318 AlphaMask( aAlpha
) );
320 return ::BitmapEx( aBitmap
);
323 // failed to read data 10 times - bail out
327 geometry::RealSize2D
size2DFromSize( const Size
& rSize
)
329 return geometry::RealSize2D( rSize
.Width(),
333 Size
sizeFromRealSize2D( const geometry::RealSize2D
& rSize
)
335 return Size( static_cast<long>(rSize
.Width
+ .5),
336 static_cast<long>(rSize
.Height
+ .5) );
339 ::Size
sizeFromB2DSize( const basegfx::B2DVector
& rVec
)
341 return ::Size( FRound( rVec
.getX() ),
342 FRound( rVec
.getY() ) );
345 ::Point
pointFromB2DPoint( const basegfx::B2DPoint
& rPoint
)
347 return ::Point( FRound( rPoint
.getX() ),
348 FRound( rPoint
.getY() ) );
351 ::Rectangle
rectangleFromB2DRectangle( const basegfx::B2DRange
& rRect
)
353 return ::Rectangle( FRound( rRect
.getMinX() ),
354 FRound( rRect
.getMinY() ),
355 FRound( rRect
.getMaxX() ),
356 FRound( rRect
.getMaxY() ) );
359 Point
pointFromB2IPoint( const basegfx::B2IPoint
& rPoint
)
361 return ::Point( rPoint
.getX(),
365 Rectangle
rectangleFromB2IRectangle( const basegfx::B2IRange
& rRect
)
367 return ::Rectangle( rRect
.getMinX(),
373 basegfx::B2DVector
b2DSizeFromSize( const ::Size
& rSize
)
375 return basegfx::B2DVector( rSize
.Width(),
379 basegfx::B2DPoint
b2DPointFromPoint( const ::Point
& rPoint
)
381 return basegfx::B2DPoint( rPoint
.X(),
385 basegfx::B2DRange
b2DRectangleFromRectangle( const ::Rectangle
& rRect
)
387 return basegfx::B2DRange( rRect
.Left(),
393 geometry::IntegerSize2D
integerSize2DFromSize( const Size
& rSize
)
395 return geometry::IntegerSize2D( rSize
.Width(),
399 Size
sizeFromIntegerSize2D( const geometry::IntegerSize2D
& rSize
)
401 return Size( rSize
.Width
,
405 Point
pointFromIntegerPoint2D( const geometry::IntegerPoint2D
& rPoint
)
407 return Point( rPoint
.X
,
411 Rectangle
rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D
& rRectangle
)
413 return Rectangle( rRectangle
.X1
, rRectangle
.Y1
,
414 rRectangle
.X2
, rRectangle
.Y2
);
419 class StandardColorSpace
: public cppu::WeakImplHelper
< css::rendering::XColorSpace
>
422 uno::Sequence
< sal_Int8
> m_aComponentTags
;
424 virtual ::sal_Int8 SAL_CALL
getType( ) throw (uno::RuntimeException
, std::exception
) override
426 return rendering::ColorSpaceType::RGB
;
428 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
getComponentTags( ) throw (uno::RuntimeException
, std::exception
) override
430 return m_aComponentTags
;
432 virtual ::sal_Int8 SAL_CALL
getRenderingIntent( ) throw (uno::RuntimeException
, std::exception
) override
434 return rendering::RenderingIntent::PERCEPTUAL
;
436 virtual uno::Sequence
< beans::PropertyValue
> SAL_CALL
getProperties( ) throw (uno::RuntimeException
, std::exception
) override
438 return uno::Sequence
< beans::PropertyValue
>();
440 virtual uno::Sequence
< double > SAL_CALL
convertColorSpace( const uno::Sequence
< double >& deviceColor
,
441 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
442 uno::RuntimeException
, std::exception
) override
444 // TODO(P3): if we know anything about target
445 // colorspace, this can be greatly sped up
446 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
447 convertToARGB(deviceColor
));
448 return targetColorSpace
->convertFromARGB(aIntermediate
);
450 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertToRGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
452 const double* pIn( deviceColor
.getConstArray() );
453 const std::size_t nLen( deviceColor
.getLength() );
454 ENSURE_ARG_OR_THROW2(nLen
%4==0,
455 "number of channels no multiple of 4",
456 static_cast<rendering::XColorSpace
*>(this), 0);
458 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
459 rendering::RGBColor
* pOut( aRes
.getArray() );
460 for( std::size_t i
=0; i
<nLen
; i
+=4 )
462 *pOut
++ = rendering::RGBColor(pIn
[0],pIn
[1],pIn
[2]);
467 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
469 const double* pIn( deviceColor
.getConstArray() );
470 const std::size_t nLen( deviceColor
.getLength() );
471 ENSURE_ARG_OR_THROW2(nLen
%4==0,
472 "number of channels no multiple of 4",
473 static_cast<rendering::XColorSpace
*>(this), 0);
475 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
476 rendering::ARGBColor
* pOut( aRes
.getArray() );
477 for( std::size_t i
=0; i
<nLen
; i
+=4 )
479 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[0],pIn
[1],pIn
[2]);
484 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToPARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
486 const double* pIn( deviceColor
.getConstArray() );
487 const std::size_t nLen( deviceColor
.getLength() );
488 ENSURE_ARG_OR_THROW2(nLen
%4==0,
489 "number of channels no multiple of 4",
490 static_cast<rendering::XColorSpace
*>(this), 0);
492 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
493 rendering::ARGBColor
* pOut( aRes
.getArray() );
494 for( std::size_t i
=0; i
<nLen
; i
+=4 )
496 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[3]*pIn
[0],pIn
[3]*pIn
[1],pIn
[3]*pIn
[2]);
501 virtual uno::Sequence
< double > SAL_CALL
convertFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
503 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
504 const std::size_t nLen( rgbColor
.getLength() );
506 uno::Sequence
< double > aRes(nLen
*4);
507 double* pColors
=aRes
.getArray();
508 for( std::size_t i
=0; i
<nLen
; ++i
)
510 *pColors
++ = pIn
->Red
;
511 *pColors
++ = pIn
->Green
;
512 *pColors
++ = pIn
->Blue
;
518 virtual uno::Sequence
< double > SAL_CALL
convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
520 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
521 const std::size_t nLen( rgbColor
.getLength() );
523 uno::Sequence
< double > aRes(nLen
*4);
524 double* pColors
=aRes
.getArray();
525 for( std::size_t i
=0; i
<nLen
; ++i
)
527 *pColors
++ = pIn
->Red
;
528 *pColors
++ = pIn
->Green
;
529 *pColors
++ = pIn
->Blue
;
530 *pColors
++ = pIn
->Alpha
;
535 virtual uno::Sequence
< double > SAL_CALL
convertFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) override
537 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
538 const std::size_t nLen( rgbColor
.getLength() );
540 uno::Sequence
< double > aRes(nLen
*4);
541 double* pColors
=aRes
.getArray();
542 for( std::size_t i
=0; i
<nLen
; ++i
)
544 *pColors
++ = pIn
->Red
/pIn
->Alpha
;
545 *pColors
++ = pIn
->Green
/pIn
->Alpha
;
546 *pColors
++ = pIn
->Blue
/pIn
->Alpha
;
547 *pColors
++ = pIn
->Alpha
;
554 StandardColorSpace() : m_aComponentTags(4)
556 sal_Int8
* pTags
= m_aComponentTags
.getArray();
557 pTags
[0] = rendering::ColorComponentTag::RGB_RED
;
558 pTags
[1] = rendering::ColorComponentTag::RGB_GREEN
;
559 pTags
[2] = rendering::ColorComponentTag::RGB_BLUE
;
560 pTags
[3] = rendering::ColorComponentTag::ALPHA
;
565 uno::Reference
<rendering::XColorSpace
> createStandardColorSpace()
567 return new StandardColorSpace();
570 uno::Sequence
< double > colorToStdColorSpaceSequence( const Color
& rColor
)
572 uno::Sequence
< double > aRet(4);
573 double* pRet
= aRet
.getArray();
575 pRet
[0] = toDoubleColor(rColor
.GetRed());
576 pRet
[1] = toDoubleColor(rColor
.GetGreen());
577 pRet
[2] = toDoubleColor(rColor
.GetBlue());
579 // VCL's notion of alpha is different from the rest of the world's
580 pRet
[3] = 1.0 - toDoubleColor(rColor
.GetTransparency());
585 Color
stdColorSpaceSequenceToColor( const uno::Sequence
< double >& rColor
)
587 ENSURE_ARG_OR_THROW( rColor
.getLength() == 4,
588 "color must have 4 channels" );
592 aColor
.SetRed ( toByteColor(rColor
[0]) );
593 aColor
.SetGreen( toByteColor(rColor
[1]) );
594 aColor
.SetBlue ( toByteColor(rColor
[2]) );
595 // VCL's notion of alpha is different from the rest of the world's
596 aColor
.SetTransparency( 255 - toByteColor(rColor
[3]) );
601 uno::Sequence
< double > colorToDoubleSequence(
603 const uno::Reference
< rendering::XColorSpace
>& xColorSpace
)
605 uno::Sequence
<rendering::ARGBColor
> aSeq(1);
606 aSeq
[0] = rendering::ARGBColor(
607 1.0-toDoubleColor(rColor
.GetTransparency()),
608 toDoubleColor(rColor
.GetRed()),
609 toDoubleColor(rColor
.GetGreen()),
610 toDoubleColor(rColor
.GetBlue()) );
612 return xColorSpace
->convertFromARGB(aSeq
);
615 Color
doubleSequenceToColor(
616 const uno::Sequence
< double >& rColor
,
617 const uno::Reference
< rendering::XColorSpace
>& xColorSpace
)
619 const rendering::ARGBColor
aARGBColor(
620 xColorSpace
->convertToARGB(rColor
)[0]);
622 return Color( 255-toByteColor(aARGBColor
.Alpha
),
623 toByteColor(aARGBColor
.Red
),
624 toByteColor(aARGBColor
.Green
),
625 toByteColor(aARGBColor
.Blue
) );
628 } // namespace vcltools
630 } // namespace canvas
632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */