1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <canvas/debug.hxx>
21 #include <tools/diagnose_ex.h>
23 #include <rtl/math.hxx>
24 #include <rtl/instance.hxx>
26 #include <com/sun/star/util/Endianness.hpp>
27 #include <com/sun/star/rendering/TexturingMode.hpp>
28 #include <com/sun/star/rendering/CompositeOperation.hpp>
29 #include <com/sun/star/rendering/RepaintResult.hpp>
30 #include <com/sun/star/rendering/PathCapType.hpp>
31 #include <com/sun/star/rendering/PathJoinType.hpp>
32 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
33 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
34 #include <com/sun/star/rendering/ColorSpaceType.hpp>
35 #include <com/sun/star/rendering/ColorComponentTag.hpp>
36 #include <com/sun/star/rendering/RenderingIntent.hpp>
38 #include <basegfx/matrix/b2dhommatrix.hxx>
39 #include <basegfx/point/b2dpoint.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/polygon/b2dpolypolygon.hxx>
42 #include <basegfx/polygon/b2dpolygontools.hxx>
43 #include <basegfx/tools/canvastools.hxx>
44 #include <basegfx/tools/keystoplerp.hxx>
45 #include <basegfx/tools/lerp.hxx>
47 #include <comphelper/sequence.hxx>
48 #include <cppuhelper/compbase1.hxx>
50 #include <canvas/canvastools.hxx>
51 #include <canvas/parametricpolypolygon.hxx>
53 #include <vcl/canvastools.hxx>
54 #include <vcl/bitmapex.hxx>
55 #include <vcl/bmpacc.hxx>
56 #include <vcl/virdev.hxx>
58 #include "cairo_spritecanvas.hxx"
59 #include "cairo_cachedbitmap.hxx"
60 #include "cairo_canvashelper.hxx"
61 #include "cairo_canvasbitmap.hxx"
63 #include <boost/tuple/tuple.hpp>
66 using namespace ::cairo
;
67 using namespace ::com::sun::star
;
71 CanvasHelper::CanvasHelper() :
72 mpSurfaceProvider(NULL
),
82 void CanvasHelper::disposing()
86 mpVirtualDevice
.disposeAndClear();
88 mpSurfaceProvider
= NULL
;
91 void CanvasHelper::init( const ::basegfx::B2ISize
& rSizePixel
,
92 SurfaceProvider
& rSurfaceProvider
,
93 rendering::XGraphicDevice
* pDevice
)
96 mpSurfaceProvider
= &rSurfaceProvider
;
100 void CanvasHelper::setSize( const ::basegfx::B2ISize
& rSize
)
105 void CanvasHelper::setSurface( const SurfaceSharedPtr
& pSurface
, bool bHasAlpha
)
107 mbHaveAlpha
= bHasAlpha
;
108 mpVirtualDevice
.disposeAndClear();
109 mpSurface
= pSurface
;
110 mpCairo
= pSurface
->getCairo();
113 static void setColor( cairo_t
* pCairo
,
114 const uno::Sequence
<double>& rColor
)
116 if( rColor
.getLength() > 3 )
118 cairo_set_source_rgba( pCairo
,
124 else if( rColor
.getLength() == 3 )
125 cairo_set_source_rgb( pCairo
,
131 void CanvasHelper::useStates( const rendering::ViewState
& viewState
,
132 const rendering::RenderState
& renderState
,
135 cairo_matrix_t aViewMatrix
;
136 cairo_matrix_t aRenderMatrix
;
137 cairo_matrix_t aCombinedMatrix
;
139 cairo_matrix_init( &aViewMatrix
,
140 viewState
.AffineTransform
.m00
, viewState
.AffineTransform
.m10
, viewState
.AffineTransform
.m01
,
141 viewState
.AffineTransform
.m11
, viewState
.AffineTransform
.m02
, viewState
.AffineTransform
.m12
);
142 cairo_matrix_init( &aRenderMatrix
,
143 renderState
.AffineTransform
.m00
, renderState
.AffineTransform
.m10
, renderState
.AffineTransform
.m01
,
144 renderState
.AffineTransform
.m11
, renderState
.AffineTransform
.m02
, renderState
.AffineTransform
.m12
);
145 cairo_matrix_multiply( &aCombinedMatrix
, &aRenderMatrix
, &aViewMatrix
);
147 if( viewState
.Clip
.is() )
149 SAL_INFO( "canvas.cairo", "view clip");
151 aViewMatrix
.x0
= basegfx::fround( aViewMatrix
.x0
);
152 aViewMatrix
.y0
= basegfx::fround( aViewMatrix
.y0
);
153 cairo_set_matrix( mpCairo
.get(), &aViewMatrix
);
154 doPolyPolygonPath( viewState
.Clip
, Clip
);
157 aCombinedMatrix
.x0
= basegfx::fround( aCombinedMatrix
.x0
);
158 aCombinedMatrix
.y0
= basegfx::fround( aCombinedMatrix
.y0
);
159 cairo_set_matrix( mpCairo
.get(), &aCombinedMatrix
);
161 if( renderState
.Clip
.is() )
163 SAL_INFO( "canvas.cairo", "render clip BEGIN");
165 doPolyPolygonPath( renderState
.Clip
, Clip
);
166 SAL_INFO( "canvas.cairo", "render clip END");
170 setColor(mpCairo
.get(),renderState
.DeviceColor
);
172 cairo_operator_t
compositingMode( CAIRO_OPERATOR_OVER
);
173 switch( renderState
.CompositeOperation
)
175 case rendering::CompositeOperation::CLEAR
:
176 compositingMode
= CAIRO_OPERATOR_CLEAR
;
178 case rendering::CompositeOperation::SOURCE
:
179 compositingMode
= CAIRO_OPERATOR_SOURCE
;
181 case rendering::CompositeOperation::DESTINATION
:
182 compositingMode
= CAIRO_OPERATOR_DEST
;
184 case rendering::CompositeOperation::OVER
:
185 compositingMode
= CAIRO_OPERATOR_OVER
;
187 case rendering::CompositeOperation::UNDER
:
188 compositingMode
= CAIRO_OPERATOR_DEST
;
190 case rendering::CompositeOperation::INSIDE
:
191 compositingMode
= CAIRO_OPERATOR_IN
;
193 case rendering::CompositeOperation::INSIDE_REVERSE
:
194 compositingMode
= CAIRO_OPERATOR_OUT
;
196 case rendering::CompositeOperation::OUTSIDE
:
197 compositingMode
= CAIRO_OPERATOR_DEST_OVER
;
199 case rendering::CompositeOperation::OUTSIDE_REVERSE
:
200 compositingMode
= CAIRO_OPERATOR_DEST_OUT
;
202 case rendering::CompositeOperation::ATOP
:
203 compositingMode
= CAIRO_OPERATOR_ATOP
;
205 case rendering::CompositeOperation::ATOP_REVERSE
:
206 compositingMode
= CAIRO_OPERATOR_DEST_ATOP
;
208 case rendering::CompositeOperation::XOR
:
209 compositingMode
= CAIRO_OPERATOR_XOR
;
211 case rendering::CompositeOperation::ADD
:
212 compositingMode
= CAIRO_OPERATOR_ADD
;
214 case rendering::CompositeOperation::SATURATE
:
215 compositingMode
= CAIRO_OPERATOR_SATURATE
;
218 cairo_set_operator( mpCairo
.get(), compositingMode
);
221 void CanvasHelper::clear()
223 SAL_INFO( "canvas.cairo", "clear whole area: " << maSize
.getX() << " x " << maSize
.getY() );
227 cairo_save( mpCairo
.get() );
229 cairo_identity_matrix( mpCairo
.get() );
230 // this does not really differ from all-zero, as cairo
231 // internally converts to premultiplied alpha. but anyway,
232 // this keeps it consistent with the other canvas impls
234 cairo_set_source_rgba( mpCairo
.get(), 1.0, 1.0, 1.0, 0.0 );
236 cairo_set_source_rgb( mpCairo
.get(), 1.0, 1.0, 1.0 );
237 cairo_set_operator( mpCairo
.get(), CAIRO_OPERATOR_SOURCE
);
239 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
240 cairo_fill( mpCairo
.get() );
242 cairo_restore( mpCairo
.get() );
246 void CanvasHelper::drawLine( const rendering::XCanvas
* /*pCanvas*/,
247 const geometry::RealPoint2D
& aStartPoint
,
248 const geometry::RealPoint2D
& aEndPoint
,
249 const rendering::ViewState
& viewState
,
250 const rendering::RenderState
& renderState
)
254 cairo_save( mpCairo
.get() );
256 cairo_set_line_width( mpCairo
.get(), 1 );
258 useStates( viewState
, renderState
, true );
260 cairo_move_to( mpCairo
.get(), aStartPoint
.X
+ 0.5, aStartPoint
.Y
+ 0.5 );
261 cairo_line_to( mpCairo
.get(), aEndPoint
.X
+ 0.5, aEndPoint
.Y
+ 0.5 );
262 cairo_stroke( mpCairo
.get() );
264 cairo_restore( mpCairo
.get() );
268 void CanvasHelper::drawBezier( const rendering::XCanvas
* ,
269 const geometry::RealBezierSegment2D
& aBezierSegment
,
270 const geometry::RealPoint2D
& aEndPoint
,
271 const rendering::ViewState
& viewState
,
272 const rendering::RenderState
& renderState
)
276 cairo_save( mpCairo
.get() );
278 cairo_set_line_width( mpCairo
.get(), 1 );
280 useStates( viewState
, renderState
, true );
282 cairo_move_to( mpCairo
.get(), aBezierSegment
.Px
+ 0.5, aBezierSegment
.Py
+ 0.5 );
283 cairo_curve_to( mpCairo
.get(),
284 aBezierSegment
.C1x
+ 0.5, aBezierSegment
.C1y
+ 0.5,
285 aBezierSegment
.C2x
+ 0.5, aBezierSegment
.C2y
+ 0.5,
286 aEndPoint
.X
+ 0.5, aEndPoint
.Y
+ 0.5 );
287 cairo_stroke( mpCairo
.get() );
289 cairo_restore( mpCairo
.get() );
293 #define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon"
295 /** surfaceFromXBitmap Create a surface from XBitmap
296 * @param xBitmap bitmap image that will be used for the surface
297 * @param bHasAlpha will be set to true if resulting surface has alpha
299 * This is a helper function for the other surfaceFromXBitmap().
300 * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas.
302 * @return created surface or NULL
304 static SurfaceSharedPtr
surfaceFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
)
306 CanvasBitmap
* pBitmapImpl
= dynamic_cast< CanvasBitmap
* >( xBitmap
.get() );
308 return pBitmapImpl
->getSurface();
310 SurfaceProvider
* pSurfaceProvider
= dynamic_cast<SurfaceProvider
*>( xBitmap
.get() );
311 if( pSurfaceProvider
)
312 return pSurfaceProvider
->getSurface();
314 return SurfaceSharedPtr();
317 static ::BitmapEx
bitmapExFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
)
319 // TODO(F1): Add support for floating point bitmap formats
320 uno::Reference
<rendering::XIntegerReadOnlyBitmap
> xIntBmp(xBitmap
,
321 uno::UNO_QUERY_THROW
);
322 ::BitmapEx aBmpEx
= vcl::unotools::bitmapExFromXBitmap(xIntBmp
);
326 // TODO(F1): extract pixel from XBitmap interface
327 ENSURE_OR_THROW( false,
328 "bitmapExFromXBitmap(): could not extract BitmapEx" );
333 static sal_uInt8
lcl_GetColor(BitmapColor
const& rColor
)
336 if (rColor
.IsIndex())
338 nTemp
= rColor
.GetIndex();
342 nTemp
= rColor
.GetBlue();
343 // greyscale expected here, or what would non-grey colors mean?
344 assert(rColor
.GetRed() == nTemp
&& rColor
.GetGreen() == nTemp
);
349 static bool readAlpha( BitmapReadAccess
* pAlphaReadAcc
, long nY
, const long nWidth
, unsigned char* data
, long nOff
)
351 bool bIsAlpha
= false;
358 switch( pAlphaReadAcc
->GetScanlineFormat() )
360 case BMP_FORMAT_8BIT_TC_MASK
:
361 pReadScan
= pAlphaReadAcc
->GetScanline( nY
);
362 for( nX
= 0; nX
< nWidth
; nX
++ )
364 nAlpha
= data
[ nOff
] = 255 - ( *pReadScan
++ );
370 case BMP_FORMAT_8BIT_PAL
:
371 pReadScan
= pAlphaReadAcc
->GetScanline( nY
);
372 for( nX
= 0; nX
< nWidth
; nX
++ )
374 BitmapColor
const& rColor(
375 pAlphaReadAcc
->GetPaletteColor(*pReadScan
));
377 nAlpha
= data
[ nOff
] = 255 - lcl_GetColor(rColor
);
384 SAL_INFO( "canvas.cairo", "fallback to GetColor for alpha - slow, format: " << pAlphaReadAcc
->GetScanlineFormat() );
385 for( nX
= 0; nX
< nWidth
; nX
++ )
387 nAlpha
= data
[ nOff
] = 255 - pAlphaReadAcc
->GetColor( nY
, nX
).GetIndex();
398 /** surfaceFromXBitmap Create a surface from XBitmap
399 * @param xBitmap bitmap image that will be used for the surface
400 * @param rDevice reference to the device into which we want to draw
401 * @param data will be filled with alpha data, if xBitmap is alpha/transparent image
402 * @param bHasAlpha will be set to true if resulting surface has alpha
404 * This function tries various methods for creating a surface from xBitmap. It also uses
405 * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha )
407 * @return created surface or NULL
409 static SurfaceSharedPtr
surfaceFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
, const SurfaceProviderRef
& rSurfaceProvider
, unsigned char*& data
, bool& bHasAlpha
)
411 bHasAlpha
= xBitmap
->hasAlpha();
412 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( xBitmap
);
417 ::BitmapEx aBmpEx
= bitmapExFromXBitmap(xBitmap
);
418 ::Bitmap aBitmap
= aBmpEx
.GetBitmap();
420 // there's no pixmap for alpha bitmap. we might still
421 // use rgb pixmap and only access alpha pixels the
422 // slow way. now we just speedup rgb bitmaps
423 if( !aBmpEx
.IsTransparent() && !aBmpEx
.IsAlpha() )
425 pSurface
= rSurfaceProvider
->createSurface( aBitmap
);
432 AlphaMask aAlpha
= aBmpEx
.GetAlpha();
434 ::BitmapReadAccess
* pBitmapReadAcc
= aBitmap
.AcquireReadAccess();
435 ::BitmapReadAccess
* pAlphaReadAcc
= NULL
;
436 const long nWidth
= pBitmapReadAcc
->Width();
437 const long nHeight
= pBitmapReadAcc
->Height();
439 bool bIsAlpha
= false;
441 if( aBmpEx
.IsTransparent() || aBmpEx
.IsAlpha() )
442 pAlphaReadAcc
= aAlpha
.AcquireReadAccess();
444 data
= static_cast<unsigned char*>(malloc( nWidth
*nHeight
*4 ));
448 unsigned int nAlpha
= 255;
450 for( nY
= 0; nY
< nHeight
; nY
++ )
452 ::Scanline pReadScan
;
454 switch( pBitmapReadAcc
->GetScanlineFormat() )
456 case BMP_FORMAT_8BIT_PAL
:
457 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
459 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
462 for( nX
= 0; nX
< nWidth
; nX
++ )
466 nAlpha
= data
[ nOff
++ ];
468 nAlpha
= data
[ nOff
++ ] = 255;
471 nAlpha
= data
[ nOff
+ 3 ];
473 nAlpha
= data
[ nOff
+ 3 ] = 255;
475 aColor
= pBitmapReadAcc
->GetPaletteColor( *pReadScan
++ );
478 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetRed() ) )/255 );
479 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetGreen() ) )/255 );
480 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetBlue() ) )/255 );
482 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetBlue() ) )/255 );
483 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetGreen() ) )/255 );
484 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetRed() ) )/255 );
489 case BMP_FORMAT_24BIT_TC_BGR
:
490 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
492 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
495 for( nX
= 0; nX
< nWidth
; nX
++ )
499 nAlpha
= data
[ nOff
];
501 nAlpha
= data
[ nOff
] = 255;
502 data
[ nOff
+ 3 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
503 data
[ nOff
+ 2 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
504 data
[ nOff
+ 1 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
508 nAlpha
= data
[ nOff
+ 3 ];
510 nAlpha
= data
[ nOff
+ 3 ] = 255;
511 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
512 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
513 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
518 case BMP_FORMAT_24BIT_TC_RGB
:
519 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
521 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
524 for( nX
= 0; nX
< nWidth
; nX
++ )
528 nAlpha
= data
[ nOff
++ ];
530 nAlpha
= data
[ nOff
++ ] = 255;
531 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
532 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
533 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
536 nAlpha
= data
[ nOff
+ 3 ];
538 nAlpha
= data
[ nOff
+ 3 ] = 255;
539 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 2 ] ) )/255 );
540 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 1 ] ) )/255 );
541 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 0 ] ) )/255 );
547 case BMP_FORMAT_32BIT_TC_BGRA
:
548 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
550 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
553 for( nX
= 0; nX
< nWidth
; nX
++ )
557 nAlpha
= data
[ nOff
++ ];
559 nAlpha
= data
[ nOff
++ ] = 255;
560 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 2 ] ) )/255 );
561 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 1 ] ) )/255 );
562 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 0 ] ) )/255 );
566 nAlpha
= data
[ nOff
+ 3 ];
568 nAlpha
= data
[ nOff
+ 3 ] = 255;
569 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
570 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
571 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
577 case BMP_FORMAT_32BIT_TC_RGBA
:
578 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
580 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
583 for( nX
= 0; nX
< nWidth
; nX
++ )
587 nAlpha
= data
[ nOff
++ ];
589 nAlpha
= data
[ nOff
++ ] = 255;
590 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
591 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
592 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
596 nAlpha
= data
[ nOff
+ 3 ];
598 nAlpha
= data
[ nOff
+ 3 ] = 255;
599 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 2 ] ) )/255 );
600 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 1 ] ) )/255 );
601 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 0 ] ) )/255 );
608 SAL_INFO( "canvas.cairo", "fallback to GetColor - slow, format: " << pBitmapReadAcc
->GetScanlineFormat() );
611 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
614 for( nX
= 0; nX
< nWidth
; nX
++ )
616 aColor
= pBitmapReadAcc
->GetColor( nY
, nX
);
618 // cairo need premultiplied color values
619 // TODO(rodo) handle endianness
622 nAlpha
= data
[ nOff
++ ];
624 nAlpha
= data
[ nOff
++ ] = 255;
625 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetRed() )/255 );
626 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetGreen() )/255 );
627 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetBlue() )/255 );
630 nAlpha
= data
[ nOff
+ 3 ];
632 nAlpha
= data
[ nOff
+ 3 ] = 255;
633 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetBlue() )/255 );
634 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetGreen() )/255 );
635 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetRed() )/255 );
642 ::Bitmap::ReleaseAccess( pBitmapReadAcc
);
644 aAlpha
.ReleaseAccess( pAlphaReadAcc
);
646 SurfaceSharedPtr pImageSurface
= rSurfaceProvider
->getOutputDevice()->CreateSurface(
647 CairoSurfaceSharedPtr(
648 cairo_image_surface_create_for_data(
650 bIsAlpha
? CAIRO_FORMAT_ARGB32
: CAIRO_FORMAT_RGB24
,
651 nWidth
, nHeight
, nWidth
*4 ),
652 &cairo_surface_destroy
) );
653 pSurface
= pImageSurface
;
655 bHasAlpha
= bIsAlpha
;
657 SAL_INFO( "canvas.cairo","image: " << nWidth
<< " x " << nHeight
<< " alpha: " << bIsAlpha
<< " alphaRead " << std::hex
<< pAlphaReadAcc
);
664 static void addColorStops( cairo_pattern_t
* pPattern
, const uno::Sequence
< uno::Sequence
< double > >& rColors
, const uno::Sequence
< double >& rStops
, bool bReverseStops
= false )
668 OSL_ASSERT( rColors
.getLength() == rStops
.getLength() );
670 for( i
= 0; i
< rColors
.getLength(); i
++ )
672 const uno::Sequence
< double >& rColor( rColors
[i
] );
673 float stop
= bReverseStops
? 1 - rStops
[i
] : rStops
[i
];
674 if( rColor
.getLength() == 3 )
675 cairo_pattern_add_color_stop_rgb( pPattern
, stop
, rColor
[0], rColor
[1], rColor
[2] );
676 else if( rColor
.getLength() == 4 )
678 double alpha
= rColor
[3];
679 // cairo expects premultiplied alpha
680 cairo_pattern_add_color_stop_rgba( pPattern
, stop
, rColor
[0]*alpha
, rColor
[1]*alpha
, rColor
[2]*alpha
, alpha
);
685 static uno::Sequence
<double> lerp(const uno::Sequence
<double>& rLeft
, const uno::Sequence
<double>& rRight
, double fAlpha
)
687 if( rLeft
.getLength() == 3 )
689 uno::Sequence
<double> aRes(3);
690 aRes
[0] = basegfx::tools::lerp(rLeft
[0],rRight
[0],fAlpha
);
691 aRes
[1] = basegfx::tools::lerp(rLeft
[1],rRight
[1],fAlpha
);
692 aRes
[2] = basegfx::tools::lerp(rLeft
[2],rRight
[2],fAlpha
);
695 else if( rLeft
.getLength() == 4 )
697 uno::Sequence
<double> aRes(4);
698 aRes
[0] = basegfx::tools::lerp(rLeft
[0],rRight
[0],fAlpha
);
699 aRes
[1] = basegfx::tools::lerp(rLeft
[1],rRight
[1],fAlpha
);
700 aRes
[2] = basegfx::tools::lerp(rLeft
[2],rRight
[2],fAlpha
);
701 aRes
[3] = basegfx::tools::lerp(rLeft
[3],rRight
[3],fAlpha
);
705 return uno::Sequence
<double>();
708 static cairo_pattern_t
* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon
& rPolygon
)
710 cairo_pattern_t
* pPattern
= NULL
;
711 const ::canvas::ParametricPolyPolygon::Values aValues
= rPolygon
.getValues();
712 double x0
, x1
, y0
, y1
, cx
, cy
, r0
, r1
;
714 switch( aValues
.meType
)
716 case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR
:
721 pPattern
= cairo_pattern_create_linear( x0
, y0
, x1
, y1
);
722 addColorStops( pPattern
, aValues
.maColors
, aValues
.maStops
);
725 case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL
:
731 pPattern
= cairo_pattern_create_radial( cx
, cy
, r0
, cy
, cy
, r1
);
732 addColorStops( pPattern
, aValues
.maColors
, aValues
.maStops
, true );
741 static void doOperation( Operation aOperation
,
743 const uno::Sequence
< rendering::Texture
>* pTextures
,
744 const SurfaceProviderRef
& pDevice
,
745 const basegfx::B2DRange
& rBounds
)
750 /* TODO: multitexturing */
753 const ::com::sun::star::rendering::Texture
& aTexture ( (*pTextures
)[0] );
754 if( aTexture
.Bitmap
.is() )
756 unsigned char* data
= NULL
;
757 bool bHasAlpha
= false;
758 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( (*pTextures
)[0].Bitmap
, pDevice
, data
, bHasAlpha
);
762 cairo_pattern_t
* pPattern
;
764 cairo_save( pCairo
);
766 ::com::sun::star::geometry::AffineMatrix2D
aTransform( aTexture
.AffineTransform
);
767 cairo_matrix_t aScaleMatrix
, aTextureMatrix
, aScaledTextureMatrix
;
769 cairo_matrix_init( &aTextureMatrix
,
770 aTransform
.m00
, aTransform
.m10
, aTransform
.m01
,
771 aTransform
.m11
, aTransform
.m02
, aTransform
.m12
);
773 geometry::IntegerSize2D aSize
= aTexture
.Bitmap
->getSize();
775 cairo_matrix_init_scale( &aScaleMatrix
, 1.0/aSize
.Width
, 1.0/aSize
.Height
);
776 cairo_matrix_multiply( &aScaledTextureMatrix
, &aTextureMatrix
, &aScaleMatrix
);
777 cairo_matrix_invert( &aScaledTextureMatrix
);
779 // we don't care about repeat mode yet, so the workaround is disabled for now
780 pPattern
= cairo_pattern_create_for_surface( pSurface
->getCairoSurface().get() );
782 if( aTexture
.RepeatModeX
== rendering::TexturingMode::REPEAT
&&
783 aTexture
.RepeatModeY
== rendering::TexturingMode::REPEAT
)
785 cairo_pattern_set_extend( pPattern
, CAIRO_EXTEND_REPEAT
);
787 else if ( aTexture
.RepeatModeX
== rendering::TexturingMode::NONE
&&
788 aTexture
.RepeatModeY
== rendering::TexturingMode::NONE
)
790 cairo_pattern_set_extend( pPattern
, CAIRO_EXTEND_NONE
);
792 else if ( aTexture
.RepeatModeX
== rendering::TexturingMode::CLAMP
&&
793 aTexture
.RepeatModeY
== rendering::TexturingMode::CLAMP
)
795 cairo_pattern_set_extend( pPattern
, CAIRO_EXTEND_PAD
);
798 aScaledTextureMatrix
.x0
= basegfx::fround( aScaledTextureMatrix
.x0
);
799 aScaledTextureMatrix
.y0
= basegfx::fround( aScaledTextureMatrix
.y0
);
800 cairo_pattern_set_matrix( pPattern
, &aScaledTextureMatrix
);
802 cairo_set_source( pCairo
, pPattern
);
804 cairo_set_operator( pCairo
, CAIRO_OPERATOR_SOURCE
);
805 cairo_fill( pCairo
);
807 cairo_restore( pCairo
);
809 cairo_pattern_destroy( pPattern
);
815 else if( aTexture
.Gradient
.is() )
817 uno::Reference
< lang::XServiceInfo
> xRef( aTexture
.Gradient
, uno::UNO_QUERY
);
819 SAL_INFO( "canvas.cairo", "gradient fill" );
820 if( xRef
.is() && xRef
->getImplementationName() == PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME
)
822 // TODO(Q1): Maybe use dynamic_cast here
824 // TODO(E1): Return value
825 // TODO(F1): FillRule
826 SAL_INFO( "canvas.cairo", "known implementation" );
828 ::canvas::ParametricPolyPolygon
* pPolyImpl
= static_cast< ::canvas::ParametricPolyPolygon
* >( aTexture
.Gradient
.get() );
829 ::com::sun::star::geometry::AffineMatrix2D
aTransform( aTexture
.AffineTransform
);
830 cairo_matrix_t aTextureMatrix
;
832 cairo_matrix_init( &aTextureMatrix
,
833 aTransform
.m00
, aTransform
.m10
, aTransform
.m01
,
834 aTransform
.m11
, aTransform
.m02
, aTransform
.m12
);
835 if( pPolyImpl
->getValues().meType
== canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR
)
837 // no general path gradient yet in cairo; emulate then
838 cairo_save( pCairo
);
839 cairo_clip( pCairo
);
841 // fill bound rect with start color
842 cairo_rectangle( pCairo
, rBounds
.getMinX(), rBounds
.getMinY(),
843 rBounds
.getWidth(), rBounds
.getHeight() );
844 setColor(pCairo
,pPolyImpl
->getValues().maColors
[0]);
847 cairo_transform( pCairo
, &aTextureMatrix
);
849 // longest line in gradient bound rect
850 const unsigned int nGradientSize(
851 static_cast<unsigned int>(
852 ::basegfx::B2DVector(rBounds
.getMinimum() - rBounds
.getMaximum()).getLength() + 1.0 ) );
854 // typical number for pixel of the same color (strip size)
855 const unsigned int nStripSize( nGradientSize
< 50 ? 2 : 4 );
857 // use at least three steps, and at utmost the number of color
859 const unsigned int nStepCount(
863 nGradientSize
/ nStripSize
,
866 const uno::Sequence
<double>* pColors
=&pPolyImpl
->getValues().maColors
[0];
867 basegfx::tools::KeyStopLerp
aLerper(pPolyImpl
->getValues().maStops
);
868 for( unsigned int i
=1; i
<nStepCount
; ++i
)
870 const double fT( i
/double(nStepCount
) );
872 std::ptrdiff_t nIndex
;
874 boost::tuples::tie(nIndex
,fAlpha
)=aLerper
.lerp(fT
);
876 setColor(pCairo
, lerp(pColors
[nIndex
], pColors
[nIndex
+1], fAlpha
));
877 cairo_rectangle( pCairo
, -1+fT
, -1+fT
, 2-2*fT
, 2-2*fT
);
881 cairo_restore( pCairo
);
885 cairo_pattern_t
* pPattern
= patternFromParametricPolyPolygon( *pPolyImpl
);
889 SAL_INFO( "canvas.cairo", "filling with pattern" );
891 cairo_save( pCairo
);
893 cairo_transform( pCairo
, &aTextureMatrix
);
894 cairo_set_source( pCairo
, pPattern
);
895 cairo_fill( pCairo
);
896 cairo_restore( pCairo
);
898 cairo_pattern_destroy( pPattern
);
905 cairo_fill( pCairo
);
906 SAL_INFO( "canvas.cairo", "fill");
909 cairo_stroke( pCairo
);
910 SAL_INFO( "canvas.cairo", "stroke");
913 cairo_clip( pCairo
);
914 SAL_INFO( "canvas.cairo", "clip");
919 static void clipNULL( cairo_t
*pCairo
)
921 SAL_INFO( "canvas.cairo", "clipNULL");
922 cairo_matrix_t aOrigMatrix
, aIdentityMatrix
;
924 /* we set identity matrix here to overcome bug in cairo 0.9.2
925 where XCreatePixmap is called with zero width and height.
927 it also reaches faster path in cairo clipping code.
929 cairo_matrix_init_identity( &aIdentityMatrix
);
930 cairo_get_matrix( pCairo
, &aOrigMatrix
);
931 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
933 cairo_reset_clip( pCairo
);
934 cairo_rectangle( pCairo
, 0, 0, 1, 1 );
935 cairo_clip( pCairo
);
936 cairo_rectangle( pCairo
, 2, 0, 1, 1 );
937 cairo_clip( pCairo
);
939 /* restore the original matrix */
940 cairo_set_matrix( pCairo
, &aOrigMatrix
);
943 void doPolyPolygonImplementation( ::basegfx::B2DPolyPolygon aPolyPolygon
,
944 Operation aOperation
,
946 const uno::Sequence
< rendering::Texture
>* pTextures
,
947 const SurfaceProviderRef
& pDevice
,
948 rendering::FillRule eFillrule
)
951 ENSURE_ARG_OR_THROW( pTextures
->getLength(),
952 "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
954 bool bOpToDo
= false;
955 cairo_matrix_t aOrigMatrix
, aIdentityMatrix
;
956 double nX
, nY
, nBX
, nBY
, nAX
, nAY
;
958 cairo_get_matrix( pCairo
, &aOrigMatrix
);
959 cairo_matrix_init_identity( &aIdentityMatrix
);
960 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
962 cairo_set_fill_rule( pCairo
,
963 eFillrule
== rendering::FillRule_EVEN_ODD
?
964 CAIRO_FILL_RULE_EVEN_ODD
: CAIRO_FILL_RULE_WINDING
);
966 for( sal_uInt32 nPolygonIndex
= 0; nPolygonIndex
< aPolyPolygon
.count(); nPolygonIndex
++ )
968 ::basegfx::B2DPolygon
aPolygon( aPolyPolygon
.getB2DPolygon( nPolygonIndex
) );
969 const sal_uInt32
nPointCount( aPolygon
.count() );
970 // to correctly render closed curves, need to output first
971 // point twice (so output one additional point)
972 const sal_uInt32
nExtendedPointCount( nPointCount
+
973 int(aPolygon
.isClosed() && aPolygon
.areControlPointsUsed()) );
977 bool bIsBezier
= aPolygon
.areControlPointsUsed();
978 bool bIsRectangle
= ::basegfx::tools::isRectangle( aPolygon
);
979 ::basegfx::B2DPoint aA
, aB
, aP
;
981 for( sal_uInt32 j
=0; j
< nExtendedPointCount
; j
++ )
983 aP
= aPolygon
.getB2DPoint( j
% nPointCount
);
987 cairo_matrix_transform_point( &aOrigMatrix
, &nX
, &nY
);
989 if( ! bIsBezier
&& (bIsRectangle
|| aOperation
== Clip
) )
991 nX
= basegfx::fround( nX
);
992 nY
= basegfx::fround( nY
);
995 if( aOperation
== Stroke
)
1003 cairo_move_to( pCairo
, nX
, nY
);
1004 SAL_INFO( "canvas.cairo", "move to " << nX
<< "," << nY
);
1010 aA
= aPolygon
.getNextControlPoint( (j
-1) % nPointCount
);
1011 aB
= aPolygon
.getPrevControlPoint( j
% nPointCount
);
1018 cairo_matrix_transform_point( &aOrigMatrix
, &nAX
, &nAY
);
1019 cairo_matrix_transform_point( &aOrigMatrix
, &nBX
, &nBY
);
1021 if( aOperation
== Stroke
)
1029 cairo_curve_to( pCairo
, nAX
, nAY
, nBX
, nBY
, nX
, nY
);
1033 cairo_line_to( pCairo
, nX
, nY
);
1034 SAL_INFO( "canvas.cairo", "line to " << nX
<< "," << nY
);
1040 if( aPolygon
.isClosed() )
1041 cairo_close_path( pCairo
);
1046 SAL_INFO( "canvas.cairo", "empty polygon for op: " << aOperation
);
1047 if( aOperation
== Clip
)
1056 if( aOperation
== Fill
&& pTextures
)
1058 cairo_set_matrix( pCairo
, &aOrigMatrix
);
1059 doOperation( aOperation
, pCairo
, pTextures
, pDevice
, aPolyPolygon
.getB2DRange() );
1060 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
1063 if( bOpToDo
&& ( aOperation
!= Fill
|| !pTextures
) )
1064 doOperation( aOperation
, pCairo
, pTextures
, pDevice
, aPolyPolygon
.getB2DRange() );
1066 cairo_set_matrix( pCairo
, &aOrigMatrix
);
1068 if( aPolyPolygon
.count() == 0 && aOperation
== Clip
)
1072 void CanvasHelper::doPolyPolygonPath( const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1073 Operation aOperation
,
1075 const uno::Sequence
< rendering::Texture
>* pTextures
,
1076 cairo_t
* pCairo
) const
1078 const ::basegfx::B2DPolyPolygon
& rPolyPoly(
1079 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon
) );
1082 pCairo
= mpCairo
.get();
1084 if(bNoLineJoin
&& Stroke
== aOperation
)
1086 // emulate rendering::PathJoinType::NONE by painting single edges
1087 for(sal_uInt32
a(0); a
< rPolyPoly
.count(); a
++)
1089 const basegfx::B2DPolygon
aCandidate(rPolyPoly
.getB2DPolygon(a
));
1090 const sal_uInt32
nPointCount(aCandidate
.count());
1094 const sal_uInt32
nEdgeCount(aCandidate
.isClosed() ? nPointCount
: nPointCount
- 1);
1095 basegfx::B2DPolygon aEdge
;
1096 aEdge
.append(aCandidate
.getB2DPoint(0));
1097 aEdge
.append(basegfx::B2DPoint(0.0, 0.0));
1099 for(sal_uInt32
b(0); b
< nEdgeCount
; b
++)
1101 const sal_uInt32
nNextIndex((b
+ 1) % nPointCount
);
1102 aEdge
.setB2DPoint(1, aCandidate
.getB2DPoint(nNextIndex
));
1103 aEdge
.setNextControlPoint(0, aCandidate
.getNextControlPoint(b
% nPointCount
));
1104 aEdge
.setPrevControlPoint(1, aCandidate
.getPrevControlPoint(nNextIndex
));
1106 doPolyPolygonImplementation( basegfx::B2DPolyPolygon(aEdge
),
1110 xPolyPolygon
->getFillRule() );
1112 // prepare next step
1113 aEdge
.setB2DPoint(0, aEdge
.getB2DPoint(1));
1120 doPolyPolygonImplementation( rPolyPoly
, aOperation
,
1123 xPolyPolygon
->getFillRule() );
1127 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawPolyPolygon( const rendering::XCanvas
* ,
1128 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1129 const rendering::ViewState
& viewState
,
1130 const rendering::RenderState
& renderState
)
1132 #ifdef CAIRO_CANVAS_PERF_TRACE
1133 struct timespec aTimer
;
1134 mxDevice
->startPerfTrace( &aTimer
);
1139 cairo_save( mpCairo
.get() );
1141 cairo_set_line_width( mpCairo
.get(), 1 );
1143 useStates( viewState
, renderState
, true );
1144 doPolyPolygonPath( xPolyPolygon
, Stroke
);
1146 cairo_restore( mpCairo
.get() );
1149 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed");
1151 #ifdef CAIRO_CANVAS_PERF_TRACE
1152 mxDevice
->stopPerfTrace( &aTimer
, "drawPolyPolygon" );
1155 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1158 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokePolyPolygon( const rendering::XCanvas
* ,
1159 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1160 const rendering::ViewState
& viewState
,
1161 const rendering::RenderState
& renderState
,
1162 const rendering::StrokeAttributes
& strokeAttributes
)
1164 #ifdef CAIRO_CANVAS_PERF_TRACE
1165 struct timespec aTimer
;
1166 mxDevice
->startPerfTrace( &aTimer
);
1171 cairo_save( mpCairo
.get() );
1173 useStates( viewState
, renderState
, true );
1175 cairo_matrix_t aMatrix
;
1176 double w
= strokeAttributes
.StrokeWidth
, h
= 0;
1177 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
1178 cairo_matrix_transform_distance( &aMatrix
, &w
, &h
);
1179 cairo_set_line_width( mpCairo
.get(), w
);
1181 cairo_set_miter_limit( mpCairo
.get(), strokeAttributes
.MiterLimit
);
1183 // FIXME: cairo doesn't handle end cap so far (rodo)
1184 switch( strokeAttributes
.StartCapType
)
1186 case rendering::PathCapType::BUTT
:
1187 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_BUTT
);
1189 case rendering::PathCapType::ROUND
:
1190 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_ROUND
);
1192 case rendering::PathCapType::SQUARE
:
1193 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_SQUARE
);
1197 bool bNoLineJoin(false);
1199 switch( strokeAttributes
.JoinType
)
1201 case rendering::PathJoinType::NONE
:
1203 // cairo doesn't have join type NONE so we use MITER as it's pretty close
1204 case rendering::PathJoinType::MITER
:
1205 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_MITER
);
1207 case rendering::PathJoinType::ROUND
:
1208 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_ROUND
);
1210 case rendering::PathJoinType::BEVEL
:
1211 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_BEVEL
);
1215 if( strokeAttributes
.DashArray
.getLength() > 0 )
1217 double* pDashArray
= new double[ strokeAttributes
.DashArray
.getLength() ];
1218 for( sal_Int32 i
=0; i
<strokeAttributes
.DashArray
.getLength(); i
++ )
1219 pDashArray
[i
] = strokeAttributes
.DashArray
[i
] * w
;
1220 cairo_set_dash( mpCairo
.get(), pDashArray
, strokeAttributes
.DashArray
.getLength(), 0 );
1221 delete[] pDashArray
;
1224 // TODO(rodo) use LineArray of strokeAttributes
1226 doPolyPolygonPath( xPolyPolygon
, Stroke
, bNoLineJoin
);
1228 cairo_restore( mpCairo
.get() );
1231 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed");
1233 #ifdef CAIRO_CANVAS_PERF_TRACE
1234 mxDevice
->stopPerfTrace( &aTimer
, "strokePolyPolygon" );
1237 // TODO(P1): Provide caching here.
1238 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1241 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas
* ,
1242 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1243 const rendering::ViewState
& /*viewState*/,
1244 const rendering::RenderState
& /*renderState*/,
1245 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1246 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1249 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1252 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas
* ,
1253 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1254 const rendering::ViewState
& /*viewState*/,
1255 const rendering::RenderState
& /*renderState*/,
1256 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1257 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/,
1258 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1261 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1264 uno::Reference
< rendering::XPolyPolygon2D
> CanvasHelper::queryStrokeShapes( const rendering::XCanvas
* ,
1265 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1266 const rendering::ViewState
& /*viewState*/,
1267 const rendering::RenderState
& /*renderState*/,
1268 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1271 return uno::Reference
< rendering::XPolyPolygon2D
>(NULL
);
1274 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillPolyPolygon( const rendering::XCanvas
* ,
1275 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1276 const rendering::ViewState
& viewState
,
1277 const rendering::RenderState
& renderState
)
1279 #ifdef CAIRO_CANVAS_PERF_TRACE
1280 struct timespec aTimer
;
1281 mxDevice
->startPerfTrace( &aTimer
);
1286 cairo_save( mpCairo
.get() );
1288 useStates( viewState
, renderState
, true );
1289 doPolyPolygonPath( xPolyPolygon
, Fill
);
1291 cairo_restore( mpCairo
.get() );
1294 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed");
1296 #ifdef CAIRO_CANVAS_PERF_TRACE
1297 mxDevice
->stopPerfTrace( &aTimer
, "fillPolyPolygon" );
1300 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1303 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas
* ,
1304 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1305 const rendering::ViewState
& viewState
,
1306 const rendering::RenderState
& renderState
,
1307 const uno::Sequence
< rendering::Texture
>& textures
)
1311 cairo_save( mpCairo
.get() );
1313 useStates( viewState
, renderState
, true );
1314 doPolyPolygonPath( xPolyPolygon
, Fill
, false, &textures
);
1316 cairo_restore( mpCairo
.get() );
1319 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1322 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas
* ,
1323 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1324 const rendering::ViewState
& /*viewState*/,
1325 const rendering::RenderState
& /*renderState*/,
1326 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1327 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/ )
1330 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1333 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::implDrawBitmapSurface( const rendering::XCanvas
* pCanvas
,
1334 const SurfaceSharedPtr
& pInputSurface
,
1335 const rendering::ViewState
& viewState
,
1336 const rendering::RenderState
& renderState
,
1337 const geometry::IntegerSize2D
& rSize
,
1338 bool bModulateColors
,
1341 SurfaceSharedPtr pSurface
=pInputSurface
;
1342 uno::Reference
< rendering::XCachedPrimitive
> rv
= uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1343 geometry::IntegerSize2D aBitmapSize
= rSize
;
1347 cairo_save( mpCairo
.get() );
1349 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
1350 cairo_clip( mpCairo
.get() );
1352 useStates( viewState
, renderState
, true );
1354 cairo_matrix_t aMatrix
;
1356 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
1357 if( ! ::rtl::math::approxEqual( aMatrix
.xx
, 1 ) &&
1358 ! ::rtl::math::approxEqual( aMatrix
.yy
, 1 ) &&
1359 ::rtl::math::approxEqual( aMatrix
.x0
, 0 ) &&
1360 ::rtl::math::approxEqual( aMatrix
.y0
, 0 ) &&
1361 basegfx::fround( rSize
.Width
* aMatrix
.xx
) > 8 &&
1362 basegfx::fround( rSize
.Height
* aMatrix
.yy
) > 8 )
1364 double dWidth
, dHeight
;
1366 dWidth
= basegfx::fround( rSize
.Width
* aMatrix
.xx
);
1367 dHeight
= basegfx::fround( rSize
.Height
* aMatrix
.yy
);
1368 aBitmapSize
.Width
= static_cast<sal_Int32
>( dWidth
);
1369 aBitmapSize
.Height
= static_cast<sal_Int32
>( dHeight
);
1371 SurfaceSharedPtr pScaledSurface
= mpSurfaceProvider
->createSurface(
1372 ::basegfx::B2ISize( aBitmapSize
.Width
, aBitmapSize
.Height
),
1373 bHasAlpha
? CAIRO_CONTENT_COLOR_ALPHA
: CAIRO_CONTENT_COLOR
);
1374 CairoSharedPtr pCairo
= pScaledSurface
->getCairo();
1376 cairo_set_operator( pCairo
.get(), CAIRO_OPERATOR_SOURCE
);
1377 // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
1378 cairo_scale( pCairo
.get(), (dWidth
+0.5)/rSize
.Width
, (dHeight
+0.5)/rSize
.Height
);
1379 cairo_set_source_surface( pCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
1380 cairo_paint( pCairo
.get() );
1382 pSurface
= pScaledSurface
;
1384 aMatrix
.xx
= aMatrix
.yy
= 1;
1385 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
1387 rv
= uno::Reference
< rendering::XCachedPrimitive
>(
1388 new CachedBitmap( pSurface
, viewState
, renderState
,
1389 // cast away const, need to
1390 // change refcount (as this is
1391 // ~invisible to client code,
1392 // still logically const)
1393 const_cast< rendering::XCanvas
* >(pCanvas
)) );
1396 if( !bHasAlpha
&& mbHaveAlpha
)
1398 double x
, y
, width
, height
;
1401 width
= aBitmapSize
.Width
;
1402 height
= aBitmapSize
.Height
;
1403 cairo_matrix_transform_point( &aMatrix
, &x
, &y
);
1404 cairo_matrix_transform_distance( &aMatrix
, &width
, &height
);
1406 // in case the bitmap doesn't have alpha and covers whole area
1407 // we try to change surface to plain rgb
1408 SAL_INFO( "canvas.cairo","chance to change surface to rgb, " << x
<< ", " << y
<< ", " << width
<< " x " << height
<< " (" << maSize
.getX() << " x " << maSize
.getY() << ")" );
1409 if( x
<= 0 && y
<= 0 && x
+ width
>= maSize
.getX() && y
+ height
>= maSize
.getY() )
1411 SAL_INFO( "canvas.cairo","trying to change surface to rgb");
1412 if( mpSurfaceProvider
) {
1413 SurfaceSharedPtr pNewSurface
= mpSurfaceProvider
->changeSurface( false, false );
1416 setSurface( pNewSurface
, false );
1418 // set state to new mpCairo.get()
1419 useStates( viewState
, renderState
, true );
1420 // use the possibly modified matrix
1421 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
1426 cairo_set_source_surface( mpCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
1428 ::rtl::math::approxEqual( aMatrix
.xx
, 1 ) &&
1429 ::rtl::math::approxEqual( aMatrix
.yy
, 1 ) &&
1430 ::rtl::math::approxEqual( aMatrix
.x0
, 0 ) &&
1431 ::rtl::math::approxEqual( aMatrix
.y0
, 0 ) )
1432 cairo_set_operator( mpCairo
.get(), CAIRO_OPERATOR_SOURCE
);
1433 cairo_pattern_set_extend( cairo_get_source(mpCairo
.get()), CAIRO_EXTEND_PAD
);
1434 cairo_rectangle( mpCairo
.get(), 0, 0, aBitmapSize
.Width
, aBitmapSize
.Height
);
1435 cairo_clip( mpCairo
.get() );
1437 if( bModulateColors
)
1438 cairo_paint_with_alpha( mpCairo
.get(), renderState
.DeviceColor
[3] );
1440 cairo_paint( mpCairo
.get() );
1441 cairo_restore( mpCairo
.get() );
1444 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed");
1446 return rv
; // uno::Reference< rendering::XCachedPrimitive >(NULL);
1449 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawBitmap( const rendering::XCanvas
* pCanvas
,
1450 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
1451 const rendering::ViewState
& viewState
,
1452 const rendering::RenderState
& renderState
)
1454 #ifdef CAIRO_CANVAS_PERF_TRACE
1455 struct timespec aTimer
;
1456 mxDevice
->startPerfTrace( &aTimer
);
1459 uno::Reference
< rendering::XCachedPrimitive
> rv
;
1460 unsigned char* data
= NULL
;
1461 bool bHasAlpha
= false;
1462 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( xBitmap
, mpSurfaceProvider
, data
, bHasAlpha
);
1463 geometry::IntegerSize2D aSize
= xBitmap
->getSize();
1467 rv
= implDrawBitmapSurface( pCanvas
, pSurface
, viewState
, renderState
, aSize
, false, bHasAlpha
);
1473 rv
= uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1475 #ifdef CAIRO_CANVAS_PERF_TRACE
1476 mxDevice
->stopPerfTrace( &aTimer
, "drawBitmap" );
1482 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawBitmapModulated( const rendering::XCanvas
* pCanvas
,
1483 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
1484 const rendering::ViewState
& viewState
,
1485 const rendering::RenderState
& renderState
)
1487 #ifdef CAIRO_CANVAS_PERF_TRACE
1488 struct timespec aTimer
;
1489 mxDevice
->startPerfTrace( &aTimer
);
1492 uno::Reference
< rendering::XCachedPrimitive
> rv
;
1493 unsigned char* data
= NULL
;
1494 bool bHasAlpha
= false;
1495 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( xBitmap
, mpSurfaceProvider
, data
, bHasAlpha
);
1496 geometry::IntegerSize2D aSize
= xBitmap
->getSize();
1500 rv
= implDrawBitmapSurface( pCanvas
, pSurface
, viewState
, renderState
, aSize
, true, bHasAlpha
);
1506 rv
= uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1508 #ifdef CAIRO_CANVAS_PERF_TRACE
1509 mxDevice
->stopPerfTrace( &aTimer
, "drawBitmap" );
1516 geometry::IntegerSize2D
CanvasHelper::getSize()
1518 if( !mpSurfaceProvider
)
1519 geometry::IntegerSize2D(1, 1); // we're disposed
1521 return ::basegfx::unotools::integerSize2DFromB2ISize( maSize
);
1524 uno::Reference
< rendering::XBitmap
> CanvasHelper::getScaledBitmap( const geometry::RealSize2D
& newSize
,
1527 #ifdef CAIRO_CANVAS_PERF_TRACE
1528 struct timespec aTimer
;
1529 mxDevice
->startPerfTrace( &aTimer
);
1534 return uno::Reference
< rendering::XBitmap
>( new CanvasBitmap( ::basegfx::B2ISize( ::canvas::tools::roundUp( newSize
.Width
),
1535 ::canvas::tools::roundUp( newSize
.Height
) ),
1536 mpSurfaceProvider
, mpDevice
, false ) );
1539 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed");
1541 #ifdef CAIRO_CANVAS_PERF_TRACE
1542 mxDevice
->stopPerfTrace( &aTimer
, "getScaledBitmap" );
1545 return uno::Reference
< rendering::XBitmap
>();
1548 uno::Sequence
< sal_Int8
> CanvasHelper::getData( rendering::IntegerBitmapLayout
& aLayout
,
1549 const geometry::IntegerRectangle2D
& rect
)
1553 const sal_Int32
nWidth( rect
.X2
- rect
.X1
);
1554 const sal_Int32
nHeight( rect
.Y2
- rect
.Y1
);
1555 const cairo_format_t
eFormat( mbHaveAlpha
? CAIRO_FORMAT_ARGB32
: CAIRO_FORMAT_RGB24
);
1556 uno::Sequence
< sal_Int8
> aRes( 4*nWidth
*nHeight
);
1557 sal_Int8
* pData
= aRes
.getArray();
1558 cairo_surface_t
* pImageSurface
= cairo_image_surface_create_for_data( reinterpret_cast<unsigned char *>(pData
),
1560 nWidth
, nHeight
, 4*nWidth
);
1561 cairo_t
* pCairo
= cairo_create( pImageSurface
);
1562 cairo_set_source_surface( pCairo
, mpSurface
->getCairoSurface().get(), -rect
.X1
, -rect
.Y1
);
1563 cairo_paint( pCairo
);
1564 cairo_destroy( pCairo
);
1565 cairo_surface_destroy( pImageSurface
);
1567 aLayout
= impl_getMemoryLayout( nWidth
, nHeight
);
1572 return uno::Sequence
< sal_Int8
>();
1575 uno::Sequence
< sal_Int8
> CanvasHelper::getPixel( rendering::IntegerBitmapLayout
& /*bitmapLayout*/,
1576 const geometry::IntegerPoint2D
& /*pos*/ )
1578 return uno::Sequence
< sal_Int8
>();
1583 class CairoColorSpace
: public cppu::WeakImplHelper1
< com::sun::star::rendering::XIntegerBitmapColorSpace
>
1586 uno::Sequence
< sal_Int8
> maComponentTags
;
1587 uno::Sequence
< sal_Int32
> maBitCounts
;
1589 virtual ::sal_Int8 SAL_CALL
getType( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1591 return rendering::ColorSpaceType::RGB
;
1593 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
getComponentTags( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1595 return maComponentTags
;
1597 virtual ::sal_Int8 SAL_CALL
getRenderingIntent( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1599 return rendering::RenderingIntent::PERCEPTUAL
;
1601 virtual uno::Sequence
< beans::PropertyValue
> SAL_CALL
getProperties( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1603 return uno::Sequence
< beans::PropertyValue
>();
1605 virtual uno::Sequence
< double > SAL_CALL
convertColorSpace( const uno::Sequence
< double >& deviceColor
,
1606 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
1607 uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1609 // TODO(P3): if we know anything about target
1610 // colorspace, this can be greatly sped up
1611 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1612 convertToARGB(deviceColor
));
1613 return targetColorSpace
->convertFromARGB(aIntermediate
);
1615 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertToRGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1617 const double* pIn( deviceColor
.getConstArray() );
1618 const sal_Size
nLen( deviceColor
.getLength() );
1619 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1620 "number of channels no multiple of 4",
1621 static_cast<rendering::XColorSpace
*>(this), 0);
1623 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
1624 rendering::RGBColor
* pOut( aRes
.getArray() );
1625 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1627 const double fAlpha(pIn
[3]);
1629 *pOut
++ = rendering::RGBColor(0.0, 0.0, 0.0);
1631 *pOut
++ = rendering::RGBColor(pIn
[2]/fAlpha
,pIn
[1]/fAlpha
,pIn
[0]/fAlpha
);
1636 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1638 const double* pIn( deviceColor
.getConstArray() );
1639 const sal_Size
nLen( deviceColor
.getLength() );
1640 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1641 "number of channels no multiple of 4",
1642 static_cast<rendering::XColorSpace
*>(this), 0);
1644 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1645 rendering::ARGBColor
* pOut( aRes
.getArray() );
1646 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1648 const double fAlpha(pIn
[3]);
1650 *pOut
++ = rendering::ARGBColor(0.0, 0.0, 0.0, 0.0);
1652 *pOut
++ = rendering::ARGBColor(fAlpha
,pIn
[2]/fAlpha
,pIn
[1]/fAlpha
,pIn
[0]/fAlpha
);
1657 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToPARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1659 const double* pIn( deviceColor
.getConstArray() );
1660 const sal_Size
nLen( deviceColor
.getLength() );
1661 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1662 "number of channels no multiple of 4",
1663 static_cast<rendering::XColorSpace
*>(this), 0);
1665 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1666 rendering::ARGBColor
* pOut( aRes
.getArray() );
1667 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1669 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[2],pIn
[1],pIn
[1]);
1674 virtual uno::Sequence
< double > SAL_CALL
convertFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1676 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
1677 const sal_Size
nLen( rgbColor
.getLength() );
1679 uno::Sequence
< double > aRes(nLen
*4);
1680 double* pColors
=aRes
.getArray();
1681 for( sal_Size i
=0; i
<nLen
; ++i
)
1683 *pColors
++ = pIn
->Blue
;
1684 *pColors
++ = pIn
->Green
;
1685 *pColors
++ = pIn
->Red
;
1691 virtual uno::Sequence
< double > SAL_CALL
convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1693 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1694 const sal_Size
nLen( rgbColor
.getLength() );
1696 uno::Sequence
< double > aRes(nLen
*4);
1697 double* pColors
=aRes
.getArray();
1698 for( sal_Size i
=0; i
<nLen
; ++i
)
1700 *pColors
++ = pIn
->Alpha
*pIn
->Blue
;
1701 *pColors
++ = pIn
->Alpha
*pIn
->Green
;
1702 *pColors
++ = pIn
->Alpha
*pIn
->Red
;
1703 *pColors
++ = pIn
->Alpha
;
1708 virtual uno::Sequence
< double > SAL_CALL
convertFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1710 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1711 const sal_Size
nLen( rgbColor
.getLength() );
1713 uno::Sequence
< double > aRes(nLen
*4);
1714 double* pColors
=aRes
.getArray();
1715 for( sal_Size i
=0; i
<nLen
; ++i
)
1717 *pColors
++ = pIn
->Blue
;
1718 *pColors
++ = pIn
->Green
;
1719 *pColors
++ = pIn
->Red
;
1720 *pColors
++ = pIn
->Alpha
;
1726 // XIntegerBitmapColorSpace
1727 virtual ::sal_Int32 SAL_CALL
getBitsPerPixel( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1731 virtual uno::Sequence
< ::sal_Int32
> SAL_CALL
getComponentBitCounts( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1735 virtual ::sal_Int8 SAL_CALL
getEndianness( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1737 return util::Endianness::LITTLE
;
1739 virtual uno::Sequence
<double> SAL_CALL
convertFromIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
1740 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
)
1741 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1743 if( dynamic_cast<CairoColorSpace
*>(targetColorSpace
.get()) )
1745 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1746 const sal_Size
nLen( deviceColor
.getLength() );
1747 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1748 "number of channels no multiple of 4",
1749 static_cast<rendering::XColorSpace
*>(this), 0);
1751 uno::Sequence
<double> aRes(nLen
);
1752 double* pOut( aRes
.getArray() );
1753 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1755 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1756 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1757 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1758 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1764 // TODO(P3): if we know anything about target
1765 // colorspace, this can be greatly sped up
1766 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1767 convertIntegerToARGB(deviceColor
));
1768 return targetColorSpace
->convertFromARGB(aIntermediate
);
1771 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertToIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
1772 const uno::Reference
< rendering::XIntegerBitmapColorSpace
>& targetColorSpace
)
1773 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1775 if( dynamic_cast<CairoColorSpace
*>(targetColorSpace
.get()) )
1777 // it's us, so simply pass-through the data
1782 // TODO(P3): if we know anything about target
1783 // colorspace, this can be greatly sped up
1784 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1785 convertIntegerToARGB(deviceColor
));
1786 return targetColorSpace
->convertIntegerFromARGB(aIntermediate
);
1789 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertIntegerToRGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
1790 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1792 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1793 const sal_Size
nLen( deviceColor
.getLength() );
1794 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1795 "number of channels no multiple of 4",
1796 static_cast<rendering::XColorSpace
*>(this), 0);
1798 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
1799 rendering::RGBColor
* pOut( aRes
.getArray() );
1800 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1802 const double fAlpha((sal_uInt8
)pIn
[3]);
1804 *pOut
++ = rendering::RGBColor(
1809 *pOut
++ = rendering::RGBColor(0,0,0);
1815 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
1816 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1818 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1819 const sal_Size
nLen( deviceColor
.getLength() );
1820 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1821 "number of channels no multiple of 4",
1822 static_cast<rendering::XColorSpace
*>(this), 0);
1824 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1825 rendering::ARGBColor
* pOut( aRes
.getArray() );
1826 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1828 const double fAlpha((sal_uInt8
)pIn
[3]);
1830 *pOut
++ = rendering::ARGBColor(
1836 *pOut
++ = rendering::ARGBColor(0,0,0,0);
1841 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToPARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
1842 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1844 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1845 const sal_Size
nLen( deviceColor
.getLength() );
1846 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1847 "number of channels no multiple of 4",
1848 static_cast<rendering::XColorSpace
*>(this), 0);
1850 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1851 rendering::ARGBColor
* pOut( aRes
.getArray() );
1852 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1854 *pOut
++ = rendering::ARGBColor(
1855 vcl::unotools::toDoubleColor(pIn
[3]),
1856 vcl::unotools::toDoubleColor(pIn
[2]),
1857 vcl::unotools::toDoubleColor(pIn
[1]),
1858 vcl::unotools::toDoubleColor(pIn
[0]));
1864 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
)
1865 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1867 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
1868 const sal_Size
nLen( rgbColor
.getLength() );
1870 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1871 sal_Int8
* pColors
=aRes
.getArray();
1872 for( sal_Size i
=0; i
<nLen
; ++i
)
1874 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
1875 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
1876 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
1883 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
1884 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1886 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1887 const sal_Size
nLen( rgbColor
.getLength() );
1889 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1890 sal_Int8
* pColors
=aRes
.getArray();
1891 for( sal_Size i
=0; i
<nLen
; ++i
)
1893 const double fAlpha(pIn
->Alpha
);
1894 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Blue
);
1895 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Green
);
1896 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Red
);
1897 *pColors
++ = vcl::unotools::toByteColor(fAlpha
);
1902 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
1903 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1905 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1906 const sal_Size
nLen( rgbColor
.getLength() );
1908 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1909 sal_Int8
* pColors
=aRes
.getArray();
1910 for( sal_Size i
=0; i
<nLen
; ++i
)
1912 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
1913 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
1914 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
1915 *pColors
++ = vcl::unotools::toByteColor(pIn
->Alpha
);
1926 sal_Int8
* pTags
= maComponentTags
.getArray();
1927 sal_Int32
* pBitCounts
= maBitCounts
.getArray();
1928 pTags
[0] = rendering::ColorComponentTag::RGB_BLUE
;
1929 pTags
[1] = rendering::ColorComponentTag::RGB_GREEN
;
1930 pTags
[2] = rendering::ColorComponentTag::RGB_RED
;
1931 pTags
[3] = rendering::ColorComponentTag::PREMULTIPLIED_ALPHA
;
1940 class CairoNoAlphaColorSpace
: public cppu::WeakImplHelper1
< com::sun::star::rendering::XIntegerBitmapColorSpace
>
1943 uno::Sequence
< sal_Int8
> maComponentTags
;
1944 uno::Sequence
< sal_Int32
> maBitCounts
;
1946 virtual ::sal_Int8 SAL_CALL
getType( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1948 return rendering::ColorSpaceType::RGB
;
1950 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
getComponentTags( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1952 return maComponentTags
;
1954 virtual ::sal_Int8 SAL_CALL
getRenderingIntent( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1956 return rendering::RenderingIntent::PERCEPTUAL
;
1958 virtual uno::Sequence
< beans::PropertyValue
> SAL_CALL
getProperties( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1960 return uno::Sequence
< beans::PropertyValue
>();
1962 virtual uno::Sequence
< double > SAL_CALL
convertColorSpace( const uno::Sequence
< double >& deviceColor
,
1963 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
1964 uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1966 // TODO(P3): if we know anything about target
1967 // colorspace, this can be greatly sped up
1968 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1969 convertToARGB(deviceColor
));
1970 return targetColorSpace
->convertFromARGB(aIntermediate
);
1972 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertToRGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1974 const double* pIn( deviceColor
.getConstArray() );
1975 const sal_Size
nLen( deviceColor
.getLength() );
1976 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1977 "number of channels no multiple of 4",
1978 static_cast<rendering::XColorSpace
*>(this), 0);
1980 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
1981 rendering::RGBColor
* pOut( aRes
.getArray() );
1982 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1984 *pOut
++ = rendering::RGBColor(pIn
[2], pIn
[1], pIn
[0]);
1989 uno::Sequence
< rendering::ARGBColor
> impl_convertToARGB( const uno::Sequence
< double >& deviceColor
)
1991 const double* pIn( deviceColor
.getConstArray() );
1992 const sal_Size
nLen( deviceColor
.getLength() );
1993 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1994 "number of channels no multiple of 4",
1995 static_cast<rendering::XColorSpace
*>(this), 0);
1997 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1998 rendering::ARGBColor
* pOut( aRes
.getArray() );
1999 for( sal_Size i
=0; i
<nLen
; i
+=4 )
2001 *pOut
++ = rendering::ARGBColor(1.0, pIn
[2], pIn
[1], pIn
[0]);
2006 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2008 return impl_convertToARGB( deviceColor
);
2010 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToPARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2012 return impl_convertToARGB( deviceColor
);
2014 virtual uno::Sequence
< double > SAL_CALL
convertFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2016 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
2017 const sal_Size
nLen( rgbColor
.getLength() );
2019 uno::Sequence
< double > aRes(nLen
*4);
2020 double* pColors
=aRes
.getArray();
2021 for( sal_Size i
=0; i
<nLen
; ++i
)
2023 *pColors
++ = pIn
->Blue
;
2024 *pColors
++ = pIn
->Green
;
2025 *pColors
++ = pIn
->Red
;
2026 *pColors
++ = 1.0; // the value does not matter
2031 uno::Sequence
< double > impl_convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
2033 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
2034 const sal_Size
nLen( rgbColor
.getLength() );
2036 uno::Sequence
< double > aRes(nLen
*4);
2037 double* pColors
=aRes
.getArray();
2038 for( sal_Size i
=0; i
<nLen
; ++i
)
2040 *pColors
++ = pIn
->Blue
;
2041 *pColors
++ = pIn
->Green
;
2042 *pColors
++ = pIn
->Red
;
2043 *pColors
++ = 1.0; // the value does not matter
2048 virtual uno::Sequence
< double > SAL_CALL
convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2050 return impl_convertFromARGB( rgbColor
);
2052 virtual uno::Sequence
< double > SAL_CALL
convertFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2054 return impl_convertFromARGB( rgbColor
);
2057 // XIntegerBitmapColorSpace
2058 virtual ::sal_Int32 SAL_CALL
getBitsPerPixel( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2062 virtual uno::Sequence
< ::sal_Int32
> SAL_CALL
getComponentBitCounts( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2066 virtual ::sal_Int8 SAL_CALL
getEndianness( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2068 return util::Endianness::LITTLE
;
2070 virtual uno::Sequence
<double> SAL_CALL
convertFromIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
2071 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
)
2072 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2074 if( dynamic_cast<CairoColorSpace
*>(targetColorSpace
.get()) )
2076 const sal_Int8
* pIn( deviceColor
.getConstArray() );
2077 const sal_Size
nLen( deviceColor
.getLength() );
2078 ENSURE_ARG_OR_THROW2(nLen
%4==0,
2079 "number of channels no multiple of 4",
2080 static_cast<rendering::XColorSpace
*>(this), 0);
2082 uno::Sequence
<double> aRes(nLen
);
2083 double* pOut( aRes
.getArray() );
2084 for( sal_Size i
=0; i
<nLen
; i
+=4 )
2086 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
2087 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
2088 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
2089 *pOut
++ = 1.0; // the value does not matter
2095 // TODO(P3): if we know anything about target
2096 // colorspace, this can be greatly sped up
2097 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
2098 convertIntegerToARGB(deviceColor
));
2099 return targetColorSpace
->convertFromARGB(aIntermediate
);
2102 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertToIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
2103 const uno::Reference
< rendering::XIntegerBitmapColorSpace
>& targetColorSpace
)
2104 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2106 if( dynamic_cast<CairoNoAlphaColorSpace
*>(targetColorSpace
.get()) )
2108 // it's us, so simply pass-through the data
2113 // TODO(P3): if we know anything about target
2114 // colorspace, this can be greatly sped up
2115 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
2116 convertIntegerToARGB(deviceColor
));
2117 return targetColorSpace
->convertIntegerFromARGB(aIntermediate
);
2120 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertIntegerToRGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
2121 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2123 const sal_Int8
* pIn( deviceColor
.getConstArray() );
2124 const sal_Size
nLen( deviceColor
.getLength() );
2125 ENSURE_ARG_OR_THROW2(nLen
%4==0,
2126 "number of channels no multiple of 4",
2127 static_cast<rendering::XColorSpace
*>(this), 0);
2129 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
2130 rendering::RGBColor
* pOut( aRes
.getArray() );
2131 for( sal_Size i
=0; i
<nLen
; i
+=4 )
2133 *pOut
++ = rendering::RGBColor( pIn
[2], pIn
[1], pIn
[0] );
2139 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
2140 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2142 return impl_convertIntegerToARGB( deviceColor
);
2144 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToPARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
2145 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2147 return impl_convertIntegerToARGB( deviceColor
);
2149 uno::Sequence
< rendering::ARGBColor
> impl_convertIntegerToARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
)
2151 const sal_Int8
* pIn( deviceColor
.getConstArray() );
2152 const sal_Size
nLen( deviceColor
.getLength() );
2153 ENSURE_ARG_OR_THROW2(nLen
%4==0,
2154 "number of channels no multiple of 4",
2155 static_cast<rendering::XColorSpace
*>(this), 0);
2157 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
2158 rendering::ARGBColor
* pOut( aRes
.getArray() );
2159 for( sal_Size i
=0; i
<nLen
; i
+=4 )
2161 *pOut
++ = rendering::ARGBColor(
2163 vcl::unotools::toDoubleColor(pIn
[2]),
2164 vcl::unotools::toDoubleColor(pIn
[1]),
2165 vcl::unotools::toDoubleColor(pIn
[0]));
2171 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
)
2172 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2174 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
2175 const sal_Size
nLen( rgbColor
.getLength() );
2177 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
2178 sal_Int8
* pColors
=aRes
.getArray();
2179 for( sal_Size i
=0; i
<nLen
; ++i
)
2181 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
2182 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
2183 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
2184 *pColors
++ = -1; // the value does not matter
2190 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
2191 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2193 return impl_convertIntegerFromARGB( rgbColor
);
2195 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
2196 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2198 return impl_convertIntegerFromARGB( rgbColor
);
2200 uno::Sequence
< ::sal_Int8
> impl_convertIntegerFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
)
2202 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
2203 const sal_Size
nLen( rgbColor
.getLength() );
2205 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
2206 sal_Int8
* pColors
=aRes
.getArray();
2207 for( sal_Size i
=0; i
<nLen
; ++i
)
2209 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
2210 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
2211 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
2212 *pColors
++ = -1; // the value does not matter
2219 CairoNoAlphaColorSpace() :
2223 sal_Int8
* pTags
= maComponentTags
.getArray();
2224 sal_Int32
* pBitCounts
= maBitCounts
.getArray();
2225 pTags
[0] = rendering::ColorComponentTag::RGB_BLUE
;
2226 pTags
[1] = rendering::ColorComponentTag::RGB_GREEN
;
2227 pTags
[2] = rendering::ColorComponentTag::RGB_RED
;
2235 struct CairoNoAlphaColorSpaceHolder
: public rtl::StaticWithInit
<uno::Reference
<rendering::XIntegerBitmapColorSpace
>,
2236 CairoNoAlphaColorSpaceHolder
>
2238 uno::Reference
<rendering::XIntegerBitmapColorSpace
> operator()()
2240 return new CairoNoAlphaColorSpace();
2244 struct CairoColorSpaceHolder
: public rtl::StaticWithInit
<uno::Reference
<rendering::XIntegerBitmapColorSpace
>,
2245 CairoColorSpaceHolder
>
2247 uno::Reference
<rendering::XIntegerBitmapColorSpace
> operator()()
2249 return new CairoColorSpace();
2255 rendering::IntegerBitmapLayout
CanvasHelper::getMemoryLayout()
2258 return rendering::IntegerBitmapLayout(); // we're disposed
2260 const geometry::IntegerSize2D
aSize(getSize());
2262 return impl_getMemoryLayout( aSize
.Width
, aSize
.Height
);
2265 rendering::IntegerBitmapLayout
2266 CanvasHelper::impl_getMemoryLayout( const sal_Int32 nWidth
, const sal_Int32 nHeight
)
2268 rendering::IntegerBitmapLayout aLayout
;
2270 aLayout
.ScanLines
= nHeight
;
2271 aLayout
.ScanLineBytes
= nWidth
*4;
2272 aLayout
.ScanLineStride
= aLayout
.ScanLineBytes
;
2273 aLayout
.PlaneStride
= 0;
2274 aLayout
.ColorSpace
= mbHaveAlpha
? CairoColorSpaceHolder::get() : CairoNoAlphaColorSpaceHolder::get();
2275 aLayout
.Palette
.clear();
2276 aLayout
.IsMsbFirst
= sal_False
;
2282 bool CanvasHelper::repaint( const SurfaceSharedPtr
& pSurface
,
2283 const rendering::ViewState
& viewState
,
2284 const rendering::RenderState
& renderState
)
2286 SAL_INFO( "canvas.cairo", "CanvasHelper::repaint");
2290 cairo_save( mpCairo
.get() );
2292 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
2293 cairo_clip( mpCairo
.get() );
2295 useStates( viewState
, renderState
, true );
2297 cairo_matrix_t aMatrix
;
2299 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
2300 aMatrix
.xx
= aMatrix
.yy
= 1;
2301 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
2303 cairo_set_source_surface( mpCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
2304 cairo_paint( mpCairo
.get() );
2305 cairo_restore( mpCairo
.get() );
2312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */