Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <rtl/logfile.hxx>
31 : : #include <cppuhelper/compbase1.hxx>
32 : :
33 : : #include <com/sun/star/geometry/RealSize2D.hpp>
34 : : #include <com/sun/star/geometry/RealPoint2D.hpp>
35 : : #include <com/sun/star/geometry/RealRectangle2D.hpp>
36 : : #include <com/sun/star/geometry/IntegerSize2D.hpp>
37 : : #include <com/sun/star/geometry/IntegerPoint2D.hpp>
38 : : #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
39 : : #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
40 : :
41 : : #include <com/sun/star/rendering/ColorSpaceType.hpp>
42 : : #include <com/sun/star/rendering/RenderingIntent.hpp>
43 : : #include <com/sun/star/rendering/XGraphicDevice.hpp>
44 : : #include <com/sun/star/rendering/XBitmap.hpp>
45 : : #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
46 : : #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
47 : : #include <com/sun/star/rendering/XIntegerBitmap.hpp>
48 : : #include <com/sun/star/rendering/ColorComponentTag.hpp>
49 : :
50 : : #include <basegfx/matrix/b2dhommatrix.hxx>
51 : : #include <basegfx/vector/b2dsize.hxx>
52 : : #include <basegfx/point/b2dpoint.hxx>
53 : : #include <basegfx/range/b2drectangle.hxx>
54 : : #include <basegfx/vector/b2isize.hxx>
55 : : #include <basegfx/point/b2ipoint.hxx>
56 : : #include <basegfx/range/b2irectangle.hxx>
57 : :
58 : : // #i79917#
59 : : #include <basegfx/polygon/b2dpolygon.hxx>
60 : : #include <basegfx/tools/canvastools.hxx>
61 : : #include <basegfx/polygon/b2dpolypolygon.hxx>
62 : :
63 : : #include <tools/poly.hxx>
64 : : #include <tools/diagnose_ex.h>
65 : : #include <rtl/uuid.h>
66 : :
67 : : #include <vcl/salbtype.hxx>
68 : : #include <vcl/bmpacc.hxx>
69 : : #include <vcl/bitmapex.hxx>
70 : :
71 : : #include <canvasbitmap.hxx>
72 : : #include <vcl/canvastools.hxx>
73 : : #include <boost/unordered_map.hpp>
74 : :
75 : :
76 : : using namespace ::com::sun::star;
77 : :
78 : : namespace vcl
79 : : {
80 : : namespace unotools
81 : : {
82 : 0 : uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/,
83 : : const ::BitmapEx& inputBitmap )
84 : : {
85 : : RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" );
86 : :
87 [ # # ][ # # ]: 0 : return new vcl::unotools::VclCanvasBitmap( inputBitmap );
88 : : }
89 : :
90 : : namespace
91 : : {
92 : 0 : inline bool operator==( const rendering::IntegerBitmapLayout& rLHS,
93 : : const rendering::IntegerBitmapLayout& rRHS )
94 : : {
95 : : return
96 : : rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
97 : : rLHS.ScanLineStride == rRHS.ScanLineStride &&
98 : : rLHS.PlaneStride == rRHS.PlaneStride &&
99 : 0 : rLHS.ColorSpace == rRHS.ColorSpace &&
100 : 0 : rLHS.Palette == rRHS.Palette &&
101 [ # # ][ # # ]: 0 : rLHS.IsMsbFirst == rRHS.IsMsbFirst;
[ # # # #
# # ][ # # ]
102 : : }
103 : :
104 : 0 : bool readBmp( sal_Int32 nWidth,
105 : : sal_Int32 nHeight,
106 : : const rendering::IntegerBitmapLayout& rLayout,
107 : : const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
108 : : Bitmap::ScopedWriteAccess& rWriteAcc,
109 : : Bitmap::ScopedWriteAccess& rAlphaAcc )
110 : : {
111 [ # # ]: 0 : rendering::IntegerBitmapLayout aCurrLayout;
112 : 0 : geometry::IntegerRectangle2D aRect;
113 [ # # ]: 0 : uno::Sequence<sal_Int8> aPixelData;
114 [ # # ]: 0 : uno::Sequence<rendering::RGBColor> aRGBColors;
115 [ # # ]: 0 : uno::Sequence<rendering::ARGBColor> aARGBColors;
116 : :
117 [ # # ]: 0 : for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
118 : : {
119 : 0 : aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
120 : : try
121 : : {
122 [ # # ][ # # ]: 0 : aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
[ # # ]
[ # # # # ]
123 : : }
124 [ # # ]: 0 : catch( rendering::VolatileContentDestroyedException& )
125 : : {
126 : : // re-read bmp from the start
127 : 0 : return false;
128 : : }
129 [ # # ][ # # ]: 0 : if( !(aCurrLayout == rLayout) )
130 : 0 : return false; // re-read bmp from the start
131 : :
132 [ # # ]: 0 : if( rAlphaAcc.get() )
133 : : {
134 : : // read ARGB color
135 [ # # ][ # # ]: 0 : aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
[ # # ][ # # ]
136 : :
137 [ # # ]: 0 : if( rWriteAcc->HasPalette() )
138 : : {
139 [ # # ]: 0 : for( sal_Int32 x=0; x<nWidth; ++x )
140 : : {
141 [ # # ]: 0 : const rendering::ARGBColor& rColor=aARGBColors[x];
142 : : rWriteAcc->SetPixel( aRect.Y1, x,
143 : 0 : (sal_uInt8)rWriteAcc->GetBestPaletteIndex(
144 [ # # ]: 0 : BitmapColor( toByteColor(rColor.Red),
145 [ # # ]: 0 : toByteColor(rColor.Green),
146 [ # # ][ # # ]: 0 : toByteColor(rColor.Blue))) );
[ # # ]
147 : : rAlphaAcc->SetPixel( aRect.Y1, x,
148 [ # # ][ # # ]: 0 : BitmapColor( 255 - toByteColor(rColor.Alpha) ));
149 : : }
150 : : }
151 : : else
152 : : {
153 [ # # ]: 0 : for( sal_Int32 x=0; x<nWidth; ++x )
154 : : {
155 [ # # ]: 0 : const rendering::ARGBColor& rColor=aARGBColors[x];
156 : : rWriteAcc->SetPixel( aRect.Y1, x,
157 [ # # ]: 0 : BitmapColor( toByteColor(rColor.Red),
158 [ # # ]: 0 : toByteColor(rColor.Green),
159 [ # # ][ # # ]: 0 : toByteColor(rColor.Blue) ));
160 : : rAlphaAcc->SetPixel( aRect.Y1, x,
161 [ # # ][ # # ]: 0 : BitmapColor( 255 - toByteColor(rColor.Alpha) ));
162 : : }
163 : : }
164 : : }
165 : : else
166 : : {
167 : : // read RGB color
168 [ # # ][ # # ]: 0 : aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
[ # # ][ # # ]
169 [ # # ]: 0 : if( rWriteAcc->HasPalette() )
170 : : {
171 [ # # ]: 0 : for( sal_Int32 x=0; x<nWidth; ++x )
172 : : {
173 [ # # ]: 0 : const rendering::RGBColor& rColor=aRGBColors[x];
174 : : rWriteAcc->SetPixel( aRect.Y1, x,
175 : 0 : (sal_uInt8)rWriteAcc->GetBestPaletteIndex(
176 [ # # ]: 0 : BitmapColor( toByteColor(rColor.Red),
177 [ # # ]: 0 : toByteColor(rColor.Green),
178 [ # # ][ # # ]: 0 : toByteColor(rColor.Blue))) );
[ # # ]
179 : : }
180 : : }
181 : : else
182 : : {
183 [ # # ]: 0 : for( sal_Int32 x=0; x<nWidth; ++x )
184 : : {
185 [ # # ]: 0 : const rendering::RGBColor& rColor=aRGBColors[x];
186 : : rWriteAcc->SetPixel( aRect.Y1, x,
187 [ # # ]: 0 : BitmapColor( toByteColor(rColor.Red),
188 [ # # ]: 0 : toByteColor(rColor.Green),
189 [ # # ][ # # ]: 0 : toByteColor(rColor.Blue) ));
190 : : }
191 : : }
192 : : }
193 : : }
194 : :
195 [ # # ][ # # ]: 0 : return true;
[ # # ][ # # ]
196 : : }
197 : : }
198 : :
199 : 0 : ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap )
200 : : {
201 : : RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" );
202 : :
203 [ # # ]: 0 : if( !xInputBitmap.is() )
204 [ # # ]: 0 : return ::BitmapEx();
205 : :
206 : : // tunnel directly for known implementation
207 : : // ----------------------------------------------------------------
208 [ # # ][ # # ]: 0 : VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get());
209 [ # # ]: 0 : if( pImplBitmap )
210 [ # # ]: 0 : return pImplBitmap->getBitmapEx();
211 : :
212 : : // retrieve data via UNO interface
213 : : // ----------------------------------------------------------------
214 : :
215 : : // volatile bitmaps are a bit more complicated to read
216 : : // from..
217 : : uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap(
218 [ # # ]: 0 : xInputBitmap, uno::UNO_QUERY);
219 : :
220 : : // loop a few times, until successfully read (for XVolatileBitmap)
221 [ # # ]: 0 : for( int i=0; i<10; ++i )
222 : : {
223 : 0 : sal_Int32 nDepth=0;
224 : 0 : sal_Int32 nAlphaDepth=0;
225 : : const rendering::IntegerBitmapLayout aLayout(
226 [ # # ][ # # ]: 0 : xInputBitmap->getMemoryLayout());
227 : :
228 : : OSL_ENSURE(aLayout.ColorSpace.is(),
229 : : "Cannot convert image without color space!");
230 [ # # ]: 0 : if( !aLayout.ColorSpace.is() )
231 [ # # ]: 0 : return ::BitmapEx();
232 : :
233 [ # # ][ # # ]: 0 : nDepth = aLayout.ColorSpace->getBitsPerPixel();
234 : :
235 [ # # ][ # # ]: 0 : if( xInputBitmap->hasAlpha() )
[ # # ]
236 : : {
237 : : // determine alpha channel depth
238 : : const uno::Sequence<sal_Int8> aTags(
239 [ # # ][ # # ]: 0 : aLayout.ColorSpace->getComponentTags() );
240 : : const uno::Sequence<sal_Int32> aDepths(
241 [ # # ][ # # ]: 0 : aLayout.ColorSpace->getComponentBitCounts() );
242 : 0 : const sal_Int8* pStart(aTags.getConstArray());
243 : 0 : const sal_Size nLen(aTags.getLength());
244 : 0 : const sal_Int8* pEnd(pStart+nLen);
245 : :
246 : : const std::ptrdiff_t nAlphaIndex =
247 : : std::find(pStart,pEnd,
248 [ # # ]: 0 : rendering::ColorComponentTag::ALPHA) - pStart;
249 : :
250 [ # # ]: 0 : if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
251 : : {
252 [ # # ][ # # ]: 0 : nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
[ # # ][ # # ]
[ # # ]
253 : 0 : nDepth -= nAlphaDepth;
254 [ # # ][ # # ]: 0 : }
255 : : }
256 : :
257 : 0 : BitmapPalette aPalette;
258 [ # # ]: 0 : if( aLayout.Palette.is() )
259 : : {
260 : : uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
261 [ # # ][ # # ]: 0 : aLayout.Palette->getColorSpace());
262 [ # # ][ # # ]: 0 : ENSURE_OR_THROW(xPaletteColorSpace.is(),
[ # # ][ # # ]
263 : : "Palette without color space");
264 : :
265 [ # # ][ # # ]: 0 : const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
266 [ # # ]: 0 : if( nEntryCount <= 256 )
267 : : {
268 [ # # ]: 0 : if( nEntryCount <= 2 )
269 : 0 : nDepth = 1;
270 : : else
271 : 0 : nDepth = 8;
272 : :
273 : : const sal_uInt16 nPaletteEntries(
274 : : sal::static_int_cast<sal_uInt16>(
275 [ # # ]: 0 : std::min(sal_Int32(255), nEntryCount)));
276 : :
277 : : // copy palette entries
278 [ # # ]: 0 : aPalette.SetEntryCount(nPaletteEntries);
279 : 0 : uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
280 [ # # ][ # # ]: 0 : uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
281 : :
282 [ # # ]: 0 : uno::Sequence<double> aPaletteEntry;
283 [ # # ]: 0 : for( sal_uInt16 j=0; j<nPaletteEntries; ++j )
284 : : {
285 [ # # ][ # # ]: 0 : if( !xPalette->getIndex(aPaletteEntry,j) &&
[ # # ][ # # ]
[ # # ]
286 : : nAlphaDepth == 0 )
287 : : {
288 : 0 : nAlphaDepth = 1;
289 : : }
290 [ # # ][ # # ]: 0 : uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
291 [ # # ][ # # ]: 0 : ENSURE_OR_THROW(aColors.getLength() == 1,
[ # # ][ # # ]
292 : : "Palette returned more or less than one entry");
293 [ # # ]: 0 : const rendering::RGBColor& rColor=aColors[0];
294 [ # # ]: 0 : aPalette[j] = BitmapColor(toByteColor(rColor.Red),
295 [ # # ]: 0 : toByteColor(rColor.Green),
296 [ # # ]: 0 : toByteColor(rColor.Blue));
297 [ # # ][ # # ]: 0 : }
298 : 0 : }
299 : : }
300 : :
301 : : const ::Size aPixelSize(
302 [ # # ][ # # ]: 0 : sizeFromIntegerSize2D(xInputBitmap->getSize()));
[ # # ]
303 : :
304 : : // normalize bitcount
305 : : nDepth =
306 : : ( nDepth <= 1 ) ? 1 :
307 : : ( nDepth <= 4 ) ? 4 :
308 [ # # ][ # # ]: 0 : ( nDepth <= 8 ) ? 8 : 24;
[ # # ]
309 : :
310 : : ::Bitmap aBitmap( aPixelSize,
311 : 0 : sal::static_int_cast<sal_uInt16>(nDepth),
312 [ # # ][ # # ]: 0 : aLayout.Palette.is() ? &aPalette : NULL );
313 [ # # ]: 0 : ::Bitmap aAlpha;
314 [ # # ]: 0 : if( nAlphaDepth )
315 : : aAlpha = ::Bitmap( aPixelSize,
316 : 0 : sal::static_int_cast<sal_uInt16>(nAlphaDepth),
317 : : &::Bitmap::GetGreyPalette(
318 [ # # # # ]: 0 : sal::static_int_cast<sal_uInt16>(1L << nAlphaDepth)) );
[ # # ][ # # ]
319 : :
320 : : { // limit scoped access
321 [ # # ]: 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
322 : : Bitmap::ScopedWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL,
323 [ # # ][ # # ]: 0 : aAlpha );
324 : :
325 [ # # ][ # # ]: 0 : ENSURE_OR_THROW(pWriteAccess.get() != NULL,
[ # # ][ # # ]
326 : : "Cannot get write access to bitmap");
327 : :
328 : 0 : const sal_Int32 nWidth(aPixelSize.Width());
329 : 0 : const sal_Int32 nHeight(aPixelSize.Height());
330 : :
331 [ # # ]: 0 : if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
332 [ # # ]: 0 : pWriteAccess,pAlphaWriteAccess) )
333 [ # # ][ # # ]: 0 : continue;
[ # # ][ # # ]
334 : : } // limit scoped access
335 : :
336 [ # # ]: 0 : if( nAlphaDepth )
337 : : return ::BitmapEx( aBitmap,
338 [ # # ][ # # ]: 0 : AlphaMask( aAlpha ) );
[ # # ]
339 : : else
340 [ # # ][ # # ]: 0 : return ::BitmapEx( aBitmap );
341 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
342 : :
343 : : // failed to read data 10 times - bail out
344 [ # # ]: 0 : return ::BitmapEx();
345 : : }
346 : :
347 : : //---------------------------------------------------------------------------------------
348 : :
349 : 0 : geometry::RealSize2D size2DFromSize( const Size& rSize )
350 : : {
351 : 0 : return geometry::RealSize2D( rSize.Width(),
352 : 0 : rSize.Height() );
353 : : }
354 : :
355 : 0 : Size sizeFromRealSize2D( const geometry::RealSize2D& rSize )
356 : : {
357 : : return Size( static_cast<long>(rSize.Width + .5),
358 : 0 : static_cast<long>(rSize.Height + .5) );
359 : : }
360 : :
361 : 0 : ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec )
362 : : {
363 : : return ::Size( FRound( rVec.getX() ),
364 : 0 : FRound( rVec.getY() ) );
365 : : }
366 : :
367 : 0 : ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
368 : : {
369 : : return ::Point( FRound( rPoint.getX() ),
370 : 0 : FRound( rPoint.getY() ) );
371 : : }
372 : :
373 : 9 : ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect )
374 : : {
375 : : return ::Rectangle( FRound( rRect.getMinX() ),
376 : : FRound( rRect.getMinY() ),
377 : : FRound( rRect.getMaxX() ),
378 : 9 : FRound( rRect.getMaxY() ) );
379 : : }
380 : :
381 : 0 : Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint )
382 : : {
383 : : return ::Point( rPoint.getX(),
384 : 0 : rPoint.getY() );
385 : : }
386 : :
387 : 0 : Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect )
388 : : {
389 : : return ::Rectangle( rRect.getMinX(),
390 : : rRect.getMinY(),
391 : : rRect.getMaxX(),
392 : 0 : rRect.getMaxY() );
393 : : }
394 : :
395 : 0 : ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize )
396 : : {
397 : 0 : return ::basegfx::B2DVector( rSize.Width(),
398 : 0 : rSize.Height() );
399 : : }
400 : :
401 : 0 : ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint )
402 : : {
403 : 0 : return ::basegfx::B2DPoint( rPoint.X(),
404 : 0 : rPoint.Y() );
405 : : }
406 : :
407 : 9 : ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect )
408 : : {
409 : 9 : return ::basegfx::B2DRange( rRect.Left(),
410 : 9 : rRect.Top(),
411 : 9 : rRect.Right(),
412 : 18 : rRect.Bottom() );
413 : : }
414 : :
415 : 0 : geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize )
416 : : {
417 : 0 : return geometry::IntegerSize2D( rSize.Width(),
418 : 0 : rSize.Height() );
419 : : }
420 : :
421 : 0 : Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
422 : : {
423 : : return Size( rSize.Width,
424 : 0 : rSize.Height );
425 : : }
426 : :
427 : 0 : Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint )
428 : : {
429 : : return Point( rPoint.X,
430 : 0 : rPoint.Y );
431 : : }
432 : :
433 : 0 : Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
434 : : {
435 : : return Rectangle( rRectangle.X1, rRectangle.Y1,
436 : 0 : rRectangle.X2, rRectangle.Y2 );
437 : : }
438 : :
439 : : namespace
440 : : {
441 [ # # ][ # # ]: 0 : class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace >
442 : : {
443 : : private:
444 : : uno::Sequence< sal_Int8 > m_aComponentTags;
445 : :
446 : 0 : virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
447 : : {
448 : 0 : return rendering::ColorSpaceType::RGB;
449 : : }
450 : 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
451 : : {
452 : 0 : return m_aComponentTags;
453 : : }
454 : 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
455 : : {
456 : 0 : return rendering::RenderingIntent::PERCEPTUAL;
457 : : }
458 : 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
459 : : {
460 : 0 : return uno::Sequence< beans::PropertyValue >();
461 : : }
462 : 0 : virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
463 : : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
464 : : uno::RuntimeException)
465 : : {
466 : : // TODO(P3): if we know anything about target
467 : : // colorspace, this can be greatly sped up
468 : : uno::Sequence<rendering::ARGBColor> aIntermediate(
469 [ # # ]: 0 : convertToARGB(deviceColor));
470 [ # # ][ # # ]: 0 : return targetColorSpace->convertFromARGB(aIntermediate);
[ # # ]
471 : : }
472 : 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
473 : : {
474 : 0 : const double* pIn( deviceColor.getConstArray() );
475 : 0 : const sal_Size nLen( deviceColor.getLength() );
476 [ # # ][ # # ]: 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
[ # # ][ # # ]
[ # # ]
477 : : "number of channels no multiple of 4",
478 : : static_cast<rendering::XColorSpace*>(this), 0);
479 : :
480 : 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
481 [ # # ]: 0 : rendering::RGBColor* pOut( aRes.getArray() );
482 [ # # ]: 0 : for( sal_Size i=0; i<nLen; i+=4 )
483 : : {
484 : 0 : *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
485 : 0 : pIn += 4;
486 : : }
487 : 0 : return aRes;
488 : : }
489 : 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
490 : : {
491 : 0 : const double* pIn( deviceColor.getConstArray() );
492 : 0 : const sal_Size nLen( deviceColor.getLength() );
493 [ # # ][ # # ]: 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
[ # # ][ # # ]
[ # # ]
494 : : "number of channels no multiple of 4",
495 : : static_cast<rendering::XColorSpace*>(this), 0);
496 : :
497 : 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
498 [ # # ]: 0 : rendering::ARGBColor* pOut( aRes.getArray() );
499 [ # # ]: 0 : for( sal_Size i=0; i<nLen; i+=4 )
500 : : {
501 : 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
502 : 0 : pIn += 4;
503 : : }
504 : 0 : return aRes;
505 : : }
506 : 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
507 : : {
508 : 0 : const double* pIn( deviceColor.getConstArray() );
509 : 0 : const sal_Size nLen( deviceColor.getLength() );
510 [ # # ][ # # ]: 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
[ # # ][ # # ]
[ # # ]
511 : : "number of channels no multiple of 4",
512 : : static_cast<rendering::XColorSpace*>(this), 0);
513 : :
514 : 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
515 [ # # ]: 0 : rendering::ARGBColor* pOut( aRes.getArray() );
516 [ # # ]: 0 : for( sal_Size i=0; i<nLen; i+=4 )
517 : : {
518 : 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
519 : 0 : pIn += 4;
520 : : }
521 : 0 : return aRes;
522 : : }
523 : 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
524 : : {
525 : 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
526 : 0 : const sal_Size nLen( rgbColor.getLength() );
527 : :
528 : 0 : uno::Sequence< double > aRes(nLen*4);
529 [ # # ]: 0 : double* pColors=aRes.getArray();
530 [ # # ]: 0 : for( sal_Size i=0; i<nLen; ++i )
531 : : {
532 : 0 : *pColors++ = pIn->Red;
533 : 0 : *pColors++ = pIn->Green;
534 : 0 : *pColors++ = pIn->Blue;
535 : 0 : *pColors++ = 1.0;
536 : 0 : ++pIn;
537 : : }
538 : 0 : return aRes;
539 : : }
540 : 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
541 : : {
542 : 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
543 : 0 : const sal_Size nLen( rgbColor.getLength() );
544 : :
545 : 0 : uno::Sequence< double > aRes(nLen*4);
546 [ # # ]: 0 : double* pColors=aRes.getArray();
547 [ # # ]: 0 : for( sal_Size i=0; i<nLen; ++i )
548 : : {
549 : 0 : *pColors++ = pIn->Red;
550 : 0 : *pColors++ = pIn->Green;
551 : 0 : *pColors++ = pIn->Blue;
552 : 0 : *pColors++ = pIn->Alpha;
553 : 0 : ++pIn;
554 : : }
555 : 0 : return aRes;
556 : : }
557 : 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
558 : : {
559 : 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
560 : 0 : const sal_Size nLen( rgbColor.getLength() );
561 : :
562 : 0 : uno::Sequence< double > aRes(nLen*4);
563 [ # # ]: 0 : double* pColors=aRes.getArray();
564 [ # # ]: 0 : for( sal_Size i=0; i<nLen; ++i )
565 : : {
566 : 0 : *pColors++ = pIn->Red/pIn->Alpha;
567 : 0 : *pColors++ = pIn->Green/pIn->Alpha;
568 : 0 : *pColors++ = pIn->Blue/pIn->Alpha;
569 : 0 : *pColors++ = pIn->Alpha;
570 : 0 : ++pIn;
571 : : }
572 : 0 : return aRes;
573 : : }
574 : :
575 : : public:
576 [ # # ]: 0 : StandardColorSpace() : m_aComponentTags(4)
577 : : {
578 [ # # ]: 0 : sal_Int8* pTags = m_aComponentTags.getArray();
579 : 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
580 : 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
581 : 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
582 : 0 : pTags[3] = rendering::ColorComponentTag::ALPHA;
583 : 0 : }
584 : : };
585 : : }
586 : :
587 : 0 : uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace()
588 : : {
589 [ # # ][ # # ]: 0 : return new StandardColorSpace();
590 : : }
591 : :
592 : : //---------------------------------------------------------------------------------------
593 : :
594 : 0 : Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor )
595 : : {
596 [ # # ][ # # ]: 0 : ENSURE_ARG_OR_THROW( rColor.getLength() == 4,
[ # # ][ # # ]
597 : : "color must have 4 channels" );
598 : :
599 : 0 : Color aColor;
600 : :
601 : 0 : aColor.SetRed ( toByteColor(rColor[0]) );
602 : 0 : aColor.SetGreen( toByteColor(rColor[1]) );
603 : 0 : aColor.SetBlue ( toByteColor(rColor[2]) );
604 : : // VCL's notion of alpha is different from the rest of the world's
605 : 0 : aColor.SetTransparency( 255 - toByteColor(rColor[3]) );
606 : :
607 : 0 : return aColor;
608 : : }
609 : :
610 : 0 : uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence(
611 : : const Color& rColor,
612 : : const uno::Reference< rendering::XColorSpace >& xColorSpace )
613 : : {
614 [ # # ]: 0 : uno::Sequence<rendering::ARGBColor> aSeq(1);
615 [ # # ]: 0 : aSeq[0] = rendering::ARGBColor(
616 : 0 : 1.0-toDoubleColor(rColor.GetTransparency()),
617 : 0 : toDoubleColor(rColor.GetRed()),
618 : 0 : toDoubleColor(rColor.GetGreen()),
619 : 0 : toDoubleColor(rColor.GetBlue()) );
620 : :
621 [ # # ][ # # ]: 0 : return xColorSpace->convertFromARGB(aSeq);
[ # # ]
622 : : }
623 : :
624 : 0 : Color VCL_DLLPUBLIC doubleSequenceToColor(
625 : : const uno::Sequence< double > rColor,
626 : : const uno::Reference< rendering::XColorSpace >& xColorSpace )
627 : : {
628 : : const rendering::ARGBColor aARGBColor(
629 [ # # ][ # # ]: 0 : xColorSpace->convertToARGB(rColor)[0]);
[ # # ][ # # ]
630 : :
631 [ # # ]: 0 : return Color( 255-toByteColor(aARGBColor.Alpha),
632 [ # # ]: 0 : toByteColor(aARGBColor.Red),
633 [ # # ]: 0 : toByteColor(aARGBColor.Green),
634 [ # # ]: 0 : toByteColor(aARGBColor.Blue) );
635 : : }
636 : :
637 : : //---------------------------------------------------------------------------------------
638 : :
639 : : } // namespace vcltools
640 : :
641 : : } // namespace canvas
642 : :
643 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|