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