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