Branch libreoffice-5-0-4
[LibreOffice.git] / canvas / source / tools / canvastools.cxx
blob7db3572b4dae3403f247789cd92905b0d8a517d7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
24 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
25 #include <com/sun/star/geometry/Matrix2D.hpp>
26 #include <com/sun/star/awt/Rectangle.hpp>
27 #include <com/sun/star/util/Endianness.hpp>
28 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
29 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
30 #include <com/sun/star/rendering/ColorSpaceType.hpp>
31 #include <com/sun/star/rendering/ColorComponentTag.hpp>
32 #include <com/sun/star/rendering/RenderingIntent.hpp>
33 #include <com/sun/star/rendering/RenderState.hpp>
34 #include <com/sun/star/rendering/ViewState.hpp>
35 #include <com/sun/star/rendering/XCanvas.hpp>
36 #include <com/sun/star/rendering/XColorSpace.hpp>
37 #include <com/sun/star/rendering/CompositeOperation.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <basegfx/range/b2drange.hxx>
43 #include <basegfx/range/b2irange.hxx>
44 #include <basegfx/range/b2drectangle.hxx>
45 #include <basegfx/point/b2dpoint.hxx>
46 #include <basegfx/point/b2ipoint.hxx>
47 #include <basegfx/vector/b2ivector.hxx>
48 #include <basegfx/polygon/b2dpolygon.hxx>
49 #include <basegfx/polygon/b2dpolygontools.hxx>
50 #include <basegfx/polygon/b2dpolypolygontools.hxx>
51 #include <basegfx/tools/canvastools.hxx>
52 #include <basegfx/numeric/ftools.hxx>
53 #include <basegfx/matrix/b2dhommatrixtools.hxx>
55 #include <cppuhelper/compbase1.hxx>
56 #include <rtl/instance.hxx>
57 #include <toolkit/helper/vclunohelper.hxx>
58 #include <vcl/window.hxx>
59 #include <vcl/canvastools.hxx>
61 #include <canvas/canvastools.hxx>
63 #include <limits>
66 using namespace ::com::sun::star;
68 namespace com { namespace sun { namespace star { namespace rendering
70 bool operator==( const RenderState& renderState1,
71 const RenderState& renderState2 )
73 if( renderState1.Clip != renderState2.Clip )
74 return false;
76 if( renderState1.DeviceColor != renderState2.DeviceColor )
77 return false;
79 if( renderState1.CompositeOperation != renderState2.CompositeOperation )
80 return false;
82 ::basegfx::B2DHomMatrix mat1, mat2;
83 ::canvas::tools::getRenderStateTransform( mat1, renderState1 );
84 ::canvas::tools::getRenderStateTransform( mat2, renderState2 );
85 if( mat1 != mat2 )
86 return false;
88 return true;
91 bool operator==( const ViewState& viewState1,
92 const ViewState& viewState2 )
94 if( viewState1.Clip != viewState2.Clip )
95 return false;
97 ::basegfx::B2DHomMatrix mat1, mat2;
98 ::canvas::tools::getViewStateTransform( mat1, viewState1 );
99 ::canvas::tools::getViewStateTransform( mat2, viewState2 );
100 if( mat1 != mat2 )
101 return false;
103 return true;
105 }}}}
107 namespace canvas
109 namespace tools
111 geometry::RealSize2D createInfiniteSize2D()
113 return geometry::RealSize2D(
114 ::std::numeric_limits<double>::infinity(),
115 ::std::numeric_limits<double>::infinity() );
118 rendering::RenderState& initRenderState( rendering::RenderState& renderState )
120 // setup identity transform
121 setIdentityAffineMatrix2D( renderState.AffineTransform );
122 renderState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
123 renderState.DeviceColor = uno::Sequence< double >();
124 renderState.CompositeOperation = rendering::CompositeOperation::OVER;
126 return renderState;
129 rendering::ViewState& initViewState( rendering::ViewState& viewState )
131 // setup identity transform
132 setIdentityAffineMatrix2D( viewState.AffineTransform );
133 viewState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
135 return viewState;
138 ::basegfx::B2DHomMatrix& getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
139 const rendering::ViewState& viewState )
141 return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, viewState.AffineTransform );
144 rendering::ViewState& setViewStateTransform( rendering::ViewState& viewState,
145 const ::basegfx::B2DHomMatrix& transform )
147 ::basegfx::unotools::affineMatrixFromHomMatrix( viewState.AffineTransform, transform );
149 return viewState;
152 ::basegfx::B2DHomMatrix& getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
153 const rendering::RenderState& renderState )
155 return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, renderState.AffineTransform );
158 rendering::RenderState& setRenderStateTransform( rendering::RenderState& renderState,
159 const ::basegfx::B2DHomMatrix& transform )
161 ::basegfx::unotools::affineMatrixFromHomMatrix( renderState.AffineTransform, transform );
163 return renderState;
166 rendering::RenderState& appendToRenderState( rendering::RenderState& renderState,
167 const ::basegfx::B2DHomMatrix& rTransform )
169 ::basegfx::B2DHomMatrix transform;
171 getRenderStateTransform( transform, renderState );
172 return setRenderStateTransform( renderState, transform * rTransform );
175 rendering::RenderState& prependToRenderState( rendering::RenderState& renderState,
176 const ::basegfx::B2DHomMatrix& rTransform )
178 ::basegfx::B2DHomMatrix transform;
180 getRenderStateTransform( transform, renderState );
181 return setRenderStateTransform( renderState, rTransform * transform );
184 ::basegfx::B2DHomMatrix& mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& combinedTransform,
185 const rendering::ViewState& viewState,
186 const rendering::RenderState& renderState )
188 ::basegfx::B2DHomMatrix viewTransform;
190 ::basegfx::unotools::homMatrixFromAffineMatrix( combinedTransform, renderState.AffineTransform );
191 ::basegfx::unotools::homMatrixFromAffineMatrix( viewTransform, viewState.AffineTransform );
193 // this statement performs combinedTransform = viewTransform * combinedTransform
194 combinedTransform *= viewTransform;
196 return combinedTransform;
199 geometry::AffineMatrix2D& setIdentityAffineMatrix2D( geometry::AffineMatrix2D& matrix )
201 matrix.m00 = 1.0;
202 matrix.m01 = 0.0;
203 matrix.m02 = 0.0;
204 matrix.m10 = 0.0;
205 matrix.m11 = 1.0;
206 matrix.m12 = 0.0;
208 return matrix;
211 geometry::Matrix2D& setIdentityMatrix2D( geometry::Matrix2D& matrix )
213 matrix.m00 = 1.0;
214 matrix.m01 = 0.0;
215 matrix.m10 = 0.0;
216 matrix.m11 = 1.0;
218 return matrix;
221 namespace
223 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
225 private:
226 uno::Sequence< sal_Int8 > maComponentTags;
227 uno::Sequence< sal_Int32 > maBitCounts;
229 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
231 return rendering::ColorSpaceType::RGB;
233 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
235 return maComponentTags;
237 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
239 return rendering::RenderingIntent::PERCEPTUAL;
241 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
243 return uno::Sequence< beans::PropertyValue >();
245 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
246 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
247 uno::RuntimeException, std::exception) SAL_OVERRIDE
249 // TODO(P3): if we know anything about target
250 // colorspace, this can be greatly sped up
251 uno::Sequence<rendering::ARGBColor> aIntermediate(
252 convertToARGB(deviceColor));
253 return targetColorSpace->convertFromARGB(aIntermediate);
255 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
257 const double* pIn( deviceColor.getConstArray() );
258 const sal_Size nLen( deviceColor.getLength() );
259 ENSURE_ARG_OR_THROW2(nLen%4==0,
260 "number of channels no multiple of 4",
261 static_cast<rendering::XColorSpace*>(this), 0);
263 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
264 rendering::RGBColor* pOut( aRes.getArray() );
265 for( sal_Size i=0; i<nLen; i+=4 )
267 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
268 pIn += 4;
270 return aRes;
272 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
274 SAL_WARN_IF(deviceColor.getLength() == 0, "canvas", "empty deviceColor argument");
275 const double* pIn( deviceColor.getConstArray() );
276 const sal_Size nLen( deviceColor.getLength() );
277 ENSURE_ARG_OR_THROW2(nLen%4==0,
278 "number of channels no multiple of 4",
279 static_cast<rendering::XColorSpace*>(this), 0);
281 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
282 rendering::ARGBColor* pOut( aRes.getArray() );
283 for( sal_Size i=0; i<nLen; i+=4 )
285 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
286 pIn += 4;
288 return aRes;
290 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
292 const double* pIn( deviceColor.getConstArray() );
293 const sal_Size nLen( deviceColor.getLength() );
294 ENSURE_ARG_OR_THROW2(nLen%4==0,
295 "number of channels no multiple of 4",
296 static_cast<rendering::XColorSpace*>(this), 0);
298 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
299 rendering::ARGBColor* pOut( aRes.getArray() );
300 for( sal_Size i=0; i<nLen; i+=4 )
302 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
303 pIn += 4;
305 return aRes;
307 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
309 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
310 const sal_Size nLen( rgbColor.getLength() );
312 uno::Sequence< double > aRes(nLen*4);
313 double* pColors=aRes.getArray();
314 for( sal_Size i=0; i<nLen; ++i )
316 *pColors++ = pIn->Red;
317 *pColors++ = pIn->Green;
318 *pColors++ = pIn->Blue;
319 *pColors++ = 1.0;
320 ++pIn;
322 return aRes;
324 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
326 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
327 const sal_Size nLen( rgbColor.getLength() );
329 uno::Sequence< double > aRes(nLen*4);
330 double* pColors=aRes.getArray();
331 for( sal_Size i=0; i<nLen; ++i )
333 *pColors++ = pIn->Red;
334 *pColors++ = pIn->Green;
335 *pColors++ = pIn->Blue;
336 *pColors++ = pIn->Alpha;
337 ++pIn;
339 return aRes;
341 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
343 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
344 const sal_Size nLen( rgbColor.getLength() );
346 uno::Sequence< double > aRes(nLen*4);
347 double* pColors=aRes.getArray();
348 for( sal_Size i=0; i<nLen; ++i )
350 *pColors++ = pIn->Red/pIn->Alpha;
351 *pColors++ = pIn->Green/pIn->Alpha;
352 *pColors++ = pIn->Blue/pIn->Alpha;
353 *pColors++ = pIn->Alpha;
354 ++pIn;
356 return aRes;
359 // XIntegerBitmapColorSpace
360 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
362 return 32;
364 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
366 return maBitCounts;
368 virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
370 return util::Endianness::LITTLE;
372 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
373 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
374 uno::RuntimeException, std::exception) SAL_OVERRIDE
376 if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
378 const sal_Int8* pIn( deviceColor.getConstArray() );
379 const sal_Size nLen( deviceColor.getLength() );
380 ENSURE_ARG_OR_THROW2(nLen%4==0,
381 "number of channels no multiple of 4",
382 static_cast<rendering::XColorSpace*>(this), 0);
384 uno::Sequence<double> aRes(nLen);
385 double* pOut( aRes.getArray() );
386 for( sal_Size i=0; i<nLen; i+=4 )
388 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
389 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
390 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
391 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
393 return aRes;
395 else
397 // TODO(P3): if we know anything about target
398 // colorspace, this can be greatly sped up
399 uno::Sequence<rendering::ARGBColor> aIntermediate(
400 convertIntegerToARGB(deviceColor));
401 return targetColorSpace->convertFromARGB(aIntermediate);
404 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
405 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
406 uno::RuntimeException, std::exception) SAL_OVERRIDE
408 if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
410 // it's us, so simply pass-through the data
411 return deviceColor;
413 else
415 // TODO(P3): if we know anything about target
416 // colorspace, this can be greatly sped up
417 uno::Sequence<rendering::ARGBColor> aIntermediate(
418 convertIntegerToARGB(deviceColor));
419 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
422 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
424 const sal_Int8* pIn( deviceColor.getConstArray() );
425 const sal_Size nLen( deviceColor.getLength() );
426 ENSURE_ARG_OR_THROW2(nLen%4==0,
427 "number of channels no multiple of 4",
428 static_cast<rendering::XColorSpace*>(this), 0);
430 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
431 rendering::RGBColor* pOut( aRes.getArray() );
432 for( sal_Size i=0; i<nLen; i+=4 )
434 *pOut++ = rendering::RGBColor(
435 vcl::unotools::toDoubleColor(pIn[0]),
436 vcl::unotools::toDoubleColor(pIn[1]),
437 vcl::unotools::toDoubleColor(pIn[2]));
438 pIn += 4;
440 return aRes;
443 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
445 const sal_Int8* pIn( deviceColor.getConstArray() );
446 const sal_Size nLen( deviceColor.getLength() );
447 ENSURE_ARG_OR_THROW2(nLen%4==0,
448 "number of channels no multiple of 4",
449 static_cast<rendering::XColorSpace*>(this), 0);
451 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
452 rendering::ARGBColor* pOut( aRes.getArray() );
453 for( sal_Size i=0; i<nLen; i+=4 )
455 *pOut++ = rendering::ARGBColor(
456 vcl::unotools::toDoubleColor(pIn[3]),
457 vcl::unotools::toDoubleColor(pIn[0]),
458 vcl::unotools::toDoubleColor(pIn[1]),
459 vcl::unotools::toDoubleColor(pIn[2]));
460 pIn += 4;
462 return aRes;
465 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
467 const sal_Int8* pIn( deviceColor.getConstArray() );
468 const sal_Size nLen( deviceColor.getLength() );
469 ENSURE_ARG_OR_THROW2(nLen%4==0,
470 "number of channels no multiple of 4",
471 static_cast<rendering::XColorSpace*>(this), 0);
473 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
474 rendering::ARGBColor* pOut( aRes.getArray() );
475 for( sal_Size i=0; i<nLen; i+=4 )
477 const sal_Int8 nAlpha( pIn[3] );
478 *pOut++ = rendering::ARGBColor(
479 vcl::unotools::toDoubleColor(nAlpha),
480 vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
481 vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
482 vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
483 pIn += 4;
485 return aRes;
488 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
490 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
491 const sal_Size nLen( rgbColor.getLength() );
493 uno::Sequence< sal_Int8 > aRes(nLen*4);
494 sal_Int8* pColors=aRes.getArray();
495 for( sal_Size i=0; i<nLen; ++i )
497 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
498 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
499 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
500 *pColors++ = 0;
501 ++pIn;
503 return aRes;
506 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
508 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
509 const sal_Size nLen( rgbColor.getLength() );
511 uno::Sequence< sal_Int8 > aRes(nLen*4);
512 sal_Int8* pColors=aRes.getArray();
513 for( sal_Size i=0; i<nLen; ++i )
515 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
516 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
517 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
518 *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
519 ++pIn;
521 return aRes;
524 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
526 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
527 const sal_Size nLen( rgbColor.getLength() );
529 uno::Sequence< sal_Int8 > aRes(nLen*4);
530 sal_Int8* pColors=aRes.getArray();
531 for( sal_Size i=0; i<nLen; ++i )
533 *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
534 *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
535 *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
536 *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
537 ++pIn;
539 return aRes;
542 public:
543 StandardColorSpace() :
544 maComponentTags(4),
545 maBitCounts(4)
547 sal_Int8* pTags = maComponentTags.getArray();
548 sal_Int32* pBitCounts = maBitCounts.getArray();
549 pTags[0] = rendering::ColorComponentTag::RGB_RED;
550 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
551 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
552 pTags[3] = rendering::ColorComponentTag::ALPHA;
554 pBitCounts[0] =
555 pBitCounts[1] =
556 pBitCounts[2] =
557 pBitCounts[3] = 8;
561 class StandardNoAlphaColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
563 private:
564 uno::Sequence< sal_Int8 > maComponentTags;
565 uno::Sequence< sal_Int32 > maBitCounts;
567 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
569 return rendering::ColorSpaceType::RGB;
571 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
573 return maComponentTags;
575 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
577 return rendering::RenderingIntent::PERCEPTUAL;
579 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
581 return uno::Sequence< beans::PropertyValue >();
583 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
584 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
585 uno::RuntimeException, std::exception) SAL_OVERRIDE
587 // TODO(P3): if we know anything about target
588 // colorspace, this can be greatly sped up
589 uno::Sequence<rendering::ARGBColor> aIntermediate(
590 convertToARGB(deviceColor));
591 return targetColorSpace->convertFromARGB(aIntermediate);
593 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
595 const double* pIn( deviceColor.getConstArray() );
596 const sal_Size nLen( deviceColor.getLength() );
597 ENSURE_ARG_OR_THROW2(nLen%4==0,
598 "number of channels no multiple of 4",
599 static_cast<rendering::XColorSpace*>(this), 0);
601 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
602 rendering::RGBColor* pOut( aRes.getArray() );
603 for( sal_Size i=0; i<nLen; i+=4 )
605 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
606 pIn += 4;
608 return aRes;
610 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
612 const double* pIn( deviceColor.getConstArray() );
613 const sal_Size nLen( deviceColor.getLength() );
614 ENSURE_ARG_OR_THROW2(nLen%4==0,
615 "number of channels no multiple of 4",
616 static_cast<rendering::XColorSpace*>(this), 0);
618 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
619 rendering::ARGBColor* pOut( aRes.getArray() );
620 for( sal_Size i=0; i<nLen; i+=4 )
622 *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
623 pIn += 4;
625 return aRes;
627 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
629 const double* pIn( deviceColor.getConstArray() );
630 const sal_Size nLen( deviceColor.getLength() );
631 ENSURE_ARG_OR_THROW2(nLen%4==0,
632 "number of channels no multiple of 4",
633 static_cast<rendering::XColorSpace*>(this), 0);
635 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
636 rendering::ARGBColor* pOut( aRes.getArray() );
637 for( sal_Size i=0; i<nLen; i+=4 )
639 *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
640 pIn += 4;
642 return aRes;
644 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
646 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
647 const sal_Size nLen( rgbColor.getLength() );
649 uno::Sequence< double > aRes(nLen*4);
650 double* pColors=aRes.getArray();
651 for( sal_Size i=0; i<nLen; ++i )
653 *pColors++ = pIn->Red;
654 *pColors++ = pIn->Green;
655 *pColors++ = pIn->Blue;
656 *pColors++ = 1.0; // the value does not matter
657 ++pIn;
659 return aRes;
661 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
663 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
664 const sal_Size nLen( rgbColor.getLength() );
666 uno::Sequence< double > aRes(nLen*4);
667 double* pColors=aRes.getArray();
668 for( sal_Size i=0; i<nLen; ++i )
670 *pColors++ = pIn->Red;
671 *pColors++ = pIn->Green;
672 *pColors++ = pIn->Blue;
673 *pColors++ = 1.0; // the value does not matter
674 ++pIn;
676 return aRes;
678 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
680 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
681 const sal_Size nLen( rgbColor.getLength() );
683 uno::Sequence< double > aRes(nLen*4);
684 double* pColors=aRes.getArray();
685 for( sal_Size i=0; i<nLen; ++i )
687 *pColors++ = pIn->Red/pIn->Alpha;
688 *pColors++ = pIn->Green/pIn->Alpha;
689 *pColors++ = pIn->Blue/pIn->Alpha;
690 *pColors++ = 1.0; // the value does not matter
691 ++pIn;
693 return aRes;
696 // XIntegerBitmapColorSpace
697 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
699 return 32;
701 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
703 return maBitCounts;
705 virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
707 return util::Endianness::LITTLE;
709 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
710 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
711 uno::RuntimeException, std::exception) SAL_OVERRIDE
713 if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
715 const sal_Int8* pIn( deviceColor.getConstArray() );
716 const sal_Size nLen( deviceColor.getLength() );
717 ENSURE_ARG_OR_THROW2(nLen%4==0,
718 "number of channels no multiple of 4",
719 static_cast<rendering::XColorSpace*>(this), 0);
721 uno::Sequence<double> aRes(nLen);
722 double* pOut( aRes.getArray() );
723 for( sal_Size i=0; i<nLen; i+=4 )
725 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
726 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
727 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
728 *pOut++ = 1.0;
730 return aRes;
732 else
734 // TODO(P3): if we know anything about target
735 // colorspace, this can be greatly sped up
736 uno::Sequence<rendering::ARGBColor> aIntermediate(
737 convertIntegerToARGB(deviceColor));
738 return targetColorSpace->convertFromARGB(aIntermediate);
741 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
742 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
743 uno::RuntimeException, std::exception) SAL_OVERRIDE
745 if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
747 // it's us, so simply pass-through the data
748 return deviceColor;
750 else
752 // TODO(P3): if we know anything about target
753 // colorspace, this can be greatly sped up
754 uno::Sequence<rendering::ARGBColor> aIntermediate(
755 convertIntegerToARGB(deviceColor));
756 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
759 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
761 const sal_Int8* pIn( deviceColor.getConstArray() );
762 const sal_Size nLen( deviceColor.getLength() );
763 ENSURE_ARG_OR_THROW2(nLen%4==0,
764 "number of channels no multiple of 4",
765 static_cast<rendering::XColorSpace*>(this), 0);
767 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
768 rendering::RGBColor* pOut( aRes.getArray() );
769 for( sal_Size i=0; i<nLen; i+=4 )
771 *pOut++ = rendering::RGBColor(
772 vcl::unotools::toDoubleColor(pIn[0]),
773 vcl::unotools::toDoubleColor(pIn[1]),
774 vcl::unotools::toDoubleColor(pIn[2]));
775 pIn += 4;
777 return aRes;
780 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
782 const sal_Int8* pIn( deviceColor.getConstArray() );
783 const sal_Size nLen( deviceColor.getLength() );
784 ENSURE_ARG_OR_THROW2(nLen%4==0,
785 "number of channels no multiple of 4",
786 static_cast<rendering::XColorSpace*>(this), 0);
788 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
789 rendering::ARGBColor* pOut( aRes.getArray() );
790 for( sal_Size i=0; i<nLen; i+=4 )
792 *pOut++ = rendering::ARGBColor(
793 1.0,
794 vcl::unotools::toDoubleColor(pIn[0]),
795 vcl::unotools::toDoubleColor(pIn[1]),
796 vcl::unotools::toDoubleColor(pIn[2]));
797 pIn += 4;
799 return aRes;
802 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
804 const sal_Int8* pIn( deviceColor.getConstArray() );
805 const sal_Size nLen( deviceColor.getLength() );
806 ENSURE_ARG_OR_THROW2(nLen%4==0,
807 "number of channels no multiple of 4",
808 static_cast<rendering::XColorSpace*>(this), 0);
810 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
811 rendering::ARGBColor* pOut( aRes.getArray() );
812 for( sal_Size i=0; i<nLen; i+=4 )
814 *pOut++ = rendering::ARGBColor(
815 1.0,
816 vcl::unotools::toDoubleColor(pIn[0]),
817 vcl::unotools::toDoubleColor(pIn[1]),
818 vcl::unotools::toDoubleColor(pIn[2]));
819 pIn += 4;
821 return aRes;
824 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
826 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
827 const sal_Size nLen( rgbColor.getLength() );
829 uno::Sequence< sal_Int8 > aRes(nLen*4);
830 sal_Int8* pColors=aRes.getArray();
831 for( sal_Size i=0; i<nLen; ++i )
833 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
834 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
835 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
836 *pColors++ = 1.0;
837 ++pIn;
839 return aRes;
842 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
844 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
845 const sal_Size nLen( rgbColor.getLength() );
847 uno::Sequence< sal_Int8 > aRes(nLen*4);
848 sal_Int8* pColors=aRes.getArray();
849 for( sal_Size i=0; i<nLen; ++i )
851 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
852 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
853 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
854 *pColors++ = -1;
855 ++pIn;
857 return aRes;
860 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
862 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
863 const sal_Size nLen( rgbColor.getLength() );
865 uno::Sequence< sal_Int8 > aRes(nLen*4);
866 sal_Int8* pColors=aRes.getArray();
867 for( sal_Size i=0; i<nLen; ++i )
869 *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
870 *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
871 *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
872 *pColors++ = -1;
873 ++pIn;
875 return aRes;
878 public:
879 StandardNoAlphaColorSpace() :
880 maComponentTags(3),
881 maBitCounts(3)
883 sal_Int8* pTags = maComponentTags.getArray();
884 sal_Int32* pBitCounts = maBitCounts.getArray();
885 pTags[0] = rendering::ColorComponentTag::RGB_RED;
886 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
887 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
889 pBitCounts[0] =
890 pBitCounts[1] =
891 pBitCounts[2] = 8;
895 struct StandardColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
896 StandardColorSpaceHolder>
898 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
900 return new StandardColorSpace();
904 struct StandardNoAlphaColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
905 StandardNoAlphaColorSpaceHolder>
907 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
909 return new StandardNoAlphaColorSpace();
914 uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpace()
916 return StandardColorSpaceHolder::get();
919 uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpaceWithoutAlpha()
921 return StandardNoAlphaColorSpaceHolder::get();
924 rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
926 rendering::IntegerBitmapLayout aLayout;
928 aLayout.ScanLines = rBmpSize.Height;
929 aLayout.ScanLineBytes = rBmpSize.Width*4;
930 aLayout.ScanLineStride = aLayout.ScanLineBytes;
931 aLayout.PlaneStride = 0;
932 aLayout.ColorSpace = getStdColorSpace();
933 aLayout.Palette.clear();
934 aLayout.IsMsbFirst = sal_False;
936 return aLayout;
939 ::Color stdIntSequenceToColor( const uno::Sequence<sal_Int8>& rColor )
941 #ifdef OSL_BIGENDIAN
942 const sal_Int8* pCols( rColor.getConstArray() );
943 return ::Color( pCols[3], pCols[0], pCols[1], pCols[2] );
944 #else
945 return ::Color( *reinterpret_cast< const ::ColorData* >(rColor.getConstArray()) );
946 #endif
949 uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
951 uno::Sequence<sal_Int8> aRet(4);
952 sal_Int8* pCols( aRet.getArray() );
953 #ifdef OSL_BIGENDIAN
954 pCols[0] = rColor.GetRed();
955 pCols[1] = rColor.GetGreen();
956 pCols[2] = rColor.GetBlue();
957 pCols[3] = 255-rColor.GetTransparency();
958 #else
959 *reinterpret_cast<sal_Int32*>(pCols) = rColor.GetColor();
960 #endif
961 return aRet;
964 // Create a corrected view transformation out of the give one,
965 // which ensures that the rectangle given by (0,0) and
966 // rSpriteSize is mapped with its left,top corner to (0,0)
967 // again. This is required to properly render sprite
968 // animations to buffer bitmaps.
969 ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
970 const ::basegfx::B2DRange& i_srcRect,
971 const ::basegfx::B2DHomMatrix& i_transformation )
973 if( i_srcRect.isEmpty() )
974 return o_transform=i_transformation;
976 // transform by given transformation
977 ::basegfx::B2DRectangle aTransformedRect;
979 calcTransformedRectBounds( aTransformedRect,
980 i_srcRect,
981 i_transformation );
983 // now move resulting left,top point of bounds to (0,0)
984 const basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
985 -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
987 // prepend to original transformation
988 o_transform = aCorrectedTransform * i_transformation;
990 return o_transform;
993 ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& outRect,
994 const ::basegfx::B2DRange& inRect,
995 const ::basegfx::B2DHomMatrix& transformation )
997 outRect.reset();
999 if( inRect.isEmpty() )
1000 return outRect;
1002 // transform all four extremal points of the rectangle,
1003 // take bounding rect of those.
1005 // transform left-top point
1006 outRect.expand( transformation * inRect.getMinimum() );
1008 // transform bottom-right point
1009 outRect.expand( transformation * inRect.getMaximum() );
1011 ::basegfx::B2DPoint aPoint;
1013 // transform top-right point
1014 aPoint.setX( inRect.getMaxX() );
1015 aPoint.setY( inRect.getMinY() );
1017 aPoint *= transformation;
1018 outRect.expand( aPoint );
1020 // transform bottom-left point
1021 aPoint.setX( inRect.getMinX() );
1022 aPoint.setY( inRect.getMaxY() );
1024 aPoint *= transformation;
1025 outRect.expand( aPoint );
1027 // over and out.
1028 return outRect;
1031 bool isInside( const ::basegfx::B2DRange& rContainedRect,
1032 const ::basegfx::B2DRange& rTransformRect,
1033 const ::basegfx::B2DHomMatrix& rTransformation )
1035 if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
1036 return false;
1038 ::basegfx::B2DPolygon aPoly(
1039 ::basegfx::tools::createPolygonFromRect( rTransformRect ) );
1040 aPoly.transform( rTransformation );
1042 return ::basegfx::tools::isInside( aPoly,
1043 ::basegfx::tools::createPolygonFromRect(
1044 rContainedRect ),
1045 true );
1048 namespace
1050 bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea,
1051 ::basegfx::B2IRange& io_rSourceArea,
1052 ::basegfx::B2IPoint& io_rDestPoint,
1053 const ::basegfx::B2IRange& rSourceBounds,
1054 const ::basegfx::B2IRange& rDestBounds )
1056 const ::basegfx::B2IPoint aSourceTopLeft(
1057 io_rSourceArea.getMinimum() );
1059 ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
1061 // clip source area (which must be inside rSourceBounds)
1062 aLocalSourceArea.intersect( rSourceBounds );
1064 if( aLocalSourceArea.isEmpty() )
1065 return false;
1067 // calc relative new source area points (relative to orig
1068 // source area)
1069 const ::basegfx::B2IVector aUpperLeftOffset(
1070 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1071 const ::basegfx::B2IVector aLowerRightOffset(
1072 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1074 ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1075 io_rDestPoint + aLowerRightOffset );
1077 // clip dest area (which must be inside rDestBounds)
1078 aLocalDestArea.intersect( rDestBounds );
1080 if( aLocalDestArea.isEmpty() )
1081 return false;
1083 // calc relative new dest area points (relative to orig
1084 // source area)
1085 const ::basegfx::B2IVector aDestUpperLeftOffset(
1086 aLocalDestArea.getMinimum()-io_rDestPoint );
1087 const ::basegfx::B2IVector aDestLowerRightOffset(
1088 aLocalDestArea.getMaximum()-io_rDestPoint );
1090 io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
1091 aSourceTopLeft + aDestLowerRightOffset );
1092 io_rDestPoint = aLocalDestArea.getMinimum();
1094 if( o_pDestArea )
1095 *o_pDestArea = aLocalDestArea;
1097 return true;
1101 bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
1102 ::basegfx::B2IPoint& io_rDestPoint,
1103 ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
1104 const ::basegfx::B2IRange& rBounds )
1106 ::basegfx::B2IRange aResultingDestArea;
1108 // compute full destination area (to determine uninitialized
1109 // areas below)
1110 const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
1111 ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
1112 io_rDestPoint.getY(),
1113 (io_rDestPoint.getX()
1114 + static_cast<sal_Int32>(rRange.getX())),
1115 (io_rDestPoint.getY()
1116 + static_cast<sal_Int32>(rRange.getY())) );
1117 // limit to output area (no point updating outside of it)
1118 aInputDestArea.intersect( rBounds );
1120 // clip to rBounds
1121 if( !clipAreaImpl( &aResultingDestArea,
1122 io_rSourceArea,
1123 io_rDestPoint,
1124 rBounds,
1125 rBounds ) )
1126 return false;
1128 // finally, compute all areas clipped off the total
1129 // destination area.
1130 ::basegfx::computeSetDifference( o_ClippedAreas,
1131 aInputDestArea,
1132 aResultingDestArea );
1134 return true;
1137 ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
1139 if( rRange.isEmpty() )
1140 return ::basegfx::B2IRange();
1142 const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
1143 ::basegfx::fround( rRange.getMinY() ) );
1144 return ::basegfx::B2IRange( aTopLeft,
1145 aTopLeft + ::basegfx::B2IPoint(
1146 ::basegfx::fround( rRange.getWidth() ),
1147 ::basegfx::fround( rRange.getHeight() ) ) );
1150 uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
1151 uno::Sequence< uno::Any >& o_rxParams )
1153 o_rxParams.realloc( 0 );
1155 if( i_rxCanvas.is() )
1159 uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
1160 uno::UNO_QUERY_THROW );
1162 uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
1163 uno::UNO_QUERY_THROW );
1164 uno::Reference< beans::XPropertySet > xPropSet( xDevice,
1165 uno::UNO_QUERY_THROW );
1167 o_rxParams.realloc( 2 );
1169 o_rxParams[ 0 ] = uno::makeAny( xServiceInfo->getImplementationName() );
1170 o_rxParams[ 1 ] = xPropSet->getPropertyValue( "DeviceHandle" );
1172 catch( const uno::Exception& )
1174 // ignore, but return empty sequence
1178 return o_rxParams;
1181 awt::Rectangle getAbsoluteWindowRect( const awt::Rectangle& rRect,
1182 const uno::Reference< awt::XWindow2 >& xWin )
1184 awt::Rectangle aRetVal( rRect );
1186 vcl::Window* pWindow = VCLUnoHelper::GetWindow(xWin);
1187 if( pWindow )
1189 ::Point aPoint( aRetVal.X,
1190 aRetVal.Y );
1192 aPoint = pWindow->OutputToScreenPixel( aPoint );
1194 aRetVal.X = aPoint.X();
1195 aRetVal.Y = aPoint.Y();
1198 return aRetVal;
1201 ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange )
1203 ::basegfx::B2DPolyPolygon aPolyPoly;
1204 ::basegfx::B2DPolygon aPoly;
1206 const double nX0( rRange.getMinX() );
1207 const double nY0( rRange.getMinY() );
1208 const double nX1( rRange.getMaxX() );
1209 const double nY1( rRange.getMaxY() );
1211 aPoly.append( ::basegfx::B2DPoint( nX0+4,
1212 nY0 ) );
1213 aPoly.append( ::basegfx::B2DPoint( nX0,
1214 nY0 ) );
1215 aPoly.append( ::basegfx::B2DPoint( nX0,
1216 nY0+4 ) );
1217 aPolyPoly.append( aPoly ); aPoly.clear();
1219 aPoly.append( ::basegfx::B2DPoint( nX1-4,
1220 nY0 ) );
1221 aPoly.append( ::basegfx::B2DPoint( nX1,
1222 nY0 ) );
1223 aPoly.append( ::basegfx::B2DPoint( nX1,
1224 nY0+4 ) );
1225 aPolyPoly.append( aPoly ); aPoly.clear();
1227 aPoly.append( ::basegfx::B2DPoint( nX0+4,
1228 nY1 ) );
1229 aPoly.append( ::basegfx::B2DPoint( nX0,
1230 nY1 ) );
1231 aPoly.append( ::basegfx::B2DPoint( nX0,
1232 nY1-4 ) );
1233 aPolyPoly.append( aPoly ); aPoly.clear();
1235 aPoly.append( ::basegfx::B2DPoint( nX1-4,
1236 nY1 ) );
1237 aPoly.append( ::basegfx::B2DPoint( nX1,
1238 nY1 ) );
1239 aPoly.append( ::basegfx::B2DPoint( nX1,
1240 nY1-4 ) );
1241 aPolyPoly.append( aPoly );
1243 return aPolyPoly;
1246 int calcGradientStepCount( ::basegfx::B2DHomMatrix& rTotalTransform,
1247 const rendering::ViewState& viewState,
1248 const rendering::RenderState& renderState,
1249 const rendering::Texture& texture,
1250 int nColorSteps )
1252 // calculate overall texture transformation (directly from
1253 // texture to device space).
1254 ::basegfx::B2DHomMatrix aMatrix;
1256 rTotalTransform.identity();
1257 ::basegfx::unotools::homMatrixFromAffineMatrix( rTotalTransform,
1258 texture.AffineTransform );
1259 ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
1260 viewState,
1261 renderState);
1262 rTotalTransform *= aMatrix; // prepend total view/render transformation
1264 // determine size of gradient in device coordinate system
1265 // (to e.g. determine sensible number of gradient steps)
1266 ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
1267 ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
1268 ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
1269 ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
1271 aLeftTop *= rTotalTransform;
1272 aLeftBottom *= rTotalTransform;
1273 aRightTop *= rTotalTransform;
1274 aRightBottom*= rTotalTransform;
1276 // longest line in gradient bound rect
1277 const int nGradientSize(
1278 static_cast<int>(
1279 ::std::max(
1280 ::basegfx::B2DVector(aRightBottom-aLeftTop).getLength(),
1281 ::basegfx::B2DVector(aRightTop-aLeftBottom).getLength() ) + 1.0 ) );
1283 // typical number for pixel of the same color (strip size)
1284 const int nStripSize( nGradientSize < 50 ? 2 : 4 );
1286 // use at least three steps, and at utmost the number of color
1287 // steps
1288 return ::std::max( 3,
1289 ::std::min(
1290 nGradientSize / nStripSize,
1291 nColorSteps ) );
1294 void clipOutDev(const rendering::ViewState& viewState,
1295 const rendering::RenderState& renderState,
1296 OutputDevice& rOutDev,
1297 OutputDevice* p2ndOutDev)
1299 // accumulate non-empty clips into one region
1300 vcl::Region aClipRegion(true);
1302 if( viewState.Clip.is() )
1304 ::basegfx::B2DPolyPolygon aClipPoly(
1305 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(viewState.Clip) );
1307 if( aClipPoly.count() )
1309 // setup non-empty clipping
1310 ::basegfx::B2DHomMatrix aMatrix;
1311 aClipPoly.transform(
1312 ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
1313 viewState.AffineTransform ) );
1315 aClipRegion = vcl::Region::GetRegionFromPolyPolygon( ::tools::PolyPolygon( aClipPoly ) );
1317 else
1319 // clip polygon is empty
1320 aClipRegion.SetEmpty();
1324 if( renderState.Clip.is() )
1326 ::basegfx::B2DPolyPolygon aClipPoly(
1327 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(renderState.Clip) );
1329 ::basegfx::B2DHomMatrix aMatrix;
1330 aClipPoly.transform(
1331 ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
1332 viewState,
1333 renderState ) );
1335 if( aClipPoly.count() )
1337 // setup non-empty clipping
1338 vcl::Region aRegion = vcl::Region::GetRegionFromPolyPolygon( ::tools::PolyPolygon( aClipPoly ) );
1339 aClipRegion.Intersect( aRegion );
1341 else
1343 // clip polygon is empty
1344 aClipRegion.SetEmpty();
1348 // setup accumulated clip region. Note that setting an
1349 // empty clip region denotes "clip everything" on the
1350 // OutputDevice (which is why we translate that into
1351 // SetClipRegion() here). When both view and render clip
1352 // are empty, aClipRegion remains default-constructed,
1353 // i.e. empty, too.
1354 if( aClipRegion.IsNull() )
1356 rOutDev.SetClipRegion();
1358 if( p2ndOutDev )
1359 p2ndOutDev->SetClipRegion();
1361 else
1363 rOutDev.SetClipRegion( aClipRegion );
1365 if( p2ndOutDev )
1366 p2ndOutDev->SetClipRegion( aClipRegion );
1369 } // namespace tools
1371 } // namespace canvas
1373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */