update dev300-m58
[ooovba.git] / canvas / source / tools / canvastools.cxx
blobc01fb7cc1544cea2692536d03fb57586efee1a54
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: canvastools.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
37 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
38 #include <com/sun/star/geometry/Matrix2D.hpp>
39 #include <com/sun/star/awt/Rectangle.hpp>
40 #include <com/sun/star/util/Endianness.hpp>
41 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
42 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
43 #include <com/sun/star/rendering/ColorSpaceType.hpp>
44 #include <com/sun/star/rendering/ColorComponentTag.hpp>
45 #include <com/sun/star/rendering/RenderingIntent.hpp>
46 #include <com/sun/star/rendering/RenderState.hpp>
47 #include <com/sun/star/rendering/ViewState.hpp>
48 #include <com/sun/star/rendering/XCanvas.hpp>
49 #include <com/sun/star/rendering/XColorSpace.hpp>
50 #include <com/sun/star/rendering/CompositeOperation.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/lang/XServiceInfo.hpp>
54 #include <basegfx/matrix/b2dhommatrix.hxx>
55 #include <basegfx/range/b2drange.hxx>
56 #include <basegfx/range/b2irange.hxx>
57 #include <basegfx/range/b2drectangle.hxx>
58 #include <basegfx/point/b2dpoint.hxx>
59 #include <basegfx/point/b2ipoint.hxx>
60 #include <basegfx/vector/b2ivector.hxx>
61 #include <basegfx/polygon/b2dpolygon.hxx>
62 #include <basegfx/polygon/b2dpolygontools.hxx>
63 #include <basegfx/polygon/b2dpolypolygontools.hxx>
64 #include <basegfx/tools/canvastools.hxx>
65 #include <basegfx/numeric/ftools.hxx>
67 #include <cppuhelper/compbase1.hxx>
68 #include <rtl/instance.hxx>
69 #include <toolkit/helper/vclunohelper.hxx>
70 #include <vcl/window.hxx>
71 #include <vcl/canvastools.hxx>
73 #include <canvas/canvastools.hxx>
75 #include <limits>
78 using namespace ::com::sun::star;
80 namespace com { namespace sun { namespace star { namespace rendering
82 bool operator==( const RenderState& renderState1,
83 const RenderState& renderState2 )
85 if( renderState1.Clip != renderState2.Clip )
86 return false;
88 if( renderState1.DeviceColor != renderState2.DeviceColor )
89 return false;
91 if( renderState1.CompositeOperation != renderState2.CompositeOperation )
92 return false;
94 ::basegfx::B2DHomMatrix mat1, mat2;
95 ::canvas::tools::getRenderStateTransform( mat1, renderState1 );
96 ::canvas::tools::getRenderStateTransform( mat2, renderState2 );
97 if( mat1 != mat2 )
98 return false;
100 return true;
103 bool operator==( const ViewState& viewState1,
104 const ViewState& viewState2 )
106 if( viewState1.Clip != viewState2.Clip )
107 return false;
109 ::basegfx::B2DHomMatrix mat1, mat2;
110 ::canvas::tools::getViewStateTransform( mat1, viewState1 );
111 ::canvas::tools::getViewStateTransform( mat2, viewState2 );
112 if( mat1 != mat2 )
113 return false;
115 return true;
117 }}}}
119 namespace canvas
121 namespace tools
123 geometry::RealSize2D createInfiniteSize2D()
125 return geometry::RealSize2D(
126 ::std::numeric_limits<double>::infinity(),
127 ::std::numeric_limits<double>::infinity() );
130 rendering::RenderState& initRenderState( rendering::RenderState& renderState )
132 // setup identity transform
133 setIdentityAffineMatrix2D( renderState.AffineTransform );
134 renderState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
135 renderState.DeviceColor = uno::Sequence< double >();
136 renderState.CompositeOperation = rendering::CompositeOperation::OVER;
138 return renderState;
141 rendering::ViewState& initViewState( rendering::ViewState& viewState )
143 // setup identity transform
144 setIdentityAffineMatrix2D( viewState.AffineTransform );
145 viewState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
147 return viewState;
150 ::basegfx::B2DHomMatrix& getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
151 const rendering::ViewState& viewState )
153 return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, viewState.AffineTransform );
156 rendering::ViewState& setViewStateTransform( rendering::ViewState& viewState,
157 const ::basegfx::B2DHomMatrix& transform )
159 ::basegfx::unotools::affineMatrixFromHomMatrix( viewState.AffineTransform, transform );
161 return viewState;
164 ::basegfx::B2DHomMatrix& getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
165 const rendering::RenderState& renderState )
167 return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, renderState.AffineTransform );
170 rendering::RenderState& setRenderStateTransform( rendering::RenderState& renderState,
171 const ::basegfx::B2DHomMatrix& transform )
173 ::basegfx::unotools::affineMatrixFromHomMatrix( renderState.AffineTransform, transform );
175 return renderState;
178 rendering::RenderState& appendToRenderState( rendering::RenderState& renderState,
179 const ::basegfx::B2DHomMatrix& rTransform )
181 ::basegfx::B2DHomMatrix transform;
183 getRenderStateTransform( transform, renderState );
184 return setRenderStateTransform( renderState, transform * rTransform );
187 rendering::ViewState& appendToViewState( rendering::ViewState& viewState,
188 const ::basegfx::B2DHomMatrix& rTransform )
190 ::basegfx::B2DHomMatrix transform;
192 getViewStateTransform( transform, viewState );
193 return setViewStateTransform( viewState, transform * rTransform );
196 rendering::RenderState& prependToRenderState( rendering::RenderState& renderState,
197 const ::basegfx::B2DHomMatrix& rTransform )
199 ::basegfx::B2DHomMatrix transform;
201 getRenderStateTransform( transform, renderState );
202 return setRenderStateTransform( renderState, rTransform * transform );
205 rendering::ViewState& prependToViewState( rendering::ViewState& viewState,
206 const ::basegfx::B2DHomMatrix& rTransform )
208 ::basegfx::B2DHomMatrix transform;
210 getViewStateTransform( transform, viewState );
211 return setViewStateTransform( viewState, rTransform * transform );
214 ::basegfx::B2DHomMatrix& mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& combinedTransform,
215 const rendering::ViewState& viewState,
216 const rendering::RenderState& renderState )
218 ::basegfx::B2DHomMatrix viewTransform;
220 ::basegfx::unotools::homMatrixFromAffineMatrix( combinedTransform, renderState.AffineTransform );
221 ::basegfx::unotools::homMatrixFromAffineMatrix( viewTransform, viewState.AffineTransform );
223 // this statement performs combinedTransform = viewTransform * combinedTransform
224 combinedTransform *= viewTransform;
226 return combinedTransform;
229 rendering::ViewState& mergeViewAndRenderState( rendering::ViewState& resultViewState,
230 const rendering::ViewState& viewState,
231 const rendering::RenderState& renderState,
232 const uno::Reference< rendering::XCanvas >& /*xCanvas*/ )
234 ::basegfx::B2DHomMatrix aTmpMatrix;
235 geometry::AffineMatrix2D convertedMatrix;
237 resultViewState.Clip = NULL; // TODO(F2): intersect clippings
239 return setViewStateTransform(
240 resultViewState,
241 mergeViewAndRenderTransform( aTmpMatrix,
242 viewState,
243 renderState ) );
246 geometry::AffineMatrix2D& setIdentityAffineMatrix2D( geometry::AffineMatrix2D& matrix )
248 matrix.m00 = 1.0;
249 matrix.m01 = 0.0;
250 matrix.m02 = 0.0;
251 matrix.m10 = 0.0;
252 matrix.m11 = 1.0;
253 matrix.m12 = 0.0;
255 return matrix;
258 geometry::Matrix2D& setIdentityMatrix2D( geometry::Matrix2D& matrix )
260 matrix.m00 = 1.0;
261 matrix.m01 = 0.0;
262 matrix.m10 = 0.0;
263 matrix.m11 = 1.0;
265 return matrix;
268 namespace
270 class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
272 private:
273 uno::Sequence< sal_Int8 > maComponentTags;
274 uno::Sequence< sal_Int32 > maBitCounts;
276 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
278 return rendering::ColorSpaceType::RGB;
280 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
282 return maComponentTags;
284 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
286 return rendering::RenderingIntent::PERCEPTUAL;
288 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
290 return uno::Sequence< beans::PropertyValue >();
292 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
293 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
294 uno::RuntimeException)
296 // TODO(P3): if we know anything about target
297 // colorspace, this can be greatly sped up
298 uno::Sequence<rendering::ARGBColor> aIntermediate(
299 convertToARGB(deviceColor));
300 return targetColorSpace->convertFromARGB(aIntermediate);
302 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
304 const double* pIn( deviceColor.getConstArray() );
305 const sal_Size nLen( deviceColor.getLength() );
306 ENSURE_ARG_OR_THROW2(nLen%4==0,
307 "number of channels no multiple of 4",
308 static_cast<rendering::XColorSpace*>(this), 0);
310 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
311 rendering::RGBColor* pOut( aRes.getArray() );
312 for( sal_Size i=0; i<nLen; i+=4 )
314 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
315 pIn += 4;
317 return aRes;
319 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
321 const double* pIn( deviceColor.getConstArray() );
322 const sal_Size nLen( deviceColor.getLength() );
323 ENSURE_ARG_OR_THROW2(nLen%4==0,
324 "number of channels no multiple of 4",
325 static_cast<rendering::XColorSpace*>(this), 0);
327 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
328 rendering::ARGBColor* pOut( aRes.getArray() );
329 for( sal_Size i=0; i<nLen; i+=4 )
331 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
332 pIn += 4;
334 return aRes;
336 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
338 const double* pIn( deviceColor.getConstArray() );
339 const sal_Size nLen( deviceColor.getLength() );
340 ENSURE_ARG_OR_THROW2(nLen%4==0,
341 "number of channels no multiple of 4",
342 static_cast<rendering::XColorSpace*>(this), 0);
344 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
345 rendering::ARGBColor* pOut( aRes.getArray() );
346 for( sal_Size i=0; i<nLen; i+=4 )
348 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
349 pIn += 4;
351 return aRes;
353 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
355 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
356 const sal_Size nLen( rgbColor.getLength() );
358 uno::Sequence< double > aRes(nLen*4);
359 double* pColors=aRes.getArray();
360 for( sal_Size i=0; i<nLen; ++i )
362 *pColors++ = pIn->Red;
363 *pColors++ = pIn->Green;
364 *pColors++ = pIn->Blue;
365 *pColors++ = 1.0;
366 ++pIn;
368 return aRes;
370 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
372 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
373 const sal_Size nLen( rgbColor.getLength() );
375 uno::Sequence< double > aRes(nLen*4);
376 double* pColors=aRes.getArray();
377 for( sal_Size i=0; i<nLen; ++i )
379 *pColors++ = pIn->Red;
380 *pColors++ = pIn->Green;
381 *pColors++ = pIn->Blue;
382 *pColors++ = pIn->Alpha;
383 ++pIn;
385 return aRes;
387 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
389 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
390 const sal_Size nLen( rgbColor.getLength() );
392 uno::Sequence< double > aRes(nLen*4);
393 double* pColors=aRes.getArray();
394 for( sal_Size i=0; i<nLen; ++i )
396 *pColors++ = pIn->Red/pIn->Alpha;
397 *pColors++ = pIn->Green/pIn->Alpha;
398 *pColors++ = pIn->Blue/pIn->Alpha;
399 *pColors++ = pIn->Alpha;
400 ++pIn;
402 return aRes;
405 // XIntegerBitmapColorSpace
406 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
408 return 32;
410 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
412 return maBitCounts;
414 virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
416 return util::Endianness::LITTLE;
418 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
419 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
420 uno::RuntimeException)
422 if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
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<double> aRes(nLen);
431 double* pOut( aRes.getArray() );
432 for( sal_Size i=0; i<nLen; i+=4 )
434 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
435 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
436 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
437 *pOut++ = vcl::unotools::toDoubleColor(255-*pIn++);
439 return aRes;
441 else
443 // TODO(P3): if we know anything about target
444 // colorspace, this can be greatly sped up
445 uno::Sequence<rendering::ARGBColor> aIntermediate(
446 convertIntegerToARGB(deviceColor));
447 return targetColorSpace->convertFromARGB(aIntermediate);
450 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
451 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
452 uno::RuntimeException)
454 if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
456 // it's us, so simply pass-through the data
457 return deviceColor;
459 else
461 // TODO(P3): if we know anything about target
462 // colorspace, this can be greatly sped up
463 uno::Sequence<rendering::ARGBColor> aIntermediate(
464 convertIntegerToARGB(deviceColor));
465 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
468 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
470 const sal_Int8* pIn( deviceColor.getConstArray() );
471 const sal_Size nLen( deviceColor.getLength() );
472 ENSURE_ARG_OR_THROW2(nLen%4==0,
473 "number of channels no multiple of 4",
474 static_cast<rendering::XColorSpace*>(this), 0);
476 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
477 rendering::RGBColor* pOut( aRes.getArray() );
478 for( sal_Size i=0; i<nLen; i+=4 )
480 *pOut++ = rendering::RGBColor(
481 vcl::unotools::toDoubleColor(pIn[0]),
482 vcl::unotools::toDoubleColor(pIn[1]),
483 vcl::unotools::toDoubleColor(pIn[2]));
484 pIn += 4;
486 return aRes;
489 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
491 const sal_Int8* pIn( deviceColor.getConstArray() );
492 const sal_Size nLen( deviceColor.getLength() );
493 ENSURE_ARG_OR_THROW2(nLen%4==0,
494 "number of channels no multiple of 4",
495 static_cast<rendering::XColorSpace*>(this), 0);
497 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
498 rendering::ARGBColor* pOut( aRes.getArray() );
499 for( sal_Size i=0; i<nLen; i+=4 )
501 *pOut++ = rendering::ARGBColor(
502 vcl::unotools::toDoubleColor(255-pIn[3]),
503 vcl::unotools::toDoubleColor(pIn[0]),
504 vcl::unotools::toDoubleColor(pIn[1]),
505 vcl::unotools::toDoubleColor(pIn[2]));
506 pIn += 4;
508 return aRes;
511 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
513 const sal_Int8* pIn( deviceColor.getConstArray() );
514 const sal_Size nLen( deviceColor.getLength() );
515 ENSURE_ARG_OR_THROW2(nLen%4==0,
516 "number of channels no multiple of 4",
517 static_cast<rendering::XColorSpace*>(this), 0);
519 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
520 rendering::ARGBColor* pOut( aRes.getArray() );
521 for( sal_Size i=0; i<nLen; i+=4 )
523 const sal_Int8 nAlpha( 255-pIn[3] );
524 *pOut++ = rendering::ARGBColor(
525 vcl::unotools::toDoubleColor(nAlpha),
526 vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
527 vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
528 vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
529 pIn += 4;
531 return aRes;
534 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
536 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
537 const sal_Size nLen( rgbColor.getLength() );
539 uno::Sequence< sal_Int8 > aRes(nLen*4);
540 sal_Int8* pColors=aRes.getArray();
541 for( sal_Size i=0; i<nLen; ++i )
543 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
544 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
545 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
546 *pColors++ = 0;
547 ++pIn;
549 return aRes;
552 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
554 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
555 const sal_Size nLen( rgbColor.getLength() );
557 uno::Sequence< sal_Int8 > aRes(nLen*4);
558 sal_Int8* pColors=aRes.getArray();
559 for( sal_Size i=0; i<nLen; ++i )
561 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
562 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
563 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
564 *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
565 ++pIn;
567 return aRes;
570 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
572 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
573 const sal_Size nLen( rgbColor.getLength() );
575 uno::Sequence< sal_Int8 > aRes(nLen*4);
576 sal_Int8* pColors=aRes.getArray();
577 for( sal_Size i=0; i<nLen; ++i )
579 *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
580 *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
581 *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
582 *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
583 ++pIn;
585 return aRes;
588 public:
589 StandardColorSpace() :
590 maComponentTags(4),
591 maBitCounts(4)
593 sal_Int8* pTags = maComponentTags.getArray();
594 sal_Int32* pBitCounts = maBitCounts.getArray();
595 pTags[0] = rendering::ColorComponentTag::RGB_RED;
596 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
597 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
598 pTags[3] = rendering::ColorComponentTag::ALPHA;
600 pBitCounts[0] =
601 pBitCounts[1] =
602 pBitCounts[2] =
603 pBitCounts[3] = 8;
607 struct StandardColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
608 StandardColorSpaceHolder>
610 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
612 return new StandardColorSpace();
617 uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpace()
619 return StandardColorSpaceHolder::get();
622 rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
624 rendering::IntegerBitmapLayout aLayout;
626 aLayout.ScanLines = rBmpSize.Height;
627 aLayout.ScanLineBytes = rBmpSize.Width*4;
628 aLayout.ScanLineStride = aLayout.ScanLineBytes;
629 aLayout.PlaneStride = 0;
630 aLayout.ColorSpace = getStdColorSpace();
631 aLayout.Palette.clear();
632 aLayout.IsMsbFirst = sal_False;
634 return aLayout;
637 ::Color stdIntSequenceToColor( const uno::Sequence<sal_Int8>& rColor )
639 #ifdef OSL_BIGENDIAN
640 const sal_Int8* pCols( rColor.getConstArray() );
641 return ::Color( pCols[3], pCols[0], pCols[1], pCols[2] );
642 #else
643 return ::Color( *reinterpret_cast< const ::ColorData* >(rColor.getConstArray()) );
644 #endif
647 uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
649 uno::Sequence<sal_Int8> aRet(4);
650 sal_Int8* pCols( aRet.getArray() );
651 #ifdef OSL_BIGENDIAN
652 pCols[0] = rColor.GetRed();
653 pCols[1] = rColor.GetGreen();
654 pCols[2] = rColor.GetBlue();
655 pCols[3] = 255-rColor.GetTransparency();
656 #else
657 *reinterpret_cast<sal_Int32*>(pCols) = rColor.GetColor();
658 #endif
659 return aRet;
662 // Create a corrected view transformation out of the give one,
663 // which ensures that the rectangle given by (0,0) and
664 // rSpriteSize is mapped with its left,top corner to (0,0)
665 // again. This is required to properly render sprite
666 // animations to buffer bitmaps.
667 ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
668 const ::basegfx::B2DRange& i_srcRect,
669 const ::basegfx::B2DHomMatrix& i_transformation )
671 if( i_srcRect.isEmpty() )
672 return o_transform=i_transformation;
674 // transform by given transformation
675 ::basegfx::B2DRectangle aTransformedRect;
677 calcTransformedRectBounds( aTransformedRect,
678 i_srcRect,
679 i_transformation );
681 // now move resulting left,top point of bounds to (0,0)
682 ::basegfx::B2DHomMatrix aCorrectedTransform;
683 aCorrectedTransform.translate( -aTransformedRect.getMinX(),
684 -aTransformedRect.getMinY() );
686 // prepend to original transformation
687 o_transform = aCorrectedTransform * i_transformation;
689 return o_transform;
692 ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& outRect,
693 const ::basegfx::B2DRange& inRect,
694 const ::basegfx::B2DHomMatrix& transformation )
696 outRect.reset();
698 if( inRect.isEmpty() )
699 return outRect;
701 // transform all four extremal points of the rectangle,
702 // take bounding rect of those.
704 // transform left-top point
705 outRect.expand( transformation * inRect.getMinimum() );
707 // transform bottom-right point
708 outRect.expand( transformation * inRect.getMaximum() );
710 ::basegfx::B2DPoint aPoint;
712 // transform top-right point
713 aPoint.setX( inRect.getMaxX() );
714 aPoint.setY( inRect.getMinY() );
716 aPoint *= transformation;
717 outRect.expand( aPoint );
719 // transform bottom-left point
720 aPoint.setX( inRect.getMinX() );
721 aPoint.setY( inRect.getMaxY() );
723 aPoint *= transformation;
724 outRect.expand( aPoint );
726 // over and out.
727 return outRect;
730 ::basegfx::B2DHomMatrix& calcRectToRectTransform( ::basegfx::B2DHomMatrix& o_transform,
731 const ::basegfx::B2DRange& destRect,
732 const ::basegfx::B2DRange& srcRect,
733 const ::basegfx::B2DHomMatrix& transformation )
735 if( srcRect.isEmpty() ||
736 destRect.isEmpty() )
738 return o_transform=transformation;
741 // transform inputRect by transformation
742 ::basegfx::B2DRectangle aTransformedRect;
743 calcTransformedRectBounds( aTransformedRect,
744 srcRect,
745 transformation );
747 // now move resulting left,top point of bounds to (0,0)
748 ::basegfx::B2DHomMatrix aCorrectedTransform;
749 aCorrectedTransform.translate( -aTransformedRect.getMinX(),
750 -aTransformedRect.getMinY() );
752 // scale to match outRect
753 const double xDenom( aTransformedRect.getWidth() );
754 const double yDenom( aTransformedRect.getHeight() );
755 if( xDenom != 0.0 && yDenom != 0.0 )
756 aCorrectedTransform.scale( destRect.getWidth() / xDenom,
757 destRect.getHeight() / yDenom );
758 // TODO(E2): error handling
760 // translate to final position
761 aCorrectedTransform.translate( destRect.getMinX(),
762 destRect.getMinY() );
764 ::basegfx::B2DHomMatrix transform( transformation );
765 o_transform = aCorrectedTransform * transform;
767 return o_transform;
770 bool isInside( const ::basegfx::B2DRange& rContainedRect,
771 const ::basegfx::B2DRange& rTransformRect,
772 const ::basegfx::B2DHomMatrix& rTransformation )
774 if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
775 return false;
777 ::basegfx::B2DPolygon aPoly(
778 ::basegfx::tools::createPolygonFromRect( rTransformRect ) );
779 aPoly.transform( rTransformation );
781 return ::basegfx::tools::isInside( aPoly,
782 ::basegfx::tools::createPolygonFromRect(
783 rContainedRect ),
784 true );
787 namespace
789 bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea,
790 ::basegfx::B2IRange& io_rSourceArea,
791 ::basegfx::B2IPoint& io_rDestPoint,
792 const ::basegfx::B2IRange& rSourceBounds,
793 const ::basegfx::B2IRange& rDestBounds )
795 const ::basegfx::B2IPoint aSourceTopLeft(
796 io_rSourceArea.getMinimum() );
798 ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
800 // clip source area (which must be inside rSourceBounds)
801 aLocalSourceArea.intersect( rSourceBounds );
803 if( aLocalSourceArea.isEmpty() )
804 return false;
806 // calc relative new source area points (relative to orig
807 // source area)
808 const ::basegfx::B2IVector aUpperLeftOffset(
809 aLocalSourceArea.getMinimum()-aSourceTopLeft );
810 const ::basegfx::B2IVector aLowerRightOffset(
811 aLocalSourceArea.getMaximum()-aSourceTopLeft );
813 ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
814 io_rDestPoint + aLowerRightOffset );
816 // clip dest area (which must be inside rDestBounds)
817 aLocalDestArea.intersect( rDestBounds );
819 if( aLocalDestArea.isEmpty() )
820 return false;
822 // calc relative new dest area points (relative to orig
823 // source area)
824 const ::basegfx::B2IVector aDestUpperLeftOffset(
825 aLocalDestArea.getMinimum()-io_rDestPoint );
826 const ::basegfx::B2IVector aDestLowerRightOffset(
827 aLocalDestArea.getMaximum()-io_rDestPoint );
829 io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
830 aSourceTopLeft + aDestLowerRightOffset );
831 io_rDestPoint = aLocalDestArea.getMinimum();
833 if( o_pDestArea )
834 *o_pDestArea = aLocalDestArea;
836 return true;
840 bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
841 ::basegfx::B2IPoint& io_rDestPoint,
842 ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
843 const ::basegfx::B2IRange& rBounds )
845 ::basegfx::B2IRange aResultingDestArea;
847 // compute full destination area (to determine uninitialized
848 // areas below)
849 const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
850 ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
851 io_rDestPoint.getY(),
852 (io_rDestPoint.getX()
853 + static_cast<sal_Int32>(rRange.getX())),
854 (io_rDestPoint.getY()
855 + static_cast<sal_Int32>(rRange.getY())) );
856 // limit to output area (no point updating outside of it)
857 aInputDestArea.intersect( rBounds );
859 // clip to rBounds
860 if( !clipAreaImpl( &aResultingDestArea,
861 io_rSourceArea,
862 io_rDestPoint,
863 rBounds,
864 rBounds ) )
865 return false;
867 // finally, compute all areas clipped off the total
868 // destination area.
869 ::basegfx::computeSetDifference( o_ClippedAreas,
870 aInputDestArea,
871 aResultingDestArea );
873 return true;
876 bool clipBlit( ::basegfx::B2IRange& io_rSourceArea,
877 ::basegfx::B2IPoint& io_rDestPoint,
878 const ::basegfx::B2IRange& rSourceBounds,
879 const ::basegfx::B2IRange& rDestBounds )
881 return clipAreaImpl( NULL,
882 io_rSourceArea,
883 io_rDestPoint,
884 rSourceBounds,
885 rDestBounds );
888 ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
890 if( rRange.isEmpty() )
891 return ::basegfx::B2IRange();
893 const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
894 ::basegfx::fround( rRange.getMinY() ) );
895 return ::basegfx::B2IRange( aTopLeft,
896 aTopLeft + ::basegfx::B2IPoint(
897 ::basegfx::fround( rRange.getWidth() ),
898 ::basegfx::fround( rRange.getHeight() ) ) );
901 uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
902 uno::Sequence< uno::Any >& o_rxParams )
904 o_rxParams.realloc( 0 );
906 if( i_rxCanvas.is() )
910 uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
911 uno::UNO_QUERY_THROW );
913 uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
914 uno::UNO_QUERY_THROW );
915 uno::Reference< beans::XPropertySet > xPropSet( xDevice,
916 uno::UNO_QUERY_THROW );
918 o_rxParams.realloc( 2 );
920 o_rxParams[ 0 ] = uno::makeAny( xServiceInfo->getImplementationName() );
921 o_rxParams[ 1 ] = uno::makeAny( xPropSet->getPropertyValue(
922 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DeviceHandle") ) ) );
924 catch( uno::Exception& )
926 // ignore, but return empty sequence
930 return o_rxParams;
933 awt::Rectangle getAbsoluteWindowRect( const awt::Rectangle& rRect,
934 const uno::Reference< awt::XWindow2 >& xWin )
936 awt::Rectangle aRetVal( rRect );
938 ::Window* pWindow = VCLUnoHelper::GetWindow(xWin);
939 if( pWindow )
941 ::Point aPoint( aRetVal.X,
942 aRetVal.Y );
944 aPoint = pWindow->OutputToScreenPixel( aPoint );
946 aRetVal.X = aPoint.X();
947 aRetVal.Y = aPoint.Y();
950 return aRetVal;
953 ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange )
955 ::basegfx::B2DPolyPolygon aPolyPoly;
956 ::basegfx::B2DPolygon aPoly;
958 const double nX0( rRange.getMinX() );
959 const double nY0( rRange.getMinY() );
960 const double nX1( rRange.getMaxX() );
961 const double nY1( rRange.getMaxY() );
963 aPoly.append( ::basegfx::B2DPoint( nX0+4,
964 nY0 ) );
965 aPoly.append( ::basegfx::B2DPoint( nX0,
966 nY0 ) );
967 aPoly.append( ::basegfx::B2DPoint( nX0,
968 nY0+4 ) );
969 aPolyPoly.append( aPoly ); aPoly.clear();
971 aPoly.append( ::basegfx::B2DPoint( nX1-4,
972 nY0 ) );
973 aPoly.append( ::basegfx::B2DPoint( nX1,
974 nY0 ) );
975 aPoly.append( ::basegfx::B2DPoint( nX1,
976 nY0+4 ) );
977 aPolyPoly.append( aPoly ); aPoly.clear();
979 aPoly.append( ::basegfx::B2DPoint( nX0+4,
980 nY1 ) );
981 aPoly.append( ::basegfx::B2DPoint( nX0,
982 nY1 ) );
983 aPoly.append( ::basegfx::B2DPoint( nX0,
984 nY1-4 ) );
985 aPolyPoly.append( aPoly ); aPoly.clear();
987 aPoly.append( ::basegfx::B2DPoint( nX1-4,
988 nY1 ) );
989 aPoly.append( ::basegfx::B2DPoint( nX1,
990 nY1 ) );
991 aPoly.append( ::basegfx::B2DPoint( nX1,
992 nY1-4 ) );
993 aPolyPoly.append( aPoly );
995 return aPolyPoly;
998 } // namespace tools
1000 } // namespace canvas