LCOV - code coverage report
Current view: top level - canvas/source/cairo - cairo_canvashelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 908 0.0 %
Date: 2012-08-25 Functions: 0 74 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.10