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 <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  }
846 
847  uno::Reference<rendering::XIntegerBitmapColorSpace> const & getStdColorSpace()
848  {
849  static uno::Reference<rendering::XIntegerBitmapColorSpace> SPACE = new StandardColorSpace();
850  return SPACE;
851  }
852 
853  uno::Reference<rendering::XIntegerBitmapColorSpace> const & getStdColorSpaceWithoutAlpha()
854  {
855  static uno::Reference<rendering::XIntegerBitmapColorSpace> SPACE = new StandardNoAlphaColorSpace();
856  return SPACE;
857  }
858 
859  rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
860  {
861  rendering::IntegerBitmapLayout aLayout;
862 
863  aLayout.ScanLines = rBmpSize.Height;
864  aLayout.ScanLineBytes = rBmpSize.Width*4;
865  aLayout.ScanLineStride = aLayout.ScanLineBytes;
866  aLayout.PlaneStride = 0;
867  aLayout.ColorSpace = getStdColorSpace();
868  aLayout.Palette.clear();
869  aLayout.IsMsbFirst = false;
870 
871  return aLayout;
872  }
873 
874  uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
875  {
876  uno::Sequence<sal_Int8> aRet(4);
877  sal_Int8* pCols( aRet.getArray() );
878 #ifdef OSL_BIGENDIAN
879  pCols[0] = rColor.GetRed();
880  pCols[1] = rColor.GetGreen();
881  pCols[2] = rColor.GetBlue();
882  pCols[3] = rColor.GetAlpha();
883 #else
884  *reinterpret_cast<sal_Int32*>(pCols) = sal_Int32(rColor);
885 #endif
886  return aRet;
887  }
888 
889  // Create a corrected view transformation out of the give one,
890  // which ensures that the rectangle given by (0,0) and
891  // rSpriteSize is mapped with its left,top corner to (0,0)
892  // again. This is required to properly render sprite
893  // animations to buffer bitmaps.
895  const ::basegfx::B2DRange& i_srcRect,
896  const ::basegfx::B2DHomMatrix& i_transformation )
897  {
898  if( i_srcRect.isEmpty() )
899  {
900  o_transform = i_transformation;
901  return o_transform;
902  }
903 
904  // transform by given transformation
905  ::basegfx::B2DRectangle aTransformedRect;
906 
907  calcTransformedRectBounds( aTransformedRect,
908  i_srcRect,
909  i_transformation );
910 
911  // now move resulting left,top point of bounds to (0,0)
913  -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
914 
915  // prepend to original transformation
916  o_transform = aCorrectedTransform * i_transformation;
917 
918  return o_transform;
919  }
920 
922  const ::basegfx::B2DRange& inRect,
923  const ::basegfx::B2DHomMatrix& transformation )
924  {
925  outRect.reset();
926 
927  if( inRect.isEmpty() )
928  return outRect;
929 
930  // transform all four extremal points of the rectangle,
931  // take bounding rect of those.
932 
933  // transform left-top point
934  outRect.expand( transformation * inRect.getMinimum() );
935 
936  // transform bottom-right point
937  outRect.expand( transformation * inRect.getMaximum() );
938 
939  ::basegfx::B2DPoint aPoint;
940 
941  // transform top-right point
942  aPoint.setX( inRect.getMaxX() );
943  aPoint.setY( inRect.getMinY() );
944 
945  aPoint *= transformation;
946  outRect.expand( aPoint );
947 
948  // transform bottom-left point
949  aPoint.setX( inRect.getMinX() );
950  aPoint.setY( inRect.getMaxY() );
951 
952  aPoint *= transformation;
953  outRect.expand( aPoint );
954 
955  // over and out.
956  return outRect;
957  }
958 
959  bool isInside( const ::basegfx::B2DRange& rContainedRect,
960  const ::basegfx::B2DRange& rTransformRect,
961  const ::basegfx::B2DHomMatrix& rTransformation )
962  {
963  if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
964  return false;
965 
966  ::basegfx::B2DPolygon aPoly(
967  ::basegfx::utils::createPolygonFromRect( rTransformRect ) );
968  aPoly.transform( rTransformation );
969 
972  rContainedRect ),
973  true );
974  }
975 
976  namespace
977  {
978  bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea,
979  ::basegfx::B2IRange& io_rSourceArea,
980  ::basegfx::B2IPoint& io_rDestPoint,
981  const ::basegfx::B2IRange& rSourceBounds,
982  const ::basegfx::B2IRange& rDestBounds )
983  {
984  const ::basegfx::B2IPoint aSourceTopLeft(
985  io_rSourceArea.getMinimum() );
986 
987  ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
988 
989  // clip source area (which must be inside rSourceBounds)
990  aLocalSourceArea.intersect( rSourceBounds );
991 
992  if( aLocalSourceArea.isEmpty() )
993  return false;
994 
995  // calc relative new source area points (relative to orig
996  // source area)
997  const ::basegfx::B2IVector aUpperLeftOffset(
998  aLocalSourceArea.getMinimum()-aSourceTopLeft );
999  const ::basegfx::B2IVector aLowerRightOffset(
1000  aLocalSourceArea.getMaximum()-aSourceTopLeft );
1001 
1002  ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1003  io_rDestPoint + aLowerRightOffset );
1004 
1005  // clip dest area (which must be inside rDestBounds)
1006  aLocalDestArea.intersect( rDestBounds );
1007 
1008  if( aLocalDestArea.isEmpty() )
1009  return false;
1010 
1011  // calc relative new dest area points (relative to orig
1012  // source area)
1013  const ::basegfx::B2IVector aDestUpperLeftOffset(
1014  aLocalDestArea.getMinimum()-io_rDestPoint );
1015  const ::basegfx::B2IVector aDestLowerRightOffset(
1016  aLocalDestArea.getMaximum()-io_rDestPoint );
1017 
1018  io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
1019  aSourceTopLeft + aDestLowerRightOffset );
1020  io_rDestPoint = aLocalDestArea.getMinimum();
1021 
1022  if( o_pDestArea )
1023  *o_pDestArea = aLocalDestArea;
1024 
1025  return true;
1026  }
1027  }
1028 
1029  bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
1030  ::basegfx::B2IPoint& io_rDestPoint,
1031  std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
1032  const ::basegfx::B2IRange& rBounds )
1033  {
1034  ::basegfx::B2IRange aResultingDestArea;
1035 
1036  // compute full destination area (to determine uninitialized
1037  // areas below)
1038  const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
1039  ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
1040  io_rDestPoint.getY(),
1041  (io_rDestPoint.getX()
1042  + static_cast<sal_Int32>(rRange.getX())),
1043  (io_rDestPoint.getY()
1044  + static_cast<sal_Int32>(rRange.getY())) );
1045  // limit to output area (no point updating outside of it)
1046  aInputDestArea.intersect( rBounds );
1047 
1048  // clip to rBounds
1049  if( !clipAreaImpl( &aResultingDestArea,
1050  io_rSourceArea,
1051  io_rDestPoint,
1052  rBounds,
1053  rBounds ) )
1054  return false;
1055 
1056  // finally, compute all areas clipped off the total
1057  // destination area.
1058  ::basegfx::computeSetDifference( o_ClippedAreas,
1059  aInputDestArea,
1060  aResultingDestArea );
1061 
1062  return true;
1063  }
1064 
1065  ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
1066  {
1067  if( rRange.isEmpty() )
1068  return ::basegfx::B2IRange();
1069 
1070  const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
1071  ::basegfx::fround( rRange.getMinY() ) );
1072  return ::basegfx::B2IRange( aTopLeft,
1073  aTopLeft + ::basegfx::B2IPoint(
1074  ::basegfx::fround( rRange.getWidth() ),
1075  ::basegfx::fround( rRange.getHeight() ) ) );
1076  }
1077 
1078  uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
1079  uno::Sequence< uno::Any >& o_rxParams )
1080  {
1081  o_rxParams.realloc( 0 );
1082 
1083  if( i_rxCanvas.is() )
1084  {
1085  try
1086  {
1087  uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
1088  uno::UNO_SET_THROW );
1089 
1090  uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
1091  uno::UNO_QUERY_THROW );
1092  uno::Reference< beans::XPropertySet > xPropSet( xDevice,
1093  uno::UNO_QUERY_THROW );
1094 
1095  o_rxParams.realloc( 2 );
1096 
1097  o_rxParams[ 0 ] <<= xServiceInfo->getImplementationName();
1098  o_rxParams[ 1 ] = xPropSet->getPropertyValue( "DeviceHandle" );
1099  }
1100  catch( const uno::Exception& )
1101  {
1102  // ignore, but return empty sequence
1103  }
1104  }
1105 
1106  return o_rxParams;
1107  }
1108 
1109  awt::Rectangle getAbsoluteWindowRect( const awt::Rectangle& rRect,
1110  const uno::Reference< awt::XWindow2 >& xWin )
1111  {
1112  awt::Rectangle aRetVal( rRect );
1113 
1115  if( pWindow )
1116  {
1117  ::Point aPoint( aRetVal.X,
1118  aRetVal.Y );
1119 
1120  aPoint = pWindow->OutputToScreenPixel( aPoint );
1121 
1122  aRetVal.X = aPoint.X();
1123  aRetVal.Y = aPoint.Y();
1124  }
1125 
1126  return aRetVal;
1127  }
1128 
1129  ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange )
1130  {
1131  ::basegfx::B2DPolyPolygon aPolyPoly;
1132  ::basegfx::B2DPolygon aPoly;
1133 
1134  const double nX0( rRange.getMinX() );
1135  const double nY0( rRange.getMinY() );
1136  const double nX1( rRange.getMaxX() );
1137  const double nY1( rRange.getMaxY() );
1138 
1139  aPoly.append( ::basegfx::B2DPoint( nX0+4,
1140  nY0 ) );
1141  aPoly.append( ::basegfx::B2DPoint( nX0,
1142  nY0 ) );
1143  aPoly.append( ::basegfx::B2DPoint( nX0,
1144  nY0+4 ) );
1145  aPolyPoly.append( aPoly ); aPoly.clear();
1146 
1147  aPoly.append( ::basegfx::B2DPoint( nX1-4,
1148  nY0 ) );
1149  aPoly.append( ::basegfx::B2DPoint( nX1,
1150  nY0 ) );
1151  aPoly.append( ::basegfx::B2DPoint( nX1,
1152  nY0+4 ) );
1153  aPolyPoly.append( aPoly ); aPoly.clear();
1154 
1155  aPoly.append( ::basegfx::B2DPoint( nX0+4,
1156  nY1 ) );
1157  aPoly.append( ::basegfx::B2DPoint( nX0,
1158  nY1 ) );
1159  aPoly.append( ::basegfx::B2DPoint( nX0,
1160  nY1-4 ) );
1161  aPolyPoly.append( aPoly ); aPoly.clear();
1162 
1163  aPoly.append( ::basegfx::B2DPoint( nX1-4,
1164  nY1 ) );
1165  aPoly.append( ::basegfx::B2DPoint( nX1,
1166  nY1 ) );
1167  aPoly.append( ::basegfx::B2DPoint( nX1,
1168  nY1-4 ) );
1169  aPolyPoly.append( aPoly );
1170 
1171  return aPolyPoly;
1172  }
1173 
1175  const rendering::ViewState& viewState,
1176  const rendering::RenderState& renderState,
1177  const rendering::Texture& texture,
1178  int nColorSteps )
1179  {
1180  // calculate overall texture transformation (directly from
1181  // texture to device space).
1182  ::basegfx::B2DHomMatrix aMatrix;
1183 
1184  rTotalTransform.identity();
1185  ::basegfx::unotools::homMatrixFromAffineMatrix( rTotalTransform,
1186  texture.AffineTransform );
1188  viewState,
1189  renderState);
1190  rTotalTransform *= aMatrix; // prepend total view/render transformation
1191 
1192  // determine size of gradient in device coordinate system
1193  // (to e.g. determine sensible number of gradient steps)
1194  ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
1195  ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
1196  ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
1197  ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
1198 
1199  aLeftTop *= rTotalTransform;
1200  aLeftBottom *= rTotalTransform;
1201  aRightTop *= rTotalTransform;
1202  aRightBottom*= rTotalTransform;
1203 
1204  // longest line in gradient bound rect
1205  const int nGradientSize(
1206  static_cast<int>(
1207  std::max(
1208  ::basegfx::B2DVector(aRightBottom-aLeftTop).getLength(),
1209  ::basegfx::B2DVector(aRightTop-aLeftBottom).getLength() ) + 1.0 ) );
1210 
1211  // typical number for pixel of the same color (strip size)
1212  const int nStripSize( nGradientSize < 50 ? 2 : 4 );
1213 
1214  // use at least three steps, and at utmost the number of color
1215  // steps
1216  return std::max( 3,
1217  std::min(
1218  nGradientSize / nStripSize,
1219  nColorSteps ) );
1220  }
1221 
1222  void clipOutDev(const rendering::ViewState& viewState,
1223  const rendering::RenderState& renderState,
1224  OutputDevice& rOutDev,
1225  OutputDevice* p2ndOutDev)
1226  {
1227  // accumulate non-empty clips into one region
1228  vcl::Region aClipRegion(true);
1229 
1230  if( viewState.Clip.is() )
1231  {
1232  ::basegfx::B2DPolyPolygon aClipPoly(
1234 
1235  if( aClipPoly.count() )
1236  {
1237  // setup non-empty clipping
1238  ::basegfx::B2DHomMatrix aMatrix;
1239  aClipPoly.transform(
1241  viewState.AffineTransform ) );
1242 
1243  aClipRegion = vcl::Region::GetRegionFromPolyPolygon( ::tools::PolyPolygon( aClipPoly ) );
1244  }
1245  else
1246  {
1247  // clip polygon is empty
1248  aClipRegion.SetEmpty();
1249  }
1250  }
1251 
1252  if( renderState.Clip.is() )
1253  {
1254  ::basegfx::B2DPolyPolygon aClipPoly(
1256 
1257  ::basegfx::B2DHomMatrix aMatrix;
1258  aClipPoly.transform(
1260  viewState,
1261  renderState ) );
1262 
1263  if( aClipPoly.count() )
1264  {
1265  // setup non-empty clipping
1267  aClipRegion.Intersect( aRegion );
1268  }
1269  else
1270  {
1271  // clip polygon is empty
1272  aClipRegion.SetEmpty();
1273  }
1274  }
1275 
1276  // setup accumulated clip region. Note that setting an
1277  // empty clip region denotes "clip everything" on the
1278  // OutputDevice (which is why we translate that into
1279  // SetClipRegion() here). When both view and render clip
1280  // are empty, aClipRegion remains default-constructed,
1281  // i.e. empty, too.
1282  if( aClipRegion.IsNull() )
1283  {
1284  rOutDev.SetClipRegion();
1285 
1286  if( p2ndOutDev )
1287  p2ndOutDev->SetClipRegion();
1288  }
1289  else
1290  {
1291  rOutDev.SetClipRegion( aClipRegion );
1292 
1293  if( p2ndOutDev )
1294  p2ndOutDev->SetClipRegion( aClipRegion );
1295  }
1296  }
1297 
1298  void extractExtraFontProperties(const uno::Sequence<beans::PropertyValue>& rExtraFontProperties,
1299  sal_uInt32 &rEmphasisMark)
1300  {
1301  for(const beans::PropertyValue& rPropVal : rExtraFontProperties)
1302  {
1303  if (rPropVal.Name == "EmphasisMark")
1304  rPropVal.Value >>= rEmphasisMark;
1305  }
1306  }
1307 
1308 } // namespace
1309 
1310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void intersect(const B2IRange &rRange)
void SetClipRegion()
sal_Int32 getY() const
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
#define max(a, b)
Definition: dx_winstuff.hxx:43
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 SPACE
void setX(double fX)
#define min(a, b)
Definition: dx_winstuff.hxx:46
bool isInside(const ::basegfx::B2DRange &rContainedRect, const ::basegfx::B2DRange &rTransformRect, const ::basegfx::B2DHomMatrix &rTransformation)
Check whether a given rectangle is within another transformed rectangle.
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
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)
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:94
void setY(double fY)
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
#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)
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
sal_Int32 getX() const
::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)