1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_canvas.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <canvas/debug.hxx> 32*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #include <rtl/logfile.hxx> 35*cdf0e10cSrcweir #include <rtl/math.hxx> 36*cdf0e10cSrcweir #include <rtl/instance.hxx> 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir #include <com/sun/star/util/Endianness.hpp> 39*cdf0e10cSrcweir #include <com/sun/star/rendering/TexturingMode.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp> 41*cdf0e10cSrcweir #include <com/sun/star/rendering/RepaintResult.hpp> 42*cdf0e10cSrcweir #include <com/sun/star/rendering/PathCapType.hpp> 43*cdf0e10cSrcweir #include <com/sun/star/rendering/PathJoinType.hpp> 44*cdf0e10cSrcweir #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp> 45*cdf0e10cSrcweir #include <com/sun/star/rendering/IntegerBitmapLayout.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/rendering/ColorSpaceType.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/rendering/ColorComponentTag.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/rendering/RenderingIntent.hpp> 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 51*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 52*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 53*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx> 54*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 55*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 56*cdf0e10cSrcweir #include <basegfx/tools/keystoplerp.hxx> 57*cdf0e10cSrcweir #include <basegfx/tools/lerp.hxx> 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir #include <comphelper/sequence.hxx> 60*cdf0e10cSrcweir #include <cppuhelper/compbase1.hxx> 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir #include <canvas/canvastools.hxx> 63*cdf0e10cSrcweir #include <canvas/parametricpolypolygon.hxx> 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir #include <vcl/canvastools.hxx> 66*cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 67*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 68*cdf0e10cSrcweir #include <vcl/virdev.hxx> 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir #include "cairo_spritecanvas.hxx" 71*cdf0e10cSrcweir #include "cairo_cachedbitmap.hxx" 72*cdf0e10cSrcweir #include "cairo_canvashelper.hxx" 73*cdf0e10cSrcweir #include "cairo_canvasbitmap.hxx" 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir #include <boost/tuple/tuple.hpp> 76*cdf0e10cSrcweir #include <algorithm> 77*cdf0e10cSrcweir 78*cdf0e10cSrcweir using namespace ::cairo; 79*cdf0e10cSrcweir using namespace ::com::sun::star; 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir namespace cairocanvas 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir CanvasHelper::CanvasHelper() : 84*cdf0e10cSrcweir mpSurfaceProvider(NULL), 85*cdf0e10cSrcweir mpDevice(NULL), 86*cdf0e10cSrcweir mpVirtualDevice(), 87*cdf0e10cSrcweir mbHaveAlpha(), 88*cdf0e10cSrcweir mpCairo(), 89*cdf0e10cSrcweir mpSurface(), 90*cdf0e10cSrcweir maSize() 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir } 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir void CanvasHelper::disposing() 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir mpSurface.reset(); 97*cdf0e10cSrcweir mpCairo.reset(); 98*cdf0e10cSrcweir mpVirtualDevice.reset(); 99*cdf0e10cSrcweir mpDevice = NULL; 100*cdf0e10cSrcweir mpSurfaceProvider = NULL; 101*cdf0e10cSrcweir } 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir void CanvasHelper::init( const ::basegfx::B2ISize& rSizePixel, 104*cdf0e10cSrcweir SurfaceProvider& rSurfaceProvider, 105*cdf0e10cSrcweir rendering::XGraphicDevice* pDevice ) 106*cdf0e10cSrcweir { 107*cdf0e10cSrcweir maSize = rSizePixel; 108*cdf0e10cSrcweir mpSurfaceProvider = &rSurfaceProvider; 109*cdf0e10cSrcweir mpDevice = pDevice; 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir void CanvasHelper::setSize( const ::basegfx::B2ISize& rSize ) 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir maSize = rSize; 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir void CanvasHelper::setSurface( const SurfaceSharedPtr& pSurface, bool bHasAlpha ) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir mbHaveAlpha = bHasAlpha; 120*cdf0e10cSrcweir mpVirtualDevice.reset(); 121*cdf0e10cSrcweir mpSurface = pSurface; 122*cdf0e10cSrcweir mpCairo = pSurface->getCairo(); 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir static void setColor( Cairo* pCairo, 126*cdf0e10cSrcweir const uno::Sequence<double>& rColor ) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir if( rColor.getLength() > 3 ) 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir const double alpha = rColor[3]; 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir cairo_set_source_rgba( pCairo, 133*cdf0e10cSrcweir alpha*rColor[0], 134*cdf0e10cSrcweir alpha*rColor[1], 135*cdf0e10cSrcweir alpha*rColor[2], 136*cdf0e10cSrcweir alpha ); 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir else if( rColor.getLength() == 3 ) 139*cdf0e10cSrcweir cairo_set_source_rgb( pCairo, 140*cdf0e10cSrcweir rColor[0], 141*cdf0e10cSrcweir rColor[1], 142*cdf0e10cSrcweir rColor[2] ); 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir void CanvasHelper::useStates( const rendering::ViewState& viewState, 146*cdf0e10cSrcweir const rendering::RenderState& renderState, 147*cdf0e10cSrcweir bool bSetColor ) 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir Matrix aViewMatrix; 150*cdf0e10cSrcweir Matrix aRenderMatrix; 151*cdf0e10cSrcweir Matrix aCombinedMatrix; 152*cdf0e10cSrcweir 153*cdf0e10cSrcweir cairo_matrix_init( &aViewMatrix, 154*cdf0e10cSrcweir viewState.AffineTransform.m00, viewState.AffineTransform.m10, viewState.AffineTransform.m01, 155*cdf0e10cSrcweir viewState.AffineTransform.m11, viewState.AffineTransform.m02, viewState.AffineTransform.m12); 156*cdf0e10cSrcweir cairo_matrix_init( &aRenderMatrix, 157*cdf0e10cSrcweir renderState.AffineTransform.m00, renderState.AffineTransform.m10, renderState.AffineTransform.m01, 158*cdf0e10cSrcweir renderState.AffineTransform.m11, renderState.AffineTransform.m02, renderState.AffineTransform.m12); 159*cdf0e10cSrcweir cairo_matrix_multiply( &aCombinedMatrix, &aRenderMatrix, &aViewMatrix); 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir if( viewState.Clip.is() ) { 162*cdf0e10cSrcweir OSL_TRACE ("view clip"); 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir aViewMatrix.x0 = basegfx::fround( aViewMatrix.x0 ); 165*cdf0e10cSrcweir aViewMatrix.y0 = basegfx::fround( aViewMatrix.y0 ); 166*cdf0e10cSrcweir cairo_set_matrix( mpCairo.get(), &aViewMatrix ); 167*cdf0e10cSrcweir doPolyPolygonPath( viewState.Clip, Clip ); 168*cdf0e10cSrcweir } 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir aCombinedMatrix.x0 = basegfx::fround( aCombinedMatrix.x0 ); 171*cdf0e10cSrcweir aCombinedMatrix.y0 = basegfx::fround( aCombinedMatrix.y0 ); 172*cdf0e10cSrcweir cairo_set_matrix( mpCairo.get(), &aCombinedMatrix ); 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir if( renderState.Clip.is() ) { 175*cdf0e10cSrcweir OSL_TRACE ("render clip BEGIN"); 176*cdf0e10cSrcweir 177*cdf0e10cSrcweir doPolyPolygonPath( renderState.Clip, Clip ); 178*cdf0e10cSrcweir OSL_TRACE ("render clip END"); 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir if( bSetColor ) 182*cdf0e10cSrcweir setColor(mpCairo.get(),renderState.DeviceColor); 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER ); 185*cdf0e10cSrcweir switch( renderState.CompositeOperation ) 186*cdf0e10cSrcweir { 187*cdf0e10cSrcweir case rendering::CompositeOperation::CLEAR: 188*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_CLEAR; 189*cdf0e10cSrcweir break; 190*cdf0e10cSrcweir case rendering::CompositeOperation::SOURCE: 191*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_SOURCE; 192*cdf0e10cSrcweir break; 193*cdf0e10cSrcweir case rendering::CompositeOperation::DESTINATION: 194*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_DEST; 195*cdf0e10cSrcweir break; 196*cdf0e10cSrcweir case rendering::CompositeOperation::OVER: 197*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_OVER; 198*cdf0e10cSrcweir break; 199*cdf0e10cSrcweir case rendering::CompositeOperation::UNDER: 200*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_DEST; 201*cdf0e10cSrcweir break; 202*cdf0e10cSrcweir case rendering::CompositeOperation::INSIDE: 203*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_IN; 204*cdf0e10cSrcweir break; 205*cdf0e10cSrcweir case rendering::CompositeOperation::INSIDE_REVERSE: 206*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_OUT; 207*cdf0e10cSrcweir break; 208*cdf0e10cSrcweir case rendering::CompositeOperation::OUTSIDE: 209*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_DEST_OVER; 210*cdf0e10cSrcweir break; 211*cdf0e10cSrcweir case rendering::CompositeOperation::OUTSIDE_REVERSE: 212*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_DEST_OUT; 213*cdf0e10cSrcweir break; 214*cdf0e10cSrcweir case rendering::CompositeOperation::ATOP: 215*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_ATOP; 216*cdf0e10cSrcweir break; 217*cdf0e10cSrcweir case rendering::CompositeOperation::ATOP_REVERSE: 218*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_DEST_ATOP; 219*cdf0e10cSrcweir break; 220*cdf0e10cSrcweir case rendering::CompositeOperation::XOR: 221*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_XOR; 222*cdf0e10cSrcweir break; 223*cdf0e10cSrcweir case rendering::CompositeOperation::ADD: 224*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_ADD; 225*cdf0e10cSrcweir break; 226*cdf0e10cSrcweir case rendering::CompositeOperation::SATURATE: 227*cdf0e10cSrcweir compositingMode = CAIRO_OPERATOR_SATURATE; 228*cdf0e10cSrcweir break; 229*cdf0e10cSrcweir } 230*cdf0e10cSrcweir cairo_set_operator( mpCairo.get(), compositingMode ); 231*cdf0e10cSrcweir } 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir void CanvasHelper::clear() 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir OSL_TRACE ("clear whole area: %d x %d", maSize.getX(), maSize.getY() ); 236*cdf0e10cSrcweir 237*cdf0e10cSrcweir if( mpCairo ) 238*cdf0e10cSrcweir { 239*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir cairo_identity_matrix( mpCairo.get() ); 242*cdf0e10cSrcweir // this does not really differ from all-zero, as cairo 243*cdf0e10cSrcweir // internally converts to premultiplied alpha. but anyway, 244*cdf0e10cSrcweir // this keeps it consistent with the other canvas impls 245*cdf0e10cSrcweir if( mbHaveAlpha ) 246*cdf0e10cSrcweir cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 ); 247*cdf0e10cSrcweir else 248*cdf0e10cSrcweir cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 ); 249*cdf0e10cSrcweir cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); 252*cdf0e10cSrcweir cairo_fill( mpCairo.get() ); 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir } 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir void CanvasHelper::drawPoint( const rendering::XCanvas* , 259*cdf0e10cSrcweir const geometry::RealPoint2D& , 260*cdf0e10cSrcweir const rendering::ViewState& , 261*cdf0e10cSrcweir const rendering::RenderState& ) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir } 264*cdf0e10cSrcweir 265*cdf0e10cSrcweir void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/, 266*cdf0e10cSrcweir const geometry::RealPoint2D& aStartPoint, 267*cdf0e10cSrcweir const geometry::RealPoint2D& aEndPoint, 268*cdf0e10cSrcweir const rendering::ViewState& viewState, 269*cdf0e10cSrcweir const rendering::RenderState& renderState ) 270*cdf0e10cSrcweir { 271*cdf0e10cSrcweir if( mpCairo ) { 272*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir cairo_set_line_width( mpCairo.get(), 1 ); 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir useStates( viewState, renderState, true ); 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 ); 279*cdf0e10cSrcweir cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 ); 280*cdf0e10cSrcweir cairo_stroke( mpCairo.get() ); 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir void CanvasHelper::drawBezier( const rendering::XCanvas* , 287*cdf0e10cSrcweir const geometry::RealBezierSegment2D& aBezierSegment, 288*cdf0e10cSrcweir const geometry::RealPoint2D& aEndPoint, 289*cdf0e10cSrcweir const rendering::ViewState& viewState, 290*cdf0e10cSrcweir const rendering::RenderState& renderState ) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir if( mpCairo ) { 293*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir cairo_set_line_width( mpCairo.get(), 1 ); 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir useStates( viewState, renderState, true ); 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 ); 300*cdf0e10cSrcweir cairo_curve_to( mpCairo.get(), 301*cdf0e10cSrcweir aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5, 302*cdf0e10cSrcweir aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5, 303*cdf0e10cSrcweir aEndPoint.X + 0.5, aEndPoint.Y + 0.5 ); 304*cdf0e10cSrcweir cairo_stroke( mpCairo.get() ); 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir #define CANVASBITMAP_IMPLEMENTATION_NAME "CairoCanvas::CanvasBitmap" 311*cdf0e10cSrcweir #define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon" 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir /** surfaceFromXBitmap Create a surface from XBitmap 315*cdf0e10cSrcweir * @param xBitmap bitmap image that will be used for the surface 316*cdf0e10cSrcweir * @param bHasAlpha will be set to true if resulting surface has alpha 317*cdf0e10cSrcweir * 318*cdf0e10cSrcweir * This is a helper function for the other surfaceFromXBitmap(). 319*cdf0e10cSrcweir * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas. 320*cdf0e10cSrcweir * 321*cdf0e10cSrcweir * @return created surface or NULL 322*cdf0e10cSrcweir **/ 323*cdf0e10cSrcweir static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() ); 326*cdf0e10cSrcweir if( pBitmapImpl ) 327*cdf0e10cSrcweir return pBitmapImpl->getSurface(); 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir SurfaceProvider* pSurfaceProvider = dynamic_cast<SurfaceProvider*>( xBitmap.get() ); 330*cdf0e10cSrcweir if( pSurfaceProvider ) 331*cdf0e10cSrcweir return pSurfaceProvider->getSurface(); 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir return SurfaceSharedPtr(); 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir static ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) 337*cdf0e10cSrcweir { 338*cdf0e10cSrcweir // TODO(F1): Add support for floating point bitmap formats 339*cdf0e10cSrcweir uno::Reference<rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap, 340*cdf0e10cSrcweir uno::UNO_QUERY_THROW); 341*cdf0e10cSrcweir ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap(xIntBmp); 342*cdf0e10cSrcweir if( !!aBmpEx ) 343*cdf0e10cSrcweir return aBmpEx; 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir // TODO(F1): extract pixel from XBitmap interface 346*cdf0e10cSrcweir ENSURE_OR_THROW( false, 347*cdf0e10cSrcweir "bitmapExFromXBitmap(): could not extract BitmapEx" ); 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir return ::BitmapEx(); 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir 352*cdf0e10cSrcweir static bool readAlpha( BitmapReadAccess* pAlphaReadAcc, long nY, const long nWidth, unsigned char* data, long nOff ) 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir bool bIsAlpha = false; 355*cdf0e10cSrcweir long nX; 356*cdf0e10cSrcweir int nAlpha; 357*cdf0e10cSrcweir Scanline pReadScan; 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir nOff += 3; 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir switch( pAlphaReadAcc->GetScanlineFormat() ) { 362*cdf0e10cSrcweir case BMP_FORMAT_8BIT_TC_MASK: 363*cdf0e10cSrcweir pReadScan = pAlphaReadAcc->GetScanline( nY ); 364*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 365*cdf0e10cSrcweir nAlpha = data[ nOff ] = 255 - ( *pReadScan++ ); 366*cdf0e10cSrcweir if( nAlpha != 255 ) 367*cdf0e10cSrcweir bIsAlpha = true; 368*cdf0e10cSrcweir nOff += 4; 369*cdf0e10cSrcweir } 370*cdf0e10cSrcweir break; 371*cdf0e10cSrcweir case BMP_FORMAT_8BIT_PAL: 372*cdf0e10cSrcweir pReadScan = pAlphaReadAcc->GetScanline( nY ); 373*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 374*cdf0e10cSrcweir nAlpha = data[ nOff ] = 255 - ( pAlphaReadAcc->GetPaletteColor( *pReadScan++ ).GetBlue() ); 375*cdf0e10cSrcweir if( nAlpha != 255 ) 376*cdf0e10cSrcweir bIsAlpha = true; 377*cdf0e10cSrcweir nOff += 4; 378*cdf0e10cSrcweir } 379*cdf0e10cSrcweir break; 380*cdf0e10cSrcweir default: 381*cdf0e10cSrcweir OSL_TRACE( "fallback to GetColor for alpha - slow, format: %d", pAlphaReadAcc->GetScanlineFormat() ); 382*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 383*cdf0e10cSrcweir nAlpha = data[ nOff ] = 255 - pAlphaReadAcc->GetColor( nY, nX ).GetBlue(); 384*cdf0e10cSrcweir if( nAlpha != 255 ) 385*cdf0e10cSrcweir bIsAlpha = true; 386*cdf0e10cSrcweir nOff += 4; 387*cdf0e10cSrcweir } 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir return bIsAlpha; 391*cdf0e10cSrcweir } 392*cdf0e10cSrcweir 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir /** surfaceFromXBitmap Create a surface from XBitmap 395*cdf0e10cSrcweir * @param xBitmap bitmap image that will be used for the surface 396*cdf0e10cSrcweir * @param rDevice reference to the device into which we want to draw 397*cdf0e10cSrcweir * @param data will be filled with alpha data, if xBitmap is alpha/transparent image 398*cdf0e10cSrcweir * @param bHasAlpha will be set to true if resulting surface has alpha 399*cdf0e10cSrcweir * 400*cdf0e10cSrcweir * This function tries various methods for creating a surface from xBitmap. It also uses 401*cdf0e10cSrcweir * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha ) 402*cdf0e10cSrcweir * 403*cdf0e10cSrcweir * @return created surface or NULL 404*cdf0e10cSrcweir **/ 405*cdf0e10cSrcweir static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, const SurfaceProviderRef& rSurfaceProvider, unsigned char*& data, bool& bHasAlpha ) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir bHasAlpha = xBitmap->hasAlpha(); 408*cdf0e10cSrcweir SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap ); 409*cdf0e10cSrcweir if( pSurface ) 410*cdf0e10cSrcweir data = NULL; 411*cdf0e10cSrcweir else 412*cdf0e10cSrcweir { 413*cdf0e10cSrcweir ::BitmapEx aBmpEx = bitmapExFromXBitmap(xBitmap); 414*cdf0e10cSrcweir ::Bitmap aBitmap = aBmpEx.GetBitmap(); 415*cdf0e10cSrcweir 416*cdf0e10cSrcweir // there's no pixmap for alpha bitmap. we might still 417*cdf0e10cSrcweir // use rgb pixmap and only access alpha pixels the 418*cdf0e10cSrcweir // slow way. now we just speedup rgb bitmaps 419*cdf0e10cSrcweir if( !aBmpEx.IsTransparent() && !aBmpEx.IsAlpha() ) { 420*cdf0e10cSrcweir pSurface = rSurfaceProvider->createSurface( aBitmap ); 421*cdf0e10cSrcweir data = NULL; 422*cdf0e10cSrcweir bHasAlpha = false; 423*cdf0e10cSrcweir } 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir if( !pSurface ) { 426*cdf0e10cSrcweir AlphaMask aAlpha = aBmpEx.GetAlpha(); 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir ::BitmapReadAccess* pBitmapReadAcc = aBitmap.AcquireReadAccess(); 429*cdf0e10cSrcweir ::BitmapReadAccess* pAlphaReadAcc = NULL; 430*cdf0e10cSrcweir const long nWidth = pBitmapReadAcc->Width(); 431*cdf0e10cSrcweir const long nHeight = pBitmapReadAcc->Height(); 432*cdf0e10cSrcweir long nX, nY; 433*cdf0e10cSrcweir bool bIsAlpha = false; 434*cdf0e10cSrcweir 435*cdf0e10cSrcweir if( aBmpEx.IsTransparent() || aBmpEx.IsAlpha() ) 436*cdf0e10cSrcweir pAlphaReadAcc = aAlpha.AcquireReadAccess(); 437*cdf0e10cSrcweir 438*cdf0e10cSrcweir data = (unsigned char*) malloc( nWidth*nHeight*4 ); 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir long nOff = 0; 441*cdf0e10cSrcweir ::Color aColor; 442*cdf0e10cSrcweir unsigned int nAlpha = 255; 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir for( nY = 0; nY < nHeight; nY++ ) { 445*cdf0e10cSrcweir ::Scanline pReadScan; 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir switch( pBitmapReadAcc->GetScanlineFormat() ) { 448*cdf0e10cSrcweir case BMP_FORMAT_8BIT_PAL: 449*cdf0e10cSrcweir pReadScan = pBitmapReadAcc->GetScanline( nY ); 450*cdf0e10cSrcweir if( pAlphaReadAcc ) 451*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 452*cdf0e10cSrcweir bIsAlpha = true; 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 455*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 456*cdf0e10cSrcweir if( pAlphaReadAcc ) 457*cdf0e10cSrcweir nAlpha = data[ nOff++ ]; 458*cdf0e10cSrcweir else 459*cdf0e10cSrcweir nAlpha = data[ nOff++ ] = 255; 460*cdf0e10cSrcweir #else 461*cdf0e10cSrcweir if( pAlphaReadAcc ) 462*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 463*cdf0e10cSrcweir else 464*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = 255; 465*cdf0e10cSrcweir #endif 466*cdf0e10cSrcweir aColor = pBitmapReadAcc->GetPaletteColor( *pReadScan++ ); 467*cdf0e10cSrcweir 468*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 469*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 ); 470*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 ); 471*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 ); 472*cdf0e10cSrcweir #else 473*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 ); 474*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 ); 475*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 ); 476*cdf0e10cSrcweir nOff++; 477*cdf0e10cSrcweir #endif 478*cdf0e10cSrcweir } 479*cdf0e10cSrcweir break; 480*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_BGR: 481*cdf0e10cSrcweir pReadScan = pBitmapReadAcc->GetScanline( nY ); 482*cdf0e10cSrcweir if( pAlphaReadAcc ) 483*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 484*cdf0e10cSrcweir bIsAlpha = true; 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 487*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 488*cdf0e10cSrcweir if( pAlphaReadAcc ) 489*cdf0e10cSrcweir nAlpha = data[ nOff ]; 490*cdf0e10cSrcweir else 491*cdf0e10cSrcweir nAlpha = data[ nOff ] = 255; 492*cdf0e10cSrcweir data[ nOff + 3 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 493*cdf0e10cSrcweir data[ nOff + 2 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 494*cdf0e10cSrcweir data[ nOff + 1 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 495*cdf0e10cSrcweir nOff += 4; 496*cdf0e10cSrcweir #else 497*cdf0e10cSrcweir if( pAlphaReadAcc ) 498*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 499*cdf0e10cSrcweir else 500*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = 255; 501*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 502*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 503*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 504*cdf0e10cSrcweir nOff++; 505*cdf0e10cSrcweir #endif 506*cdf0e10cSrcweir } 507*cdf0e10cSrcweir break; 508*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_RGB: 509*cdf0e10cSrcweir pReadScan = pBitmapReadAcc->GetScanline( nY ); 510*cdf0e10cSrcweir if( pAlphaReadAcc ) 511*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 512*cdf0e10cSrcweir bIsAlpha = true; 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 515*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 516*cdf0e10cSrcweir if( pAlphaReadAcc ) 517*cdf0e10cSrcweir nAlpha = data[ nOff++ ]; 518*cdf0e10cSrcweir else 519*cdf0e10cSrcweir nAlpha = data[ nOff++ ] = 255; 520*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 521*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 522*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 523*cdf0e10cSrcweir #else 524*cdf0e10cSrcweir if( pAlphaReadAcc ) 525*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 526*cdf0e10cSrcweir else 527*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = 255; 528*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); 529*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); 530*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); 531*cdf0e10cSrcweir pReadScan += 3; 532*cdf0e10cSrcweir nOff++; 533*cdf0e10cSrcweir #endif 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir break; 536*cdf0e10cSrcweir case BMP_FORMAT_32BIT_TC_BGRA: 537*cdf0e10cSrcweir pReadScan = pBitmapReadAcc->GetScanline( nY ); 538*cdf0e10cSrcweir if( pAlphaReadAcc ) 539*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 540*cdf0e10cSrcweir bIsAlpha = true; 541*cdf0e10cSrcweir 542*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 543*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 544*cdf0e10cSrcweir if( pAlphaReadAcc ) 545*cdf0e10cSrcweir nAlpha = data[ nOff++ ]; 546*cdf0e10cSrcweir else 547*cdf0e10cSrcweir nAlpha = data[ nOff++ ] = pReadScan[ 3 ]; 548*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); 549*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); 550*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); 551*cdf0e10cSrcweir pReadScan += 4; 552*cdf0e10cSrcweir #else 553*cdf0e10cSrcweir if( pAlphaReadAcc ) 554*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 555*cdf0e10cSrcweir else 556*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = pReadScan[ 3 ]; 557*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 558*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 559*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 560*cdf0e10cSrcweir pReadScan++; 561*cdf0e10cSrcweir nOff++; 562*cdf0e10cSrcweir #endif 563*cdf0e10cSrcweir } 564*cdf0e10cSrcweir break; 565*cdf0e10cSrcweir case BMP_FORMAT_32BIT_TC_RGBA: 566*cdf0e10cSrcweir pReadScan = pBitmapReadAcc->GetScanline( nY ); 567*cdf0e10cSrcweir if( pAlphaReadAcc ) 568*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 569*cdf0e10cSrcweir bIsAlpha = true; 570*cdf0e10cSrcweir 571*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 572*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 573*cdf0e10cSrcweir if( pAlphaReadAcc ) 574*cdf0e10cSrcweir nAlpha = data[ nOff ++ ]; 575*cdf0e10cSrcweir else 576*cdf0e10cSrcweir nAlpha = data[ nOff ++ ] = 255; 577*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 578*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 579*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); 580*cdf0e10cSrcweir pReadScan++; 581*cdf0e10cSrcweir #else 582*cdf0e10cSrcweir if( pAlphaReadAcc ) 583*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 584*cdf0e10cSrcweir else 585*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = 255; 586*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); 587*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); 588*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); 589*cdf0e10cSrcweir pReadScan += 4; 590*cdf0e10cSrcweir nOff++; 591*cdf0e10cSrcweir #endif 592*cdf0e10cSrcweir } 593*cdf0e10cSrcweir break; 594*cdf0e10cSrcweir default: 595*cdf0e10cSrcweir OSL_TRACE( "fallback to GetColor - slow, format: %d", pBitmapReadAcc->GetScanlineFormat() ); 596*cdf0e10cSrcweir 597*cdf0e10cSrcweir if( pAlphaReadAcc ) 598*cdf0e10cSrcweir if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) 599*cdf0e10cSrcweir bIsAlpha = true; 600*cdf0e10cSrcweir 601*cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) { 602*cdf0e10cSrcweir aColor = pBitmapReadAcc->GetColor( nY, nX ); 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir // cairo need premultiplied color values 605*cdf0e10cSrcweir // TODO(rodo) handle endianess 606*cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 607*cdf0e10cSrcweir if( pAlphaReadAcc ) 608*cdf0e10cSrcweir nAlpha = data[ nOff++ ]; 609*cdf0e10cSrcweir else 610*cdf0e10cSrcweir nAlpha = data[ nOff++ ] = 255; 611*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 ); 612*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 ); 613*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 ); 614*cdf0e10cSrcweir #else 615*cdf0e10cSrcweir if( pAlphaReadAcc ) 616*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ]; 617*cdf0e10cSrcweir else 618*cdf0e10cSrcweir nAlpha = data[ nOff + 3 ] = 255; 619*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 ); 620*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 ); 621*cdf0e10cSrcweir data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 ); 622*cdf0e10cSrcweir nOff ++; 623*cdf0e10cSrcweir #endif 624*cdf0e10cSrcweir } 625*cdf0e10cSrcweir } 626*cdf0e10cSrcweir } 627*cdf0e10cSrcweir 628*cdf0e10cSrcweir aBitmap.ReleaseAccess( pBitmapReadAcc ); 629*cdf0e10cSrcweir if( pAlphaReadAcc ) 630*cdf0e10cSrcweir aAlpha.ReleaseAccess( pAlphaReadAcc ); 631*cdf0e10cSrcweir 632*cdf0e10cSrcweir SurfaceSharedPtr pImageSurface = createSurface( 633*cdf0e10cSrcweir CairoSurfaceSharedPtr( 634*cdf0e10cSrcweir cairo_image_surface_create_for_data( 635*cdf0e10cSrcweir data, 636*cdf0e10cSrcweir bIsAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, 637*cdf0e10cSrcweir nWidth, nHeight, nWidth*4 ), 638*cdf0e10cSrcweir &cairo_surface_destroy) ); 639*cdf0e10cSrcweir 640*cdf0e10cSrcweir // pSurface = rSurfaceProvider->getSurface( ::basegfx::B2ISize( nWidth, nHeight ), bIsAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR ); 641*cdf0e10cSrcweir // Cairo* pTargetCairo = cairo_create( pSurface ); 642*cdf0e10cSrcweir // cairo_set_source_surface( pTargetCairo, pImageSurface, 0, 0 ); 643*cdf0e10cSrcweir 644*cdf0e10cSrcweir // //if( !bIsAlpha ) 645*cdf0e10cSrcweir // //cairo_set_operator( pTargetCairo, CAIRO_OPERATOR_SOURCE ); 646*cdf0e10cSrcweir 647*cdf0e10cSrcweir // cairo_paint( pTargetCairo ); 648*cdf0e10cSrcweir // cairo_destroy( pTargetCairo ); 649*cdf0e10cSrcweir // cairo_surface_destroy( pImageSurface ); 650*cdf0e10cSrcweir pSurface = pImageSurface; 651*cdf0e10cSrcweir 652*cdf0e10cSrcweir bHasAlpha = bIsAlpha; 653*cdf0e10cSrcweir 654*cdf0e10cSrcweir OSL_TRACE("image: %d x %d alpha: %d alphaRead %p", nWidth, nHeight, bIsAlpha, pAlphaReadAcc); 655*cdf0e10cSrcweir } 656*cdf0e10cSrcweir } 657*cdf0e10cSrcweir 658*cdf0e10cSrcweir return pSurface; 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir 661*cdf0e10cSrcweir static void addColorStops( Pattern* pPattern, const uno::Sequence< uno::Sequence< double > >& rColors, const uno::Sequence< double >& rStops, bool bReverseStops = false ) 662*cdf0e10cSrcweir { 663*cdf0e10cSrcweir float stop; 664*cdf0e10cSrcweir int i; 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir OSL_ASSERT( rColors.getLength() == rStops.getLength() ); 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir for( i = 0; i < rColors.getLength(); i++ ) { 669*cdf0e10cSrcweir const uno::Sequence< double >& rColor( rColors[i] ); 670*cdf0e10cSrcweir stop = bReverseStops ? 1 - rStops[i] : rStops[i]; 671*cdf0e10cSrcweir if( rColor.getLength() == 3 ) 672*cdf0e10cSrcweir cairo_pattern_add_color_stop_rgb( pPattern, stop, rColor[0], rColor[1], rColor[2] ); 673*cdf0e10cSrcweir else if( rColor.getLength() == 4 ) { 674*cdf0e10cSrcweir double alpha = rColor[3]; 675*cdf0e10cSrcweir // cairo expects premultiplied alpha 676*cdf0e10cSrcweir cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha ); 677*cdf0e10cSrcweir } 678*cdf0e10cSrcweir } 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha) 682*cdf0e10cSrcweir { 683*cdf0e10cSrcweir if( rLeft.getLength() == 3 ) 684*cdf0e10cSrcweir { 685*cdf0e10cSrcweir uno::Sequence<double> aRes(3); 686*cdf0e10cSrcweir aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha); 687*cdf0e10cSrcweir aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha); 688*cdf0e10cSrcweir aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha); 689*cdf0e10cSrcweir return aRes; 690*cdf0e10cSrcweir } 691*cdf0e10cSrcweir else if( rLeft.getLength() == 4 ) 692*cdf0e10cSrcweir { 693*cdf0e10cSrcweir uno::Sequence<double> aRes(4); 694*cdf0e10cSrcweir aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha); 695*cdf0e10cSrcweir aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha); 696*cdf0e10cSrcweir aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha); 697*cdf0e10cSrcweir aRes[3] = basegfx::tools::lerp(rLeft[3],rRight[3],fAlpha); 698*cdf0e10cSrcweir return aRes; 699*cdf0e10cSrcweir } 700*cdf0e10cSrcweir 701*cdf0e10cSrcweir return uno::Sequence<double>(); 702*cdf0e10cSrcweir } 703*cdf0e10cSrcweir 704*cdf0e10cSrcweir static Pattern* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon& rPolygon ) 705*cdf0e10cSrcweir { 706*cdf0e10cSrcweir Pattern* pPattern = NULL; 707*cdf0e10cSrcweir const ::canvas::ParametricPolyPolygon::Values aValues = rPolygon.getValues(); 708*cdf0e10cSrcweir double x0, x1, y0, y1, cx, cy, r0, r1; 709*cdf0e10cSrcweir 710*cdf0e10cSrcweir // undef macros from vclenum.hxx which conflicts with GradientType enum values 711*cdf0e10cSrcweir #undef GRADIENT_LINEAR 712*cdf0e10cSrcweir #undef GRADIENT_ELLIPTICAL 713*cdf0e10cSrcweir 714*cdf0e10cSrcweir switch( aValues.meType ) { 715*cdf0e10cSrcweir case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR: 716*cdf0e10cSrcweir x0 = 0; 717*cdf0e10cSrcweir y0 = 0; 718*cdf0e10cSrcweir x1 = 1; 719*cdf0e10cSrcweir y1 = 0; 720*cdf0e10cSrcweir pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 ); 721*cdf0e10cSrcweir addColorStops( pPattern, aValues.maColors, aValues.maStops ); 722*cdf0e10cSrcweir break; 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL: 725*cdf0e10cSrcweir cx = 0; 726*cdf0e10cSrcweir cy = 0; 727*cdf0e10cSrcweir r0 = 0; 728*cdf0e10cSrcweir r1 = 1; 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 ); 731*cdf0e10cSrcweir addColorStops( pPattern, aValues.maColors, aValues.maStops, true ); 732*cdf0e10cSrcweir break; 733*cdf0e10cSrcweir default: 734*cdf0e10cSrcweir break; 735*cdf0e10cSrcweir } 736*cdf0e10cSrcweir 737*cdf0e10cSrcweir return pPattern; 738*cdf0e10cSrcweir } 739*cdf0e10cSrcweir 740*cdf0e10cSrcweir static void doOperation( Operation aOperation, 741*cdf0e10cSrcweir Cairo* pCairo, 742*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >* pTextures, 743*cdf0e10cSrcweir const SurfaceProviderRef& pDevice, 744*cdf0e10cSrcweir const basegfx::B2DRange& rBounds ) 745*cdf0e10cSrcweir { 746*cdf0e10cSrcweir switch( aOperation ) { 747*cdf0e10cSrcweir case Fill: 748*cdf0e10cSrcweir /* TODO: multitexturing */ 749*cdf0e10cSrcweir if( pTextures ) { 750*cdf0e10cSrcweir const ::com::sun::star::rendering::Texture& aTexture ( (*pTextures)[0] ); 751*cdf0e10cSrcweir if( aTexture.Bitmap.is() ) { 752*cdf0e10cSrcweir unsigned char* data = NULL; 753*cdf0e10cSrcweir bool bHasAlpha = false; 754*cdf0e10cSrcweir SurfaceSharedPtr pSurface = surfaceFromXBitmap( (*pTextures)[0].Bitmap, pDevice, data, bHasAlpha ); 755*cdf0e10cSrcweir 756*cdf0e10cSrcweir if( pSurface ) { 757*cdf0e10cSrcweir cairo_pattern_t* pPattern; 758*cdf0e10cSrcweir 759*cdf0e10cSrcweir cairo_save( pCairo ); 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir ::com::sun::star::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform ); 762*cdf0e10cSrcweir Matrix aScaleMatrix, aTextureMatrix, aScaledTextureMatrix; 763*cdf0e10cSrcweir 764*cdf0e10cSrcweir cairo_matrix_init( &aTextureMatrix, 765*cdf0e10cSrcweir aTransform.m00, aTransform.m10, aTransform.m01, 766*cdf0e10cSrcweir aTransform.m11, aTransform.m02, aTransform.m12); 767*cdf0e10cSrcweir 768*cdf0e10cSrcweir geometry::IntegerSize2D aSize = aTexture.Bitmap->getSize(); 769*cdf0e10cSrcweir 770*cdf0e10cSrcweir cairo_matrix_init_scale( &aScaleMatrix, 1.0/aSize.Width, 1.0/aSize.Height ); 771*cdf0e10cSrcweir cairo_matrix_multiply( &aScaledTextureMatrix, &aTextureMatrix, &aScaleMatrix ); 772*cdf0e10cSrcweir cairo_matrix_invert( &aScaledTextureMatrix ); 773*cdf0e10cSrcweir 774*cdf0e10cSrcweir // we don't care about repeat mode yet, so the workaround is disabled for now 775*cdf0e10cSrcweir pPattern = cairo_pattern_create_for_surface( pSurface->getCairoSurface().get() ); 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir if( aTexture.RepeatModeX == rendering::TexturingMode::REPEAT && 778*cdf0e10cSrcweir aTexture.RepeatModeY == rendering::TexturingMode::REPEAT ) 779*cdf0e10cSrcweir { 780*cdf0e10cSrcweir cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_REPEAT ); 781*cdf0e10cSrcweir } 782*cdf0e10cSrcweir else if ( aTexture.RepeatModeX == rendering::TexturingMode::NONE && 783*cdf0e10cSrcweir aTexture.RepeatModeY == rendering::TexturingMode::NONE ) 784*cdf0e10cSrcweir { 785*cdf0e10cSrcweir cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_NONE ); 786*cdf0e10cSrcweir } 787*cdf0e10cSrcweir else if ( aTexture.RepeatModeX == rendering::TexturingMode::CLAMP && 788*cdf0e10cSrcweir aTexture.RepeatModeY == rendering::TexturingMode::CLAMP ) 789*cdf0e10cSrcweir { 790*cdf0e10cSrcweir cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_PAD ); 791*cdf0e10cSrcweir } 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir aScaledTextureMatrix.x0 = basegfx::fround( aScaledTextureMatrix.x0 ); 794*cdf0e10cSrcweir aScaledTextureMatrix.y0 = basegfx::fround( aScaledTextureMatrix.y0 ); 795*cdf0e10cSrcweir cairo_pattern_set_matrix( pPattern, &aScaledTextureMatrix ); 796*cdf0e10cSrcweir 797*cdf0e10cSrcweir cairo_set_source( pCairo, pPattern ); 798*cdf0e10cSrcweir if( !bHasAlpha ) 799*cdf0e10cSrcweir cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE ); 800*cdf0e10cSrcweir cairo_fill( pCairo ); 801*cdf0e10cSrcweir 802*cdf0e10cSrcweir cairo_restore( pCairo ); 803*cdf0e10cSrcweir 804*cdf0e10cSrcweir cairo_pattern_destroy( pPattern ); 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir 807*cdf0e10cSrcweir if( data ) 808*cdf0e10cSrcweir free( data ); 809*cdf0e10cSrcweir } else if( aTexture.Gradient.is() ) { 810*cdf0e10cSrcweir uno::Reference< lang::XServiceInfo > xRef( aTexture.Gradient, uno::UNO_QUERY ); 811*cdf0e10cSrcweir 812*cdf0e10cSrcweir OSL_TRACE( "gradient fill" ); 813*cdf0e10cSrcweir if( xRef.is() && 814*cdf0e10cSrcweir xRef->getImplementationName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME ) ) ) ) { 815*cdf0e10cSrcweir // TODO(Q1): Maybe use dynamic_cast here 816*cdf0e10cSrcweir 817*cdf0e10cSrcweir // TODO(E1): Return value 818*cdf0e10cSrcweir // TODO(F1): FillRule 819*cdf0e10cSrcweir OSL_TRACE( "known implementation" ); 820*cdf0e10cSrcweir 821*cdf0e10cSrcweir ::canvas::ParametricPolyPolygon* pPolyImpl = static_cast< ::canvas::ParametricPolyPolygon* >( aTexture.Gradient.get() ); 822*cdf0e10cSrcweir ::com::sun::star::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform ); 823*cdf0e10cSrcweir Matrix aTextureMatrix; 824*cdf0e10cSrcweir 825*cdf0e10cSrcweir cairo_matrix_init( &aTextureMatrix, 826*cdf0e10cSrcweir aTransform.m00, aTransform.m10, aTransform.m01, 827*cdf0e10cSrcweir aTransform.m11, aTransform.m02, aTransform.m12); 828*cdf0e10cSrcweir if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR ) 829*cdf0e10cSrcweir { 830*cdf0e10cSrcweir // no general path gradient yet in cairo; emulate then 831*cdf0e10cSrcweir cairo_save( pCairo ); 832*cdf0e10cSrcweir cairo_clip( pCairo ); 833*cdf0e10cSrcweir 834*cdf0e10cSrcweir // fill bound rect with start color 835*cdf0e10cSrcweir cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(), 836*cdf0e10cSrcweir rBounds.getWidth(), rBounds.getHeight() ); 837*cdf0e10cSrcweir setColor(pCairo,pPolyImpl->getValues().maColors[0]); 838*cdf0e10cSrcweir cairo_fill(pCairo); 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir cairo_transform( pCairo, &aTextureMatrix ); 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir // longest line in gradient bound rect 843*cdf0e10cSrcweir const unsigned int nGradientSize( 844*cdf0e10cSrcweir static_cast<unsigned int>( 845*cdf0e10cSrcweir ::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) ); 846*cdf0e10cSrcweir 847*cdf0e10cSrcweir // typical number for pixel of the same color (strip size) 848*cdf0e10cSrcweir const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 ); 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir // use at least three steps, and at utmost the number of color 851*cdf0e10cSrcweir // steps 852*cdf0e10cSrcweir const unsigned int nStepCount( 853*cdf0e10cSrcweir ::std::max( 854*cdf0e10cSrcweir 3U, 855*cdf0e10cSrcweir ::std::min( 856*cdf0e10cSrcweir nGradientSize / nStripSize, 857*cdf0e10cSrcweir 128U )) + 1 ); 858*cdf0e10cSrcweir 859*cdf0e10cSrcweir const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0]; 860*cdf0e10cSrcweir basegfx::tools::KeyStopLerp aLerper(pPolyImpl->getValues().maStops); 861*cdf0e10cSrcweir for( unsigned int i=1; i<nStepCount; ++i ) 862*cdf0e10cSrcweir { 863*cdf0e10cSrcweir const double fT( i/double(nStepCount) ); 864*cdf0e10cSrcweir 865*cdf0e10cSrcweir std::ptrdiff_t nIndex; 866*cdf0e10cSrcweir double fAlpha; 867*cdf0e10cSrcweir boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT); 868*cdf0e10cSrcweir 869*cdf0e10cSrcweir setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha)); 870*cdf0e10cSrcweir cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT ); 871*cdf0e10cSrcweir cairo_fill(pCairo); 872*cdf0e10cSrcweir } 873*cdf0e10cSrcweir 874*cdf0e10cSrcweir cairo_restore( pCairo ); 875*cdf0e10cSrcweir } 876*cdf0e10cSrcweir else 877*cdf0e10cSrcweir { 878*cdf0e10cSrcweir Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl ); 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir if( pPattern ) { 881*cdf0e10cSrcweir OSL_TRACE( "filling with pattern" ); 882*cdf0e10cSrcweir 883*cdf0e10cSrcweir cairo_save( pCairo ); 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir cairo_transform( pCairo, &aTextureMatrix ); 886*cdf0e10cSrcweir cairo_set_source( pCairo, pPattern ); 887*cdf0e10cSrcweir cairo_fill( pCairo ); 888*cdf0e10cSrcweir cairo_restore( pCairo ); 889*cdf0e10cSrcweir 890*cdf0e10cSrcweir cairo_pattern_destroy( pPattern ); 891*cdf0e10cSrcweir } 892*cdf0e10cSrcweir } 893*cdf0e10cSrcweir } 894*cdf0e10cSrcweir } 895*cdf0e10cSrcweir } else 896*cdf0e10cSrcweir cairo_fill( pCairo ); 897*cdf0e10cSrcweir OSL_TRACE("fill"); 898*cdf0e10cSrcweir break; 899*cdf0e10cSrcweir case Stroke: 900*cdf0e10cSrcweir cairo_stroke( pCairo ); 901*cdf0e10cSrcweir OSL_TRACE("stroke"); 902*cdf0e10cSrcweir break; 903*cdf0e10cSrcweir case Clip: 904*cdf0e10cSrcweir cairo_clip( pCairo ); 905*cdf0e10cSrcweir OSL_TRACE("clip"); 906*cdf0e10cSrcweir break; 907*cdf0e10cSrcweir } 908*cdf0e10cSrcweir } 909*cdf0e10cSrcweir 910*cdf0e10cSrcweir static void clipNULL( Cairo *pCairo ) 911*cdf0e10cSrcweir { 912*cdf0e10cSrcweir OSL_TRACE("clipNULL"); 913*cdf0e10cSrcweir Matrix aOrigMatrix, aIdentityMatrix; 914*cdf0e10cSrcweir 915*cdf0e10cSrcweir /* we set identity matrix here to overcome bug in cairo 0.9.2 916*cdf0e10cSrcweir where XCreatePixmap is called with zero width and height. 917*cdf0e10cSrcweir 918*cdf0e10cSrcweir it also reaches faster path in cairo clipping code. 919*cdf0e10cSrcweir */ 920*cdf0e10cSrcweir cairo_matrix_init_identity( &aIdentityMatrix ); 921*cdf0e10cSrcweir cairo_get_matrix( pCairo, &aOrigMatrix ); 922*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aIdentityMatrix ); 923*cdf0e10cSrcweir 924*cdf0e10cSrcweir cairo_reset_clip( pCairo ); 925*cdf0e10cSrcweir cairo_rectangle( pCairo, 0, 0, 1, 1 ); 926*cdf0e10cSrcweir cairo_clip( pCairo ); 927*cdf0e10cSrcweir cairo_rectangle( pCairo, 2, 0, 1, 1 ); 928*cdf0e10cSrcweir cairo_clip( pCairo ); 929*cdf0e10cSrcweir 930*cdf0e10cSrcweir /* restore the original matrix */ 931*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aOrigMatrix ); 932*cdf0e10cSrcweir } 933*cdf0e10cSrcweir 934*cdf0e10cSrcweir void doPolyPolygonImplementation( ::basegfx::B2DPolyPolygon aPolyPolygon, 935*cdf0e10cSrcweir Operation aOperation, 936*cdf0e10cSrcweir Cairo* pCairo, 937*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >* pTextures, 938*cdf0e10cSrcweir const SurfaceProviderRef& pDevice, 939*cdf0e10cSrcweir rendering::FillRule eFillrule ) 940*cdf0e10cSrcweir { 941*cdf0e10cSrcweir if( pTextures ) 942*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pTextures->getLength(), 943*cdf0e10cSrcweir "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence"); 944*cdf0e10cSrcweir 945*cdf0e10cSrcweir bool bOpToDo = false; 946*cdf0e10cSrcweir Matrix aOrigMatrix, aIdentityMatrix; 947*cdf0e10cSrcweir double nX, nY, nBX, nBY, nAX, nAY; 948*cdf0e10cSrcweir 949*cdf0e10cSrcweir cairo_get_matrix( pCairo, &aOrigMatrix ); 950*cdf0e10cSrcweir cairo_matrix_init_identity( &aIdentityMatrix ); 951*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aIdentityMatrix ); 952*cdf0e10cSrcweir 953*cdf0e10cSrcweir cairo_set_fill_rule( pCairo, 954*cdf0e10cSrcweir eFillrule == rendering::FillRule_EVEN_ODD ? 955*cdf0e10cSrcweir CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING ); 956*cdf0e10cSrcweir 957*cdf0e10cSrcweir for( sal_uInt32 nPolygonIndex = 0; nPolygonIndex < aPolyPolygon.count(); nPolygonIndex++ ) { 958*cdf0e10cSrcweir ::basegfx::B2DPolygon aPolygon( aPolyPolygon.getB2DPolygon( nPolygonIndex ) ); 959*cdf0e10cSrcweir const sal_uInt32 nPointCount( aPolygon.count() ); 960*cdf0e10cSrcweir // to correctly render closed curves, need to output first 961*cdf0e10cSrcweir // point twice (so output one additional point) 962*cdf0e10cSrcweir const sal_uInt32 nExtendedPointCount( nPointCount + 963*cdf0e10cSrcweir aPolygon.isClosed()*aPolygon.areControlPointsUsed() ); 964*cdf0e10cSrcweir 965*cdf0e10cSrcweir if( nPointCount > 1) { 966*cdf0e10cSrcweir bool bIsBezier = aPolygon.areControlPointsUsed(); 967*cdf0e10cSrcweir bool bIsRectangle = ::basegfx::tools::isRectangle( aPolygon ); 968*cdf0e10cSrcweir ::basegfx::B2DPoint aA, aB, aP; 969*cdf0e10cSrcweir 970*cdf0e10cSrcweir for( sal_uInt32 j=0; j < nExtendedPointCount; j++ ) { 971*cdf0e10cSrcweir aP = aPolygon.getB2DPoint( j % nPointCount ); 972*cdf0e10cSrcweir 973*cdf0e10cSrcweir nX = aP.getX(); 974*cdf0e10cSrcweir nY = aP.getY(); 975*cdf0e10cSrcweir cairo_matrix_transform_point( &aOrigMatrix, &nX, &nY ); 976*cdf0e10cSrcweir 977*cdf0e10cSrcweir if( ! bIsBezier && (bIsRectangle || aOperation == Clip) ) { 978*cdf0e10cSrcweir nX = basegfx::fround( nX ); 979*cdf0e10cSrcweir nY = basegfx::fround( nY ); 980*cdf0e10cSrcweir } 981*cdf0e10cSrcweir 982*cdf0e10cSrcweir if( aOperation == Stroke ) { 983*cdf0e10cSrcweir nX += 0.5; 984*cdf0e10cSrcweir nY += 0.5; 985*cdf0e10cSrcweir } 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir if( j==0 ) 988*cdf0e10cSrcweir { 989*cdf0e10cSrcweir cairo_move_to( pCairo, nX, nY ); 990*cdf0e10cSrcweir OSL_TRACE( "move to %f,%f", nX, nY ); 991*cdf0e10cSrcweir } 992*cdf0e10cSrcweir else { 993*cdf0e10cSrcweir if( bIsBezier ) { 994*cdf0e10cSrcweir aA = aPolygon.getNextControlPoint( (j-1) % nPointCount ); 995*cdf0e10cSrcweir aB = aPolygon.getPrevControlPoint( j % nPointCount ); 996*cdf0e10cSrcweir 997*cdf0e10cSrcweir nAX = aA.getX(); 998*cdf0e10cSrcweir nAY = aA.getY(); 999*cdf0e10cSrcweir nBX = aB.getX(); 1000*cdf0e10cSrcweir nBY = aB.getY(); 1001*cdf0e10cSrcweir 1002*cdf0e10cSrcweir if( aOperation == Stroke ) { 1003*cdf0e10cSrcweir nAX += 0.5; 1004*cdf0e10cSrcweir nAY += 0.5; 1005*cdf0e10cSrcweir nBX += 0.5; 1006*cdf0e10cSrcweir nBY += 0.5; 1007*cdf0e10cSrcweir } 1008*cdf0e10cSrcweir cairo_matrix_transform_point( &aOrigMatrix, &nAX, &nAY ); 1009*cdf0e10cSrcweir cairo_matrix_transform_point( &aOrigMatrix, &nBX, &nBY ); 1010*cdf0e10cSrcweir cairo_curve_to( pCairo, nAX, nAY, nBX, nBY, nX, nY ); 1011*cdf0e10cSrcweir } else { 1012*cdf0e10cSrcweir cairo_line_to( pCairo, nX, nY ); 1013*cdf0e10cSrcweir OSL_TRACE( "line to %f,%f", nX, nY ); 1014*cdf0e10cSrcweir } 1015*cdf0e10cSrcweir bOpToDo = true; 1016*cdf0e10cSrcweir } 1017*cdf0e10cSrcweir } 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir if( aPolygon.isClosed() ) 1020*cdf0e10cSrcweir cairo_close_path( pCairo ); 1021*cdf0e10cSrcweir 1022*cdf0e10cSrcweir if( aOperation == Fill && pTextures ) { 1023*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aOrigMatrix ); 1024*cdf0e10cSrcweir doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() ); 1025*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aIdentityMatrix ); 1026*cdf0e10cSrcweir } 1027*cdf0e10cSrcweir } else { 1028*cdf0e10cSrcweir OSL_TRACE( "empty polygon for op: %d\n", aOperation ); 1029*cdf0e10cSrcweir if( aOperation == Clip ) { 1030*cdf0e10cSrcweir clipNULL( pCairo ); 1031*cdf0e10cSrcweir 1032*cdf0e10cSrcweir return; 1033*cdf0e10cSrcweir } 1034*cdf0e10cSrcweir } 1035*cdf0e10cSrcweir } 1036*cdf0e10cSrcweir if( bOpToDo && ( aOperation != Fill || !pTextures ) ) 1037*cdf0e10cSrcweir doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() ); 1038*cdf0e10cSrcweir 1039*cdf0e10cSrcweir cairo_set_matrix( pCairo, &aOrigMatrix ); 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir if( aPolyPolygon.count() == 0 && aOperation == Clip ) 1042*cdf0e10cSrcweir clipNULL( pCairo ); 1043*cdf0e10cSrcweir } 1044*cdf0e10cSrcweir 1045*cdf0e10cSrcweir void CanvasHelper::doPolyPolygonPath( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 1046*cdf0e10cSrcweir Operation aOperation, 1047*cdf0e10cSrcweir bool bNoLineJoin, 1048*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >* pTextures, 1049*cdf0e10cSrcweir Cairo* pCairo ) const 1050*cdf0e10cSrcweir { 1051*cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPoly( 1052*cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) ); 1053*cdf0e10cSrcweir 1054*cdf0e10cSrcweir if( !pCairo ) 1055*cdf0e10cSrcweir pCairo = mpCairo.get(); 1056*cdf0e10cSrcweir 1057*cdf0e10cSrcweir if(bNoLineJoin && Stroke == aOperation) 1058*cdf0e10cSrcweir { 1059*cdf0e10cSrcweir // emulate rendering::PathJoinType::NONE by painting single edges 1060*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rPolyPoly.count(); a++) 1061*cdf0e10cSrcweir { 1062*cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(rPolyPoly.getB2DPolygon(a)); 1063*cdf0e10cSrcweir const sal_uInt32 nPointCount(aCandidate.count()); 1064*cdf0e10cSrcweir 1065*cdf0e10cSrcweir if(nPointCount) 1066*cdf0e10cSrcweir { 1067*cdf0e10cSrcweir const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1: nPointCount); 1068*cdf0e10cSrcweir basegfx::B2DPolygon aEdge; 1069*cdf0e10cSrcweir aEdge.append(aCandidate.getB2DPoint(0)); 1070*cdf0e10cSrcweir aEdge.append(basegfx::B2DPoint(0.0, 0.0)); 1071*cdf0e10cSrcweir 1072*cdf0e10cSrcweir for(sal_uInt32 b(0); b < nEdgeCount; b++) 1073*cdf0e10cSrcweir { 1074*cdf0e10cSrcweir const sal_uInt32 nNextIndex((b + 1) % nPointCount); 1075*cdf0e10cSrcweir aEdge.setB2DPoint(1, aCandidate.getB2DPoint(nNextIndex)); 1076*cdf0e10cSrcweir aEdge.setNextControlPoint(0, aCandidate.getNextControlPoint(b)); 1077*cdf0e10cSrcweir aEdge.setPrevControlPoint(1, aCandidate.getPrevControlPoint(nNextIndex)); 1078*cdf0e10cSrcweir 1079*cdf0e10cSrcweir doPolyPolygonImplementation( basegfx::B2DPolyPolygon(aEdge), 1080*cdf0e10cSrcweir aOperation, 1081*cdf0e10cSrcweir pCairo, pTextures, 1082*cdf0e10cSrcweir mpSurfaceProvider, 1083*cdf0e10cSrcweir xPolyPolygon->getFillRule() ); 1084*cdf0e10cSrcweir 1085*cdf0e10cSrcweir // prepare next step 1086*cdf0e10cSrcweir aEdge.setB2DPoint(0, aEdge.getB2DPoint(1)); 1087*cdf0e10cSrcweir } 1088*cdf0e10cSrcweir } 1089*cdf0e10cSrcweir } 1090*cdf0e10cSrcweir } 1091*cdf0e10cSrcweir else 1092*cdf0e10cSrcweir { 1093*cdf0e10cSrcweir doPolyPolygonImplementation( rPolyPoly, aOperation, 1094*cdf0e10cSrcweir pCairo, pTextures, 1095*cdf0e10cSrcweir mpSurfaceProvider, 1096*cdf0e10cSrcweir xPolyPolygon->getFillRule() ); 1097*cdf0e10cSrcweir } 1098*cdf0e10cSrcweir } 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* , 1101*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 1102*cdf0e10cSrcweir const rendering::ViewState& viewState, 1103*cdf0e10cSrcweir const rendering::RenderState& renderState ) 1104*cdf0e10cSrcweir { 1105*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1106*cdf0e10cSrcweir struct timespec aTimer; 1107*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1108*cdf0e10cSrcweir #endif 1109*cdf0e10cSrcweir 1110*cdf0e10cSrcweir if( mpCairo ) { 1111*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1112*cdf0e10cSrcweir 1113*cdf0e10cSrcweir cairo_set_line_width( mpCairo.get(), 1 ); 1114*cdf0e10cSrcweir 1115*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1116*cdf0e10cSrcweir doPolyPolygonPath( xPolyPolygon, Stroke ); 1117*cdf0e10cSrcweir 1118*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1119*cdf0e10cSrcweir } else 1120*cdf0e10cSrcweir OSL_TRACE ("CanvasHelper called after it was disposed"); 1121*cdf0e10cSrcweir 1122*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1123*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "drawPolyPolygon" ); 1124*cdf0e10cSrcweir #endif 1125*cdf0e10cSrcweir 1126*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1127*cdf0e10cSrcweir } 1128*cdf0e10cSrcweir 1129*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* , 1130*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 1131*cdf0e10cSrcweir const rendering::ViewState& viewState, 1132*cdf0e10cSrcweir const rendering::RenderState& renderState, 1133*cdf0e10cSrcweir const rendering::StrokeAttributes& strokeAttributes ) 1134*cdf0e10cSrcweir { 1135*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1136*cdf0e10cSrcweir struct timespec aTimer; 1137*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1138*cdf0e10cSrcweir #endif 1139*cdf0e10cSrcweir 1140*cdf0e10cSrcweir if( mpCairo ) { 1141*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1142*cdf0e10cSrcweir 1143*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1144*cdf0e10cSrcweir 1145*cdf0e10cSrcweir Matrix aMatrix; 1146*cdf0e10cSrcweir double w = strokeAttributes.StrokeWidth, h = 0; 1147*cdf0e10cSrcweir cairo_get_matrix( mpCairo.get(), &aMatrix ); 1148*cdf0e10cSrcweir cairo_matrix_transform_distance( &aMatrix, &w, &h ); 1149*cdf0e10cSrcweir cairo_set_line_width( mpCairo.get(), w ); 1150*cdf0e10cSrcweir 1151*cdf0e10cSrcweir cairo_set_miter_limit( mpCairo.get(), strokeAttributes.MiterLimit ); 1152*cdf0e10cSrcweir 1153*cdf0e10cSrcweir // FIXME: cairo doesn't handle end cap so far (rodo) 1154*cdf0e10cSrcweir switch( strokeAttributes.StartCapType ) { 1155*cdf0e10cSrcweir case rendering::PathCapType::BUTT: 1156*cdf0e10cSrcweir cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_BUTT ); 1157*cdf0e10cSrcweir break; 1158*cdf0e10cSrcweir case rendering::PathCapType::ROUND: 1159*cdf0e10cSrcweir cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_ROUND ); 1160*cdf0e10cSrcweir break; 1161*cdf0e10cSrcweir case rendering::PathCapType::SQUARE: 1162*cdf0e10cSrcweir cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_SQUARE ); 1163*cdf0e10cSrcweir break; 1164*cdf0e10cSrcweir } 1165*cdf0e10cSrcweir 1166*cdf0e10cSrcweir bool bNoLineJoin(false); 1167*cdf0e10cSrcweir 1168*cdf0e10cSrcweir switch( strokeAttributes.JoinType ) { 1169*cdf0e10cSrcweir // cairo doesn't have join type NONE so we use MITER as it's pretty close 1170*cdf0e10cSrcweir case rendering::PathJoinType::NONE: 1171*cdf0e10cSrcweir bNoLineJoin = true; 1172*cdf0e10cSrcweir case rendering::PathJoinType::MITER: 1173*cdf0e10cSrcweir cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_MITER ); 1174*cdf0e10cSrcweir break; 1175*cdf0e10cSrcweir case rendering::PathJoinType::ROUND: 1176*cdf0e10cSrcweir cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_ROUND ); 1177*cdf0e10cSrcweir break; 1178*cdf0e10cSrcweir case rendering::PathJoinType::BEVEL: 1179*cdf0e10cSrcweir cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_BEVEL ); 1180*cdf0e10cSrcweir break; 1181*cdf0e10cSrcweir } 1182*cdf0e10cSrcweir 1183*cdf0e10cSrcweir if( strokeAttributes.DashArray.getLength() > 0 ) { 1184*cdf0e10cSrcweir double* pDashArray = new double[ strokeAttributes.DashArray.getLength() ]; 1185*cdf0e10cSrcweir for( sal_Int32 i=0; i<strokeAttributes.DashArray.getLength(); i++ ) 1186*cdf0e10cSrcweir pDashArray[i]=strokeAttributes.DashArray[i]; 1187*cdf0e10cSrcweir cairo_set_dash( mpCairo.get(), pDashArray, strokeAttributes.DashArray.getLength(), 0 ); 1188*cdf0e10cSrcweir delete[] pDashArray; 1189*cdf0e10cSrcweir } 1190*cdf0e10cSrcweir 1191*cdf0e10cSrcweir // TODO(rodo) use LineArray of strokeAttributes 1192*cdf0e10cSrcweir 1193*cdf0e10cSrcweir doPolyPolygonPath( xPolyPolygon, Stroke, bNoLineJoin ); 1194*cdf0e10cSrcweir 1195*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1196*cdf0e10cSrcweir } else 1197*cdf0e10cSrcweir OSL_TRACE ("CanvasHelper called after it was disposed"); 1198*cdf0e10cSrcweir 1199*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1200*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "strokePolyPolygon" ); 1201*cdf0e10cSrcweir #endif 1202*cdf0e10cSrcweir 1203*cdf0e10cSrcweir // TODO(P1): Provide caching here. 1204*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1205*cdf0e10cSrcweir } 1206*cdf0e10cSrcweir 1207*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* , 1208*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, 1209*cdf0e10cSrcweir const rendering::ViewState& /*viewState*/, 1210*cdf0e10cSrcweir const rendering::RenderState& /*renderState*/, 1211*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& /*textures*/, 1212*cdf0e10cSrcweir const rendering::StrokeAttributes& /*strokeAttributes*/ ) 1213*cdf0e10cSrcweir { 1214*cdf0e10cSrcweir // TODO 1215*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1216*cdf0e10cSrcweir } 1217*cdf0e10cSrcweir 1218*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* , 1219*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, 1220*cdf0e10cSrcweir const rendering::ViewState& /*viewState*/, 1221*cdf0e10cSrcweir const rendering::RenderState& /*renderState*/, 1222*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& /*textures*/, 1223*cdf0e10cSrcweir const uno::Reference< geometry::XMapping2D >& /*xMapping*/, 1224*cdf0e10cSrcweir const rendering::StrokeAttributes& /*strokeAttributes*/ ) 1225*cdf0e10cSrcweir { 1226*cdf0e10cSrcweir // TODO 1227*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1228*cdf0e10cSrcweir } 1229*cdf0e10cSrcweir 1230*cdf0e10cSrcweir uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* , 1231*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, 1232*cdf0e10cSrcweir const rendering::ViewState& /*viewState*/, 1233*cdf0e10cSrcweir const rendering::RenderState& /*renderState*/, 1234*cdf0e10cSrcweir const rendering::StrokeAttributes& /*strokeAttributes*/ ) 1235*cdf0e10cSrcweir { 1236*cdf0e10cSrcweir // TODO 1237*cdf0e10cSrcweir return uno::Reference< rendering::XPolyPolygon2D >(NULL); 1238*cdf0e10cSrcweir } 1239*cdf0e10cSrcweir 1240*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* , 1241*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 1242*cdf0e10cSrcweir const rendering::ViewState& viewState, 1243*cdf0e10cSrcweir const rendering::RenderState& renderState ) 1244*cdf0e10cSrcweir { 1245*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1246*cdf0e10cSrcweir struct timespec aTimer; 1247*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1248*cdf0e10cSrcweir #endif 1249*cdf0e10cSrcweir 1250*cdf0e10cSrcweir if( mpCairo ) { 1251*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1252*cdf0e10cSrcweir 1253*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1254*cdf0e10cSrcweir doPolyPolygonPath( xPolyPolygon, Fill ); 1255*cdf0e10cSrcweir 1256*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1257*cdf0e10cSrcweir } else 1258*cdf0e10cSrcweir OSL_TRACE ("CanvasHelper called after it was disposed"); 1259*cdf0e10cSrcweir 1260*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1261*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "fillPolyPolygon" ); 1262*cdf0e10cSrcweir #endif 1263*cdf0e10cSrcweir 1264*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1265*cdf0e10cSrcweir } 1266*cdf0e10cSrcweir 1267*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* , 1268*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 1269*cdf0e10cSrcweir const rendering::ViewState& viewState, 1270*cdf0e10cSrcweir const rendering::RenderState& renderState, 1271*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& textures ) 1272*cdf0e10cSrcweir { 1273*cdf0e10cSrcweir if( mpCairo ) { 1274*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1275*cdf0e10cSrcweir 1276*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1277*cdf0e10cSrcweir doPolyPolygonPath( xPolyPolygon, Fill, false, &textures ); 1278*cdf0e10cSrcweir 1279*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1280*cdf0e10cSrcweir } 1281*cdf0e10cSrcweir 1282*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1283*cdf0e10cSrcweir } 1284*cdf0e10cSrcweir 1285*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* , 1286*cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, 1287*cdf0e10cSrcweir const rendering::ViewState& /*viewState*/, 1288*cdf0e10cSrcweir const rendering::RenderState& /*renderState*/, 1289*cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& /*textures*/, 1290*cdf0e10cSrcweir const uno::Reference< geometry::XMapping2D >& /*xMapping*/ ) 1291*cdf0e10cSrcweir { 1292*cdf0e10cSrcweir // TODO 1293*cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 1294*cdf0e10cSrcweir } 1295*cdf0e10cSrcweir 1296*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::implDrawBitmapSurface( const rendering::XCanvas* pCanvas, 1297*cdf0e10cSrcweir const SurfaceSharedPtr& pInputSurface, 1298*cdf0e10cSrcweir const rendering::ViewState& viewState, 1299*cdf0e10cSrcweir const rendering::RenderState& renderState, 1300*cdf0e10cSrcweir const geometry::IntegerSize2D& rSize, 1301*cdf0e10cSrcweir bool bModulateColors, 1302*cdf0e10cSrcweir bool bHasAlpha ) 1303*cdf0e10cSrcweir { 1304*cdf0e10cSrcweir SurfaceSharedPtr pSurface=pInputSurface; 1305*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > rv = uno::Reference< rendering::XCachedPrimitive >(NULL); 1306*cdf0e10cSrcweir geometry::IntegerSize2D aBitmapSize = rSize; 1307*cdf0e10cSrcweir 1308*cdf0e10cSrcweir if( mpCairo ) { 1309*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1310*cdf0e10cSrcweir 1311*cdf0e10cSrcweir cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); 1312*cdf0e10cSrcweir cairo_clip( mpCairo.get() ); 1313*cdf0e10cSrcweir 1314*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1315*cdf0e10cSrcweir 1316*cdf0e10cSrcweir // if( !bHasAlpha ) 1317*cdf0e10cSrcweir // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); 1318*cdf0e10cSrcweir 1319*cdf0e10cSrcweir Matrix aMatrix; 1320*cdf0e10cSrcweir 1321*cdf0e10cSrcweir cairo_get_matrix( mpCairo.get(), &aMatrix ); 1322*cdf0e10cSrcweir if( ! ::rtl::math::approxEqual( aMatrix.xx, 1 ) && 1323*cdf0e10cSrcweir ! ::rtl::math::approxEqual( aMatrix.yy, 1 ) && 1324*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.x0, 0 ) && 1325*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.y0, 0 ) && 1326*cdf0e10cSrcweir basegfx::fround( rSize.Width * aMatrix.xx ) > 8 && 1327*cdf0e10cSrcweir basegfx::fround( rSize.Height* aMatrix.yy ) > 8 ) 1328*cdf0e10cSrcweir { 1329*cdf0e10cSrcweir double dWidth, dHeight; 1330*cdf0e10cSrcweir 1331*cdf0e10cSrcweir dWidth = basegfx::fround( rSize.Width * aMatrix.xx ); 1332*cdf0e10cSrcweir dHeight = basegfx::fround( rSize.Height* aMatrix.yy ); 1333*cdf0e10cSrcweir aBitmapSize.Width = static_cast<sal_Int32>( dWidth ); 1334*cdf0e10cSrcweir aBitmapSize.Height = static_cast<sal_Int32>( dHeight ); 1335*cdf0e10cSrcweir 1336*cdf0e10cSrcweir SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface( 1337*cdf0e10cSrcweir ::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ), 1338*cdf0e10cSrcweir bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR ); 1339*cdf0e10cSrcweir CairoSharedPtr pCairo = pScaledSurface->getCairo(); 1340*cdf0e10cSrcweir 1341*cdf0e10cSrcweir cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE ); 1342*cdf0e10cSrcweir // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders 1343*cdf0e10cSrcweir cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height ); 1344*cdf0e10cSrcweir cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 ); 1345*cdf0e10cSrcweir cairo_paint( pCairo.get() ); 1346*cdf0e10cSrcweir 1347*cdf0e10cSrcweir pSurface = pScaledSurface; 1348*cdf0e10cSrcweir 1349*cdf0e10cSrcweir aMatrix.xx = aMatrix.yy = 1; 1350*cdf0e10cSrcweir cairo_set_matrix( mpCairo.get(), &aMatrix ); 1351*cdf0e10cSrcweir 1352*cdf0e10cSrcweir rv = uno::Reference< rendering::XCachedPrimitive >( 1353*cdf0e10cSrcweir new CachedBitmap( pSurface, viewState, renderState, 1354*cdf0e10cSrcweir // cast away const, need to 1355*cdf0e10cSrcweir // change refcount (as this is 1356*cdf0e10cSrcweir // ~invisible to client code, 1357*cdf0e10cSrcweir // still logically const) 1358*cdf0e10cSrcweir const_cast< rendering::XCanvas* >(pCanvas)) ); 1359*cdf0e10cSrcweir } 1360*cdf0e10cSrcweir 1361*cdf0e10cSrcweir if( !bHasAlpha && mbHaveAlpha ) 1362*cdf0e10cSrcweir { 1363*cdf0e10cSrcweir double x, y, width, height; 1364*cdf0e10cSrcweir 1365*cdf0e10cSrcweir x = y = 0; 1366*cdf0e10cSrcweir width = aBitmapSize.Width; 1367*cdf0e10cSrcweir height = aBitmapSize.Height; 1368*cdf0e10cSrcweir cairo_matrix_transform_point( &aMatrix, &x, &y ); 1369*cdf0e10cSrcweir cairo_matrix_transform_distance( &aMatrix, &width, &height ); 1370*cdf0e10cSrcweir 1371*cdf0e10cSrcweir // in case the bitmap doesn't have alpha and covers whole area 1372*cdf0e10cSrcweir // we try to change surface to plain rgb 1373*cdf0e10cSrcweir OSL_TRACE ("chance to change surface to rgb, %f, %f, %f x %f (%d x %d)", x, y, width, height, maSize.getX(), maSize.getY() ); 1374*cdf0e10cSrcweir if( x <= 0 && y <= 0 && x + width >= maSize.getX() && y + height >= maSize.getY() ) 1375*cdf0e10cSrcweir { 1376*cdf0e10cSrcweir OSL_TRACE ("trying to change surface to rgb"); 1377*cdf0e10cSrcweir if( mpSurfaceProvider ) { 1378*cdf0e10cSrcweir SurfaceSharedPtr pNewSurface = mpSurfaceProvider->changeSurface( false, false ); 1379*cdf0e10cSrcweir 1380*cdf0e10cSrcweir if( pNewSurface ) 1381*cdf0e10cSrcweir setSurface( pNewSurface, false ); 1382*cdf0e10cSrcweir 1383*cdf0e10cSrcweir // set state to new mpCairo.get() 1384*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1385*cdf0e10cSrcweir // use the possibly modified matrix 1386*cdf0e10cSrcweir cairo_set_matrix( mpCairo.get(), &aMatrix ); 1387*cdf0e10cSrcweir } 1388*cdf0e10cSrcweir } 1389*cdf0e10cSrcweir } 1390*cdf0e10cSrcweir 1391*cdf0e10cSrcweir cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 ); 1392*cdf0e10cSrcweir if( !bHasAlpha && 1393*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.xx, 1 ) && 1394*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.yy, 1 ) && 1395*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.x0, 0 ) && 1396*cdf0e10cSrcweir ::rtl::math::approxEqual( aMatrix.y0, 0 ) ) 1397*cdf0e10cSrcweir cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); 1398*cdf0e10cSrcweir cairo_pattern_set_extend( cairo_get_source(mpCairo.get()), CAIRO_EXTEND_PAD ); 1399*cdf0e10cSrcweir cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height ); 1400*cdf0e10cSrcweir cairo_clip( mpCairo.get() ); 1401*cdf0e10cSrcweir 1402*cdf0e10cSrcweir if( bModulateColors ) 1403*cdf0e10cSrcweir cairo_paint_with_alpha( mpCairo.get(), renderState.DeviceColor[3] ); 1404*cdf0e10cSrcweir else 1405*cdf0e10cSrcweir cairo_paint( mpCairo.get() ); 1406*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1407*cdf0e10cSrcweir } else 1408*cdf0e10cSrcweir OSL_TRACE ("CanvasHelper called after it was disposed"); 1409*cdf0e10cSrcweir 1410*cdf0e10cSrcweir return rv; // uno::Reference< rendering::XCachedPrimitive >(NULL); 1411*cdf0e10cSrcweir } 1412*cdf0e10cSrcweir 1413*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* pCanvas, 1414*cdf0e10cSrcweir const uno::Reference< rendering::XBitmap >& xBitmap, 1415*cdf0e10cSrcweir const rendering::ViewState& viewState, 1416*cdf0e10cSrcweir const rendering::RenderState& renderState ) 1417*cdf0e10cSrcweir { 1418*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1419*cdf0e10cSrcweir struct timespec aTimer; 1420*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1421*cdf0e10cSrcweir #endif 1422*cdf0e10cSrcweir 1423*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > rv; 1424*cdf0e10cSrcweir unsigned char* data = NULL; 1425*cdf0e10cSrcweir bool bHasAlpha = false; 1426*cdf0e10cSrcweir SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha ); 1427*cdf0e10cSrcweir geometry::IntegerSize2D aSize = xBitmap->getSize(); 1428*cdf0e10cSrcweir 1429*cdf0e10cSrcweir if( pSurface ) { 1430*cdf0e10cSrcweir rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, false, bHasAlpha ); 1431*cdf0e10cSrcweir 1432*cdf0e10cSrcweir if( data ) 1433*cdf0e10cSrcweir free( data ); 1434*cdf0e10cSrcweir } else 1435*cdf0e10cSrcweir rv = uno::Reference< rendering::XCachedPrimitive >(NULL); 1436*cdf0e10cSrcweir 1437*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1438*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "drawBitmap" ); 1439*cdf0e10cSrcweir #endif 1440*cdf0e10cSrcweir 1441*cdf0e10cSrcweir return rv; 1442*cdf0e10cSrcweir } 1443*cdf0e10cSrcweir 1444*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas, 1445*cdf0e10cSrcweir const uno::Reference< rendering::XBitmap >& xBitmap, 1446*cdf0e10cSrcweir const rendering::ViewState& viewState, 1447*cdf0e10cSrcweir const rendering::RenderState& renderState ) 1448*cdf0e10cSrcweir { 1449*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1450*cdf0e10cSrcweir struct timespec aTimer; 1451*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1452*cdf0e10cSrcweir #endif 1453*cdf0e10cSrcweir 1454*cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > rv; 1455*cdf0e10cSrcweir unsigned char* data = NULL; 1456*cdf0e10cSrcweir bool bHasAlpha = false; 1457*cdf0e10cSrcweir SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha ); 1458*cdf0e10cSrcweir geometry::IntegerSize2D aSize = xBitmap->getSize(); 1459*cdf0e10cSrcweir 1460*cdf0e10cSrcweir if( pSurface ) { 1461*cdf0e10cSrcweir rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, true, bHasAlpha ); 1462*cdf0e10cSrcweir 1463*cdf0e10cSrcweir if( data ) 1464*cdf0e10cSrcweir free( data ); 1465*cdf0e10cSrcweir } else 1466*cdf0e10cSrcweir rv = uno::Reference< rendering::XCachedPrimitive >(NULL); 1467*cdf0e10cSrcweir 1468*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1469*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "drawBitmap" ); 1470*cdf0e10cSrcweir #endif 1471*cdf0e10cSrcweir 1472*cdf0e10cSrcweir return rv; 1473*cdf0e10cSrcweir } 1474*cdf0e10cSrcweir 1475*cdf0e10cSrcweir uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice() 1476*cdf0e10cSrcweir { 1477*cdf0e10cSrcweir return uno::Reference< rendering::XGraphicDevice >(mpDevice); 1478*cdf0e10cSrcweir } 1479*cdf0e10cSrcweir 1480*cdf0e10cSrcweir void CanvasHelper::copyRect( const rendering::XCanvas* , 1481*cdf0e10cSrcweir const uno::Reference< rendering::XBitmapCanvas >& /*sourceCanvas*/, 1482*cdf0e10cSrcweir const geometry::RealRectangle2D& /*sourceRect*/, 1483*cdf0e10cSrcweir const rendering::ViewState& /*sourceViewState*/, 1484*cdf0e10cSrcweir const rendering::RenderState& /*sourceRenderState*/, 1485*cdf0e10cSrcweir const geometry::RealRectangle2D& /*destRect*/, 1486*cdf0e10cSrcweir const rendering::ViewState& /*destViewState*/, 1487*cdf0e10cSrcweir const rendering::RenderState& /*destRenderState*/ ) 1488*cdf0e10cSrcweir { 1489*cdf0e10cSrcweir // TODO(F2): copyRect NYI 1490*cdf0e10cSrcweir } 1491*cdf0e10cSrcweir 1492*cdf0e10cSrcweir geometry::IntegerSize2D CanvasHelper::getSize() 1493*cdf0e10cSrcweir { 1494*cdf0e10cSrcweir if( !mpSurfaceProvider ) 1495*cdf0e10cSrcweir geometry::IntegerSize2D(1, 1); // we're disposed 1496*cdf0e10cSrcweir 1497*cdf0e10cSrcweir return ::basegfx::unotools::integerSize2DFromB2ISize( maSize ); 1498*cdf0e10cSrcweir } 1499*cdf0e10cSrcweir 1500*cdf0e10cSrcweir uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize, 1501*cdf0e10cSrcweir sal_Bool /*beFast*/ ) 1502*cdf0e10cSrcweir { 1503*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1504*cdf0e10cSrcweir struct timespec aTimer; 1505*cdf0e10cSrcweir mxDevice->startPerfTrace( &aTimer ); 1506*cdf0e10cSrcweir #endif 1507*cdf0e10cSrcweir 1508*cdf0e10cSrcweir if( mpCairo ) { 1509*cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >( new CanvasBitmap( ::basegfx::B2ISize( ::canvas::tools::roundUp( newSize.Width ), 1510*cdf0e10cSrcweir ::canvas::tools::roundUp( newSize.Height ) ), 1511*cdf0e10cSrcweir mpSurfaceProvider, mpDevice, false ) ); 1512*cdf0e10cSrcweir } else 1513*cdf0e10cSrcweir OSL_TRACE ("CanvasHelper called after it was disposed"); 1514*cdf0e10cSrcweir 1515*cdf0e10cSrcweir #ifdef CAIRO_CANVAS_PERF_TRACE 1516*cdf0e10cSrcweir mxDevice->stopPerfTrace( &aTimer, "getScaledBitmap" ); 1517*cdf0e10cSrcweir #endif 1518*cdf0e10cSrcweir 1519*cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >(); 1520*cdf0e10cSrcweir } 1521*cdf0e10cSrcweir 1522*cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& aLayout, 1523*cdf0e10cSrcweir const geometry::IntegerRectangle2D& rect ) 1524*cdf0e10cSrcweir { 1525*cdf0e10cSrcweir if( mpCairo ) { 1526*cdf0e10cSrcweir aLayout = getMemoryLayout(); 1527*cdf0e10cSrcweir 1528*cdf0e10cSrcweir const sal_Int32 nWidth( rect.X2 - rect.X1 ); 1529*cdf0e10cSrcweir const sal_Int32 nHeight( rect.Y2 - rect.Y1 ); 1530*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight ); 1531*cdf0e10cSrcweir sal_Int8* pData = aRes.getArray(); 1532*cdf0e10cSrcweir cairo_surface_t* pImageSurface = cairo_image_surface_create_for_data( (unsigned char *) pData, 1533*cdf0e10cSrcweir CAIRO_FORMAT_ARGB32, 1534*cdf0e10cSrcweir nWidth, nHeight, 4*nWidth ); 1535*cdf0e10cSrcweir cairo_t* pCairo = cairo_create( pImageSurface ); 1536*cdf0e10cSrcweir cairo_set_source_surface( pCairo, mpSurface->getCairoSurface().get(), -rect.X1, -rect.Y1); 1537*cdf0e10cSrcweir cairo_paint( pCairo ); 1538*cdf0e10cSrcweir cairo_destroy( pCairo ); 1539*cdf0e10cSrcweir cairo_surface_destroy( pImageSurface ); 1540*cdf0e10cSrcweir 1541*cdf0e10cSrcweir aLayout.ScanLines = nHeight; 1542*cdf0e10cSrcweir aLayout.ScanLineBytes = nWidth*4; 1543*cdf0e10cSrcweir aLayout.ScanLineStride = aLayout.ScanLineBytes; 1544*cdf0e10cSrcweir 1545*cdf0e10cSrcweir return aRes; 1546*cdf0e10cSrcweir } 1547*cdf0e10cSrcweir 1548*cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); 1549*cdf0e10cSrcweir } 1550*cdf0e10cSrcweir 1551*cdf0e10cSrcweir void CanvasHelper::setData( const uno::Sequence< sal_Int8 >& /*data*/, 1552*cdf0e10cSrcweir const rendering::IntegerBitmapLayout& /*bitmapLayout*/, 1553*cdf0e10cSrcweir const geometry::IntegerRectangle2D& /*rect*/ ) 1554*cdf0e10cSrcweir { 1555*cdf0e10cSrcweir } 1556*cdf0e10cSrcweir 1557*cdf0e10cSrcweir void CanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& /*color*/, 1558*cdf0e10cSrcweir const rendering::IntegerBitmapLayout& /*bitmapLayout*/, 1559*cdf0e10cSrcweir const geometry::IntegerPoint2D& /*pos*/ ) 1560*cdf0e10cSrcweir { 1561*cdf0e10cSrcweir } 1562*cdf0e10cSrcweir 1563*cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/, 1564*cdf0e10cSrcweir const geometry::IntegerPoint2D& /*pos*/ ) 1565*cdf0e10cSrcweir { 1566*cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); 1567*cdf0e10cSrcweir } 1568*cdf0e10cSrcweir 1569*cdf0e10cSrcweir uno::Reference< rendering::XBitmapPalette > CanvasHelper::getPalette() 1570*cdf0e10cSrcweir { 1571*cdf0e10cSrcweir // TODO(F1): Palette bitmaps NYI 1572*cdf0e10cSrcweir return uno::Reference< rendering::XBitmapPalette >(); 1573*cdf0e10cSrcweir } 1574*cdf0e10cSrcweir 1575*cdf0e10cSrcweir namespace 1576*cdf0e10cSrcweir { 1577*cdf0e10cSrcweir class CairoColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace > 1578*cdf0e10cSrcweir { 1579*cdf0e10cSrcweir private: 1580*cdf0e10cSrcweir uno::Sequence< sal_Int8 > maComponentTags; 1581*cdf0e10cSrcweir uno::Sequence< sal_Int32 > maBitCounts; 1582*cdf0e10cSrcweir 1583*cdf0e10cSrcweir virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) 1584*cdf0e10cSrcweir { 1585*cdf0e10cSrcweir return rendering::ColorSpaceType::RGB; 1586*cdf0e10cSrcweir } 1587*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) 1588*cdf0e10cSrcweir { 1589*cdf0e10cSrcweir return maComponentTags; 1590*cdf0e10cSrcweir } 1591*cdf0e10cSrcweir virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) 1592*cdf0e10cSrcweir { 1593*cdf0e10cSrcweir return rendering::RenderingIntent::PERCEPTUAL; 1594*cdf0e10cSrcweir } 1595*cdf0e10cSrcweir virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) 1596*cdf0e10cSrcweir { 1597*cdf0e10cSrcweir return uno::Sequence< beans::PropertyValue >(); 1598*cdf0e10cSrcweir } 1599*cdf0e10cSrcweir virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, 1600*cdf0e10cSrcweir const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, 1601*cdf0e10cSrcweir uno::RuntimeException) 1602*cdf0e10cSrcweir { 1603*cdf0e10cSrcweir // TODO(P3): if we know anything about target 1604*cdf0e10cSrcweir // colorspace, this can be greatly sped up 1605*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> aIntermediate( 1606*cdf0e10cSrcweir convertToARGB(deviceColor)); 1607*cdf0e10cSrcweir return targetColorSpace->convertFromARGB(aIntermediate); 1608*cdf0e10cSrcweir } 1609*cdf0e10cSrcweir virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1610*cdf0e10cSrcweir { 1611*cdf0e10cSrcweir const double* pIn( deviceColor.getConstArray() ); 1612*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1613*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1614*cdf0e10cSrcweir "number of channels no multiple of 4", 1615*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1616*cdf0e10cSrcweir 1617*cdf0e10cSrcweir uno::Sequence< rendering::RGBColor > aRes(nLen/4); 1618*cdf0e10cSrcweir rendering::RGBColor* pOut( aRes.getArray() ); 1619*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1620*cdf0e10cSrcweir { 1621*cdf0e10cSrcweir const double fAlpha(pIn[3]); 1622*cdf0e10cSrcweir if( fAlpha == 0.0 ) 1623*cdf0e10cSrcweir *pOut++ = rendering::RGBColor(0.0, 0.0, 0.0); 1624*cdf0e10cSrcweir else 1625*cdf0e10cSrcweir *pOut++ = rendering::RGBColor(pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha); 1626*cdf0e10cSrcweir pIn += 4; 1627*cdf0e10cSrcweir } 1628*cdf0e10cSrcweir return aRes; 1629*cdf0e10cSrcweir } 1630*cdf0e10cSrcweir virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1631*cdf0e10cSrcweir { 1632*cdf0e10cSrcweir const double* pIn( deviceColor.getConstArray() ); 1633*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1634*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1635*cdf0e10cSrcweir "number of channels no multiple of 4", 1636*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1637*cdf0e10cSrcweir 1638*cdf0e10cSrcweir uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 1639*cdf0e10cSrcweir rendering::ARGBColor* pOut( aRes.getArray() ); 1640*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1641*cdf0e10cSrcweir { 1642*cdf0e10cSrcweir const double fAlpha(pIn[3]); 1643*cdf0e10cSrcweir if( fAlpha == 0.0 ) 1644*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor(0.0, 0.0, 0.0, 0.0); 1645*cdf0e10cSrcweir else 1646*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor(fAlpha,pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha); 1647*cdf0e10cSrcweir pIn += 4; 1648*cdf0e10cSrcweir } 1649*cdf0e10cSrcweir return aRes; 1650*cdf0e10cSrcweir } 1651*cdf0e10cSrcweir virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1652*cdf0e10cSrcweir { 1653*cdf0e10cSrcweir const double* pIn( deviceColor.getConstArray() ); 1654*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1655*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1656*cdf0e10cSrcweir "number of channels no multiple of 4", 1657*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1658*cdf0e10cSrcweir 1659*cdf0e10cSrcweir uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 1660*cdf0e10cSrcweir rendering::ARGBColor* pOut( aRes.getArray() ); 1661*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1662*cdf0e10cSrcweir { 1663*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor(pIn[3],pIn[2],pIn[1],pIn[1]); 1664*cdf0e10cSrcweir pIn += 4; 1665*cdf0e10cSrcweir } 1666*cdf0e10cSrcweir return aRes; 1667*cdf0e10cSrcweir } 1668*cdf0e10cSrcweir virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1669*cdf0e10cSrcweir { 1670*cdf0e10cSrcweir const rendering::RGBColor* pIn( rgbColor.getConstArray() ); 1671*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1672*cdf0e10cSrcweir 1673*cdf0e10cSrcweir uno::Sequence< double > aRes(nLen*4); 1674*cdf0e10cSrcweir double* pColors=aRes.getArray(); 1675*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1676*cdf0e10cSrcweir { 1677*cdf0e10cSrcweir *pColors++ = pIn->Blue; 1678*cdf0e10cSrcweir *pColors++ = pIn->Green; 1679*cdf0e10cSrcweir *pColors++ = pIn->Red; 1680*cdf0e10cSrcweir *pColors++ = 1.0; 1681*cdf0e10cSrcweir ++pIn; 1682*cdf0e10cSrcweir } 1683*cdf0e10cSrcweir return aRes; 1684*cdf0e10cSrcweir } 1685*cdf0e10cSrcweir virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1686*cdf0e10cSrcweir { 1687*cdf0e10cSrcweir const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 1688*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1689*cdf0e10cSrcweir 1690*cdf0e10cSrcweir uno::Sequence< double > aRes(nLen*4); 1691*cdf0e10cSrcweir double* pColors=aRes.getArray(); 1692*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1693*cdf0e10cSrcweir { 1694*cdf0e10cSrcweir *pColors++ = pIn->Alpha*pIn->Blue; 1695*cdf0e10cSrcweir *pColors++ = pIn->Alpha*pIn->Green; 1696*cdf0e10cSrcweir *pColors++ = pIn->Alpha*pIn->Red; 1697*cdf0e10cSrcweir *pColors++ = pIn->Alpha; 1698*cdf0e10cSrcweir ++pIn; 1699*cdf0e10cSrcweir } 1700*cdf0e10cSrcweir return aRes; 1701*cdf0e10cSrcweir } 1702*cdf0e10cSrcweir virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1703*cdf0e10cSrcweir { 1704*cdf0e10cSrcweir const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 1705*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1706*cdf0e10cSrcweir 1707*cdf0e10cSrcweir uno::Sequence< double > aRes(nLen*4); 1708*cdf0e10cSrcweir double* pColors=aRes.getArray(); 1709*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1710*cdf0e10cSrcweir { 1711*cdf0e10cSrcweir *pColors++ = pIn->Blue; 1712*cdf0e10cSrcweir *pColors++ = pIn->Green; 1713*cdf0e10cSrcweir *pColors++ = pIn->Red; 1714*cdf0e10cSrcweir *pColors++ = pIn->Alpha; 1715*cdf0e10cSrcweir ++pIn; 1716*cdf0e10cSrcweir } 1717*cdf0e10cSrcweir return aRes; 1718*cdf0e10cSrcweir } 1719*cdf0e10cSrcweir 1720*cdf0e10cSrcweir // XIntegerBitmapColorSpace 1721*cdf0e10cSrcweir virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException) 1722*cdf0e10cSrcweir { 1723*cdf0e10cSrcweir return 32; 1724*cdf0e10cSrcweir } 1725*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException) 1726*cdf0e10cSrcweir { 1727*cdf0e10cSrcweir return maBitCounts; 1728*cdf0e10cSrcweir } 1729*cdf0e10cSrcweir virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException) 1730*cdf0e10cSrcweir { 1731*cdf0e10cSrcweir return util::Endianness::LITTLE; 1732*cdf0e10cSrcweir } 1733*cdf0e10cSrcweir virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, 1734*cdf0e10cSrcweir const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, 1735*cdf0e10cSrcweir uno::RuntimeException) 1736*cdf0e10cSrcweir { 1737*cdf0e10cSrcweir if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) ) 1738*cdf0e10cSrcweir { 1739*cdf0e10cSrcweir const sal_Int8* pIn( deviceColor.getConstArray() ); 1740*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1741*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1742*cdf0e10cSrcweir "number of channels no multiple of 4", 1743*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1744*cdf0e10cSrcweir 1745*cdf0e10cSrcweir uno::Sequence<double> aRes(nLen); 1746*cdf0e10cSrcweir double* pOut( aRes.getArray() ); 1747*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1748*cdf0e10cSrcweir { 1749*cdf0e10cSrcweir *pOut++ = vcl::unotools::toDoubleColor(*pIn++); 1750*cdf0e10cSrcweir *pOut++ = vcl::unotools::toDoubleColor(*pIn++); 1751*cdf0e10cSrcweir *pOut++ = vcl::unotools::toDoubleColor(*pIn++); 1752*cdf0e10cSrcweir *pOut++ = vcl::unotools::toDoubleColor(*pIn++); 1753*cdf0e10cSrcweir } 1754*cdf0e10cSrcweir return aRes; 1755*cdf0e10cSrcweir } 1756*cdf0e10cSrcweir else 1757*cdf0e10cSrcweir { 1758*cdf0e10cSrcweir // TODO(P3): if we know anything about target 1759*cdf0e10cSrcweir // colorspace, this can be greatly sped up 1760*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> aIntermediate( 1761*cdf0e10cSrcweir convertIntegerToARGB(deviceColor)); 1762*cdf0e10cSrcweir return targetColorSpace->convertFromARGB(aIntermediate); 1763*cdf0e10cSrcweir } 1764*cdf0e10cSrcweir } 1765*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, 1766*cdf0e10cSrcweir const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, 1767*cdf0e10cSrcweir uno::RuntimeException) 1768*cdf0e10cSrcweir { 1769*cdf0e10cSrcweir if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) ) 1770*cdf0e10cSrcweir { 1771*cdf0e10cSrcweir // it's us, so simply pass-through the data 1772*cdf0e10cSrcweir return deviceColor; 1773*cdf0e10cSrcweir } 1774*cdf0e10cSrcweir else 1775*cdf0e10cSrcweir { 1776*cdf0e10cSrcweir // TODO(P3): if we know anything about target 1777*cdf0e10cSrcweir // colorspace, this can be greatly sped up 1778*cdf0e10cSrcweir uno::Sequence<rendering::ARGBColor> aIntermediate( 1779*cdf0e10cSrcweir convertIntegerToARGB(deviceColor)); 1780*cdf0e10cSrcweir return targetColorSpace->convertIntegerFromARGB(aIntermediate); 1781*cdf0e10cSrcweir } 1782*cdf0e10cSrcweir } 1783*cdf0e10cSrcweir virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1784*cdf0e10cSrcweir { 1785*cdf0e10cSrcweir const sal_Int8* pIn( deviceColor.getConstArray() ); 1786*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1787*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1788*cdf0e10cSrcweir "number of channels no multiple of 4", 1789*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1790*cdf0e10cSrcweir 1791*cdf0e10cSrcweir uno::Sequence< rendering::RGBColor > aRes(nLen/4); 1792*cdf0e10cSrcweir rendering::RGBColor* pOut( aRes.getArray() ); 1793*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1794*cdf0e10cSrcweir { 1795*cdf0e10cSrcweir const double fAlpha((sal_uInt8)pIn[3]); 1796*cdf0e10cSrcweir if( fAlpha ) 1797*cdf0e10cSrcweir *pOut++ = rendering::RGBColor( 1798*cdf0e10cSrcweir pIn[2]/fAlpha, 1799*cdf0e10cSrcweir pIn[1]/fAlpha, 1800*cdf0e10cSrcweir pIn[0]/fAlpha); 1801*cdf0e10cSrcweir else 1802*cdf0e10cSrcweir *pOut++ = rendering::RGBColor(0,0,0); 1803*cdf0e10cSrcweir pIn += 4; 1804*cdf0e10cSrcweir } 1805*cdf0e10cSrcweir return aRes; 1806*cdf0e10cSrcweir } 1807*cdf0e10cSrcweir 1808*cdf0e10cSrcweir virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1809*cdf0e10cSrcweir { 1810*cdf0e10cSrcweir const sal_Int8* pIn( deviceColor.getConstArray() ); 1811*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1812*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1813*cdf0e10cSrcweir "number of channels no multiple of 4", 1814*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1815*cdf0e10cSrcweir 1816*cdf0e10cSrcweir uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 1817*cdf0e10cSrcweir rendering::ARGBColor* pOut( aRes.getArray() ); 1818*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1819*cdf0e10cSrcweir { 1820*cdf0e10cSrcweir const double fAlpha((sal_uInt8)pIn[3]); 1821*cdf0e10cSrcweir if( fAlpha ) 1822*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor( 1823*cdf0e10cSrcweir fAlpha/255.0, 1824*cdf0e10cSrcweir pIn[2]/fAlpha, 1825*cdf0e10cSrcweir pIn[1]/fAlpha, 1826*cdf0e10cSrcweir pIn[0]/fAlpha); 1827*cdf0e10cSrcweir else 1828*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor(0,0,0,0); 1829*cdf0e10cSrcweir pIn += 4; 1830*cdf0e10cSrcweir } 1831*cdf0e10cSrcweir return aRes; 1832*cdf0e10cSrcweir } 1833*cdf0e10cSrcweir virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1834*cdf0e10cSrcweir { 1835*cdf0e10cSrcweir const sal_Int8* pIn( deviceColor.getConstArray() ); 1836*cdf0e10cSrcweir const sal_Size nLen( deviceColor.getLength() ); 1837*cdf0e10cSrcweir ENSURE_ARG_OR_THROW2(nLen%4==0, 1838*cdf0e10cSrcweir "number of channels no multiple of 4", 1839*cdf0e10cSrcweir static_cast<rendering::XColorSpace*>(this), 0); 1840*cdf0e10cSrcweir 1841*cdf0e10cSrcweir uno::Sequence< rendering::ARGBColor > aRes(nLen/4); 1842*cdf0e10cSrcweir rendering::ARGBColor* pOut( aRes.getArray() ); 1843*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; i+=4 ) 1844*cdf0e10cSrcweir { 1845*cdf0e10cSrcweir *pOut++ = rendering::ARGBColor( 1846*cdf0e10cSrcweir vcl::unotools::toDoubleColor(pIn[3]), 1847*cdf0e10cSrcweir vcl::unotools::toDoubleColor(pIn[2]), 1848*cdf0e10cSrcweir vcl::unotools::toDoubleColor(pIn[1]), 1849*cdf0e10cSrcweir vcl::unotools::toDoubleColor(pIn[0])); 1850*cdf0e10cSrcweir pIn += 4; 1851*cdf0e10cSrcweir } 1852*cdf0e10cSrcweir return aRes; 1853*cdf0e10cSrcweir } 1854*cdf0e10cSrcweir 1855*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1856*cdf0e10cSrcweir { 1857*cdf0e10cSrcweir const rendering::RGBColor* pIn( rgbColor.getConstArray() ); 1858*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1859*cdf0e10cSrcweir 1860*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes(nLen*4); 1861*cdf0e10cSrcweir sal_Int8* pColors=aRes.getArray(); 1862*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1863*cdf0e10cSrcweir { 1864*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Blue); 1865*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Green); 1866*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Red); 1867*cdf0e10cSrcweir *pColors++ = 255; 1868*cdf0e10cSrcweir ++pIn; 1869*cdf0e10cSrcweir } 1870*cdf0e10cSrcweir return aRes; 1871*cdf0e10cSrcweir } 1872*cdf0e10cSrcweir 1873*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1874*cdf0e10cSrcweir { 1875*cdf0e10cSrcweir const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 1876*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1877*cdf0e10cSrcweir 1878*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes(nLen*4); 1879*cdf0e10cSrcweir sal_Int8* pColors=aRes.getArray(); 1880*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1881*cdf0e10cSrcweir { 1882*cdf0e10cSrcweir const double fAlpha(pIn->Alpha); 1883*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Blue); 1884*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Green); 1885*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Red); 1886*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(fAlpha); 1887*cdf0e10cSrcweir ++pIn; 1888*cdf0e10cSrcweir } 1889*cdf0e10cSrcweir return aRes; 1890*cdf0e10cSrcweir } 1891*cdf0e10cSrcweir virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) 1892*cdf0e10cSrcweir { 1893*cdf0e10cSrcweir const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); 1894*cdf0e10cSrcweir const sal_Size nLen( rgbColor.getLength() ); 1895*cdf0e10cSrcweir 1896*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes(nLen*4); 1897*cdf0e10cSrcweir sal_Int8* pColors=aRes.getArray(); 1898*cdf0e10cSrcweir for( sal_Size i=0; i<nLen; ++i ) 1899*cdf0e10cSrcweir { 1900*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Blue); 1901*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Green); 1902*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Red); 1903*cdf0e10cSrcweir *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); 1904*cdf0e10cSrcweir ++pIn; 1905*cdf0e10cSrcweir } 1906*cdf0e10cSrcweir return aRes; 1907*cdf0e10cSrcweir } 1908*cdf0e10cSrcweir 1909*cdf0e10cSrcweir public: 1910*cdf0e10cSrcweir CairoColorSpace() : 1911*cdf0e10cSrcweir maComponentTags(4), 1912*cdf0e10cSrcweir maBitCounts(4) 1913*cdf0e10cSrcweir { 1914*cdf0e10cSrcweir sal_Int8* pTags = maComponentTags.getArray(); 1915*cdf0e10cSrcweir sal_Int32* pBitCounts = maBitCounts.getArray(); 1916*cdf0e10cSrcweir pTags[0] = rendering::ColorComponentTag::RGB_BLUE; 1917*cdf0e10cSrcweir pTags[1] = rendering::ColorComponentTag::RGB_GREEN; 1918*cdf0e10cSrcweir pTags[2] = rendering::ColorComponentTag::RGB_RED; 1919*cdf0e10cSrcweir pTags[3] = rendering::ColorComponentTag::PREMULTIPLIED_ALPHA; 1920*cdf0e10cSrcweir 1921*cdf0e10cSrcweir pBitCounts[0] = 1922*cdf0e10cSrcweir pBitCounts[1] = 1923*cdf0e10cSrcweir pBitCounts[2] = 1924*cdf0e10cSrcweir pBitCounts[3] = 8; 1925*cdf0e10cSrcweir } 1926*cdf0e10cSrcweir }; 1927*cdf0e10cSrcweir 1928*cdf0e10cSrcweir struct CairoColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, 1929*cdf0e10cSrcweir CairoColorSpaceHolder> 1930*cdf0e10cSrcweir { 1931*cdf0e10cSrcweir uno::Reference<rendering::XIntegerBitmapColorSpace> operator()() 1932*cdf0e10cSrcweir { 1933*cdf0e10cSrcweir return new CairoColorSpace(); 1934*cdf0e10cSrcweir } 1935*cdf0e10cSrcweir }; 1936*cdf0e10cSrcweir } 1937*cdf0e10cSrcweir 1938*cdf0e10cSrcweir rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout() 1939*cdf0e10cSrcweir { 1940*cdf0e10cSrcweir if( !mpCairo ) 1941*cdf0e10cSrcweir return rendering::IntegerBitmapLayout(); // we're disposed 1942*cdf0e10cSrcweir 1943*cdf0e10cSrcweir const geometry::IntegerSize2D aSize(getSize()); 1944*cdf0e10cSrcweir rendering::IntegerBitmapLayout aLayout; 1945*cdf0e10cSrcweir 1946*cdf0e10cSrcweir aLayout.ScanLines = aSize.Height; 1947*cdf0e10cSrcweir aLayout.ScanLineBytes = aSize.Width*4; 1948*cdf0e10cSrcweir aLayout.ScanLineStride = aLayout.ScanLineBytes; 1949*cdf0e10cSrcweir aLayout.PlaneStride = 0; 1950*cdf0e10cSrcweir aLayout.ColorSpace = CairoColorSpaceHolder::get(); 1951*cdf0e10cSrcweir aLayout.Palette.clear(); 1952*cdf0e10cSrcweir aLayout.IsMsbFirst = sal_False; 1953*cdf0e10cSrcweir 1954*cdf0e10cSrcweir return aLayout; 1955*cdf0e10cSrcweir } 1956*cdf0e10cSrcweir 1957*cdf0e10cSrcweir void CanvasHelper::flush() const 1958*cdf0e10cSrcweir { 1959*cdf0e10cSrcweir } 1960*cdf0e10cSrcweir 1961*cdf0e10cSrcweir bool CanvasHelper::hasAlpha() const 1962*cdf0e10cSrcweir { 1963*cdf0e10cSrcweir return mbHaveAlpha; 1964*cdf0e10cSrcweir } 1965*cdf0e10cSrcweir 1966*cdf0e10cSrcweir bool CanvasHelper::repaint( const SurfaceSharedPtr& pSurface, 1967*cdf0e10cSrcweir const rendering::ViewState& viewState, 1968*cdf0e10cSrcweir const rendering::RenderState& renderState ) 1969*cdf0e10cSrcweir { 1970*cdf0e10cSrcweir OSL_TRACE("CanvasHelper::repaint"); 1971*cdf0e10cSrcweir 1972*cdf0e10cSrcweir if( mpCairo ) { 1973*cdf0e10cSrcweir cairo_save( mpCairo.get() ); 1974*cdf0e10cSrcweir 1975*cdf0e10cSrcweir cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); 1976*cdf0e10cSrcweir cairo_clip( mpCairo.get() ); 1977*cdf0e10cSrcweir 1978*cdf0e10cSrcweir useStates( viewState, renderState, true ); 1979*cdf0e10cSrcweir 1980*cdf0e10cSrcweir Matrix aMatrix; 1981*cdf0e10cSrcweir 1982*cdf0e10cSrcweir cairo_get_matrix( mpCairo.get(), &aMatrix ); 1983*cdf0e10cSrcweir aMatrix.xx = aMatrix.yy = 1; 1984*cdf0e10cSrcweir cairo_set_matrix( mpCairo.get(), &aMatrix ); 1985*cdf0e10cSrcweir 1986*cdf0e10cSrcweir // if( !bHasAlpha ) 1987*cdf0e10cSrcweir // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); 1988*cdf0e10cSrcweir 1989*cdf0e10cSrcweir cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 ); 1990*cdf0e10cSrcweir cairo_paint( mpCairo.get() ); 1991*cdf0e10cSrcweir cairo_restore( mpCairo.get() ); 1992*cdf0e10cSrcweir } 1993*cdf0e10cSrcweir 1994*cdf0e10cSrcweir return true; 1995*cdf0e10cSrcweir } 1996*cdf0e10cSrcweir } 1997