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 14 : rendering::RenderState& initRenderState( rendering::RenderState& renderState )
119 : {
120 : // setup identity transform
121 14 : setIdentityAffineMatrix2D( renderState.AffineTransform );
122 14 : renderState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
123 14 : renderState.DeviceColor = uno::Sequence< double >();
124 14 : renderState.CompositeOperation = rendering::CompositeOperation::OVER;
125 :
126 14 : return renderState;
127 : }
128 :
129 2 : rendering::ViewState& initViewState( rendering::ViewState& viewState )
130 : {
131 : // setup identity transform
132 2 : setIdentityAffineMatrix2D( viewState.AffineTransform );
133 2 : viewState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
134 :
135 2 : return viewState;
136 : }
137 :
138 12 : ::basegfx::B2DHomMatrix& getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
139 : const rendering::ViewState& viewState )
140 : {
141 12 : return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, viewState.AffineTransform );
142 : }
143 :
144 2 : rendering::ViewState& setViewStateTransform( rendering::ViewState& viewState,
145 : const ::basegfx::B2DHomMatrix& transform )
146 : {
147 2 : ::basegfx::unotools::affineMatrixFromHomMatrix( viewState.AffineTransform, transform );
148 :
149 2 : return viewState;
150 : }
151 :
152 16 : ::basegfx::B2DHomMatrix& getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
153 : const rendering::RenderState& renderState )
154 : {
155 16 : return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, renderState.AffineTransform );
156 : }
157 :
158 26 : rendering::RenderState& setRenderStateTransform( rendering::RenderState& renderState,
159 : const ::basegfx::B2DHomMatrix& transform )
160 : {
161 26 : ::basegfx::unotools::affineMatrixFromHomMatrix( renderState.AffineTransform, transform );
162 :
163 26 : return renderState;
164 : }
165 :
166 2 : rendering::RenderState& appendToRenderState( rendering::RenderState& renderState,
167 : const ::basegfx::B2DHomMatrix& rTransform )
168 : {
169 2 : ::basegfx::B2DHomMatrix transform;
170 :
171 2 : getRenderStateTransform( transform, renderState );
172 2 : return setRenderStateTransform( renderState, transform * rTransform );
173 : }
174 :
175 12 : rendering::RenderState& prependToRenderState( rendering::RenderState& renderState,
176 : const ::basegfx::B2DHomMatrix& rTransform )
177 : {
178 12 : ::basegfx::B2DHomMatrix transform;
179 :
180 12 : getRenderStateTransform( transform, renderState );
181 12 : 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 16 : geometry::AffineMatrix2D& setIdentityAffineMatrix2D( geometry::AffineMatrix2D& matrix )
200 : {
201 16 : matrix.m00 = 1.0;
202 16 : matrix.m01 = 0.0;
203 16 : matrix.m02 = 0.0;
204 16 : matrix.m10 = 0.0;
205 16 : matrix.m11 = 1.0;
206 16 : matrix.m12 = 0.0;
207 :
208 16 : 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, std::exception) SAL_OVERRIDE
230 : {
231 0 : return rendering::ColorSpaceType::RGB;
232 : }
233 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
234 : {
235 0 : return maComponentTags;
236 : }
237 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
238 : {
239 0 : return rendering::RenderingIntent::PERCEPTUAL;
240 : }
241 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
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, std::exception) SAL_OVERRIDE
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, std::exception) SAL_OVERRIDE
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, std::exception) SAL_OVERRIDE
273 : {
274 : SAL_WARN_IF(deviceColor.getLength() == 0, "canvas", "empty deviceColor argument");
275 0 : const double* pIn( deviceColor.getConstArray() );
276 0 : const sal_Size nLen( deviceColor.getLength() );
277 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
278 : "number of channels no multiple of 4",
279 : static_cast<rendering::XColorSpace*>(this), 0);
280 :
281 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
282 0 : rendering::ARGBColor* pOut( aRes.getArray() );
283 0 : for( sal_Size i=0; i<nLen; i+=4 )
284 : {
285 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
286 0 : pIn += 4;
287 : }
288 0 : return aRes;
289 : }
290 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
291 : {
292 0 : const double* pIn( deviceColor.getConstArray() );
293 0 : const sal_Size nLen( deviceColor.getLength() );
294 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
295 : "number of channels no multiple of 4",
296 : static_cast<rendering::XColorSpace*>(this), 0);
297 :
298 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
299 0 : rendering::ARGBColor* pOut( aRes.getArray() );
300 0 : for( sal_Size i=0; i<nLen; i+=4 )
301 : {
302 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
303 0 : pIn += 4;
304 : }
305 0 : return aRes;
306 : }
307 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
308 : {
309 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
310 0 : const sal_Size nLen( rgbColor.getLength() );
311 :
312 0 : uno::Sequence< double > aRes(nLen*4);
313 0 : double* pColors=aRes.getArray();
314 0 : for( sal_Size i=0; i<nLen; ++i )
315 : {
316 0 : *pColors++ = pIn->Red;
317 0 : *pColors++ = pIn->Green;
318 0 : *pColors++ = pIn->Blue;
319 0 : *pColors++ = 1.0;
320 0 : ++pIn;
321 : }
322 0 : return aRes;
323 : }
324 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
325 : {
326 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
327 0 : const sal_Size nLen( rgbColor.getLength() );
328 :
329 0 : uno::Sequence< double > aRes(nLen*4);
330 0 : double* pColors=aRes.getArray();
331 0 : for( sal_Size i=0; i<nLen; ++i )
332 : {
333 0 : *pColors++ = pIn->Red;
334 0 : *pColors++ = pIn->Green;
335 0 : *pColors++ = pIn->Blue;
336 0 : *pColors++ = pIn->Alpha;
337 0 : ++pIn;
338 : }
339 0 : return aRes;
340 : }
341 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
342 : {
343 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
344 0 : const sal_Size nLen( rgbColor.getLength() );
345 :
346 0 : uno::Sequence< double > aRes(nLen*4);
347 0 : double* pColors=aRes.getArray();
348 0 : for( sal_Size i=0; i<nLen; ++i )
349 : {
350 0 : *pColors++ = pIn->Red/pIn->Alpha;
351 0 : *pColors++ = pIn->Green/pIn->Alpha;
352 0 : *pColors++ = pIn->Blue/pIn->Alpha;
353 0 : *pColors++ = pIn->Alpha;
354 0 : ++pIn;
355 : }
356 0 : return aRes;
357 : }
358 :
359 : // XIntegerBitmapColorSpace
360 0 : virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
361 : {
362 0 : return 32;
363 : }
364 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
365 : {
366 0 : return maBitCounts;
367 : }
368 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
369 : {
370 0 : return util::Endianness::LITTLE;
371 : }
372 0 : 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
375 : {
376 0 : if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
377 : {
378 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
379 0 : const sal_Size nLen( deviceColor.getLength() );
380 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
381 : "number of channels no multiple of 4",
382 : static_cast<rendering::XColorSpace*>(this), 0);
383 :
384 0 : uno::Sequence<double> aRes(nLen);
385 0 : double* pOut( aRes.getArray() );
386 0 : for( sal_Size i=0; i<nLen; i+=4 )
387 : {
388 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
389 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
390 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
391 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
392 : }
393 0 : return aRes;
394 : }
395 : else
396 : {
397 : // TODO(P3): if we know anything about target
398 : // colorspace, this can be greatly sped up
399 : uno::Sequence<rendering::ARGBColor> aIntermediate(
400 0 : convertIntegerToARGB(deviceColor));
401 0 : return targetColorSpace->convertFromARGB(aIntermediate);
402 : }
403 : }
404 0 : 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
407 : {
408 0 : if( dynamic_cast<StandardColorSpace*>(targetColorSpace.get()) )
409 : {
410 : // it's us, so simply pass-through the data
411 0 : return deviceColor;
412 : }
413 : else
414 : {
415 : // TODO(P3): if we know anything about target
416 : // colorspace, this can be greatly sped up
417 : uno::Sequence<rendering::ARGBColor> aIntermediate(
418 0 : convertIntegerToARGB(deviceColor));
419 0 : return targetColorSpace->convertIntegerFromARGB(aIntermediate);
420 : }
421 : }
422 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
423 : {
424 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
425 0 : const sal_Size nLen( deviceColor.getLength() );
426 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
427 : "number of channels no multiple of 4",
428 : static_cast<rendering::XColorSpace*>(this), 0);
429 :
430 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
431 0 : rendering::RGBColor* pOut( aRes.getArray() );
432 0 : for( sal_Size i=0; i<nLen; i+=4 )
433 : {
434 : *pOut++ = rendering::RGBColor(
435 0 : vcl::unotools::toDoubleColor(pIn[0]),
436 0 : vcl::unotools::toDoubleColor(pIn[1]),
437 0 : vcl::unotools::toDoubleColor(pIn[2]));
438 0 : pIn += 4;
439 : }
440 0 : return aRes;
441 : }
442 :
443 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
444 : {
445 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
446 0 : const sal_Size nLen( deviceColor.getLength() );
447 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
448 : "number of channels no multiple of 4",
449 : static_cast<rendering::XColorSpace*>(this), 0);
450 :
451 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
452 0 : rendering::ARGBColor* pOut( aRes.getArray() );
453 0 : for( sal_Size i=0; i<nLen; i+=4 )
454 : {
455 : *pOut++ = rendering::ARGBColor(
456 0 : vcl::unotools::toDoubleColor(pIn[3]),
457 0 : vcl::unotools::toDoubleColor(pIn[0]),
458 0 : vcl::unotools::toDoubleColor(pIn[1]),
459 0 : vcl::unotools::toDoubleColor(pIn[2]));
460 0 : pIn += 4;
461 : }
462 0 : return aRes;
463 : }
464 :
465 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
466 : {
467 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
468 0 : const sal_Size nLen( deviceColor.getLength() );
469 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
470 : "number of channels no multiple of 4",
471 : static_cast<rendering::XColorSpace*>(this), 0);
472 :
473 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
474 0 : rendering::ARGBColor* pOut( aRes.getArray() );
475 0 : for( sal_Size i=0; i<nLen; i+=4 )
476 : {
477 0 : const sal_Int8 nAlpha( pIn[3] );
478 : *pOut++ = rendering::ARGBColor(
479 0 : vcl::unotools::toDoubleColor(nAlpha),
480 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
481 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
482 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
483 0 : pIn += 4;
484 : }
485 0 : return aRes;
486 : }
487 :
488 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
489 : {
490 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
491 0 : const sal_Size nLen( rgbColor.getLength() );
492 :
493 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
494 0 : sal_Int8* pColors=aRes.getArray();
495 0 : for( sal_Size i=0; i<nLen; ++i )
496 : {
497 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
498 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
499 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
500 0 : *pColors++ = 0;
501 0 : ++pIn;
502 : }
503 0 : return aRes;
504 : }
505 :
506 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
507 : {
508 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
509 0 : const sal_Size nLen( rgbColor.getLength() );
510 :
511 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
512 0 : sal_Int8* pColors=aRes.getArray();
513 0 : for( sal_Size i=0; i<nLen; ++i )
514 : {
515 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
516 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
517 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
518 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
519 0 : ++pIn;
520 : }
521 0 : return aRes;
522 : }
523 :
524 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
525 : {
526 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
527 0 : const sal_Size nLen( rgbColor.getLength() );
528 :
529 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
530 0 : sal_Int8* pColors=aRes.getArray();
531 0 : for( sal_Size i=0; i<nLen; ++i )
532 : {
533 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
534 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
535 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
536 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
537 0 : ++pIn;
538 : }
539 0 : return aRes;
540 : }
541 :
542 : public:
543 0 : StandardColorSpace() :
544 : maComponentTags(4),
545 0 : maBitCounts(4)
546 : {
547 0 : sal_Int8* pTags = maComponentTags.getArray();
548 0 : sal_Int32* pBitCounts = maBitCounts.getArray();
549 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
550 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
551 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
552 0 : pTags[3] = rendering::ColorComponentTag::ALPHA;
553 :
554 : pBitCounts[0] =
555 0 : pBitCounts[1] =
556 0 : pBitCounts[2] =
557 0 : pBitCounts[3] = 8;
558 0 : }
559 : };
560 :
561 0 : class StandardNoAlphaColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
562 : {
563 : private:
564 : uno::Sequence< sal_Int8 > maComponentTags;
565 : uno::Sequence< sal_Int32 > maBitCounts;
566 :
567 0 : virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
568 : {
569 0 : return rendering::ColorSpaceType::RGB;
570 : }
571 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
572 : {
573 0 : return maComponentTags;
574 : }
575 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
576 : {
577 0 : return rendering::RenderingIntent::PERCEPTUAL;
578 : }
579 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
580 : {
581 0 : return uno::Sequence< beans::PropertyValue >();
582 : }
583 0 : 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
586 : {
587 : // TODO(P3): if we know anything about target
588 : // colorspace, this can be greatly sped up
589 : uno::Sequence<rendering::ARGBColor> aIntermediate(
590 0 : convertToARGB(deviceColor));
591 0 : return targetColorSpace->convertFromARGB(aIntermediate);
592 : }
593 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
594 : {
595 0 : const double* pIn( deviceColor.getConstArray() );
596 0 : const sal_Size nLen( deviceColor.getLength() );
597 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
598 : "number of channels no multiple of 4",
599 : static_cast<rendering::XColorSpace*>(this), 0);
600 :
601 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
602 0 : rendering::RGBColor* pOut( aRes.getArray() );
603 0 : for( sal_Size i=0; i<nLen; i+=4 )
604 : {
605 0 : *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
606 0 : pIn += 4;
607 : }
608 0 : return aRes;
609 : }
610 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
611 : {
612 0 : const double* pIn( deviceColor.getConstArray() );
613 0 : const sal_Size nLen( deviceColor.getLength() );
614 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
615 : "number of channels no multiple of 4",
616 : static_cast<rendering::XColorSpace*>(this), 0);
617 :
618 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
619 0 : rendering::ARGBColor* pOut( aRes.getArray() );
620 0 : for( sal_Size i=0; i<nLen; i+=4 )
621 : {
622 0 : *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
623 0 : pIn += 4;
624 : }
625 0 : return aRes;
626 : }
627 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
628 : {
629 0 : const double* pIn( deviceColor.getConstArray() );
630 0 : const sal_Size nLen( deviceColor.getLength() );
631 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
632 : "number of channels no multiple of 4",
633 : static_cast<rendering::XColorSpace*>(this), 0);
634 :
635 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
636 0 : rendering::ARGBColor* pOut( aRes.getArray() );
637 0 : for( sal_Size i=0; i<nLen; i+=4 )
638 : {
639 0 : *pOut++ = rendering::ARGBColor(1.0,pIn[0],pIn[1],pIn[2]);
640 0 : pIn += 4;
641 : }
642 0 : return aRes;
643 : }
644 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
645 : {
646 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
647 0 : const sal_Size nLen( rgbColor.getLength() );
648 :
649 0 : uno::Sequence< double > aRes(nLen*4);
650 0 : double* pColors=aRes.getArray();
651 0 : for( sal_Size i=0; i<nLen; ++i )
652 : {
653 0 : *pColors++ = pIn->Red;
654 0 : *pColors++ = pIn->Green;
655 0 : *pColors++ = pIn->Blue;
656 0 : *pColors++ = 1.0; // the value does not matter
657 0 : ++pIn;
658 : }
659 0 : return aRes;
660 : }
661 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
662 : {
663 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
664 0 : const sal_Size nLen( rgbColor.getLength() );
665 :
666 0 : uno::Sequence< double > aRes(nLen*4);
667 0 : double* pColors=aRes.getArray();
668 0 : for( sal_Size i=0; i<nLen; ++i )
669 : {
670 0 : *pColors++ = pIn->Red;
671 0 : *pColors++ = pIn->Green;
672 0 : *pColors++ = pIn->Blue;
673 0 : *pColors++ = 1.0; // the value does not matter
674 0 : ++pIn;
675 : }
676 0 : return aRes;
677 : }
678 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
679 : {
680 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
681 0 : const sal_Size nLen( rgbColor.getLength() );
682 :
683 0 : uno::Sequence< double > aRes(nLen*4);
684 0 : double* pColors=aRes.getArray();
685 0 : for( sal_Size i=0; i<nLen; ++i )
686 : {
687 0 : *pColors++ = pIn->Red/pIn->Alpha;
688 0 : *pColors++ = pIn->Green/pIn->Alpha;
689 0 : *pColors++ = pIn->Blue/pIn->Alpha;
690 0 : *pColors++ = 1.0; // the value does not matter
691 0 : ++pIn;
692 : }
693 0 : return aRes;
694 : }
695 :
696 : // XIntegerBitmapColorSpace
697 0 : virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
698 : {
699 0 : return 32;
700 : }
701 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
702 : {
703 0 : return maBitCounts;
704 : }
705 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
706 : {
707 0 : return util::Endianness::LITTLE;
708 : }
709 0 : 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
712 : {
713 0 : if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
714 : {
715 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
716 0 : const sal_Size nLen( deviceColor.getLength() );
717 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
718 : "number of channels no multiple of 4",
719 : static_cast<rendering::XColorSpace*>(this), 0);
720 :
721 0 : uno::Sequence<double> aRes(nLen);
722 0 : double* pOut( aRes.getArray() );
723 0 : for( sal_Size i=0; i<nLen; i+=4 )
724 : {
725 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
726 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
727 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
728 0 : *pOut++ = 1.0;
729 : }
730 0 : return aRes;
731 : }
732 : else
733 : {
734 : // TODO(P3): if we know anything about target
735 : // colorspace, this can be greatly sped up
736 : uno::Sequence<rendering::ARGBColor> aIntermediate(
737 0 : convertIntegerToARGB(deviceColor));
738 0 : return targetColorSpace->convertFromARGB(aIntermediate);
739 : }
740 : }
741 0 : 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
744 : {
745 0 : if( dynamic_cast<StandardNoAlphaColorSpace*>(targetColorSpace.get()) )
746 : {
747 : // it's us, so simply pass-through the data
748 0 : return deviceColor;
749 : }
750 : else
751 : {
752 : // TODO(P3): if we know anything about target
753 : // colorspace, this can be greatly sped up
754 : uno::Sequence<rendering::ARGBColor> aIntermediate(
755 0 : convertIntegerToARGB(deviceColor));
756 0 : return targetColorSpace->convertIntegerFromARGB(aIntermediate);
757 : }
758 : }
759 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
760 : {
761 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
762 0 : const sal_Size nLen( deviceColor.getLength() );
763 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
764 : "number of channels no multiple of 4",
765 : static_cast<rendering::XColorSpace*>(this), 0);
766 :
767 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
768 0 : rendering::RGBColor* pOut( aRes.getArray() );
769 0 : for( sal_Size i=0; i<nLen; i+=4 )
770 : {
771 : *pOut++ = rendering::RGBColor(
772 0 : vcl::unotools::toDoubleColor(pIn[0]),
773 0 : vcl::unotools::toDoubleColor(pIn[1]),
774 0 : vcl::unotools::toDoubleColor(pIn[2]));
775 0 : pIn += 4;
776 : }
777 0 : return aRes;
778 : }
779 :
780 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
781 : {
782 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
783 0 : const sal_Size nLen( deviceColor.getLength() );
784 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
785 : "number of channels no multiple of 4",
786 : static_cast<rendering::XColorSpace*>(this), 0);
787 :
788 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
789 0 : rendering::ARGBColor* pOut( aRes.getArray() );
790 0 : for( sal_Size i=0; i<nLen; i+=4 )
791 : {
792 : *pOut++ = rendering::ARGBColor(
793 : 1.0,
794 0 : vcl::unotools::toDoubleColor(pIn[0]),
795 0 : vcl::unotools::toDoubleColor(pIn[1]),
796 0 : vcl::unotools::toDoubleColor(pIn[2]));
797 0 : pIn += 4;
798 : }
799 0 : return aRes;
800 : }
801 :
802 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
803 : {
804 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
805 0 : const sal_Size nLen( deviceColor.getLength() );
806 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
807 : "number of channels no multiple of 4",
808 : static_cast<rendering::XColorSpace*>(this), 0);
809 :
810 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
811 0 : rendering::ARGBColor* pOut( aRes.getArray() );
812 0 : for( sal_Size i=0; i<nLen; i+=4 )
813 : {
814 : *pOut++ = rendering::ARGBColor(
815 : 1.0,
816 0 : vcl::unotools::toDoubleColor(pIn[0]),
817 0 : vcl::unotools::toDoubleColor(pIn[1]),
818 0 : vcl::unotools::toDoubleColor(pIn[2]));
819 0 : pIn += 4;
820 : }
821 0 : return aRes;
822 : }
823 :
824 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
825 : {
826 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
827 0 : const sal_Size nLen( rgbColor.getLength() );
828 :
829 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
830 0 : sal_Int8* pColors=aRes.getArray();
831 0 : for( sal_Size i=0; i<nLen; ++i )
832 : {
833 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
834 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
835 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
836 0 : *pColors++ = 1.0;
837 0 : ++pIn;
838 : }
839 0 : return aRes;
840 : }
841 :
842 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
843 : {
844 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
845 0 : const sal_Size nLen( rgbColor.getLength() );
846 :
847 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
848 0 : sal_Int8* pColors=aRes.getArray();
849 0 : for( sal_Size i=0; i<nLen; ++i )
850 : {
851 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
852 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
853 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
854 0 : *pColors++ = -1;
855 0 : ++pIn;
856 : }
857 0 : return aRes;
858 : }
859 :
860 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE
861 : {
862 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
863 0 : const sal_Size nLen( rgbColor.getLength() );
864 :
865 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
866 0 : sal_Int8* pColors=aRes.getArray();
867 0 : for( sal_Size i=0; i<nLen; ++i )
868 : {
869 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
870 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
871 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
872 0 : *pColors++ = -1;
873 0 : ++pIn;
874 : }
875 0 : return aRes;
876 : }
877 :
878 : public:
879 0 : StandardNoAlphaColorSpace() :
880 : maComponentTags(3),
881 0 : maBitCounts(3)
882 : {
883 0 : sal_Int8* pTags = maComponentTags.getArray();
884 0 : sal_Int32* pBitCounts = maBitCounts.getArray();
885 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
886 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
887 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
888 :
889 : pBitCounts[0] =
890 0 : pBitCounts[1] =
891 0 : pBitCounts[2] = 8;
892 0 : }
893 : };
894 :
895 : struct StandardColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
896 : StandardColorSpaceHolder>
897 : {
898 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
899 : {
900 0 : return new StandardColorSpace();
901 : }
902 : };
903 :
904 : struct StandardNoAlphaColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
905 : StandardNoAlphaColorSpaceHolder>
906 : {
907 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
908 : {
909 0 : return new StandardNoAlphaColorSpace();
910 : }
911 : };
912 : }
913 :
914 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpace()
915 : {
916 0 : return StandardColorSpaceHolder::get();
917 : }
918 :
919 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpaceWithoutAlpha()
920 : {
921 0 : return StandardNoAlphaColorSpaceHolder::get();
922 : }
923 :
924 0 : rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
925 : {
926 0 : rendering::IntegerBitmapLayout aLayout;
927 :
928 0 : aLayout.ScanLines = rBmpSize.Height;
929 0 : aLayout.ScanLineBytes = rBmpSize.Width*4;
930 0 : aLayout.ScanLineStride = aLayout.ScanLineBytes;
931 0 : aLayout.PlaneStride = 0;
932 0 : aLayout.ColorSpace = getStdColorSpace();
933 0 : aLayout.Palette.clear();
934 0 : aLayout.IsMsbFirst = sal_False;
935 :
936 0 : return aLayout;
937 : }
938 :
939 0 : ::Color stdIntSequenceToColor( const uno::Sequence<sal_Int8>& rColor )
940 : {
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 0 : return ::Color( *reinterpret_cast< const ::ColorData* >(rColor.getConstArray()) );
946 : #endif
947 : }
948 :
949 0 : uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
950 : {
951 0 : uno::Sequence<sal_Int8> aRet(4);
952 0 : 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 0 : *reinterpret_cast<sal_Int32*>(pCols) = rColor.GetColor();
960 : #endif
961 0 : return aRet;
962 : }
963 :
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 0 : ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
970 : const ::basegfx::B2DRange& i_srcRect,
971 : const ::basegfx::B2DHomMatrix& i_transformation )
972 : {
973 0 : if( i_srcRect.isEmpty() )
974 0 : return o_transform=i_transformation;
975 :
976 : // transform by given transformation
977 0 : ::basegfx::B2DRectangle aTransformedRect;
978 :
979 : calcTransformedRectBounds( aTransformedRect,
980 : i_srcRect,
981 0 : i_transformation );
982 :
983 : // now move resulting left,top point of bounds to (0,0)
984 : const basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
985 0 : -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
986 :
987 : // prepend to original transformation
988 0 : o_transform = aCorrectedTransform * i_transformation;
989 :
990 0 : return o_transform;
991 : }
992 :
993 0 : ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& outRect,
994 : const ::basegfx::B2DRange& inRect,
995 : const ::basegfx::B2DHomMatrix& transformation )
996 : {
997 0 : outRect.reset();
998 :
999 0 : if( inRect.isEmpty() )
1000 0 : return outRect;
1001 :
1002 : // transform all four extremal points of the rectangle,
1003 : // take bounding rect of those.
1004 :
1005 : // transform left-top point
1006 0 : outRect.expand( transformation * inRect.getMinimum() );
1007 :
1008 : // transform bottom-right point
1009 0 : outRect.expand( transformation * inRect.getMaximum() );
1010 :
1011 0 : ::basegfx::B2DPoint aPoint;
1012 :
1013 : // transform top-right point
1014 0 : aPoint.setX( inRect.getMaxX() );
1015 0 : aPoint.setY( inRect.getMinY() );
1016 :
1017 0 : aPoint *= transformation;
1018 0 : outRect.expand( aPoint );
1019 :
1020 : // transform bottom-left point
1021 0 : aPoint.setX( inRect.getMinX() );
1022 0 : aPoint.setY( inRect.getMaxY() );
1023 :
1024 0 : aPoint *= transformation;
1025 0 : outRect.expand( aPoint );
1026 :
1027 : // over and out.
1028 0 : return outRect;
1029 : }
1030 :
1031 0 : bool isInside( const ::basegfx::B2DRange& rContainedRect,
1032 : const ::basegfx::B2DRange& rTransformRect,
1033 : const ::basegfx::B2DHomMatrix& rTransformation )
1034 : {
1035 0 : if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
1036 0 : return false;
1037 :
1038 : ::basegfx::B2DPolygon aPoly(
1039 0 : ::basegfx::tools::createPolygonFromRect( rTransformRect ) );
1040 0 : aPoly.transform( rTransformation );
1041 :
1042 : return ::basegfx::tools::isInside( aPoly,
1043 : ::basegfx::tools::createPolygonFromRect(
1044 : rContainedRect ),
1045 0 : true );
1046 : }
1047 :
1048 : namespace
1049 : {
1050 0 : 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 )
1055 : {
1056 : const ::basegfx::B2IPoint aSourceTopLeft(
1057 0 : io_rSourceArea.getMinimum() );
1058 :
1059 0 : ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
1060 :
1061 : // clip source area (which must be inside rSourceBounds)
1062 0 : aLocalSourceArea.intersect( rSourceBounds );
1063 :
1064 0 : if( aLocalSourceArea.isEmpty() )
1065 0 : return false;
1066 :
1067 : // calc relative new source area points (relative to orig
1068 : // source area)
1069 : const ::basegfx::B2IVector aUpperLeftOffset(
1070 0 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1071 : const ::basegfx::B2IVector aLowerRightOffset(
1072 0 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1073 :
1074 0 : ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1075 0 : io_rDestPoint + aLowerRightOffset );
1076 :
1077 : // clip dest area (which must be inside rDestBounds)
1078 0 : aLocalDestArea.intersect( rDestBounds );
1079 :
1080 0 : if( aLocalDestArea.isEmpty() )
1081 0 : return false;
1082 :
1083 : // calc relative new dest area points (relative to orig
1084 : // source area)
1085 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1086 0 : aLocalDestArea.getMinimum()-io_rDestPoint );
1087 : const ::basegfx::B2IVector aDestLowerRightOffset(
1088 0 : aLocalDestArea.getMaximum()-io_rDestPoint );
1089 :
1090 0 : io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
1091 0 : aSourceTopLeft + aDestLowerRightOffset );
1092 0 : io_rDestPoint = aLocalDestArea.getMinimum();
1093 :
1094 0 : if( o_pDestArea )
1095 0 : *o_pDestArea = aLocalDestArea;
1096 :
1097 0 : return true;
1098 : }
1099 : }
1100 :
1101 0 : bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
1102 : ::basegfx::B2IPoint& io_rDestPoint,
1103 : ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
1104 : const ::basegfx::B2IRange& rBounds )
1105 : {
1106 0 : ::basegfx::B2IRange aResultingDestArea;
1107 :
1108 : // compute full destination area (to determine uninitialized
1109 : // areas below)
1110 0 : const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
1111 : ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
1112 : io_rDestPoint.getY(),
1113 0 : (io_rDestPoint.getX()
1114 0 : + static_cast<sal_Int32>(rRange.getX())),
1115 0 : (io_rDestPoint.getY()
1116 0 : + static_cast<sal_Int32>(rRange.getY())) );
1117 : // limit to output area (no point updating outside of it)
1118 0 : aInputDestArea.intersect( rBounds );
1119 :
1120 : // clip to rBounds
1121 0 : if( !clipAreaImpl( &aResultingDestArea,
1122 : io_rSourceArea,
1123 : io_rDestPoint,
1124 : rBounds,
1125 0 : rBounds ) )
1126 0 : return false;
1127 :
1128 : // finally, compute all areas clipped off the total
1129 : // destination area.
1130 : ::basegfx::computeSetDifference( o_ClippedAreas,
1131 : aInputDestArea,
1132 0 : aResultingDestArea );
1133 :
1134 0 : return true;
1135 : }
1136 :
1137 0 : ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
1138 : {
1139 0 : if( rRange.isEmpty() )
1140 0 : return ::basegfx::B2IRange();
1141 :
1142 : const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
1143 0 : ::basegfx::fround( rRange.getMinY() ) );
1144 : return ::basegfx::B2IRange( aTopLeft,
1145 0 : aTopLeft + ::basegfx::B2IPoint(
1146 : ::basegfx::fround( rRange.getWidth() ),
1147 0 : ::basegfx::fround( rRange.getHeight() ) ) );
1148 : }
1149 :
1150 0 : uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
1151 : uno::Sequence< uno::Any >& o_rxParams )
1152 : {
1153 0 : o_rxParams.realloc( 0 );
1154 :
1155 0 : if( i_rxCanvas.is() )
1156 : {
1157 : try
1158 : {
1159 0 : uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
1160 0 : uno::UNO_QUERY_THROW );
1161 :
1162 : uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
1163 0 : uno::UNO_QUERY_THROW );
1164 : uno::Reference< beans::XPropertySet > xPropSet( xDevice,
1165 0 : uno::UNO_QUERY_THROW );
1166 :
1167 0 : o_rxParams.realloc( 2 );
1168 :
1169 0 : o_rxParams[ 0 ] = uno::makeAny( xServiceInfo->getImplementationName() );
1170 0 : o_rxParams[ 1 ] = xPropSet->getPropertyValue( "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 : vcl::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 0 : nGradientSize / nStripSize,
1291 0 : nColorSteps ) );
1292 : }
1293 :
1294 0 : void clipOutDev(const rendering::ViewState& viewState,
1295 : const rendering::RenderState& renderState,
1296 : OutputDevice& rOutDev,
1297 : OutputDevice* p2ndOutDev)
1298 : {
1299 : // accumulate non-empty clips into one region
1300 0 : vcl::Region aClipRegion(true);
1301 :
1302 0 : if( viewState.Clip.is() )
1303 : {
1304 : ::basegfx::B2DPolyPolygon aClipPoly(
1305 0 : ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(viewState.Clip) );
1306 :
1307 0 : if( aClipPoly.count() )
1308 : {
1309 : // setup non-empty clipping
1310 0 : ::basegfx::B2DHomMatrix aMatrix;
1311 : aClipPoly.transform(
1312 : ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
1313 0 : viewState.AffineTransform ) );
1314 :
1315 0 : aClipRegion = vcl::Region::GetRegionFromPolyPolygon( ::tools::PolyPolygon( aClipPoly ) );
1316 : }
1317 : else
1318 : {
1319 : // clip polygon is empty
1320 0 : aClipRegion.SetEmpty();
1321 0 : }
1322 : }
1323 :
1324 0 : if( renderState.Clip.is() )
1325 : {
1326 : ::basegfx::B2DPolyPolygon aClipPoly(
1327 0 : ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(renderState.Clip) );
1328 :
1329 0 : ::basegfx::B2DHomMatrix aMatrix;
1330 : aClipPoly.transform(
1331 : ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
1332 : viewState,
1333 0 : renderState ) );
1334 :
1335 0 : if( aClipPoly.count() )
1336 : {
1337 : // setup non-empty clipping
1338 0 : vcl::Region aRegion = vcl::Region::GetRegionFromPolyPolygon( ::tools::PolyPolygon( aClipPoly ) );
1339 0 : aClipRegion.Intersect( aRegion );
1340 : }
1341 : else
1342 : {
1343 : // clip polygon is empty
1344 0 : aClipRegion.SetEmpty();
1345 0 : }
1346 : }
1347 :
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 0 : if( aClipRegion.IsNull() )
1355 : {
1356 0 : rOutDev.SetClipRegion();
1357 :
1358 0 : if( p2ndOutDev )
1359 0 : p2ndOutDev->SetClipRegion();
1360 : }
1361 : else
1362 : {
1363 0 : rOutDev.SetClipRegion( aClipRegion );
1364 :
1365 0 : if( p2ndOutDev )
1366 0 : p2ndOutDev->SetClipRegion( aClipRegion );
1367 0 : }
1368 0 : }
1369 : } // namespace tools
1370 :
1371 : } // namespace canvas
1372 :
1373 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|