1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cairo_canvashelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
37 #include <rtl/logfile.hxx>
38 #include <rtl/math.hxx>
39 #include <rtl/instance.hxx>
41 #include <com/sun/star/util/Endianness.hpp>
42 #include <com/sun/star/rendering/TexturingMode.hpp>
43 #include <com/sun/star/rendering/CompositeOperation.hpp>
44 #include <com/sun/star/rendering/RepaintResult.hpp>
45 #include <com/sun/star/rendering/PathCapType.hpp>
46 #include <com/sun/star/rendering/PathJoinType.hpp>
47 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
48 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
49 #include <com/sun/star/rendering/ColorSpaceType.hpp>
50 #include <com/sun/star/rendering/ColorComponentTag.hpp>
51 #include <com/sun/star/rendering/RenderingIntent.hpp>
53 #include <basegfx/matrix/b2dhommatrix.hxx>
54 #include <basegfx/point/b2dpoint.hxx>
55 #include <basegfx/polygon/b2dpolygon.hxx>
56 #include <basegfx/polygon/b2dpolypolygon.hxx>
57 #include <basegfx/polygon/b2dpolygontools.hxx>
58 #include <basegfx/tools/canvastools.hxx>
60 #include <comphelper/sequence.hxx>
61 #include <cppuhelper/compbase1.hxx>
63 #include <canvas/canvastools.hxx>
64 #include <canvas/parametricpolypolygon.hxx>
66 #include <vcl/canvastools.hxx>
67 #include <vcl/bitmapex.hxx>
68 #include <vcl/bmpacc.hxx>
69 #include <vcl/virdev.hxx>
71 #include "cairo_spritecanvas.hxx"
72 #include "cairo_cachedbitmap.hxx"
73 #include "cairo_canvashelper.hxx"
74 #include "cairo_canvasbitmap.hxx"
78 using namespace ::cairo
;
79 using namespace ::com::sun::star
;
83 CanvasHelper::CanvasHelper() :
84 mpSurfaceProvider(NULL
),
94 void CanvasHelper::disposing()
98 mpVirtualDevice
.reset();
100 mpSurfaceProvider
= NULL
;
103 void CanvasHelper::init( const ::basegfx::B2ISize
& rSizePixel
,
104 SurfaceProvider
& rSurfaceProvider
,
105 rendering::XGraphicDevice
* pDevice
)
108 mpSurfaceProvider
= &rSurfaceProvider
;
112 void CanvasHelper::setSize( const ::basegfx::B2ISize
& rSize
)
117 void CanvasHelper::setSurface( const SurfaceSharedPtr
& pSurface
, bool bHasAlpha
)
119 mbHaveAlpha
= bHasAlpha
;
120 mpVirtualDevice
.reset();
121 mpSurface
= pSurface
;
122 mpCairo
= pSurface
->getCairo();
125 void CanvasHelper::useStates( const rendering::ViewState
& viewState
,
126 const rendering::RenderState
& renderState
,
130 Matrix aRenderMatrix
;
131 Matrix aCombinedMatrix
;
133 cairo_matrix_init( &aViewMatrix
,
134 viewState
.AffineTransform
.m00
, viewState
.AffineTransform
.m10
, viewState
.AffineTransform
.m01
,
135 viewState
.AffineTransform
.m11
, viewState
.AffineTransform
.m02
, viewState
.AffineTransform
.m12
);
136 cairo_matrix_init( &aRenderMatrix
,
137 renderState
.AffineTransform
.m00
, renderState
.AffineTransform
.m10
, renderState
.AffineTransform
.m01
,
138 renderState
.AffineTransform
.m11
, renderState
.AffineTransform
.m02
, renderState
.AffineTransform
.m12
);
139 cairo_matrix_multiply( &aCombinedMatrix
, &aRenderMatrix
, &aViewMatrix
);
141 if( viewState
.Clip
.is() ) {
142 OSL_TRACE ("view clip");
144 aViewMatrix
.x0
= basegfx::fround( aViewMatrix
.x0
);
145 aViewMatrix
.y0
= basegfx::fround( aViewMatrix
.y0
);
146 cairo_set_matrix( mpCairo
.get(), &aViewMatrix
);
147 doPolyPolygonPath( viewState
.Clip
, Clip
);
150 aCombinedMatrix
.x0
= basegfx::fround( aCombinedMatrix
.x0
);
151 aCombinedMatrix
.y0
= basegfx::fround( aCombinedMatrix
.y0
);
152 cairo_set_matrix( mpCairo
.get(), &aCombinedMatrix
);
154 if( renderState
.Clip
.is() ) {
155 OSL_TRACE ("render clip BEGIN");
157 doPolyPolygonPath( renderState
.Clip
, Clip
);
158 OSL_TRACE ("render clip END");
162 if( renderState
.DeviceColor
.getLength() > 3 )
163 cairo_set_source_rgba( mpCairo
.get(),
164 renderState
.DeviceColor
[0],
165 renderState
.DeviceColor
[1],
166 renderState
.DeviceColor
[2],
167 renderState
.DeviceColor
[3] );
168 else if (renderState
.DeviceColor
.getLength() == 3)
169 cairo_set_source_rgb( mpCairo
.get(),
170 renderState
.DeviceColor
[0],
171 renderState
.DeviceColor
[1],
172 renderState
.DeviceColor
[2] );
175 cairo_operator_t
compositingMode( CAIRO_OPERATOR_OVER
);
176 switch( renderState
.CompositeOperation
)
178 case rendering::CompositeOperation::CLEAR
:
179 compositingMode
= CAIRO_OPERATOR_CLEAR
;
181 case rendering::CompositeOperation::SOURCE
:
182 compositingMode
= CAIRO_OPERATOR_SOURCE
;
184 case rendering::CompositeOperation::DESTINATION
:
185 compositingMode
= CAIRO_OPERATOR_DEST
;
187 case rendering::CompositeOperation::OVER
:
188 compositingMode
= CAIRO_OPERATOR_OVER
;
190 case rendering::CompositeOperation::UNDER
:
191 compositingMode
= CAIRO_OPERATOR_DEST
;
193 case rendering::CompositeOperation::INSIDE
:
194 compositingMode
= CAIRO_OPERATOR_IN
;
196 case rendering::CompositeOperation::INSIDE_REVERSE
:
197 compositingMode
= CAIRO_OPERATOR_OUT
;
199 case rendering::CompositeOperation::OUTSIDE
:
200 compositingMode
= CAIRO_OPERATOR_DEST_OVER
;
202 case rendering::CompositeOperation::OUTSIDE_REVERSE
:
203 compositingMode
= CAIRO_OPERATOR_DEST_OUT
;
205 case rendering::CompositeOperation::ATOP
:
206 compositingMode
= CAIRO_OPERATOR_ATOP
;
208 case rendering::CompositeOperation::ATOP_REVERSE
:
209 compositingMode
= CAIRO_OPERATOR_DEST_ATOP
;
211 case rendering::CompositeOperation::XOR
:
212 compositingMode
= CAIRO_OPERATOR_XOR
;
214 case rendering::CompositeOperation::ADD
:
215 compositingMode
= CAIRO_OPERATOR_ADD
;
217 case rendering::CompositeOperation::SATURATE
:
218 compositingMode
= CAIRO_OPERATOR_SATURATE
;
221 cairo_set_operator( mpCairo
.get(), compositingMode
);
224 void CanvasHelper::clear()
226 OSL_TRACE ("clear whole area: %d x %d", maSize
.getX(), maSize
.getY() );
230 cairo_save( mpCairo
.get() );
232 cairo_identity_matrix( mpCairo
.get() );
233 // this does not really differ from all-zero, as cairo
234 // internally converts to premultiplied alpha. but anyway,
235 // this keeps it consistent with the other canvas impls
237 cairo_set_source_rgba( mpCairo
.get(), 1.0, 1.0, 1.0, 0.0 );
239 cairo_set_source_rgb( mpCairo
.get(), 1.0, 1.0, 1.0 );
240 cairo_set_operator( mpCairo
.get(), CAIRO_OPERATOR_SOURCE
);
242 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
243 cairo_fill( mpCairo
.get() );
245 cairo_restore( mpCairo
.get() );
249 void CanvasHelper::drawPoint( const rendering::XCanvas
* ,
250 const geometry::RealPoint2D
& ,
251 const rendering::ViewState
& ,
252 const rendering::RenderState
& )
256 void CanvasHelper::drawLine( const rendering::XCanvas
* /*pCanvas*/,
257 const geometry::RealPoint2D
& aStartPoint
,
258 const geometry::RealPoint2D
& aEndPoint
,
259 const rendering::ViewState
& viewState
,
260 const rendering::RenderState
& renderState
)
263 cairo_save( mpCairo
.get() );
265 cairo_set_line_width( mpCairo
.get(), 1 );
267 useStates( viewState
, renderState
, true );
269 cairo_move_to( mpCairo
.get(), aStartPoint
.X
+ 0.5, aStartPoint
.Y
+ 0.5 );
270 cairo_line_to( mpCairo
.get(), aEndPoint
.X
+ 0.5, aEndPoint
.Y
+ 0.5 );
271 cairo_stroke( mpCairo
.get() );
273 cairo_restore( mpCairo
.get() );
277 void CanvasHelper::drawBezier( const rendering::XCanvas
* ,
278 const geometry::RealBezierSegment2D
& aBezierSegment
,
279 const geometry::RealPoint2D
& aEndPoint
,
280 const rendering::ViewState
& viewState
,
281 const rendering::RenderState
& renderState
)
284 cairo_save( mpCairo
.get() );
286 cairo_set_line_width( mpCairo
.get(), 1 );
288 useStates( viewState
, renderState
, true );
290 cairo_move_to( mpCairo
.get(), aBezierSegment
.Px
+ 0.5, aBezierSegment
.Py
+ 0.5 );
291 cairo_curve_to( mpCairo
.get(),
292 aBezierSegment
.C1x
+ 0.5, aBezierSegment
.C1y
+ 0.5,
293 aBezierSegment
.C2x
+ 0.5, aBezierSegment
.C2y
+ 0.5,
294 aEndPoint
.X
+ 0.5, aEndPoint
.Y
+ 0.5 );
295 cairo_stroke( mpCairo
.get() );
297 cairo_restore( mpCairo
.get() );
301 #define CANVASBITMAP_IMPLEMENTATION_NAME "CairoCanvas::CanvasBitmap"
302 #define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon"
305 /** surfaceFromXBitmap Create a surface from XBitmap
306 * @param xBitmap bitmap image that will be used for the surface
307 * @param bHasAlpha will be set to true if resulting surface has alpha
309 * This is a helper function for the other surfaceFromXBitmap().
310 * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas.
312 * @return created surface or NULL
314 static SurfaceSharedPtr
surfaceFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
)
316 CanvasBitmap
* pBitmapImpl
= dynamic_cast< CanvasBitmap
* >( xBitmap
.get() );
318 return pBitmapImpl
->getSurface();
320 SurfaceProvider
* pSurfaceProvider
= dynamic_cast<SurfaceProvider
*>( xBitmap
.get() );
321 if( pSurfaceProvider
)
322 return pSurfaceProvider
->getSurface();
324 return SurfaceSharedPtr();
327 static ::BitmapEx
bitmapExFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
)
329 // TODO(F1): Add support for floating point bitmap formats
330 uno::Reference
<rendering::XIntegerReadOnlyBitmap
> xIntBmp(xBitmap
,
331 uno::UNO_QUERY_THROW
);
332 ::BitmapEx aBmpEx
= ::vcl::unotools::bitmapExFromXBitmap(xIntBmp
);
336 // TODO(F1): extract pixel from XBitmap interface
337 ENSURE_OR_THROW( false,
338 "bitmapExFromXBitmap(): could not extract BitmapEx" );
343 static bool readAlpha( BitmapReadAccess
* pAlphaReadAcc
, long nY
, const long nWidth
, unsigned char* data
, long nOff
)
345 bool bIsAlpha
= false;
352 switch( pAlphaReadAcc
->GetScanlineFormat() ) {
353 case BMP_FORMAT_8BIT_TC_MASK
:
354 pReadScan
= pAlphaReadAcc
->GetScanline( nY
);
355 for( nX
= 0; nX
< nWidth
; nX
++ ) {
356 nAlpha
= data
[ nOff
] = 255 - ( *pReadScan
++ );
362 case BMP_FORMAT_8BIT_PAL
:
363 pReadScan
= pAlphaReadAcc
->GetScanline( nY
);
364 for( nX
= 0; nX
< nWidth
; nX
++ ) {
365 nAlpha
= data
[ nOff
] = 255 - ( pAlphaReadAcc
->GetPaletteColor( *pReadScan
++ ).GetBlue() );
372 OSL_TRACE( "fallback to GetColor for alpha - slow, format: %d", pAlphaReadAcc
->GetScanlineFormat() );
373 for( nX
= 0; nX
< nWidth
; nX
++ ) {
374 nAlpha
= data
[ nOff
] = 255 - pAlphaReadAcc
->GetColor( nY
, nX
).GetBlue();
385 /** surfaceFromXBitmap Create a surface from XBitmap
386 * @param xBitmap bitmap image that will be used for the surface
387 * @param rDevice reference to the device into which we want to draw
388 * @param data will be filled with alpha data, if xBitmap is alpha/transparent image
389 * @param bHasAlpha will be set to true if resulting surface has alpha
391 * This function tries various methods for creating a surface from xBitmap. It also uses
392 * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha )
394 * @return created surface or NULL
396 static SurfaceSharedPtr
surfaceFromXBitmap( const uno::Reference
< rendering::XBitmap
>& xBitmap
, const SurfaceProviderRef
& rSurfaceProvider
, unsigned char*& data
, bool& bHasAlpha
)
398 bHasAlpha
= xBitmap
->hasAlpha();
399 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( xBitmap
);
404 ::BitmapEx aBmpEx
= bitmapExFromXBitmap(xBitmap
);
405 ::Bitmap aBitmap
= aBmpEx
.GetBitmap();
407 // there's no pixmap for alpha bitmap. we might still
408 // use rgb pixmap and only access alpha pixels the
409 // slow way. now we just speedup rgb bitmaps
410 if( !aBmpEx
.IsTransparent() && !aBmpEx
.IsAlpha() ) {
411 pSurface
= rSurfaceProvider
->createSurface( aBitmap
);
417 AlphaMask aAlpha
= aBmpEx
.GetAlpha();
419 ::BitmapReadAccess
* pBitmapReadAcc
= aBitmap
.AcquireReadAccess();
420 ::BitmapReadAccess
* pAlphaReadAcc
= NULL
;
421 const long nWidth
= pBitmapReadAcc
->Width();
422 const long nHeight
= pBitmapReadAcc
->Height();
424 bool bIsAlpha
= false;
426 if( aBmpEx
.IsTransparent() || aBmpEx
.IsAlpha() )
427 pAlphaReadAcc
= aAlpha
.AcquireReadAccess();
429 data
= (unsigned char*) malloc( nWidth
*nHeight
*4 );
433 unsigned int nAlpha
= 255;
435 for( nY
= 0; nY
< nHeight
; nY
++ ) {
436 ::Scanline pReadScan
;
438 switch( pBitmapReadAcc
->GetScanlineFormat() ) {
439 case BMP_FORMAT_8BIT_PAL
:
440 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
442 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
445 for( nX
= 0; nX
< nWidth
; nX
++ ) {
448 nAlpha
= data
[ nOff
++ ];
450 nAlpha
= data
[ nOff
++ ] = 255;
453 nAlpha
= data
[ nOff
+ 3 ];
455 nAlpha
= data
[ nOff
+ 3 ] = 255;
457 aColor
= pBitmapReadAcc
->GetPaletteColor( *pReadScan
++ );
460 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetRed() ) )/255 );
461 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetGreen() ) )/255 );
462 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetBlue() ) )/255 );
464 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetBlue() ) )/255 );
465 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetGreen() ) )/255 );
466 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( aColor
.GetRed() ) )/255 );
471 case BMP_FORMAT_24BIT_TC_BGR
:
472 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
474 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
477 for( nX
= 0; nX
< nWidth
; nX
++ ) {
480 nAlpha
= data
[ nOff
];
482 nAlpha
= data
[ nOff
] = 255;
483 data
[ nOff
+ 3 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
484 data
[ nOff
+ 2 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
485 data
[ nOff
+ 1 ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
489 nAlpha
= data
[ nOff
+ 3 ];
491 nAlpha
= data
[ nOff
+ 3 ] = 255;
492 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
493 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
494 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
499 case BMP_FORMAT_24BIT_TC_RGB
:
500 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
502 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
505 for( nX
= 0; nX
< nWidth
; nX
++ ) {
508 nAlpha
= data
[ nOff
++ ];
510 nAlpha
= data
[ nOff
++ ] = 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 );
516 nAlpha
= data
[ nOff
+ 3 ];
518 nAlpha
= data
[ nOff
+ 3 ] = 255;
519 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 2 ] ) )/255 );
520 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 1 ] ) )/255 );
521 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 0 ] ) )/255 );
527 case BMP_FORMAT_32BIT_TC_BGRA
:
528 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
530 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
533 for( nX
= 0; nX
< nWidth
; nX
++ ) {
536 nAlpha
= data
[ nOff
++ ];
538 nAlpha
= data
[ nOff
++ ] = pReadScan
[ 3 ];
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 );
545 nAlpha
= data
[ nOff
+ 3 ];
547 nAlpha
= data
[ nOff
+ 3 ] = pReadScan
[ 3 ];
548 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
549 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
550 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/255 );
556 case BMP_FORMAT_32BIT_TC_RGBA
:
557 pReadScan
= pBitmapReadAcc
->GetScanline( nY
);
559 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
562 for( nX
= 0; nX
< nWidth
; nX
++ ) {
565 nAlpha
= data
[ nOff
++ ];
567 nAlpha
= data
[ nOff
++ ] = 255;
568 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( *pReadScan
++ ) )/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 );
574 nAlpha
= data
[ nOff
+ 3 ];
576 nAlpha
= data
[ nOff
+ 3 ] = 255;
577 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 2 ] ) )/255 );
578 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 1 ] ) )/255 );
579 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*( pReadScan
[ 0 ] ) )/255 );
586 OSL_TRACE( "fallback to GetColor - slow, format: %d", pBitmapReadAcc
->GetScanlineFormat() );
589 if( readAlpha( pAlphaReadAcc
, nY
, nWidth
, data
, nOff
) )
592 for( nX
= 0; nX
< nWidth
; nX
++ ) {
593 aColor
= pBitmapReadAcc
->GetColor( nY
, nX
);
595 // cairo need premultiplied color values
596 // TODO(rodo) handle endianess
599 nAlpha
= data
[ nOff
++ ];
601 nAlpha
= data
[ nOff
++ ] = 255;
602 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetRed() )/255 );
603 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetGreen() )/255 );
604 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetBlue() )/255 );
607 nAlpha
= data
[ nOff
+ 3 ];
609 nAlpha
= data
[ nOff
+ 3 ] = 255;
610 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetBlue() )/255 );
611 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetGreen() )/255 );
612 data
[ nOff
++ ] = sal::static_int_cast
<unsigned char>(( nAlpha
*aColor
.GetRed() )/255 );
619 aBitmap
.ReleaseAccess( pBitmapReadAcc
);
621 aAlpha
.ReleaseAccess( pAlphaReadAcc
);
623 SurfaceSharedPtr pImageSurface
= createSurface(
624 CairoSurfaceSharedPtr(
625 cairo_image_surface_create_for_data(
627 bIsAlpha
? CAIRO_FORMAT_ARGB32
: CAIRO_FORMAT_RGB24
,
628 nWidth
, nHeight
, nWidth
*4 ),
629 &cairo_surface_destroy
) );
631 // pSurface = rSurfaceProvider->getSurface( ::basegfx::B2ISize( nWidth, nHeight ), bIsAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
632 // Cairo* pTargetCairo = cairo_create( pSurface );
633 // cairo_set_source_surface( pTargetCairo, pImageSurface, 0, 0 );
636 // //cairo_set_operator( pTargetCairo, CAIRO_OPERATOR_SOURCE );
638 // cairo_paint( pTargetCairo );
639 // cairo_destroy( pTargetCairo );
640 // cairo_surface_destroy( pImageSurface );
641 pSurface
= pImageSurface
;
643 bHasAlpha
= bIsAlpha
;
645 OSL_TRACE("image: %d x %d alpha: %d alphaRead %p", nWidth
, nHeight
, bIsAlpha
, pAlphaReadAcc
);
652 static void addColorStops( Pattern
* pPattern
, const uno::Sequence
< uno::Sequence
< double > >& rColors
, const uno::Sequence
< double >& rStops
, bool bReverseStops
= false )
657 OSL_ASSERT( rColors
.getLength() == rStops
.getLength() );
659 for( i
= 0; i
< rColors
.getLength(); i
++ ) {
660 const uno::Sequence
< double >& rColor( rColors
[i
] );
661 stop
= bReverseStops
? 1 - rStops
[i
] : rStops
[i
];
662 if( rColor
.getLength() == 3 )
663 cairo_pattern_add_color_stop_rgb( pPattern
, stop
, rColor
[0], rColor
[1], rColor
[2] );
664 else if( rColor
.getLength() == 4 ) {
665 double alpha
= rColor
[3];
666 // cairo expects premultiplied alpha
667 cairo_pattern_add_color_stop_rgba( pPattern
, stop
, rColor
[0]*alpha
, rColor
[1]*alpha
, rColor
[2]*alpha
, alpha
);
668 //cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0], rColor[1], rColor[2], alpha );
673 static Pattern
* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon
& rPolygon
)
675 Pattern
* pPattern
= NULL
;
676 const ::canvas::ParametricPolyPolygon::Values aValues
= rPolygon
.getValues();
677 double x0
, x1
, y0
, y1
, cx
, cy
, r0
, r1
;
679 // undef macros from vclenum.hxx which conflicts with GradientType enum values
680 #undef GRADIENT_LINEAR
681 #undef GRADIENT_AXIAL
682 #undef GRADIENT_ELLIPTICAL
684 switch( aValues
.meType
) {
685 case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR
:
690 pPattern
= cairo_pattern_create_linear( x0
, y0
, x1
, y1
);
691 addColorStops( pPattern
, aValues
.maColors
, aValues
.maStops
);
695 case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR
:
696 case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL
:
701 pPattern
= cairo_pattern_create_linear( x0
, y0
, x1
, y1
);
702 addColorStops( pPattern
, aValues
.maColors
, aValues
.maStops
);
705 case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL
:
711 pPattern
= cairo_pattern_create_radial( cx
, cy
, r0
, cx
, cy
, r1
);
712 addColorStops( pPattern
, aValues
.maColors
, aValues
.maStops
, true );
719 static void doOperation( Operation aOperation
,
721 const uno::Sequence
< rendering::Texture
>* pTextures
,
722 const SurfaceProviderRef
& pDevice
)
724 switch( aOperation
) {
726 /* TODO: multitexturing */
728 const ::com::sun::star::rendering::Texture
& aTexture ( (*pTextures
)[0] );
729 if( aTexture
.Bitmap
.is() ) {
730 unsigned char* data
= NULL
;
731 bool bHasAlpha
= false;
732 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( (*pTextures
)[0].Bitmap
, pDevice
, data
, bHasAlpha
);
735 cairo_pattern_t
* pPattern
;
737 cairo_save( pCairo
);
739 ::com::sun::star::geometry::AffineMatrix2D
aTransform( aTexture
.AffineTransform
);
740 Matrix aScaleMatrix
, aTextureMatrix
, aScaledTextureMatrix
;
742 cairo_matrix_init( &aTextureMatrix
,
743 aTransform
.m00
, aTransform
.m10
, aTransform
.m01
,
744 aTransform
.m11
, aTransform
.m02
, aTransform
.m12
);
746 geometry::IntegerSize2D aSize
= aTexture
.Bitmap
->getSize();
748 cairo_matrix_init_scale( &aScaleMatrix
, 1.0/aSize
.Width
, 1.0/aSize
.Height
);
749 cairo_matrix_multiply( &aScaledTextureMatrix
, &aTextureMatrix
, &aScaleMatrix
);
750 cairo_matrix_invert( &aScaledTextureMatrix
);
752 // we don't care about repeat mode yet, so the workaround is disabled for now
753 pPattern
= cairo_pattern_create_for_surface( pSurface
->getCairoSurface().get() );
755 if( aTexture
.RepeatModeX
== rendering::TexturingMode::REPEAT
&&
756 aTexture
.RepeatModeY
== rendering::TexturingMode::REPEAT
)
757 cairo_pattern_set_extend( pPattern
, CAIRO_EXTEND_REPEAT
);
758 aScaledTextureMatrix
.x0
= basegfx::fround( aScaledTextureMatrix
.x0
);
759 aScaledTextureMatrix
.y0
= basegfx::fround( aScaledTextureMatrix
.y0
);
760 cairo_pattern_set_matrix( pPattern
, &aScaledTextureMatrix
);
762 cairo_set_source( pCairo
, pPattern
);
764 cairo_set_operator( pCairo
, CAIRO_OPERATOR_SOURCE
);
765 cairo_fill( pCairo
);
767 cairo_restore( pCairo
);
769 cairo_pattern_destroy( pPattern
);
774 } else if( aTexture
.Gradient
.is() ) {
775 uno::Reference
< lang::XServiceInfo
> xRef( aTexture
.Gradient
, uno::UNO_QUERY
);
777 OSL_TRACE( "gradient fill" );
779 xRef
->getImplementationName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME
) ) ) ) {
780 // TODO(Q1): Maybe use dynamic_cast here
782 // TODO(E1): Return value
783 // TODO(F1): FillRule
784 OSL_TRACE( "known implementation" );
786 ::canvas::ParametricPolyPolygon
* pPolyImpl
= static_cast< ::canvas::ParametricPolyPolygon
* >( aTexture
.Gradient
.get() );
787 ::com::sun::star::geometry::AffineMatrix2D
aTransform( aTexture
.AffineTransform
);
788 Matrix aTextureMatrix
;
790 cairo_matrix_init( &aTextureMatrix
,
791 aTransform
.m00
, aTransform
.m10
, aTransform
.m01
,
792 aTransform
.m11
, aTransform
.m02
, aTransform
.m12
);
793 Pattern
* pPattern
= patternFromParametricPolyPolygon( *pPolyImpl
);
796 OSL_TRACE( "filling with pattern" );
798 cairo_save( pCairo
);
800 cairo_transform( pCairo
, &aTextureMatrix
);
801 cairo_set_source( pCairo
, pPattern
);
802 cairo_fill( pCairo
);
803 cairo_restore( pCairo
);
805 cairo_pattern_destroy( pPattern
);
810 cairo_fill( pCairo
);
814 cairo_stroke( pCairo
);
818 cairo_clip( pCairo
);
824 static void clipNULL( Cairo
*pCairo
)
826 OSL_TRACE("clipNULL");
827 Matrix aOrigMatrix
, aIdentityMatrix
;
829 /* we set identity matrix here to overcome bug in cairo 0.9.2
830 where XCreatePixmap is called with zero width and height.
832 it also reaches faster path in cairo clipping code.
834 cairo_matrix_init_identity( &aIdentityMatrix
);
835 cairo_get_matrix( pCairo
, &aOrigMatrix
);
836 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
838 cairo_reset_clip( pCairo
);
839 cairo_rectangle( pCairo
, 0, 0, 1, 1 );
840 cairo_clip( pCairo
);
841 cairo_rectangle( pCairo
, 2, 0, 1, 1 );
842 cairo_clip( pCairo
);
844 /* restore the original matrix */
845 cairo_set_matrix( pCairo
, &aOrigMatrix
);
848 void doPolyPolygonImplementation( ::basegfx::B2DPolyPolygon aPolyPolygon
,
849 Operation aOperation
,
851 const uno::Sequence
< rendering::Texture
>* pTextures
,
852 const SurfaceProviderRef
& pDevice
,
853 rendering::FillRule eFillrule
)
856 ENSURE_ARG_OR_THROW( pTextures
->getLength(),
857 "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
859 bool bOpToDo
= false;
860 Matrix aOrigMatrix
, aIdentityMatrix
;
861 double nX
, nY
, nBX
, nBY
, nAX
, nAY
;
863 cairo_get_matrix( pCairo
, &aOrigMatrix
);
864 cairo_matrix_init_identity( &aIdentityMatrix
);
865 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
867 cairo_set_fill_rule( pCairo
,
868 eFillrule
== rendering::FillRule_EVEN_ODD
?
869 CAIRO_FILL_RULE_EVEN_ODD
: CAIRO_FILL_RULE_WINDING
);
871 for( sal_uInt32 nPolygonIndex
= 0; nPolygonIndex
< aPolyPolygon
.count(); nPolygonIndex
++ ) {
872 ::basegfx::B2DPolygon
aPolygon( aPolyPolygon
.getB2DPolygon( nPolygonIndex
) );
873 const sal_uInt32
nPointCount( aPolygon
.count() );
874 // to correctly render closed curves, need to output first
875 // point twice (so output one additional point)
876 const sal_uInt32
nExtendedPointCount( nPointCount
+
877 aPolygon
.isClosed()*aPolygon
.areControlPointsUsed() );
879 if( nPointCount
> 1) {
880 bool bIsBezier
= aPolygon
.areControlPointsUsed();
881 bool bIsRectangle
= ::basegfx::tools::isRectangle( aPolygon
);
882 ::basegfx::B2DPoint aA
, aB
, aP
;
884 for( sal_uInt32 j
=0; j
< nExtendedPointCount
; j
++ ) {
885 aP
= aPolygon
.getB2DPoint( j
% nPointCount
);
889 cairo_matrix_transform_point( &aOrigMatrix
, &nX
, &nY
);
891 if( ! bIsBezier
&& (bIsRectangle
|| aOperation
== Clip
) ) {
892 nX
= basegfx::fround( nX
);
893 nY
= basegfx::fround( nY
);
896 if( aOperation
== Stroke
) {
903 cairo_move_to( pCairo
, nX
, nY
);
904 OSL_TRACE( "move to %f,%f", nX
, nY
);
908 aA
= aPolygon
.getNextControlPoint( (j
-1) % nPointCount
);
909 aB
= aPolygon
.getPrevControlPoint( j
% nPointCount
);
916 if( aOperation
== Stroke
) {
922 cairo_matrix_transform_point( &aOrigMatrix
, &nAX
, &nAY
);
923 cairo_matrix_transform_point( &aOrigMatrix
, &nBX
, &nBY
);
924 cairo_curve_to( pCairo
, nAX
, nAY
, nBX
, nBY
, nX
, nY
);
926 cairo_line_to( pCairo
, nX
, nY
);
927 OSL_TRACE( "line to %f,%f", nX
, nY
);
933 if( aPolygon
.isClosed() )
934 cairo_close_path( pCairo
);
936 if( aOperation
== Fill
&& pTextures
) {
937 cairo_set_matrix( pCairo
, &aOrigMatrix
);
938 doOperation( aOperation
, pCairo
, pTextures
, pDevice
);
939 cairo_set_matrix( pCairo
, &aIdentityMatrix
);
942 OSL_TRACE( "empty polygon for op: %d\n", aOperation
);
943 if( aOperation
== Clip
) {
950 if( bOpToDo
&& ( aOperation
!= Fill
|| !pTextures
) )
951 doOperation( aOperation
, pCairo
, pTextures
, pDevice
);
953 cairo_set_matrix( pCairo
, &aOrigMatrix
);
955 if( aPolyPolygon
.count() == 0 && aOperation
== Clip
)
959 void CanvasHelper::doPolyPolygonPath( const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
960 Operation aOperation
,
961 const uno::Sequence
< rendering::Texture
>* pTextures
,
962 Cairo
* pCairo
) const
964 const ::basegfx::B2DPolyPolygon
& rPolyPoly(
965 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon
) );
968 pCairo
= mpCairo
.get();
970 doPolyPolygonImplementation( rPolyPoly
, aOperation
,
973 xPolyPolygon
->getFillRule() );
976 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawPolyPolygon( const rendering::XCanvas
* ,
977 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
978 const rendering::ViewState
& viewState
,
979 const rendering::RenderState
& renderState
)
981 #ifdef CAIRO_CANVAS_PERF_TRACE
982 struct timespec aTimer
;
983 mxDevice
->startPerfTrace( &aTimer
);
987 cairo_save( mpCairo
.get() );
989 cairo_set_line_width( mpCairo
.get(), 1 );
991 useStates( viewState
, renderState
, true );
992 doPolyPolygonPath( xPolyPolygon
, Stroke
);
994 cairo_restore( mpCairo
.get() );
996 OSL_TRACE ("CanvasHelper called after it was disposed");
998 #ifdef CAIRO_CANVAS_PERF_TRACE
999 mxDevice
->stopPerfTrace( &aTimer
, "drawPolyPolygon" );
1002 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1005 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokePolyPolygon( const rendering::XCanvas
* ,
1006 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1007 const rendering::ViewState
& viewState
,
1008 const rendering::RenderState
& renderState
,
1009 const rendering::StrokeAttributes
& strokeAttributes
)
1011 #ifdef CAIRO_CANVAS_PERF_TRACE
1012 struct timespec aTimer
;
1013 mxDevice
->startPerfTrace( &aTimer
);
1017 cairo_save( mpCairo
.get() );
1019 useStates( viewState
, renderState
, true );
1022 double w
= strokeAttributes
.StrokeWidth
, h
= 0;
1023 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
1024 cairo_matrix_transform_distance( &aMatrix
, &w
, &h
);
1025 cairo_set_line_width( mpCairo
.get(), w
);
1027 cairo_set_miter_limit( mpCairo
.get(), strokeAttributes
.MiterLimit
);
1029 // FIXME: cairo doesn't handle end cap so far (rodo)
1030 switch( strokeAttributes
.StartCapType
) {
1031 case rendering::PathCapType::BUTT
:
1032 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_BUTT
);
1034 case rendering::PathCapType::ROUND
:
1035 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_ROUND
);
1037 case rendering::PathCapType::SQUARE
:
1038 cairo_set_line_cap( mpCairo
.get(), CAIRO_LINE_CAP_SQUARE
);
1042 switch( strokeAttributes
.JoinType
) {
1043 // cairo doesn't have join type NONE so we use MITER as it's pretty close
1044 case rendering::PathJoinType::NONE
:
1045 case rendering::PathJoinType::MITER
:
1046 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_MITER
);
1048 case rendering::PathJoinType::ROUND
:
1049 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_ROUND
);
1051 case rendering::PathJoinType::BEVEL
:
1052 cairo_set_line_join( mpCairo
.get(), CAIRO_LINE_JOIN_BEVEL
);
1056 if( strokeAttributes
.DashArray
.getLength() > 0 ) {
1057 double* pDashArray
= new double[ strokeAttributes
.DashArray
.getLength() ];
1058 for( sal_Int32 i
=0; i
<strokeAttributes
.DashArray
.getLength(); i
++ )
1059 pDashArray
[i
]=strokeAttributes
.DashArray
[i
];
1060 cairo_set_dash( mpCairo
.get(), pDashArray
, strokeAttributes
.DashArray
.getLength(), 0 );
1061 delete[] pDashArray
;
1064 // TODO(rodo) use LineArray of strokeAttributes
1066 doPolyPolygonPath( xPolyPolygon
, Stroke
);
1068 cairo_restore( mpCairo
.get() );
1070 OSL_TRACE ("CanvasHelper called after it was disposed");
1072 #ifdef CAIRO_CANVAS_PERF_TRACE
1073 mxDevice
->stopPerfTrace( &aTimer
, "strokePolyPolygon" );
1076 // TODO(P1): Provide caching here.
1077 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1080 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas
* ,
1081 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1082 const rendering::ViewState
& /*viewState*/,
1083 const rendering::RenderState
& /*renderState*/,
1084 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1085 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1088 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1091 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas
* ,
1092 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1093 const rendering::ViewState
& /*viewState*/,
1094 const rendering::RenderState
& /*renderState*/,
1095 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1096 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/,
1097 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1100 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1103 uno::Reference
< rendering::XPolyPolygon2D
> CanvasHelper::queryStrokeShapes( const rendering::XCanvas
* ,
1104 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1105 const rendering::ViewState
& /*viewState*/,
1106 const rendering::RenderState
& /*renderState*/,
1107 const rendering::StrokeAttributes
& /*strokeAttributes*/ )
1110 return uno::Reference
< rendering::XPolyPolygon2D
>(NULL
);
1113 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillPolyPolygon( const rendering::XCanvas
* ,
1114 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1115 const rendering::ViewState
& viewState
,
1116 const rendering::RenderState
& renderState
)
1118 #ifdef CAIRO_CANVAS_PERF_TRACE
1119 struct timespec aTimer
;
1120 mxDevice
->startPerfTrace( &aTimer
);
1124 cairo_save( mpCairo
.get() );
1126 useStates( viewState
, renderState
, true );
1127 doPolyPolygonPath( xPolyPolygon
, Fill
);
1129 cairo_restore( mpCairo
.get() );
1131 OSL_TRACE ("CanvasHelper called after it was disposed");
1133 #ifdef CAIRO_CANVAS_PERF_TRACE
1134 mxDevice
->stopPerfTrace( &aTimer
, "fillPolyPolygon" );
1137 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1140 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas
* ,
1141 const uno::Reference
< rendering::XPolyPolygon2D
>& xPolyPolygon
,
1142 const rendering::ViewState
& viewState
,
1143 const rendering::RenderState
& renderState
,
1144 const uno::Sequence
< rendering::Texture
>& textures
)
1147 cairo_save( mpCairo
.get() );
1149 useStates( viewState
, renderState
, true );
1150 doPolyPolygonPath( xPolyPolygon
, Fill
, &textures
);
1152 cairo_restore( mpCairo
.get() );
1155 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1158 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas
* ,
1159 const uno::Reference
< rendering::XPolyPolygon2D
>& /*xPolyPolygon*/,
1160 const rendering::ViewState
& /*viewState*/,
1161 const rendering::RenderState
& /*renderState*/,
1162 const uno::Sequence
< rendering::Texture
>& /*textures*/,
1163 const uno::Reference
< geometry::XMapping2D
>& /*xMapping*/ )
1166 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1169 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::implDrawBitmapSurface( const rendering::XCanvas
* pCanvas
,
1170 const SurfaceSharedPtr
& pInputSurface
,
1171 const rendering::ViewState
& viewState
,
1172 const rendering::RenderState
& renderState
,
1173 const geometry::IntegerSize2D
& rSize
,
1174 bool /*bModulateColors*/,
1177 SurfaceSharedPtr pSurface
=pInputSurface
;
1178 uno::Reference
< rendering::XCachedPrimitive
> rv
= uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1179 geometry::IntegerSize2D aBitmapSize
= rSize
;
1182 cairo_save( mpCairo
.get() );
1184 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
1185 cairo_clip( mpCairo
.get() );
1187 useStates( viewState
, renderState
, true );
1190 // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
1194 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
1195 if( ! ::rtl::math::approxEqual( aMatrix
.xx
, 1 ) &&
1196 ! ::rtl::math::approxEqual( aMatrix
.yy
, 1 ) &&
1197 ::rtl::math::approxEqual( aMatrix
.x0
, 0 ) &&
1198 ::rtl::math::approxEqual( aMatrix
.y0
, 0 ) &&
1199 basegfx::fround( rSize
.Width
* aMatrix
.xx
) > 8 &&
1200 basegfx::fround( rSize
.Height
* aMatrix
.yy
) > 8 )
1202 double dWidth
, dHeight
;
1204 dWidth
= basegfx::fround( rSize
.Width
* aMatrix
.xx
);
1205 dHeight
= basegfx::fround( rSize
.Height
* aMatrix
.yy
);
1206 aBitmapSize
.Width
= static_cast<sal_Int32
>( dWidth
);
1207 aBitmapSize
.Height
= static_cast<sal_Int32
>( dHeight
);
1209 SurfaceSharedPtr pScaledSurface
= mpSurfaceProvider
->createSurface(
1210 ::basegfx::B2ISize( aBitmapSize
.Width
, aBitmapSize
.Height
),
1211 bHasAlpha
? CAIRO_CONTENT_COLOR_ALPHA
: CAIRO_CONTENT_COLOR
);
1212 CairoSharedPtr pCairo
= pScaledSurface
->getCairo();
1214 cairo_set_operator( pCairo
.get(), CAIRO_OPERATOR_SOURCE
);
1215 // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
1216 cairo_scale( pCairo
.get(), (dWidth
+0.5)/rSize
.Width
, (dHeight
+0.5)/rSize
.Height
);
1217 cairo_set_source_surface( pCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
1218 cairo_paint( pCairo
.get() );
1220 pSurface
= pScaledSurface
;
1222 aMatrix
.xx
= aMatrix
.yy
= 1;
1223 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
1225 rv
= uno::Reference
< rendering::XCachedPrimitive
>(
1226 new CachedBitmap( pSurface
, viewState
, renderState
,
1227 // cast away const, need to
1228 // change refcount (as this is
1229 // ~invisible to client code,
1230 // still logically const)
1231 const_cast< rendering::XCanvas
* >(pCanvas
)) );
1234 if( !bHasAlpha
&& mbHaveAlpha
)
1236 double x
, y
, width
, height
;
1239 width
= aBitmapSize
.Width
;
1240 height
= aBitmapSize
.Height
;
1241 cairo_matrix_transform_point( &aMatrix
, &x
, &y
);
1242 cairo_matrix_transform_distance( &aMatrix
, &width
, &height
);
1244 // in case the bitmap doesn't have alpha and covers whole area
1245 // we try to change surface to plain rgb
1246 OSL_TRACE ("chance to change surface to rgb, %f, %f, %f x %f (%d x %d)", x
, y
, width
, height
, maSize
.getX(), maSize
.getY() );
1247 if( x
<= 0 && y
<= 0 && x
+ width
>= maSize
.getX() && y
+ height
>= maSize
.getY() )
1249 OSL_TRACE ("trying to change surface to rgb");
1250 if( mpSurfaceProvider
) {
1251 SurfaceSharedPtr pNewSurface
= mpSurfaceProvider
->changeSurface( false, false );
1254 setSurface( pNewSurface
, false );
1256 // set state to new mpCairo.get()
1257 useStates( viewState
, renderState
, true );
1258 // use the possibly modified matrix
1259 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
1264 cairo_set_source_surface( mpCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
1266 ::rtl::math::approxEqual( aMatrix
.xx
, 1 ) &&
1267 ::rtl::math::approxEqual( aMatrix
.yy
, 1 ) &&
1268 ::rtl::math::approxEqual( aMatrix
.x0
, 0 ) &&
1269 ::rtl::math::approxEqual( aMatrix
.y0
, 0 ) )
1270 cairo_set_operator( mpCairo
.get(), CAIRO_OPERATOR_SOURCE
);
1271 cairo_rectangle( mpCairo
.get(), 0, 0, aBitmapSize
.Width
, aBitmapSize
.Height
);
1272 cairo_clip( mpCairo
.get() );
1273 cairo_paint( mpCairo
.get() );
1274 cairo_restore( mpCairo
.get() );
1276 OSL_TRACE ("CanvasHelper called after it was disposed");
1278 return rv
; // uno::Reference< rendering::XCachedPrimitive >(NULL);
1281 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawBitmap( const rendering::XCanvas
* pCanvas
,
1282 const uno::Reference
< rendering::XBitmap
>& xBitmap
,
1283 const rendering::ViewState
& viewState
,
1284 const rendering::RenderState
& renderState
)
1286 #ifdef CAIRO_CANVAS_PERF_TRACE
1287 struct timespec aTimer
;
1288 mxDevice
->startPerfTrace( &aTimer
);
1291 uno::Reference
< rendering::XCachedPrimitive
> rv
;
1292 unsigned char* data
= NULL
;
1293 bool bHasAlpha
= false;
1294 SurfaceSharedPtr pSurface
= surfaceFromXBitmap( xBitmap
, mpSurfaceProvider
, data
, bHasAlpha
);
1295 geometry::IntegerSize2D aSize
= xBitmap
->getSize();
1298 rv
= implDrawBitmapSurface( pCanvas
, pSurface
, viewState
, renderState
, aSize
, false, bHasAlpha
);
1303 rv
= uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1305 #ifdef CAIRO_CANVAS_PERF_TRACE
1306 mxDevice
->stopPerfTrace( &aTimer
, "drawBitmap" );
1312 uno::Reference
< rendering::XCachedPrimitive
> CanvasHelper::drawBitmapModulated( const rendering::XCanvas
* ,
1313 const uno::Reference
< rendering::XBitmap
>& /*xBitmap*/,
1314 const rendering::ViewState
& /*viewState*/,
1315 const rendering::RenderState
& /*renderState*/ )
1317 // TODO(F3): Implement modulated bitmap!
1319 // TODO(P1): Provide caching here.
1320 return uno::Reference
< rendering::XCachedPrimitive
>(NULL
);
1323 uno::Reference
< rendering::XGraphicDevice
> CanvasHelper::getDevice()
1325 return uno::Reference
< rendering::XGraphicDevice
>(mpDevice
);
1328 void CanvasHelper::copyRect( const rendering::XCanvas
* ,
1329 const uno::Reference
< rendering::XBitmapCanvas
>& /*sourceCanvas*/,
1330 const geometry::RealRectangle2D
& /*sourceRect*/,
1331 const rendering::ViewState
& /*sourceViewState*/,
1332 const rendering::RenderState
& /*sourceRenderState*/,
1333 const geometry::RealRectangle2D
& /*destRect*/,
1334 const rendering::ViewState
& /*destViewState*/,
1335 const rendering::RenderState
& /*destRenderState*/ )
1337 // TODO(F2): copyRect NYI
1340 geometry::IntegerSize2D
CanvasHelper::getSize()
1342 if( !mpSurfaceProvider
)
1343 geometry::IntegerSize2D(1, 1); // we're disposed
1345 return ::basegfx::unotools::integerSize2DFromB2ISize( maSize
);
1348 uno::Reference
< rendering::XBitmap
> CanvasHelper::getScaledBitmap( const geometry::RealSize2D
& newSize
,
1349 sal_Bool
/*beFast*/ )
1351 #ifdef CAIRO_CANVAS_PERF_TRACE
1352 struct timespec aTimer
;
1353 mxDevice
->startPerfTrace( &aTimer
);
1357 return uno::Reference
< rendering::XBitmap
>( new CanvasBitmap( ::basegfx::B2ISize( ::canvas::tools::roundUp( newSize
.Width
),
1358 ::canvas::tools::roundUp( newSize
.Height
) ),
1359 mpSurfaceProvider
, mpDevice
, false ) );
1361 OSL_TRACE ("CanvasHelper called after it was disposed");
1363 #ifdef CAIRO_CANVAS_PERF_TRACE
1364 mxDevice
->stopPerfTrace( &aTimer
, "getScaledBitmap" );
1367 return uno::Reference
< rendering::XBitmap
>();
1370 uno::Sequence
< sal_Int8
> CanvasHelper::getData( rendering::IntegerBitmapLayout
& aLayout
,
1371 const geometry::IntegerRectangle2D
& rect
)
1374 aLayout
= getMemoryLayout();
1376 const sal_Int32
nWidth( rect
.X2
- rect
.X1
);
1377 const sal_Int32
nHeight( rect
.Y2
- rect
.Y1
);
1378 uno::Sequence
< sal_Int8
> aRes( 4*nWidth
*nHeight
);
1379 sal_Int8
* pData
= aRes
.getArray();
1380 cairo_surface_t
* pImageSurface
= cairo_image_surface_create_for_data( (unsigned char *) pData
,
1381 CAIRO_FORMAT_ARGB32
,
1382 nWidth
, nHeight
, 4*nWidth
);
1383 cairo_t
* pCairo
= cairo_create( pImageSurface
);
1384 cairo_set_source_surface( pCairo
, mpSurface
->getCairoSurface().get(), -rect
.X1
, -rect
.Y1
);
1385 cairo_paint( pCairo
);
1386 cairo_destroy( pCairo
);
1387 cairo_surface_destroy( pImageSurface
);
1389 aLayout
.ScanLines
= nHeight
;
1390 aLayout
.ScanLineBytes
= nWidth
*4;
1391 aLayout
.ScanLineStride
= aLayout
.ScanLineBytes
;
1396 return uno::Sequence
< sal_Int8
>();
1399 void CanvasHelper::setData( const uno::Sequence
< sal_Int8
>& /*data*/,
1400 const rendering::IntegerBitmapLayout
& /*bitmapLayout*/,
1401 const geometry::IntegerRectangle2D
& /*rect*/ )
1405 void CanvasHelper::setPixel( const uno::Sequence
< sal_Int8
>& /*color*/,
1406 const rendering::IntegerBitmapLayout
& /*bitmapLayout*/,
1407 const geometry::IntegerPoint2D
& /*pos*/ )
1411 uno::Sequence
< sal_Int8
> CanvasHelper::getPixel( rendering::IntegerBitmapLayout
& /*bitmapLayout*/,
1412 const geometry::IntegerPoint2D
& /*pos*/ )
1414 return uno::Sequence
< sal_Int8
>();
1417 uno::Reference
< rendering::XBitmapPalette
> CanvasHelper::getPalette()
1419 // TODO(F1): Palette bitmaps NYI
1420 return uno::Reference
< rendering::XBitmapPalette
>();
1425 class CairoColorSpace
: public cppu::WeakImplHelper1
< com::sun::star::rendering::XIntegerBitmapColorSpace
>
1428 uno::Sequence
< sal_Int8
> maComponentTags
;
1429 uno::Sequence
< sal_Int32
> maBitCounts
;
1431 virtual ::sal_Int8 SAL_CALL
getType( ) throw (uno::RuntimeException
)
1433 return rendering::ColorSpaceType::RGB
;
1435 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
getComponentTags( ) throw (uno::RuntimeException
)
1437 return maComponentTags
;
1439 virtual ::sal_Int8 SAL_CALL
getRenderingIntent( ) throw (uno::RuntimeException
)
1441 return rendering::RenderingIntent::PERCEPTUAL
;
1443 virtual uno::Sequence
< beans::PropertyValue
> SAL_CALL
getProperties( ) throw (uno::RuntimeException
)
1445 return uno::Sequence
< beans::PropertyValue
>();
1447 virtual uno::Sequence
< double > SAL_CALL
convertColorSpace( const uno::Sequence
< double >& deviceColor
,
1448 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
1449 uno::RuntimeException
)
1451 // TODO(P3): if we know anything about target
1452 // colorspace, this can be greatly sped up
1453 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1454 convertToARGB(deviceColor
));
1455 return targetColorSpace
->convertFromARGB(aIntermediate
);
1457 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertToRGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1459 const double* pIn( deviceColor
.getConstArray() );
1460 const sal_Size
nLen( deviceColor
.getLength() );
1461 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1462 "number of channels no multiple of 4",
1463 static_cast<rendering::XColorSpace
*>(this), 0);
1465 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
1466 rendering::RGBColor
* pOut( aRes
.getArray() );
1467 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1469 const double fAlpha(pIn
[3]);
1471 *pOut
++ = rendering::RGBColor(0.0, 0.0, 0.0);
1473 *pOut
++ = rendering::RGBColor(pIn
[2]/fAlpha
,pIn
[1]/fAlpha
,pIn
[0]/fAlpha
);
1478 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1480 const double* pIn( deviceColor
.getConstArray() );
1481 const sal_Size
nLen( deviceColor
.getLength() );
1482 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1483 "number of channels no multiple of 4",
1484 static_cast<rendering::XColorSpace
*>(this), 0);
1486 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1487 rendering::ARGBColor
* pOut( aRes
.getArray() );
1488 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1490 const double fAlpha(pIn
[3]);
1492 *pOut
++ = rendering::ARGBColor(0.0, 0.0, 0.0, 0.0);
1494 *pOut
++ = rendering::ARGBColor(fAlpha
,pIn
[2]/fAlpha
,pIn
[1]/fAlpha
,pIn
[0]/fAlpha
);
1499 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToPARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1501 const double* pIn( deviceColor
.getConstArray() );
1502 const sal_Size
nLen( deviceColor
.getLength() );
1503 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1504 "number of channels no multiple of 4",
1505 static_cast<rendering::XColorSpace
*>(this), 0);
1507 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1508 rendering::ARGBColor
* pOut( aRes
.getArray() );
1509 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1511 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[2],pIn
[1],pIn
[1]);
1516 virtual uno::Sequence
< double > SAL_CALL
convertFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1518 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
1519 const sal_Size
nLen( rgbColor
.getLength() );
1521 uno::Sequence
< double > aRes(nLen
*4);
1522 double* pColors
=aRes
.getArray();
1523 for( sal_Size i
=0; i
<nLen
; ++i
)
1525 *pColors
++ = pIn
->Blue
;
1526 *pColors
++ = pIn
->Green
;
1527 *pColors
++ = pIn
->Red
;
1533 virtual uno::Sequence
< double > SAL_CALL
convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1535 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1536 const sal_Size
nLen( rgbColor
.getLength() );
1538 uno::Sequence
< double > aRes(nLen
*4);
1539 double* pColors
=aRes
.getArray();
1540 for( sal_Size i
=0; i
<nLen
; ++i
)
1542 *pColors
++ = pIn
->Alpha
*pIn
->Blue
;
1543 *pColors
++ = pIn
->Alpha
*pIn
->Green
;
1544 *pColors
++ = pIn
->Alpha
*pIn
->Red
;
1545 *pColors
++ = pIn
->Alpha
;
1550 virtual uno::Sequence
< double > SAL_CALL
convertFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1552 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1553 const sal_Size
nLen( rgbColor
.getLength() );
1555 uno::Sequence
< double > aRes(nLen
*4);
1556 double* pColors
=aRes
.getArray();
1557 for( sal_Size i
=0; i
<nLen
; ++i
)
1559 *pColors
++ = pIn
->Blue
;
1560 *pColors
++ = pIn
->Green
;
1561 *pColors
++ = pIn
->Red
;
1562 *pColors
++ = pIn
->Alpha
;
1568 // XIntegerBitmapColorSpace
1569 virtual ::sal_Int32 SAL_CALL
getBitsPerPixel( ) throw (uno::RuntimeException
)
1573 virtual uno::Sequence
< ::sal_Int32
> SAL_CALL
getComponentBitCounts( ) throw (uno::RuntimeException
)
1577 virtual ::sal_Int8 SAL_CALL
getEndianness( ) throw (uno::RuntimeException
)
1579 return util::Endianness::LITTLE
;
1581 virtual uno::Sequence
<double> SAL_CALL
convertFromIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
1582 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
1583 uno::RuntimeException
)
1585 if( dynamic_cast<CairoColorSpace
*>(targetColorSpace
.get()) )
1587 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1588 const sal_Size
nLen( deviceColor
.getLength() );
1589 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1590 "number of channels no multiple of 4",
1591 static_cast<rendering::XColorSpace
*>(this), 0);
1593 uno::Sequence
<double> aRes(nLen
);
1594 double* pOut( aRes
.getArray() );
1595 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1597 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1598 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1599 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1600 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
1606 // TODO(P3): if we know anything about target
1607 // colorspace, this can be greatly sped up
1608 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1609 convertIntegerToARGB(deviceColor
));
1610 return targetColorSpace
->convertFromARGB(aIntermediate
);
1613 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertToIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
1614 const uno::Reference
< rendering::XIntegerBitmapColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
1615 uno::RuntimeException
)
1617 if( dynamic_cast<CairoColorSpace
*>(targetColorSpace
.get()) )
1619 // it's us, so simply pass-through the data
1624 // TODO(P3): if we know anything about target
1625 // colorspace, this can be greatly sped up
1626 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
1627 convertIntegerToARGB(deviceColor
));
1628 return targetColorSpace
->convertIntegerFromARGB(aIntermediate
);
1631 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertIntegerToRGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1633 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1634 const sal_Size
nLen( deviceColor
.getLength() );
1635 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1636 "number of channels no multiple of 4",
1637 static_cast<rendering::XColorSpace
*>(this), 0);
1639 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
1640 rendering::RGBColor
* pOut( aRes
.getArray() );
1641 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1643 const double fAlpha((sal_uInt8
)pIn
[3]);
1645 *pOut
++ = rendering::RGBColor(
1650 *pOut
++ = rendering::RGBColor(0,0,0);
1656 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1658 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1659 const sal_Size
nLen( deviceColor
.getLength() );
1660 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1661 "number of channels no multiple of 4",
1662 static_cast<rendering::XColorSpace
*>(this), 0);
1664 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1665 rendering::ARGBColor
* pOut( aRes
.getArray() );
1666 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1668 const double fAlpha((sal_uInt8
)pIn
[3]);
1670 *pOut
++ = rendering::ARGBColor(
1676 *pOut
++ = rendering::ARGBColor(0,0,0,0);
1681 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToPARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1683 const sal_Int8
* pIn( deviceColor
.getConstArray() );
1684 const sal_Size
nLen( deviceColor
.getLength() );
1685 ENSURE_ARG_OR_THROW2(nLen
%4==0,
1686 "number of channels no multiple of 4",
1687 static_cast<rendering::XColorSpace
*>(this), 0);
1689 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
1690 rendering::ARGBColor
* pOut( aRes
.getArray() );
1691 for( sal_Size i
=0; i
<nLen
; i
+=4 )
1693 *pOut
++ = rendering::ARGBColor(
1694 vcl::unotools::toDoubleColor(pIn
[3]),
1695 vcl::unotools::toDoubleColor(pIn
[2]),
1696 vcl::unotools::toDoubleColor(pIn
[1]),
1697 vcl::unotools::toDoubleColor(pIn
[0]));
1703 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1705 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
1706 const sal_Size
nLen( rgbColor
.getLength() );
1708 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1709 sal_Int8
* pColors
=aRes
.getArray();
1710 for( sal_Size i
=0; i
<nLen
; ++i
)
1712 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
1713 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
1714 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
1721 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1723 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1724 const sal_Size
nLen( rgbColor
.getLength() );
1726 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1727 sal_Int8
* pColors
=aRes
.getArray();
1728 for( sal_Size i
=0; i
<nLen
; ++i
)
1730 const double fAlpha(pIn
->Alpha
);
1731 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Blue
);
1732 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Green
);
1733 *pColors
++ = vcl::unotools::toByteColor(fAlpha
*pIn
->Red
);
1734 *pColors
++ = vcl::unotools::toByteColor(fAlpha
);
1739 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
)
1741 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
1742 const sal_Size
nLen( rgbColor
.getLength() );
1744 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
1745 sal_Int8
* pColors
=aRes
.getArray();
1746 for( sal_Size i
=0; i
<nLen
; ++i
)
1748 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
1749 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
1750 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
1751 *pColors
++ = vcl::unotools::toByteColor(pIn
->Alpha
);
1762 sal_Int8
* pTags
= maComponentTags
.getArray();
1763 sal_Int32
* pBitCounts
= maBitCounts
.getArray();
1764 pTags
[0] = rendering::ColorComponentTag::RGB_BLUE
;
1765 pTags
[1] = rendering::ColorComponentTag::RGB_GREEN
;
1766 pTags
[2] = rendering::ColorComponentTag::RGB_RED
;
1767 pTags
[3] = rendering::ColorComponentTag::PREMULTIPLIED_ALPHA
;
1776 struct CairoColorSpaceHolder
: public rtl::StaticWithInit
<uno::Reference
<rendering::XIntegerBitmapColorSpace
>,
1777 CairoColorSpaceHolder
>
1779 uno::Reference
<rendering::XIntegerBitmapColorSpace
> operator()()
1781 return new CairoColorSpace();
1786 rendering::IntegerBitmapLayout
CanvasHelper::getMemoryLayout()
1789 return rendering::IntegerBitmapLayout(); // we're disposed
1791 const geometry::IntegerSize2D
aSize(getSize());
1792 rendering::IntegerBitmapLayout aLayout
;
1794 aLayout
.ScanLines
= aSize
.Height
;
1795 aLayout
.ScanLineBytes
= aSize
.Width
*4;
1796 aLayout
.ScanLineStride
= aLayout
.ScanLineBytes
;
1797 aLayout
.PlaneStride
= 0;
1798 aLayout
.ColorSpace
= CairoColorSpaceHolder::get();
1799 aLayout
.Palette
.clear();
1800 aLayout
.IsMsbFirst
= sal_False
;
1805 void CanvasHelper::flush() const
1809 bool CanvasHelper::hasAlpha() const
1814 bool CanvasHelper::repaint( const SurfaceSharedPtr
& pSurface
,
1815 const rendering::ViewState
& viewState
,
1816 const rendering::RenderState
& renderState
)
1818 OSL_TRACE("CanvasHelper::repaint");
1821 cairo_save( mpCairo
.get() );
1823 cairo_rectangle( mpCairo
.get(), 0, 0, maSize
.getX(), maSize
.getY() );
1824 cairo_clip( mpCairo
.get() );
1826 useStates( viewState
, renderState
, true );
1830 cairo_get_matrix( mpCairo
.get(), &aMatrix
);
1831 aMatrix
.xx
= aMatrix
.yy
= 1;
1832 cairo_set_matrix( mpCairo
.get(), &aMatrix
);
1835 // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
1837 cairo_set_source_surface( mpCairo
.get(), pSurface
->getCairoSurface().get(), 0, 0 );
1838 cairo_paint( mpCairo
.get() );
1839 cairo_restore( mpCairo
.get() );