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 :
21 : #include <canvas/debug.hxx>
22 : #include <tools/diagnose_ex.h>
23 :
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>
40 :
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>
54 :
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>
60 :
61 : #include <canvas/canvastools.hxx>
62 :
63 : #include <limits>
64 :
65 :
66 : using namespace ::com::sun::star;
67 :
68 : namespace com { namespace sun { namespace star { namespace rendering
69 : {
70 0 : bool operator==( const RenderState& renderState1,
71 : const RenderState& renderState2 )
72 : {
73 0 : if( renderState1.Clip != renderState2.Clip )
74 0 : return false;
75 :
76 0 : if( renderState1.DeviceColor != renderState2.DeviceColor )
77 0 : return false;
78 :
79 0 : if( renderState1.CompositeOperation != renderState2.CompositeOperation )
80 0 : return false;
81 :
82 0 : ::basegfx::B2DHomMatrix mat1, mat2;
83 0 : ::canvas::tools::getRenderStateTransform( mat1, renderState1 );
84 0 : ::canvas::tools::getRenderStateTransform( mat2, renderState2 );
85 0 : if( mat1 != mat2 )
86 0 : return false;
87 :
88 0 : return true;
89 : }
90 :
91 0 : bool operator==( const ViewState& viewState1,
92 : const ViewState& viewState2 )
93 : {
94 0 : if( viewState1.Clip != viewState2.Clip )
95 0 : return false;
96 :
97 0 : ::basegfx::B2DHomMatrix mat1, mat2;
98 0 : ::canvas::tools::getViewStateTransform( mat1, viewState1 );
99 0 : ::canvas::tools::getViewStateTransform( mat2, viewState2 );
100 0 : if( mat1 != mat2 )
101 0 : return false;
102 :
103 0 : return true;
104 : }
105 : }}}}
106 :
107 : namespace canvas
108 : {
109 : namespace tools
110 : {
111 0 : geometry::RealSize2D createInfiniteSize2D()
112 : {
113 : return geometry::RealSize2D(
114 0 : ::std::numeric_limits<double>::infinity(),
115 0 : ::std::numeric_limits<double>::infinity() );
116 : }
117 :
118 0 : rendering::RenderState& initRenderState( rendering::RenderState& renderState )
119 : {
120 : // setup identity transform
121 0 : setIdentityAffineMatrix2D( renderState.AffineTransform );
122 0 : renderState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
123 0 : renderState.DeviceColor = uno::Sequence< double >();
124 0 : renderState.CompositeOperation = rendering::CompositeOperation::OVER;
125 :
126 0 : return renderState;
127 : }
128 :
129 0 : rendering::ViewState& initViewState( rendering::ViewState& viewState )
130 : {
131 : // setup identity transform
132 0 : setIdentityAffineMatrix2D( viewState.AffineTransform );
133 0 : viewState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
134 :
135 0 : return viewState;
136 : }
137 :
138 0 : ::basegfx::B2DHomMatrix& getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
139 : const rendering::ViewState& viewState )
140 : {
141 0 : return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, viewState.AffineTransform );
142 : }
143 :
144 0 : rendering::ViewState& setViewStateTransform( rendering::ViewState& viewState,
145 : const ::basegfx::B2DHomMatrix& transform )
146 : {
147 0 : ::basegfx::unotools::affineMatrixFromHomMatrix( viewState.AffineTransform, transform );
148 :
149 0 : return viewState;
150 : }
151 :
152 0 : ::basegfx::B2DHomMatrix& getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
153 : const rendering::RenderState& renderState )
154 : {
155 0 : return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, renderState.AffineTransform );
156 : }
157 :
158 0 : rendering::RenderState& setRenderStateTransform( rendering::RenderState& renderState,
159 : const ::basegfx::B2DHomMatrix& transform )
160 : {
161 0 : ::basegfx::unotools::affineMatrixFromHomMatrix( renderState.AffineTransform, transform );
162 :
163 0 : return renderState;
164 : }
165 :
166 0 : rendering::RenderState& appendToRenderState( rendering::RenderState& renderState,
167 : const ::basegfx::B2DHomMatrix& rTransform )
168 : {
169 0 : ::basegfx::B2DHomMatrix transform;
170 :
171 0 : getRenderStateTransform( transform, renderState );
172 0 : return setRenderStateTransform( renderState, transform * rTransform );
173 : }
174 :
175 0 : rendering::RenderState& prependToRenderState( rendering::RenderState& renderState,
176 : const ::basegfx::B2DHomMatrix& rTransform )
177 : {
178 0 : ::basegfx::B2DHomMatrix transform;
179 :
180 0 : getRenderStateTransform( transform, renderState );
181 0 : return setRenderStateTransform( renderState, rTransform * transform );
182 : }
183 :
184 0 : ::basegfx::B2DHomMatrix& mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& combinedTransform,
185 : const rendering::ViewState& viewState,
186 : const rendering::RenderState& renderState )
187 : {
188 0 : ::basegfx::B2DHomMatrix viewTransform;
189 :
190 0 : ::basegfx::unotools::homMatrixFromAffineMatrix( combinedTransform, renderState.AffineTransform );
191 0 : ::basegfx::unotools::homMatrixFromAffineMatrix( viewTransform, viewState.AffineTransform );
192 :
193 : // this statement performs combinedTransform = viewTransform * combinedTransform
194 0 : combinedTransform *= viewTransform;
195 :
196 0 : return combinedTransform;
197 : }
198 :
199 0 : geometry::AffineMatrix2D& setIdentityAffineMatrix2D( geometry::AffineMatrix2D& matrix )
200 : {
201 0 : matrix.m00 = 1.0;
202 0 : matrix.m01 = 0.0;
203 0 : matrix.m02 = 0.0;
204 0 : matrix.m10 = 0.0;
205 0 : matrix.m11 = 1.0;
206 0 : matrix.m12 = 0.0;
207 :
208 0 : return matrix;
209 : }
210 :
211 0 : geometry::Matrix2D& setIdentityMatrix2D( geometry::Matrix2D& matrix )
212 : {
213 0 : matrix.m00 = 1.0;
214 0 : matrix.m01 = 0.0;
215 0 : matrix.m10 = 0.0;
216 0 : matrix.m11 = 1.0;
217 :
218 0 : return matrix;
219 : }
220 :
221 : namespace
222 : {
223 0 : class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
224 : {
225 : private:
226 : uno::Sequence< sal_Int8 > maComponentTags;
227 : uno::Sequence< sal_Int32 > maBitCounts;
228 :
229 0 : virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
230 : {
231 0 : return rendering::ColorSpaceType::RGB;
232 : }
233 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
234 : {
235 0 : return maComponentTags;
236 : }
237 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
238 : {
239 0 : return rendering::RenderingIntent::PERCEPTUAL;
240 : }
241 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
242 : {
243 0 : return uno::Sequence< beans::PropertyValue >();
244 : }
245 0 : 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)
248 : {
249 : // TODO(P3): if we know anything about target
250 : // colorspace, this can be greatly sped up
251 : uno::Sequence<rendering::ARGBColor> aIntermediate(
252 0 : convertToARGB(deviceColor));
253 0 : return targetColorSpace->convertFromARGB(aIntermediate);
254 : }
255 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
256 : {
257 0 : const double* pIn( deviceColor.getConstArray() );
258 0 : const sal_Size nLen( deviceColor.getLength() );
259 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
260 : "number of channels no multiple of 4",
261 : static_cast<rendering::XColorSpace*>(this), 0);
262 :
263 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
264 0 : rendering::RGBColor* pOut( aRes.getArray() );
265 0 : for( sal_Size i=0; i<nLen; i+=4 )
266 : {
267 0 : *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
268 0 : pIn += 4;
269 : }
270 0 : return aRes;
271 : }
272 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
273 : {
274 0 : const double* pIn( deviceColor.getConstArray() );
275 0 : const sal_Size nLen( deviceColor.getLength() );
276 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
277 : "number of channels no multiple of 4",
278 : static_cast<rendering::XColorSpace*>(this), 0);
279 :
280 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
281 0 : rendering::ARGBColor* pOut( aRes.getArray() );
282 0 : for( sal_Size i=0; i<nLen; i+=4 )
283 : {
284 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
285 0 : pIn += 4;
286 : }
287 0 : return aRes;
288 : }
289 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
290 : {
291 0 : const double* pIn( deviceColor.getConstArray() );
292 0 : const sal_Size nLen( deviceColor.getLength() );
293 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
294 : "number of channels no multiple of 4",
295 : static_cast<rendering::XColorSpace*>(this), 0);
296 :
297 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
298 0 : rendering::ARGBColor* pOut( aRes.getArray() );
299 0 : for( sal_Size i=0; i<nLen; i+=4 )
300 : {
301 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
302 0 : pIn += 4;
303 : }
304 0 : return aRes;
305 : }
306 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
307 : {
308 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
309 0 : const sal_Size nLen( rgbColor.getLength() );
310 :
311 0 : uno::Sequence< double > aRes(nLen*4);
312 0 : double* pColors=aRes.getArray();
313 0 : for( sal_Size i=0; i<nLen; ++i )
314 : {
315 0 : *pColors++ = pIn->Red;
316 0 : *pColors++ = pIn->Green;
317 0 : *pColors++ = pIn->Blue;
318 0 : *pColors++ = 1.0;
319 0 : ++pIn;
320 : }
321 0 : return aRes;
322 : }
323 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
324 : {
325 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
326 0 : const sal_Size nLen( rgbColor.getLength() );
327 :
328 0 : uno::Sequence< double > aRes(nLen*4);
329 0 : double* pColors=aRes.getArray();
330 0 : for( sal_Size i=0; i<nLen; ++i )
331 : {
332 0 : *pColors++ = pIn->Red;
333 0 : *pColors++ = pIn->Green;
334 0 : *pColors++ = pIn->Blue;
335 0 : *pColors++ = pIn->Alpha;
336 0 : ++pIn;
337 : }
338 0 : return aRes;
339 : }
340 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
341 : {
342 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
343 0 : const sal_Size nLen( rgbColor.getLength() );
344 :
345 0 : uno::Sequence< double > aRes(nLen*4);
346 0 : double* pColors=aRes.getArray();
347 0 : for( sal_Size i=0; i<nLen; ++i )
348 : {
349 0 : *pColors++ = pIn->Red/pIn->Alpha;
350 0 : *pColors++ = pIn->Green/pIn->Alpha;
351 0 : *pColors++ = pIn->Blue/pIn->Alpha;
352 0 : *pColors++ = pIn->Alpha;
353 0 : ++pIn;
354 : }
355 0 : return aRes;
356 : }
357 :
358 : // XIntegerBitmapColorSpace
359 0 : virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
360 : {
361 0 : return 32;
362 : }
363 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
364 : {
365 0 : return maBitCounts;
366 : }
367 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
368 : {
369 0 : return util::Endianness::LITTLE;
370 : }
371 0 : virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
372 : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
373 : uno::RuntimeException)
374 : {
375 0 : if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
376 : {
377 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
378 0 : const sal_Size nLen( deviceColor.getLength() );
379 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
380 : "number of channels no multiple of 4",
381 : static_cast<rendering::XColorSpace*>(this), 0);
382 :
383 0 : uno::Sequence<double> aRes(nLen);
384 0 : double* pOut( aRes.getArray() );
385 0 : for( sal_Size i=0; i<nLen; i+=4 )
386 : {
387 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
388 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
389 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
390 0 : *pOut++ = vcl::unotools::toDoubleColor(255-*pIn++);
391 : }
392 0 : return aRes;
393 : }
394 : else
395 : {
396 : // TODO(P3): if we know anything about target
397 : // colorspace, this can be greatly sped up
398 : uno::Sequence<rendering::ARGBColor> aIntermediate(
399 0 : convertIntegerToARGB(deviceColor));
400 0 : return targetColorSpace->convertFromARGB(aIntermediate);
401 : }
402 : }
403 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
404 : const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
405 : uno::RuntimeException)
406 : {
407 0 : if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
408 : {
409 : // it's us, so simply pass-through the data
410 0 : return deviceColor;
411 : }
412 : else
413 : {
414 : // TODO(P3): if we know anything about target
415 : // colorspace, this can be greatly sped up
416 : uno::Sequence<rendering::ARGBColor> aIntermediate(
417 0 : convertIntegerToARGB(deviceColor));
418 0 : return targetColorSpace->convertIntegerFromARGB(aIntermediate);
419 : }
420 : }
421 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
422 : {
423 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
424 0 : const sal_Size nLen( deviceColor.getLength() );
425 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
426 : "number of channels no multiple of 4",
427 : static_cast<rendering::XColorSpace*>(this), 0);
428 :
429 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
430 0 : rendering::RGBColor* pOut( aRes.getArray() );
431 0 : for( sal_Size i=0; i<nLen; i+=4 )
432 : {
433 : *pOut++ = rendering::RGBColor(
434 0 : vcl::unotools::toDoubleColor(pIn[0]),
435 0 : vcl::unotools::toDoubleColor(pIn[1]),
436 0 : vcl::unotools::toDoubleColor(pIn[2]));
437 0 : pIn += 4;
438 : }
439 0 : return aRes;
440 : }
441 :
442 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
443 : {
444 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
445 0 : const sal_Size nLen( deviceColor.getLength() );
446 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
447 : "number of channels no multiple of 4",
448 : static_cast<rendering::XColorSpace*>(this), 0);
449 :
450 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
451 0 : rendering::ARGBColor* pOut( aRes.getArray() );
452 0 : for( sal_Size i=0; i<nLen; i+=4 )
453 : {
454 : *pOut++ = rendering::ARGBColor(
455 0 : vcl::unotools::toDoubleColor(255-pIn[3]),
456 0 : vcl::unotools::toDoubleColor(pIn[0]),
457 0 : vcl::unotools::toDoubleColor(pIn[1]),
458 0 : vcl::unotools::toDoubleColor(pIn[2]));
459 0 : pIn += 4;
460 : }
461 0 : return aRes;
462 : }
463 :
464 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
465 : {
466 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
467 0 : const sal_Size nLen( deviceColor.getLength() );
468 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
469 : "number of channels no multiple of 4",
470 : static_cast<rendering::XColorSpace*>(this), 0);
471 :
472 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
473 0 : rendering::ARGBColor* pOut( aRes.getArray() );
474 0 : for( sal_Size i=0; i<nLen; i+=4 )
475 : {
476 0 : const sal_Int8 nAlpha( 255-pIn[3] );
477 : *pOut++ = rendering::ARGBColor(
478 0 : vcl::unotools::toDoubleColor(nAlpha),
479 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
480 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
481 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
482 0 : pIn += 4;
483 : }
484 0 : return aRes;
485 : }
486 :
487 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
488 : {
489 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
490 0 : const sal_Size nLen( rgbColor.getLength() );
491 :
492 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
493 0 : sal_Int8* pColors=aRes.getArray();
494 0 : for( sal_Size i=0; i<nLen; ++i )
495 : {
496 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
497 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
498 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
499 0 : *pColors++ = 0;
500 0 : ++pIn;
501 : }
502 0 : return aRes;
503 : }
504 :
505 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
506 : {
507 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
508 0 : const sal_Size nLen( rgbColor.getLength() );
509 :
510 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
511 0 : sal_Int8* pColors=aRes.getArray();
512 0 : for( sal_Size i=0; i<nLen; ++i )
513 : {
514 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
515 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
516 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
517 0 : *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
518 0 : ++pIn;
519 : }
520 0 : return aRes;
521 : }
522 :
523 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
524 : {
525 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
526 0 : const sal_Size nLen( rgbColor.getLength() );
527 :
528 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
529 0 : sal_Int8* pColors=aRes.getArray();
530 0 : for( sal_Size i=0; i<nLen; ++i )
531 : {
532 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
533 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
534 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
535 0 : *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
536 0 : ++pIn;
537 : }
538 0 : return aRes;
539 : }
540 :
541 : public:
542 0 : StandardColorSpace() :
543 : maComponentTags(4),
544 0 : maBitCounts(4)
545 : {
546 0 : sal_Int8* pTags = maComponentTags.getArray();
547 0 : sal_Int32* pBitCounts = maBitCounts.getArray();
548 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
549 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
550 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
551 0 : pTags[3] = rendering::ColorComponentTag::ALPHA;
552 :
553 : pBitCounts[0] =
554 0 : pBitCounts[1] =
555 0 : pBitCounts[2] =
556 0 : pBitCounts[3] = 8;
557 0 : }
558 : };
559 :
560 0 : class StandardNoAlphaColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
561 : {
562 : private:
563 : uno::Sequence< sal_Int8 > maComponentTags;
564 : uno::Sequence< sal_Int32 > maBitCounts;
565 :
566 0 : virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
567 : {
568 0 : return rendering::ColorSpaceType::RGB;
569 : }
570 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
571 : {
572 0 : return maComponentTags;
573 : }
574 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
575 : {
576 0 : return rendering::RenderingIntent::PERCEPTUAL;
577 : }
578 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
579 : {
580 0 : return uno::Sequence< beans::PropertyValue >();
581 : }
582 0 : virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
583 : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
584 : uno::RuntimeException)
585 : {
586 : // TODO(P3): if we know anything about target
587 : // colorspace, this can be greatly sped up
588 : uno::Sequence<rendering::ARGBColor> aIntermediate(
589 0 : convertToARGB(deviceColor));
590 0 : return targetColorSpace->convertFromARGB(aIntermediate);
591 : }
592 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
593 : {
594 0 : const double* pIn( deviceColor.getConstArray() );
595 0 : const sal_Size nLen( deviceColor.getLength() );
596 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
597 : "number of channels no multiple of 4",
598 : static_cast<rendering::XColorSpace*>(this), 0);
599 :
600 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
601 0 : rendering::RGBColor* pOut( aRes.getArray() );
602 0 : for( sal_Size i=0; i<nLen; i+=4 )
603 : {
604 0 : *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
605 0 : pIn += 4;
606 : }
607 0 : return aRes;
608 : }
609 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
610 : {
611 0 : const double* pIn( deviceColor.getConstArray() );
612 0 : const sal_Size nLen( deviceColor.getLength() );
613 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
614 : "number of channels no multiple of 4",
615 : static_cast<rendering::XColorSpace*>(this), 0);
616 :
617 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
618 0 : rendering::ARGBColor* pOut( aRes.getArray() );
619 0 : for( sal_Size i=0; i<nLen; i+=4 )
620 : {
621 0 : *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
622 0 : pIn += 4;
623 : }
624 0 : return aRes;
625 : }
626 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
627 : {
628 0 : const double* pIn( deviceColor.getConstArray() );
629 0 : const sal_Size nLen( deviceColor.getLength() );
630 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
631 : "number of channels no multiple of 4",
632 : static_cast<rendering::XColorSpace*>(this), 0);
633 :
634 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
635 0 : rendering::ARGBColor* pOut( aRes.getArray() );
636 0 : for( sal_Size i=0; i<nLen; i+=4 )
637 : {
638 0 : *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
639 0 : pIn += 4;
640 : }
641 0 : return aRes;
642 : }
643 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
644 : {
645 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
646 0 : const sal_Size nLen( rgbColor.getLength() );
647 :
648 0 : uno::Sequence< double > aRes(nLen*4);
649 0 : double* pColors=aRes.getArray();
650 0 : for( sal_Size i=0; i<nLen; ++i )
651 : {
652 0 : *pColors++ = pIn->Red;
653 0 : *pColors++ = pIn->Green;
654 0 : *pColors++ = pIn->Blue;
655 0 : *pColors++ = 1.0; // the value does not matter
656 0 : ++pIn;
657 : }
658 0 : return aRes;
659 : }
660 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
661 : {
662 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
663 0 : const sal_Size nLen( rgbColor.getLength() );
664 :
665 0 : uno::Sequence< double > aRes(nLen*4);
666 0 : double* pColors=aRes.getArray();
667 0 : for( sal_Size i=0; i<nLen; ++i )
668 : {
669 0 : *pColors++ = pIn->Red;
670 0 : *pColors++ = pIn->Green;
671 0 : *pColors++ = pIn->Blue;
672 0 : *pColors++ = 1.0; // the value does not matter
673 0 : ++pIn;
674 : }
675 0 : return aRes;
676 : }
677 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
678 : {
679 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
680 0 : const sal_Size nLen( rgbColor.getLength() );
681 :
682 0 : uno::Sequence< double > aRes(nLen*4);
683 0 : double* pColors=aRes.getArray();
684 0 : for( sal_Size i=0; i<nLen; ++i )
685 : {
686 0 : *pColors++ = pIn->Red/pIn->Alpha;
687 0 : *pColors++ = pIn->Green/pIn->Alpha;
688 0 : *pColors++ = pIn->Blue/pIn->Alpha;
689 0 : *pColors++ = 1.0; // the value does not matter
690 0 : ++pIn;
691 : }
692 0 : return aRes;
693 : }
694 :
695 : // XIntegerBitmapColorSpace
696 0 : virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
697 : {
698 0 : return 32;
699 : }
700 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
701 : {
702 0 : return maBitCounts;
703 : }
704 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
705 : {
706 0 : return util::Endianness::LITTLE;
707 : }
708 0 : virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
709 : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
710 : uno::RuntimeException)
711 : {
712 0 : if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
713 : {
714 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
715 0 : const sal_Size nLen( deviceColor.getLength() );
716 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
717 : "number of channels no multiple of 4",
718 : static_cast<rendering::XColorSpace*>(this), 0);
719 :
720 0 : uno::Sequence<double> aRes(nLen);
721 0 : double* pOut( aRes.getArray() );
722 0 : for( sal_Size i=0; i<nLen; i+=4 )
723 : {
724 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
725 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
726 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
727 0 : *pOut++ = 1.0;
728 : }
729 0 : return aRes;
730 : }
731 : else
732 : {
733 : // TODO(P3): if we know anything about target
734 : // colorspace, this can be greatly sped up
735 : uno::Sequence<rendering::ARGBColor> aIntermediate(
736 0 : convertIntegerToARGB(deviceColor));
737 0 : return targetColorSpace->convertFromARGB(aIntermediate);
738 : }
739 : }
740 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
741 : const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
742 : uno::RuntimeException)
743 : {
744 0 : if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
745 : {
746 : // it's us, so simply pass-through the data
747 0 : return deviceColor;
748 : }
749 : else
750 : {
751 : // TODO(P3): if we know anything about target
752 : // colorspace, this can be greatly sped up
753 : uno::Sequence<rendering::ARGBColor> aIntermediate(
754 0 : convertIntegerToARGB(deviceColor));
755 0 : return targetColorSpace->convertIntegerFromARGB(aIntermediate);
756 : }
757 : }
758 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
759 : {
760 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
761 0 : const sal_Size nLen( deviceColor.getLength() );
762 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
763 : "number of channels no multiple of 4",
764 : static_cast<rendering::XColorSpace*>(this), 0);
765 :
766 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
767 0 : rendering::RGBColor* pOut( aRes.getArray() );
768 0 : for( sal_Size i=0; i<nLen; i+=4 )
769 : {
770 : *pOut++ = rendering::RGBColor(
771 0 : vcl::unotools::toDoubleColor(pIn[0]),
772 0 : vcl::unotools::toDoubleColor(pIn[1]),
773 0 : vcl::unotools::toDoubleColor(pIn[2]));
774 0 : pIn += 4;
775 : }
776 0 : return aRes;
777 : }
778 :
779 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
780 : {
781 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
782 0 : const sal_Size nLen( deviceColor.getLength() );
783 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
784 : "number of channels no multiple of 4",
785 : static_cast<rendering::XColorSpace*>(this), 0);
786 :
787 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
788 0 : rendering::ARGBColor* pOut( aRes.getArray() );
789 0 : for( sal_Size i=0; i<nLen; i+=4 )
790 : {
791 : *pOut++ = rendering::ARGBColor(
792 : 1.0,
793 0 : vcl::unotools::toDoubleColor(pIn[0]),
794 0 : vcl::unotools::toDoubleColor(pIn[1]),
795 0 : vcl::unotools::toDoubleColor(pIn[2]));
796 0 : pIn += 4;
797 : }
798 0 : return aRes;
799 : }
800 :
801 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
802 : {
803 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
804 0 : const sal_Size nLen( deviceColor.getLength() );
805 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
806 : "number of channels no multiple of 4",
807 : static_cast<rendering::XColorSpace*>(this), 0);
808 :
809 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
810 0 : rendering::ARGBColor* pOut( aRes.getArray() );
811 0 : for( sal_Size i=0; i<nLen; i+=4 )
812 : {
813 : *pOut++ = rendering::ARGBColor(
814 : 1.0,
815 0 : vcl::unotools::toDoubleColor(pIn[0]),
816 0 : vcl::unotools::toDoubleColor(pIn[1]),
817 0 : vcl::unotools::toDoubleColor(pIn[2]));
818 0 : pIn += 4;
819 : }
820 0 : return aRes;
821 : }
822 :
823 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
824 : {
825 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
826 0 : const sal_Size nLen( rgbColor.getLength() );
827 :
828 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
829 0 : sal_Int8* pColors=aRes.getArray();
830 0 : for( sal_Size i=0; i<nLen; ++i )
831 : {
832 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
833 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
834 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
835 0 : *pColors++ = 1.0;
836 0 : ++pIn;
837 : }
838 0 : return aRes;
839 : }
840 :
841 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
842 : {
843 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
844 0 : const sal_Size nLen( rgbColor.getLength() );
845 :
846 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
847 0 : sal_Int8* pColors=aRes.getArray();
848 0 : for( sal_Size i=0; i<nLen; ++i )
849 : {
850 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
851 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
852 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
853 0 : *pColors++ = -1;
854 0 : ++pIn;
855 : }
856 0 : return aRes;
857 : }
858 :
859 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
860 : {
861 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
862 0 : const sal_Size nLen( rgbColor.getLength() );
863 :
864 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
865 0 : sal_Int8* pColors=aRes.getArray();
866 0 : for( sal_Size i=0; i<nLen; ++i )
867 : {
868 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
869 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
870 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
871 0 : *pColors++ = -1;
872 0 : ++pIn;
873 : }
874 0 : return aRes;
875 : }
876 :
877 : public:
878 0 : StandardNoAlphaColorSpace() :
879 : maComponentTags(3),
880 0 : maBitCounts(3)
881 : {
882 0 : sal_Int8* pTags = maComponentTags.getArray();
883 0 : sal_Int32* pBitCounts = maBitCounts.getArray();
884 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
885 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
886 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
887 :
888 : pBitCounts[0] =
889 0 : pBitCounts[1] =
890 0 : pBitCounts[2] = 8;
891 0 : }
892 : };
893 :
894 : struct StandardColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
895 : StandardColorSpaceHolder>
896 : {
897 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
898 : {
899 0 : return new StandardColorSpace();
900 : }
901 : };
902 :
903 : struct StandardNoAlphaColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
904 : StandardNoAlphaColorSpaceHolder>
905 : {
906 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
907 : {
908 0 : return new StandardNoAlphaColorSpace();
909 : }
910 : };
911 : }
912 :
913 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpace()
914 : {
915 0 : return StandardColorSpaceHolder::get();
916 : }
917 :
918 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpaceWithoutAlpha()
919 : {
920 0 : return StandardNoAlphaColorSpaceHolder::get();
921 : }
922 :
923 0 : rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
924 : {
925 0 : rendering::IntegerBitmapLayout aLayout;
926 :
927 0 : aLayout.ScanLines = rBmpSize.Height;
928 0 : aLayout.ScanLineBytes = rBmpSize.Width*4;
929 0 : aLayout.ScanLineStride = aLayout.ScanLineBytes;
930 0 : aLayout.PlaneStride = 0;
931 0 : aLayout.ColorSpace = getStdColorSpace();
932 0 : aLayout.Palette.clear();
933 0 : aLayout.IsMsbFirst = sal_False;
934 :
935 0 : return aLayout;
936 : }
937 :
938 0 : ::Color stdIntSequenceToColor( const uno::Sequence<sal_Int8>& rColor )
939 : {
940 : #ifdef OSL_BIGENDIAN
941 : const sal_Int8* pCols( rColor.getConstArray() );
942 : return ::Color( pCols[3], pCols[0], pCols[1], pCols[2] );
943 : #else
944 0 : return ::Color( *reinterpret_cast< const ::ColorData* >(rColor.getConstArray()) );
945 : #endif
946 : }
947 :
948 0 : uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
949 : {
950 0 : uno::Sequence<sal_Int8> aRet(4);
951 0 : sal_Int8* pCols( aRet.getArray() );
952 : #ifdef OSL_BIGENDIAN
953 : pCols[0] = rColor.GetRed();
954 : pCols[1] = rColor.GetGreen();
955 : pCols[2] = rColor.GetBlue();
956 : pCols[3] = 255-rColor.GetTransparency();
957 : #else
958 0 : *reinterpret_cast<sal_Int32*>(pCols) = rColor.GetColor();
959 : #endif
960 0 : return aRet;
961 : }
962 :
963 : // Create a corrected view transformation out of the give one,
964 : // which ensures that the rectangle given by (0,0) and
965 : // rSpriteSize is mapped with its left,top corner to (0,0)
966 : // again. This is required to properly render sprite
967 : // animations to buffer bitmaps.
968 0 : ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
969 : const ::basegfx::B2DRange& i_srcRect,
970 : const ::basegfx::B2DHomMatrix& i_transformation )
971 : {
972 0 : if( i_srcRect.isEmpty() )
973 0 : return o_transform=i_transformation;
974 :
975 : // transform by given transformation
976 0 : ::basegfx::B2DRectangle aTransformedRect;
977 :
978 : calcTransformedRectBounds( aTransformedRect,
979 : i_srcRect,
980 0 : i_transformation );
981 :
982 : // now move resulting left,top point of bounds to (0,0)
983 : const basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
984 0 : -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
985 :
986 : // prepend to original transformation
987 0 : o_transform = aCorrectedTransform * i_transformation;
988 :
989 0 : return o_transform;
990 : }
991 :
992 0 : ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& outRect,
993 : const ::basegfx::B2DRange& inRect,
994 : const ::basegfx::B2DHomMatrix& transformation )
995 : {
996 0 : outRect.reset();
997 :
998 0 : if( inRect.isEmpty() )
999 0 : return outRect;
1000 :
1001 : // transform all four extremal points of the rectangle,
1002 : // take bounding rect of those.
1003 :
1004 : // transform left-top point
1005 0 : outRect.expand( transformation * inRect.getMinimum() );
1006 :
1007 : // transform bottom-right point
1008 0 : outRect.expand( transformation * inRect.getMaximum() );
1009 :
1010 0 : ::basegfx::B2DPoint aPoint;
1011 :
1012 : // transform top-right point
1013 0 : aPoint.setX( inRect.getMaxX() );
1014 0 : aPoint.setY( inRect.getMinY() );
1015 :
1016 0 : aPoint *= transformation;
1017 0 : outRect.expand( aPoint );
1018 :
1019 : // transform bottom-left point
1020 0 : aPoint.setX( inRect.getMinX() );
1021 0 : aPoint.setY( inRect.getMaxY() );
1022 :
1023 0 : aPoint *= transformation;
1024 0 : outRect.expand( aPoint );
1025 :
1026 : // over and out.
1027 0 : return outRect;
1028 : }
1029 :
1030 0 : bool isInside( const ::basegfx::B2DRange& rContainedRect,
1031 : const ::basegfx::B2DRange& rTransformRect,
1032 : const ::basegfx::B2DHomMatrix& rTransformation )
1033 : {
1034 0 : if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
1035 0 : return false;
1036 :
1037 : ::basegfx::B2DPolygon aPoly(
1038 0 : ::basegfx::tools::createPolygonFromRect( rTransformRect ) );
1039 0 : aPoly.transform( rTransformation );
1040 :
1041 : return ::basegfx::tools::isInside( aPoly,
1042 : ::basegfx::tools::createPolygonFromRect(
1043 : rContainedRect ),
1044 0 : true );
1045 : }
1046 :
1047 : namespace
1048 : {
1049 0 : bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea,
1050 : ::basegfx::B2IRange& io_rSourceArea,
1051 : ::basegfx::B2IPoint& io_rDestPoint,
1052 : const ::basegfx::B2IRange& rSourceBounds,
1053 : const ::basegfx::B2IRange& rDestBounds )
1054 : {
1055 : const ::basegfx::B2IPoint aSourceTopLeft(
1056 0 : io_rSourceArea.getMinimum() );
1057 :
1058 0 : ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
1059 :
1060 : // clip source area (which must be inside rSourceBounds)
1061 0 : aLocalSourceArea.intersect( rSourceBounds );
1062 :
1063 0 : if( aLocalSourceArea.isEmpty() )
1064 0 : return false;
1065 :
1066 : // calc relative new source area points (relative to orig
1067 : // source area)
1068 : const ::basegfx::B2IVector aUpperLeftOffset(
1069 0 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1070 : const ::basegfx::B2IVector aLowerRightOffset(
1071 0 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1072 :
1073 : ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1074 0 : io_rDestPoint + aLowerRightOffset );
1075 :
1076 : // clip dest area (which must be inside rDestBounds)
1077 0 : aLocalDestArea.intersect( rDestBounds );
1078 :
1079 0 : if( aLocalDestArea.isEmpty() )
1080 0 : return false;
1081 :
1082 : // calc relative new dest area points (relative to orig
1083 : // source area)
1084 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1085 0 : aLocalDestArea.getMinimum()-io_rDestPoint );
1086 : const ::basegfx::B2IVector aDestLowerRightOffset(
1087 0 : aLocalDestArea.getMaximum()-io_rDestPoint );
1088 :
1089 : io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
1090 0 : aSourceTopLeft + aDestLowerRightOffset );
1091 0 : io_rDestPoint = aLocalDestArea.getMinimum();
1092 :
1093 0 : if( o_pDestArea )
1094 0 : *o_pDestArea = aLocalDestArea;
1095 :
1096 0 : return true;
1097 : }
1098 : }
1099 :
1100 0 : bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
1101 : ::basegfx::B2IPoint& io_rDestPoint,
1102 : ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
1103 : const ::basegfx::B2IRange& rBounds )
1104 : {
1105 0 : ::basegfx::B2IRange aResultingDestArea;
1106 :
1107 : // compute full destination area (to determine uninitialized
1108 : // areas below)
1109 0 : const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
1110 : ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
1111 : io_rDestPoint.getY(),
1112 0 : (io_rDestPoint.getX()
1113 0 : + static_cast<sal_Int32>(rRange.getX())),
1114 0 : (io_rDestPoint.getY()
1115 0 : + static_cast<sal_Int32>(rRange.getY())) );
1116 : // limit to output area (no point updating outside of it)
1117 0 : aInputDestArea.intersect( rBounds );
1118 :
1119 : // clip to rBounds
1120 0 : if( !clipAreaImpl( &aResultingDestArea,
1121 : io_rSourceArea,
1122 : io_rDestPoint,
1123 : rBounds,
1124 0 : rBounds ) )
1125 0 : return false;
1126 :
1127 : // finally, compute all areas clipped off the total
1128 : // destination area.
1129 : ::basegfx::computeSetDifference( o_ClippedAreas,
1130 : aInputDestArea,
1131 0 : aResultingDestArea );
1132 :
1133 0 : return true;
1134 : }
1135 :
1136 0 : ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
1137 : {
1138 0 : if( rRange.isEmpty() )
1139 0 : return ::basegfx::B2IRange();
1140 :
1141 : const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
1142 0 : ::basegfx::fround( rRange.getMinY() ) );
1143 : return ::basegfx::B2IRange( aTopLeft,
1144 : aTopLeft + ::basegfx::B2IPoint(
1145 : ::basegfx::fround( rRange.getWidth() ),
1146 0 : ::basegfx::fround( rRange.getHeight() ) ) );
1147 : }
1148 :
1149 0 : uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
1150 : uno::Sequence< uno::Any >& o_rxParams )
1151 : {
1152 0 : o_rxParams.realloc( 0 );
1153 :
1154 0 : if( i_rxCanvas.is() )
1155 : {
1156 : try
1157 : {
1158 0 : uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
1159 0 : uno::UNO_QUERY_THROW );
1160 :
1161 : uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
1162 0 : uno::UNO_QUERY_THROW );
1163 : uno::Reference< beans::XPropertySet > xPropSet( xDevice,
1164 0 : uno::UNO_QUERY_THROW );
1165 :
1166 0 : o_rxParams.realloc( 2 );
1167 :
1168 0 : o_rxParams[ 0 ] = uno::makeAny( xServiceInfo->getImplementationName() );
1169 0 : o_rxParams[ 1 ] = uno::makeAny( xPropSet->getPropertyValue(
1170 0 : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DeviceHandle") ) ) );
1171 : }
1172 0 : catch( const uno::Exception& )
1173 : {
1174 : // ignore, but return empty sequence
1175 : }
1176 : }
1177 :
1178 0 : return o_rxParams;
1179 : }
1180 :
1181 0 : awt::Rectangle getAbsoluteWindowRect( const awt::Rectangle& rRect,
1182 : const uno::Reference< awt::XWindow2 >& xWin )
1183 : {
1184 0 : awt::Rectangle aRetVal( rRect );
1185 :
1186 0 : ::Window* pWindow = VCLUnoHelper::GetWindow(xWin);
1187 0 : if( pWindow )
1188 : {
1189 : ::Point aPoint( aRetVal.X,
1190 0 : aRetVal.Y );
1191 :
1192 0 : aPoint = pWindow->OutputToScreenPixel( aPoint );
1193 :
1194 0 : aRetVal.X = aPoint.X();
1195 0 : aRetVal.Y = aPoint.Y();
1196 : }
1197 :
1198 0 : return aRetVal;
1199 : }
1200 :
1201 0 : ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange )
1202 : {
1203 0 : ::basegfx::B2DPolyPolygon aPolyPoly;
1204 0 : ::basegfx::B2DPolygon aPoly;
1205 :
1206 0 : const double nX0( rRange.getMinX() );
1207 0 : const double nY0( rRange.getMinY() );
1208 0 : const double nX1( rRange.getMaxX() );
1209 0 : const double nY1( rRange.getMaxY() );
1210 :
1211 : aPoly.append( ::basegfx::B2DPoint( nX0+4,
1212 0 : nY0 ) );
1213 : aPoly.append( ::basegfx::B2DPoint( nX0,
1214 0 : nY0 ) );
1215 : aPoly.append( ::basegfx::B2DPoint( nX0,
1216 0 : nY0+4 ) );
1217 0 : aPolyPoly.append( aPoly ); aPoly.clear();
1218 :
1219 : aPoly.append( ::basegfx::B2DPoint( nX1-4,
1220 0 : nY0 ) );
1221 : aPoly.append( ::basegfx::B2DPoint( nX1,
1222 0 : nY0 ) );
1223 : aPoly.append( ::basegfx::B2DPoint( nX1,
1224 0 : nY0+4 ) );
1225 0 : aPolyPoly.append( aPoly ); aPoly.clear();
1226 :
1227 : aPoly.append( ::basegfx::B2DPoint( nX0+4,
1228 0 : nY1 ) );
1229 : aPoly.append( ::basegfx::B2DPoint( nX0,
1230 0 : nY1 ) );
1231 : aPoly.append( ::basegfx::B2DPoint( nX0,
1232 0 : nY1-4 ) );
1233 0 : aPolyPoly.append( aPoly ); aPoly.clear();
1234 :
1235 : aPoly.append( ::basegfx::B2DPoint( nX1-4,
1236 0 : nY1 ) );
1237 : aPoly.append( ::basegfx::B2DPoint( nX1,
1238 0 : nY1 ) );
1239 : aPoly.append( ::basegfx::B2DPoint( nX1,
1240 0 : nY1-4 ) );
1241 0 : aPolyPoly.append( aPoly );
1242 :
1243 0 : return aPolyPoly;
1244 : }
1245 :
1246 0 : int calcGradientStepCount( ::basegfx::B2DHomMatrix& rTotalTransform,
1247 : const rendering::ViewState& viewState,
1248 : const rendering::RenderState& renderState,
1249 : const rendering::Texture& texture,
1250 : int nColorSteps )
1251 : {
1252 : // calculate overall texture transformation (directly from
1253 : // texture to device space).
1254 0 : ::basegfx::B2DHomMatrix aMatrix;
1255 :
1256 0 : rTotalTransform.identity();
1257 : ::basegfx::unotools::homMatrixFromAffineMatrix( rTotalTransform,
1258 0 : texture.AffineTransform );
1259 : ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
1260 : viewState,
1261 0 : renderState);
1262 0 : rTotalTransform *= aMatrix; // prepend total view/render transformation
1263 :
1264 : // determine size of gradient in device coordinate system
1265 : // (to e.g. determine sensible number of gradient steps)
1266 0 : ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
1267 0 : ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
1268 0 : ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
1269 0 : ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
1270 :
1271 0 : aLeftTop *= rTotalTransform;
1272 0 : aLeftBottom *= rTotalTransform;
1273 0 : aRightTop *= rTotalTransform;
1274 0 : aRightBottom*= rTotalTransform;
1275 :
1276 : // longest line in gradient bound rect
1277 : const int nGradientSize(
1278 : static_cast<int>(
1279 : ::std::max(
1280 0 : ::basegfx::B2DVector(aRightBottom-aLeftTop).getLength(),
1281 0 : ::basegfx::B2DVector(aRightTop-aLeftBottom).getLength() ) + 1.0 ) );
1282 :
1283 : // typical number for pixel of the same color (strip size)
1284 0 : const int nStripSize( nGradientSize < 50 ? 2 : 4 );
1285 :
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 0 : nColorSteps ) );
1292 : }
1293 :
1294 : } // namespace tools
1295 :
1296 : } // namespace canvas
1297 :
1298 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|