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