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