LCOV - code coverage report
Current view: top level - canvas/source/opengl - ogl_canvashelper.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 394 0.0 %
Date: 2014-11-03 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "ogl_canvashelper.hxx"
      11             : 
      12             : #include <rtl/crc.h>
      13             : #include <canvas/debug.hxx>
      14             : #include <tools/diagnose_ex.h>
      15             : #include <basegfx/tools/canvastools.hxx>
      16             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      17             : #include <basegfx/polygon/b2dpolygontriangulator.hxx>
      18             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      19             : 
      20             : #include <com/sun/star/rendering/TexturingMode.hpp>
      21             : #include <com/sun/star/rendering/CompositeOperation.hpp>
      22             : #include <com/sun/star/rendering/RepaintResult.hpp>
      23             : #include <com/sun/star/rendering/PathCapType.hpp>
      24             : #include <com/sun/star/rendering/PathJoinType.hpp>
      25             : 
      26             : #include <vcl/virdev.hxx>
      27             : #include <vcl/metric.hxx>
      28             : #include <vcl/font.hxx>
      29             : 
      30             : #include "ogl_canvasfont.hxx"
      31             : #include "ogl_canvastools.hxx"
      32             : #include "ogl_canvasbitmap.hxx"
      33             : #include "ogl_spritecanvas.hxx"
      34             : #include "ogl_texturecache.hxx"
      35             : #include "ogl_tools.hxx"
      36             : 
      37             : #include <GL/glew.h>
      38             : 
      39             : #include <boost/scoped_array.hpp>
      40             : 
      41             : 
      42             : using namespace ::com::sun::star;
      43             : 
      44             : namespace oglcanvas
      45             : {
      46             :     /* Concepts:
      47             :        =========
      48             : 
      49             :        This OpenGL canvas implementation tries to keep all render
      50             :        output as high-level as possible, i.e. geometry data and
      51             :        externally-provided bitmaps. Therefore, calls at the
      52             :        XCanvas-interfaces are not immediately transformed into colored
      53             :        pixel inside some GL buffer, but are retained simply with their
      54             :        call parameters. Only after XSpriteCanvas::updateScreen() has
      55             :        been called, this all gets transferred to the OpenGL subsystem
      56             :        and converted to a visible scene. The big advantage is, this
      57             :        makes sprite modifications practically zero-overhead, and saves
      58             :        a lot on texture memory (compared to the directx canvas, which
      59             :        immediately dumps every render call into a texture).
      60             : 
      61             :        The drawback, of course, is that complex images churn a lot of
      62             :        GPU cycles on every re-rendering.
      63             : 
      64             :        For the while, I'll be using immediate mode, i.e. transfer data
      65             :        over and over again to the OpenGL subsystem. Alternatively,
      66             :        there are display lists, which at least keep the data on the
      67             :        server, or even better, vertex buffers, which copy geometry
      68             :        data over en bloc.
      69             : 
      70             :        Next todo: put polygon geometry into vertex buffer (LRU cache
      71             :        necessary?) - or, rather, buffer objects! prune entries older
      72             :        than one updateScreen() call)
      73             : 
      74             :        Text: http://www.opengl.org/resources/features/fontsurvey/
      75             :      */
      76             : 
      77           0 :     struct CanvasHelper::Action
      78             :     {
      79             :         ::basegfx::B2DHomMatrix         maTransform;
      80             :         GLenum                          meSrcBlendMode;
      81             :         GLenum                          meDstBlendMode;
      82             :         rendering::ARGBColor            maARGBColor;
      83             :         ::basegfx::B2DPolyPolygonVector maPolyPolys;
      84             : 
      85             :         ::boost::function6< bool,
      86             :                             const CanvasHelper&,
      87             :                             const ::basegfx::B2DHomMatrix&,
      88             :                             GLenum,
      89             :                             GLenum,
      90             :                             const rendering::ARGBColor&,
      91             :                             const ::basegfx::B2DPolyPolygonVector& > maFunction;
      92             :     };
      93             : 
      94             :     namespace
      95             :     {
      96           0 :         bool lcl_drawPoint( const CanvasHelper&              /*rHelper*/,
      97             :                             const ::basegfx::B2DHomMatrix&   rTransform,
      98             :                             GLenum                           eSrcBlend,
      99             :                             GLenum                           eDstBlend,
     100             :                             const rendering::ARGBColor&      rColor,
     101             :                             const geometry::RealPoint2D&     rPoint )
     102             :         {
     103           0 :             TransformationPreserver aPreserver;
     104           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     105             : 
     106           0 :             glBegin(GL_POINTS);
     107           0 :             glVertex2d(rPoint.X, rPoint.Y);
     108           0 :             glEnd();
     109             : 
     110           0 :             return true;
     111             :         }
     112             : 
     113           0 :         bool lcl_drawLine( const CanvasHelper&              /*rHelper*/,
     114             :                            const ::basegfx::B2DHomMatrix&   rTransform,
     115             :                            GLenum                           eSrcBlend,
     116             :                            GLenum                           eDstBlend,
     117             :                            const rendering::ARGBColor&      rColor,
     118             :                            const geometry::RealPoint2D&     rStartPoint,
     119             :                            const geometry::RealPoint2D&     rEndPoint )
     120             :         {
     121           0 :             TransformationPreserver aPreserver;
     122           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     123             : 
     124           0 :             glBegin(GL_LINES);
     125           0 :             glVertex2d(rStartPoint.X, rStartPoint.Y);
     126           0 :             glVertex2d(rEndPoint.X, rEndPoint.Y);
     127           0 :             glEnd();
     128             : 
     129           0 :             return true;
     130             :         }
     131             : 
     132           0 :         bool lcl_drawPolyPolygon( const CanvasHelper&                    /*rHelper*/,
     133             :                                   const ::basegfx::B2DHomMatrix&         rTransform,
     134             :                                   GLenum                                 eSrcBlend,
     135             :                                   GLenum                                 eDstBlend,
     136             :                                   const rendering::ARGBColor&            rColor,
     137             :                                   const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
     138             :         {
     139           0 :             TransformationPreserver aPreserver;
     140           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     141             : 
     142           0 :             ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
     143           0 :             const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
     144           0 :             while( aCurr != aEnd )
     145           0 :                 renderPolyPolygon(*aCurr++);
     146             : 
     147           0 :             return true;
     148             :         }
     149             : 
     150           0 :         bool lcl_fillPolyPolygon( const CanvasHelper&                    /*rHelper*/,
     151             :                                   const ::basegfx::B2DHomMatrix&         rTransform,
     152             :                                   GLenum                                 eSrcBlend,
     153             :                                   GLenum                                 eDstBlend,
     154             :                                   const rendering::ARGBColor&            rColor,
     155             :                                   const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
     156             :         {
     157           0 :             TransformationPreserver aPreserver;
     158           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     159             : 
     160           0 :             ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
     161           0 :             const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
     162           0 :             while( aCurr != aEnd )
     163             :             {
     164           0 :                 glBegin(GL_TRIANGLES);
     165           0 :                 renderComplexPolyPolygon(*aCurr++);
     166           0 :                 glEnd();
     167             :             }
     168             : 
     169           0 :             return true;
     170             :         }
     171             : 
     172           0 :         bool lcl_fillGradientPolyPolygon( const CanvasHelper&                            rHelper,
     173             :                                           const ::basegfx::B2DHomMatrix&                 rTransform,
     174             :                                           GLenum                                         eSrcBlend,
     175             :                                           GLenum                                         eDstBlend,
     176             :                                           const ::canvas::ParametricPolyPolygon::Values& rValues,
     177             :                                           const rendering::Texture&                      rTexture,
     178             :                                           const ::basegfx::B2DPolyPolygonVector&         rPolyPolygons )
     179             :         {
     180           0 :             TransformationPreserver aPreserver;
     181           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
     182             : 
     183             :             // convert to weird canvas textur coordinate system (not
     184             :             // [0,1]^2, but path coordinate system)
     185           0 :             ::basegfx::B2DHomMatrix aTextureTransform;
     186             :             ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
     187           0 :                                                             rTexture.AffineTransform );
     188           0 :             ::basegfx::B2DRange aBounds;
     189           0 :             ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
     190           0 :             const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
     191           0 :             while( aCurr != aEnd )
     192           0 :                 aBounds.expand(::basegfx::tools::getRange(*aCurr++));
     193           0 :             aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
     194           0 :             aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
     195             : 
     196           0 :             const sal_Int32 nNumCols=rValues.maColors.getLength();
     197           0 :             uno::Sequence< rendering::ARGBColor > aColors(nNumCols);
     198           0 :             rendering::ARGBColor* const pColors=aColors.getArray();
     199           0 :             rendering::ARGBColor* pCurrCol=pColors;
     200           0 :             for( sal_Int32 i=0; i<nNumCols; ++i )
     201           0 :                 *pCurrCol++ = rHelper.getDevice()->getDeviceColorSpace()->convertToARGB(rValues.maColors[i])[0];
     202             : 
     203             :             OSL_ASSERT(nNumCols == rValues.maStops.getLength());
     204             : 
     205           0 :             switch( rValues.meType )
     206             :             {
     207             :                 case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
     208             :                     rHelper.getDeviceHelper()->useLinearGradientShader(pColors,
     209             :                                                                        rValues.maStops,
     210           0 :                                                                        aTextureTransform);
     211           0 :                     break;
     212             : 
     213             :                 case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
     214             :                     rHelper.getDeviceHelper()->useRadialGradientShader(pColors,
     215             :                                                                        rValues.maStops,
     216           0 :                                                                        aTextureTransform);
     217           0 :                     break;
     218             : 
     219             :                 case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
     220             :                     rHelper.getDeviceHelper()->useRectangularGradientShader(pColors,
     221             :                                                                             rValues.maStops,
     222           0 :                                                                             aTextureTransform);
     223           0 :                     break;
     224             : 
     225             :                 default:
     226           0 :                     ENSURE_OR_THROW( false,
     227             :                                       "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case" );
     228             :             }
     229             : 
     230             : 
     231           0 :             aCurr=rPolyPolygons.begin();
     232           0 :             while( aCurr != aEnd )
     233             :             {
     234           0 :                 glBegin(GL_TRIANGLES);
     235           0 :                 renderComplexPolyPolygon(*aCurr++);
     236           0 :                 glEnd();
     237             :             }
     238             : 
     239           0 :             glUseProgram(0);
     240           0 :             glLoadIdentity();
     241           0 :             glMatrixMode(GL_MODELVIEW);
     242             : 
     243           0 :             return true;
     244             :         }
     245             : 
     246           0 :         bool lcl_drawOwnBitmap( const CanvasHelper&              /*rHelper*/,
     247             :                                 const ::basegfx::B2DHomMatrix&   rTransform,
     248             :                                 GLenum                           eSrcBlend,
     249             :                                 GLenum                           eDstBlend,
     250             :                                 const rendering::ARGBColor&      rColor,
     251             :                                 const CanvasBitmap&              rBitmap )
     252             :         {
     253           0 :             TransformationPreserver aPreserver;
     254           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     255             : 
     256           0 :             return rBitmap.renderRecordedActions();
     257             :         }
     258             : 
     259           0 :         bool lcl_drawGenericBitmap( const CanvasHelper&              rHelper,
     260             :                                     const ::basegfx::B2DHomMatrix&   rTransform,
     261             :                                     GLenum                           eSrcBlend,
     262             :                                     GLenum                           eDstBlend,
     263             :                                     const rendering::ARGBColor&      rColor,
     264             :                                     const geometry::IntegerSize2D&   rPixelSize,
     265             :                                     const uno::Sequence<sal_Int8>&   rPixelData,
     266             :                                     sal_uInt32                       nPixelCrc32 )
     267             :         {
     268           0 :             TransformationPreserver aPreserver;
     269           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rColor);
     270             : 
     271           0 :             const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
     272           0 :                 rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
     273             : 
     274           0 :             glBindTexture(GL_TEXTURE_2D, nTexId);
     275           0 :             glEnable(GL_TEXTURE_2D);
     276             :             glTexParameteri(GL_TEXTURE_2D,
     277             :                             GL_TEXTURE_MIN_FILTER,
     278           0 :                             GL_NEAREST);
     279             :             glTexParameteri(GL_TEXTURE_2D,
     280             :                             GL_TEXTURE_MAG_FILTER,
     281           0 :                             GL_NEAREST);
     282           0 :             glEnable(GL_BLEND);
     283             :             glBlendFunc(GL_SRC_ALPHA,
     284           0 :                         GL_ONE_MINUS_SRC_ALPHA);
     285             : 
     286             :             // blend against fixed vertex color; texture alpha is multiplied in
     287           0 :             glColor4f(1,1,1,1);
     288             : 
     289           0 :             glBegin(GL_TRIANGLE_STRIP);
     290           0 :             glTexCoord2f(0,0); glVertex2d(0,0);
     291           0 :             glTexCoord2f(0,1); glVertex2d(0, rPixelSize.Height);
     292           0 :             glTexCoord2f(1,0); glVertex2d(rPixelSize.Width,0);
     293           0 :             glTexCoord2f(1,1); glVertex2d(rPixelSize.Width,rPixelSize.Height);
     294           0 :             glEnd();
     295             : 
     296           0 :             glBindTexture(GL_TEXTURE_2D, 0);
     297           0 :             glDisable(GL_TEXTURE_2D);
     298             : 
     299           0 :             return true;
     300             :         }
     301             : 
     302           0 :         bool lcl_fillTexturedPolyPolygon( const CanvasHelper&                    rHelper,
     303             :                                           const ::basegfx::B2DHomMatrix&         rTransform,
     304             :                                           GLenum                                 eSrcBlend,
     305             :                                           GLenum                                 eDstBlend,
     306             :                                           const rendering::Texture&              rTexture,
     307             :                                           const geometry::IntegerSize2D&         rPixelSize,
     308             :                                           const uno::Sequence<sal_Int8>&         rPixelData,
     309             :                                           sal_uInt32                             nPixelCrc32,
     310             :                                           const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
     311             :         {
     312           0 :             TransformationPreserver aPreserver;
     313           0 :             setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
     314             : 
     315           0 :             const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
     316           0 :                 rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
     317             : 
     318           0 :             glBindTexture(GL_TEXTURE_2D, nTexId);
     319           0 :             glEnable(GL_TEXTURE_2D);
     320             :             glTexParameteri(GL_TEXTURE_2D,
     321             :                             GL_TEXTURE_MIN_FILTER,
     322           0 :                             GL_NEAREST);
     323             :             glTexParameteri(GL_TEXTURE_2D,
     324             :                             GL_TEXTURE_MAG_FILTER,
     325           0 :                             GL_NEAREST);
     326           0 :             glEnable(GL_BLEND);
     327             :             glBlendFunc(GL_SRC_ALPHA,
     328           0 :                         GL_ONE_MINUS_SRC_ALPHA);
     329             : 
     330             :             // convert to weird canvas textur coordinate system (not
     331             :             // [0,1]^2, but path coordinate system)
     332           0 :             ::basegfx::B2DHomMatrix aTextureTransform;
     333             :             ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
     334           0 :                                                             rTexture.AffineTransform );
     335           0 :             ::basegfx::B2DRange aBounds;
     336           0 :             ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
     337           0 :             const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
     338           0 :             while( aCurr != aEnd )
     339           0 :                 aBounds.expand(::basegfx::tools::getRange(*aCurr++));
     340           0 :             aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
     341           0 :             aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
     342           0 :             aTextureTransform.invert();
     343             : 
     344           0 :             glMatrixMode(GL_TEXTURE);
     345             :             double aTexTransform[] =
     346             :                 {
     347           0 :                     aTextureTransform.get(0,0), aTextureTransform.get(1,0), 0, 0,
     348           0 :                     aTextureTransform.get(0,1), aTextureTransform.get(1,1), 0, 0,
     349             :                     0,                          0,                          1, 0,
     350           0 :                     aTextureTransform.get(0,2), aTextureTransform.get(1,2), 0, 1
     351           0 :                 };
     352           0 :             glLoadMatrixd(aTexTransform);
     353             : 
     354             :             // blend against fixed vertex color; texture alpha is multiplied in
     355           0 :             glColor4f(1,1,1,rTexture.Alpha);
     356             : 
     357           0 :             aCurr=rPolyPolygons.begin();
     358           0 :             while( aCurr != aEnd )
     359             :             {
     360           0 :                 glBegin(GL_TRIANGLES);
     361           0 :                 renderComplexPolyPolygon(*aCurr++);
     362           0 :                 glEnd();
     363             :             }
     364             : 
     365           0 :             glLoadIdentity();
     366           0 :             glMatrixMode(GL_MODELVIEW);
     367             : 
     368           0 :             glBindTexture(GL_TEXTURE_2D, 0);
     369           0 :             glDisable(GL_TEXTURE_2D);
     370             : 
     371           0 :             return true;
     372             :         }
     373             :     }
     374             : 
     375           0 :     CanvasHelper::CanvasHelper() :
     376             :         mpDevice( NULL ),
     377             :         mpDeviceHelper( NULL ),
     378           0 :         mpRecordedActions()
     379           0 :     {}
     380             : 
     381           0 :     CanvasHelper::~CanvasHelper()
     382           0 :     {}
     383             : 
     384           0 :     CanvasHelper& CanvasHelper::operator=( const CanvasHelper& rSrc )
     385             :     {
     386           0 :         mpDevice = rSrc.mpDevice;
     387           0 :         mpDeviceHelper = rSrc.mpDeviceHelper;
     388           0 :         mpRecordedActions = rSrc.mpRecordedActions;
     389           0 :         return *this;
     390             :     }
     391             : 
     392           0 :     void CanvasHelper::disposing()
     393             :     {
     394           0 :         RecordVectorT aThrowaway;
     395           0 :         mpRecordedActions.swap( aThrowaway );
     396           0 :         mpDevice = NULL;
     397           0 :         mpDeviceHelper = NULL;
     398           0 :     }
     399             : 
     400           0 :     void CanvasHelper::init( rendering::XGraphicDevice& rDevice,
     401             :                              SpriteDeviceHelper& rDeviceHelper )
     402             :     {
     403           0 :         mpDevice = &rDevice;
     404           0 :         mpDeviceHelper = &rDeviceHelper;
     405           0 :     }
     406             : 
     407           0 :     void CanvasHelper::clear()
     408             :     {
     409           0 :         mpRecordedActions->clear();
     410           0 :     }
     411             : 
     412           0 :     void CanvasHelper::drawPoint( const rendering::XCanvas*     /*pCanvas*/,
     413             :                                   const geometry::RealPoint2D&  aPoint,
     414             :                                   const rendering::ViewState&   viewState,
     415             :                                   const rendering::RenderState& renderState )
     416             :     {
     417           0 :         if( mpDevice )
     418             :         {
     419           0 :             mpRecordedActions->push_back( Action() );
     420           0 :             Action& rAct=mpRecordedActions->back();
     421             : 
     422           0 :             setupGraphicsState( rAct, viewState, renderState );
     423           0 :             rAct.maFunction = ::boost::bind(&lcl_drawPoint,
     424             :                                             _1,_2,_3,_4,_5,
     425           0 :                                             aPoint);
     426             :         }
     427           0 :     }
     428             : 
     429           0 :     void CanvasHelper::drawLine( const rendering::XCanvas*      /*pCanvas*/,
     430             :                                  const geometry::RealPoint2D&   aStartPoint,
     431             :                                  const geometry::RealPoint2D&   aEndPoint,
     432             :                                  const rendering::ViewState&    viewState,
     433             :                                  const rendering::RenderState&  renderState )
     434             :     {
     435           0 :         if( mpDevice )
     436             :         {
     437           0 :             mpRecordedActions->push_back( Action() );
     438           0 :             Action& rAct=mpRecordedActions->back();
     439             : 
     440           0 :             setupGraphicsState( rAct, viewState, renderState );
     441           0 :             rAct.maFunction = ::boost::bind(&lcl_drawLine,
     442             :                                             _1,_2,_3,_4,_5,
     443           0 :                                             aStartPoint,aEndPoint);
     444             :         }
     445           0 :     }
     446             : 
     447           0 :     void CanvasHelper::drawBezier( const rendering::XCanvas*            /*pCanvas*/,
     448             :                                    const geometry::RealBezierSegment2D& aBezierSegment,
     449             :                                    const geometry::RealPoint2D&         aEndPoint,
     450             :                                    const rendering::ViewState&          viewState,
     451             :                                    const rendering::RenderState&        renderState )
     452             :     {
     453           0 :         if( mpDevice )
     454             :         {
     455           0 :             mpRecordedActions->push_back( Action() );
     456           0 :             Action& rAct=mpRecordedActions->back();
     457             : 
     458           0 :             setupGraphicsState( rAct, viewState, renderState );
     459             : 
     460             :             // TODO(F2): subdivide&render whole curve
     461           0 :             rAct.maFunction = ::boost::bind(&lcl_drawLine,
     462             :                                             _1,_2,_3,_4,_5,
     463             :                                             geometry::RealPoint2D(
     464             :                                                 aBezierSegment.Px,
     465             :                                                 aBezierSegment.Py),
     466           0 :                                             aEndPoint);
     467             :         }
     468           0 :     }
     469             : 
     470           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
     471             :                                                                                  const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
     472             :                                                                                  const rendering::ViewState&                        viewState,
     473             :                                                                                  const rendering::RenderState&                      renderState )
     474             :     {
     475           0 :         ENSURE_OR_THROW( xPolyPolygon.is(),
     476             :                           "CanvasHelper::drawPolyPolygon: polygon is NULL");
     477             : 
     478           0 :         if( mpDevice )
     479             :         {
     480           0 :             mpRecordedActions->push_back( Action() );
     481           0 :             Action& rAct=mpRecordedActions->back();
     482             : 
     483           0 :             setupGraphicsState( rAct, viewState, renderState );
     484             :             rAct.maPolyPolys.push_back(
     485           0 :                 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
     486           0 :             rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
     487             : 
     488           0 :             rAct.maFunction = &lcl_drawPolyPolygon;
     489             :         }
     490             : 
     491             :         // TODO(P1): Provide caching here.
     492           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     493             :     }
     494             : 
     495           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas*                            /*pCanvas*/,
     496             :                                                                                    const uno::Reference< rendering::XPolyPolygon2D >&   xPolyPolygon,
     497             :                                                                                    const rendering::ViewState&                          viewState,
     498             :                                                                                    const rendering::RenderState&                        renderState,
     499             :                                                                                    const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
     500             :     {
     501           0 :         ENSURE_OR_THROW( xPolyPolygon.is(),
     502             :                           "CanvasHelper::strokePolyPolygon: polygon is NULL");
     503             : 
     504           0 :         if( mpDevice )
     505             :         {
     506           0 :             mpRecordedActions->push_back( Action() );
     507           0 :             Action& rAct=mpRecordedActions->back();
     508             : 
     509           0 :             setupGraphicsState( rAct, viewState, renderState );
     510             :             rAct.maPolyPolys.push_back(
     511           0 :                 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
     512           0 :             rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
     513             : 
     514             :             // TODO(F3): fallback to drawPolyPolygon currently
     515           0 :             rAct.maFunction = &lcl_drawPolyPolygon;
     516             :         }
     517             : 
     518             :         // TODO(P1): Provide caching here.
     519           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     520             :     }
     521             : 
     522           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas*                            /*pCanvas*/,
     523             :                                                                                            const uno::Reference< rendering::XPolyPolygon2D >&   /*xPolyPolygon*/,
     524             :                                                                                            const rendering::ViewState&                          /*viewState*/,
     525             :                                                                                            const rendering::RenderState&                        /*renderState*/,
     526             :                                                                                            const uno::Sequence< rendering::Texture >&           /*textures*/,
     527             :                                                                                            const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
     528             :     {
     529             :         // TODO
     530           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     531             :     }
     532             : 
     533           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas*                           /*pCanvas*/,
     534             :                                                                                                 const uno::Reference< rendering::XPolyPolygon2D >&  /*xPolyPolygon*/,
     535             :                                                                                                 const rendering::ViewState&                         /*viewState*/,
     536             :                                                                                                 const rendering::RenderState&                       /*renderState*/,
     537             :                                                                                                 const uno::Sequence< rendering::Texture >&          /*textures*/,
     538             :                                                                                                 const uno::Reference< geometry::XMapping2D >&       /*xMapping*/,
     539             :                                                                                                 const rendering::StrokeAttributes&                  /*strokeAttributes*/ )
     540             :     {
     541             :         // TODO
     542           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     543             :     }
     544             : 
     545           0 :     uno::Reference< rendering::XPolyPolygon2D >   CanvasHelper::queryStrokeShapes( const rendering::XCanvas*                            /*pCanvas*/,
     546             :                                                                                    const uno::Reference< rendering::XPolyPolygon2D >&   /*xPolyPolygon*/,
     547             :                                                                                    const rendering::ViewState&                          /*viewState*/,
     548             :                                                                                    const rendering::RenderState&                        /*renderState*/,
     549             :                                                                                    const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
     550             :     {
     551             :         // TODO
     552           0 :         return uno::Reference< rendering::XPolyPolygon2D >(NULL);
     553             :     }
     554             : 
     555           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
     556             :                                                                                  const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
     557             :                                                                                  const rendering::ViewState&                        viewState,
     558             :                                                                                  const rendering::RenderState&                      renderState )
     559             :     {
     560           0 :         ENSURE_OR_THROW( xPolyPolygon.is(),
     561             :                           "CanvasHelper::fillPolyPolygon: polygon is NULL");
     562             : 
     563           0 :         if( mpDevice )
     564             :         {
     565           0 :             mpRecordedActions->push_back( Action() );
     566           0 :             Action& rAct=mpRecordedActions->back();
     567             : 
     568           0 :             setupGraphicsState( rAct, viewState, renderState );
     569             :             rAct.maPolyPolys.push_back(
     570           0 :                 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
     571           0 :             rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
     572             : 
     573           0 :             rAct.maFunction = &lcl_fillPolyPolygon;
     574             :         }
     575             : 
     576             :         // TODO(P1): Provide caching here.
     577           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     578             :     }
     579             : 
     580           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
     581             :                                                                                          const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
     582             :                                                                                          const rendering::ViewState&                        viewState,
     583             :                                                                                          const rendering::RenderState&                      renderState,
     584             :                                                                                          const uno::Sequence< rendering::Texture >&         textures )
     585             :     {
     586           0 :         ENSURE_OR_THROW( xPolyPolygon.is(),
     587             :                           "CanvasHelper::fillPolyPolygon: polygon is NULL");
     588             : 
     589           0 :         if( mpDevice )
     590             :         {
     591           0 :             mpRecordedActions->push_back( Action() );
     592           0 :             Action& rAct=mpRecordedActions->back();
     593             : 
     594           0 :             setupGraphicsState( rAct, viewState, renderState );
     595             :             rAct.maPolyPolys.push_back(
     596           0 :                 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
     597           0 :             rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
     598             : 
     599             :             // TODO(F1): Multi-texturing
     600           0 :             if( textures[0].Gradient.is() )
     601             :             {
     602             :                 // try to cast XParametricPolyPolygon2D reference to
     603             :                 // our implementation class.
     604             :                 ::canvas::ParametricPolyPolygon* pGradient =
     605           0 :                       dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
     606             : 
     607           0 :                 if( pGradient )
     608             :                 {
     609             :                     // copy state from Gradient polypoly locally
     610             :                     // (given object might change!)
     611             :                     const ::canvas::ParametricPolyPolygon::Values& rValues(
     612           0 :                         pGradient->getValues() );
     613             : 
     614           0 :                     rAct.maFunction = ::boost::bind(&lcl_fillGradientPolyPolygon,
     615             :                                                     _1,_2,_3,_4,
     616             :                                                     rValues,
     617           0 :                                                     textures[0],
     618           0 :                                                     _6);
     619             :                 }
     620             :                 else
     621             :                 {
     622             :                     // TODO(F1): The generic case is missing here
     623           0 :                     ENSURE_OR_THROW( false,
     624             :                                       "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered" );
     625             :                 }
     626             :             }
     627           0 :             else if( textures[0].Bitmap.is() )
     628             :             {
     629             :                 // own bitmap?
     630           0 :                 CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(textures[0].Bitmap.get());
     631           0 :                 if( pOwnBitmap )
     632             :                 {
     633             :                     // TODO(F2): own texture bitmap
     634             :                 }
     635             :                 else
     636             :                 {
     637             :                     // TODO(P3): Highly inefficient - simply copies pixel data
     638             : 
     639             :                     uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
     640           0 :                         textures[0].Bitmap,
     641           0 :                         uno::UNO_QUERY);
     642           0 :                     if( xIntegerBitmap.is() )
     643             :                     {
     644           0 :                         const geometry::IntegerSize2D aSize=xIntegerBitmap->getSize();
     645           0 :                         rendering::IntegerBitmapLayout aLayout;
     646             :                         uno::Sequence<sal_Int8> aPixelData=
     647           0 :                             xIntegerBitmap->getData(
     648             :                                 aLayout,
     649           0 :                                 geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
     650             : 
     651             :                         // force-convert color to ARGB8888 int color space
     652             :                         uno::Sequence<sal_Int8> aARGBBytes(
     653           0 :                             aLayout.ColorSpace->convertToIntegerColorSpace(
     654             :                                 aPixelData,
     655           0 :                                 canvas::tools::getStdColorSpace()));
     656             : 
     657           0 :                         rAct.maFunction = ::boost::bind(&lcl_fillTexturedPolyPolygon,
     658             :                                                         _1,_2,_3,_4,
     659           0 :                                                         textures[0],
     660             :                                                         aSize,
     661             :                                                         aARGBBytes,
     662             :                                                         rtl_crc32(0,
     663           0 :                                                                   aARGBBytes.getConstArray(),
     664           0 :                                                                   aARGBBytes.getLength()),
     665           0 :                                                         _6);
     666           0 :                     }
     667             :                     // TODO(F1): handle non-integer case
     668             :                 }
     669             :             }
     670             :         }
     671             : 
     672             :         // TODO(P1): Provide caching here.
     673           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     674             :     }
     675             : 
     676           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas*                             /*pCanvas*/,
     677             :                                                                                               const uno::Reference< rendering::XPolyPolygon2D >&    /*xPolyPolygon*/,
     678             :                                                                                               const rendering::ViewState&                           /*viewState*/,
     679             :                                                                                               const rendering::RenderState&                         /*renderState*/,
     680             :                                                                                               const uno::Sequence< rendering::Texture >&            /*textures*/,
     681             :                                                                                               const uno::Reference< geometry::XMapping2D >&         /*xMapping*/ )
     682             :     {
     683             :         // TODO
     684           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     685             :     }
     686             : 
     687           0 :     uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas*                    /*pCanvas*/,
     688             :                                                                        const rendering::FontRequest&                fontRequest,
     689             :                                                                        const uno::Sequence< beans::PropertyValue >& extraFontProperties,
     690             :                                                                        const geometry::Matrix2D&                    fontMatrix )
     691             :     {
     692           0 :         if( mpDevice )
     693             :             return uno::Reference< rendering::XCanvasFont >(
     694           0 :                     new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
     695             : 
     696           0 :         return uno::Reference< rendering::XCanvasFont >();
     697             :     }
     698             : 
     699           0 :     uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas*                       /*pCanvas*/,
     700             :                                                                             const rendering::FontInfo&                      /*aFilter*/,
     701             :                                                                             const uno::Sequence< beans::PropertyValue >&    /*aFontProperties*/ )
     702             :     {
     703             :         // TODO
     704           0 :         return uno::Sequence< rendering::FontInfo >();
     705             :     }
     706             : 
     707           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas*                         /*pCanvas*/,
     708             :                                                                           const rendering::StringContext&                   /*text*/,
     709             :                                                                           const uno::Reference< rendering::XCanvasFont >&   /*xFont*/,
     710             :                                                                           const rendering::ViewState&                       /*viewState*/,
     711             :                                                                           const rendering::RenderState&                     /*renderState*/,
     712             :                                                                           sal_Int8                                          /*textDirection*/ )
     713             :     {
     714             :         // TODO - but not used from slideshow
     715           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     716             :     }
     717             : 
     718           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas*                       /*pCanvas*/,
     719             :                                                                                 const uno::Reference< rendering::XTextLayout >& xLayoutetText,
     720             :                                                                                 const rendering::ViewState&                     viewState,
     721             :                                                                                 const rendering::RenderState&                   renderState )
     722             :     {
     723           0 :         ENSURE_OR_THROW( xLayoutetText.is(),
     724             :                           "CanvasHelper::drawTextLayout: text is NULL");
     725             : 
     726           0 :         if( mpDevice )
     727             :         {
     728           0 :             VirtualDevice aVDev;
     729           0 :             aVDev.EnableOutput(false);
     730             : 
     731           0 :             CanvasFont* pFont=dynamic_cast<CanvasFont*>(xLayoutetText->getFont().get());
     732           0 :             const rendering::StringContext& rTxt=xLayoutetText->getText();
     733           0 :             if( pFont && rTxt.Length )
     734             :             {
     735             :                 // create the font
     736           0 :                 const rendering::FontRequest& rFontRequest = pFont->getFontRequest();
     737           0 :                 const geometry::Matrix2D&     rFontMatrix = pFont->getFontMatrix();
     738             :                 vcl::Font aFont(
     739             :                     rFontRequest.FontDescription.FamilyName,
     740             :                     rFontRequest.FontDescription.StyleName,
     741           0 :                     Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
     742             : 
     743           0 :                 aFont.SetAlign( ALIGN_BASELINE );
     744           0 :                 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
     745           0 :                 aFont.SetVertical( rFontRequest.FontDescription.IsVertical==util::TriState_YES );
     746           0 :                 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
     747           0 :                 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
     748             : 
     749             :                 // adjust to stretched font
     750           0 :                 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
     751             :                 {
     752           0 :                     const Size aSize = aVDev.GetFontMetric( aFont ).GetSize();
     753           0 :                     const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
     754           0 :                     double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
     755             : 
     756           0 :                     if( !::basegfx::fTools::equalZero( fDividend) )
     757           0 :                         fStretch /= fDividend;
     758             : 
     759           0 :                     const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
     760             : 
     761           0 :                     aFont.SetWidth( nNewWidth );
     762             :                 }
     763             : 
     764             :                 // set font
     765           0 :                 aVDev.SetFont(aFont);
     766             : 
     767           0 :                 mpRecordedActions->push_back( Action() );
     768           0 :                 Action& rAct=mpRecordedActions->back();
     769             : 
     770           0 :                 setupGraphicsState( rAct, viewState, renderState );
     771             : 
     772             :                 // handle custom spacing, if there
     773           0 :                 uno::Sequence<double> aLogicalAdvancements=xLayoutetText->queryLogicalAdvancements();
     774           0 :                 if( aLogicalAdvancements.getLength() )
     775             :                 {
     776             :                     // create the DXArray
     777           0 :                     const sal_Int32 nLen( aLogicalAdvancements.getLength() );
     778           0 :                     ::boost::scoped_array<long> pDXArray( new long[nLen] );
     779           0 :                     for( sal_Int32 i=0; i<nLen; ++i )
     780           0 :                         pDXArray[i] = basegfx::fround( aLogicalAdvancements[i] );
     781             : 
     782             :                     // get the glyphs
     783             :                     aVDev.GetTextOutlines(rAct.maPolyPolys,
     784             :                                           rTxt.Text,
     785             :                                           0,
     786             :                                           rTxt.StartPosition,
     787             :                                           rTxt.Length,
     788             :                                           true,
     789             :                                           0,
     790           0 :                                           pDXArray.get() );
     791             :                 }
     792             :                 else
     793             :                 {
     794             :                     // get the glyphs
     795             :                     aVDev.GetTextOutlines(rAct.maPolyPolys,
     796             :                                           rTxt.Text,
     797             :                                           0,
     798             :                                           rTxt.StartPosition,
     799           0 :                                           rTxt.Length );
     800             :                 }
     801             : 
     802             :                 // own copy, for thread safety
     803             :                 std::for_each(rAct.maPolyPolys.begin(),
     804             :                               rAct.maPolyPolys.end(),
     805           0 :                               ::boost::mem_fn(&::basegfx::B2DPolyPolygon::makeUnique));
     806             : 
     807           0 :                 rAct.maFunction = &lcl_fillPolyPolygon;
     808           0 :             }
     809             :         }
     810             : 
     811             :         // TODO
     812           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     813             :     }
     814             : 
     815           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas*                   /*pCanvas*/,
     816             :                                                                             const uno::Reference< rendering::XBitmap >& xBitmap,
     817             :                                                                             const rendering::ViewState&                 viewState,
     818             :                                                                             const rendering::RenderState&               renderState )
     819             :     {
     820           0 :         ENSURE_OR_THROW( xBitmap.is(),
     821             :                           "CanvasHelper::drawBitmap: bitmap is NULL");
     822             : 
     823           0 :         if( mpDevice )
     824             :         {
     825             :             // own bitmap?
     826           0 :             CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(xBitmap.get());
     827           0 :             if( pOwnBitmap )
     828             :             {
     829             :                 // insert as transformed copy of bitmap action vector -
     830             :                 // during rendering, this gets rendered into a temporary
     831             :                 // buffer, and then composited to the front
     832           0 :                 mpRecordedActions->push_back( Action() );
     833           0 :                 Action& rAct=mpRecordedActions->back();
     834             : 
     835           0 :                 setupGraphicsState( rAct, viewState, renderState );
     836           0 :                 rAct.maFunction = ::boost::bind(&lcl_drawOwnBitmap,
     837             :                                                 _1,_2,_3,_4,_5,
     838           0 :                                                 *pOwnBitmap);
     839             :             }
     840             :             else
     841             :             {
     842             :                 // TODO(P3): Highly inefficient - simply copies pixel data
     843             : 
     844             :                 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
     845           0 :                     xBitmap, uno::UNO_QUERY);
     846           0 :                 if( xIntegerBitmap.is() )
     847             :                 {
     848           0 :                     const geometry::IntegerSize2D aSize=xBitmap->getSize();
     849           0 :                     rendering::IntegerBitmapLayout aLayout;
     850             :                     uno::Sequence<sal_Int8> aPixelData=
     851           0 :                         xIntegerBitmap->getData(
     852             :                             aLayout,
     853           0 :                             geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
     854             : 
     855             :                     // force-convert color to ARGB8888 int color space
     856             :                     uno::Sequence<sal_Int8> aARGBBytes(
     857           0 :                         aLayout.ColorSpace->convertToIntegerColorSpace(
     858             :                             aPixelData,
     859           0 :                             canvas::tools::getStdColorSpace()));
     860             : 
     861           0 :                     mpRecordedActions->push_back( Action() );
     862           0 :                     Action& rAct=mpRecordedActions->back();
     863             : 
     864           0 :                     setupGraphicsState( rAct, viewState, renderState );
     865           0 :                     rAct.maFunction = ::boost::bind(&lcl_drawGenericBitmap,
     866             :                                                     _1,_2,_3,_4,_5,
     867             :                                                     aSize, aARGBBytes,
     868             :                                                     rtl_crc32(0,
     869           0 :                                                               aARGBBytes.getConstArray(),
     870           0 :                                                               aARGBBytes.getLength()));
     871           0 :                 }
     872             :                 // TODO(F1): handle non-integer case
     873             :             }
     874             :         }
     875             : 
     876             :         // TODO(P1): Provide caching here.
     877           0 :         return uno::Reference< rendering::XCachedPrimitive >(NULL);
     878             :     }
     879             : 
     880           0 :     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas*                      pCanvas,
     881             :                                                                                      const uno::Reference< rendering::XBitmap >&    xBitmap,
     882             :                                                                                      const rendering::ViewState&                    viewState,
     883             :                                                                                      const rendering::RenderState&                  renderState )
     884             :     {
     885             :         // TODO(F3): remove this wart altogether
     886           0 :         return drawBitmap(pCanvas, xBitmap, viewState, renderState);
     887             :     }
     888             : 
     889             : 
     890           0 :     void CanvasHelper::setupGraphicsState( Action&                       o_action,
     891             :                                            const rendering::ViewState&   viewState,
     892             :                                            const rendering::RenderState& renderState )
     893             :     {
     894           0 :         ENSURE_OR_THROW( mpDevice,
     895             :                           "CanvasHelper::setupGraphicsState: reference device invalid" );
     896             : 
     897             :         // TODO(F3): clipping
     898             :         // TODO(P2): think about caching transformations between canvas calls
     899             : 
     900             :         // setup overall transform only now. View clip above was
     901             :         // relative to view transform
     902           0 :         ::basegfx::B2DHomMatrix aTransform;
     903             :         ::canvas::tools::mergeViewAndRenderTransform(o_action.maTransform,
     904             :                                                      viewState,
     905           0 :                                                      renderState);
     906             :         // setup compositing - mapping courtesy David Reveman
     907             :         // (glitz_operator.c)
     908           0 :         switch( renderState.CompositeOperation )
     909             :         {
     910             :             case rendering::CompositeOperation::OVER:
     911           0 :                 o_action.meSrcBlendMode=GL_ONE;
     912           0 :                 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
     913           0 :                 break;
     914             :             case rendering::CompositeOperation::CLEAR:
     915           0 :                 o_action.meSrcBlendMode=GL_ZERO;
     916           0 :                 o_action.meDstBlendMode=GL_ZERO;
     917           0 :                 break;
     918             :             case rendering::CompositeOperation::SOURCE:
     919           0 :                 o_action.meSrcBlendMode=GL_ONE;
     920           0 :                 o_action.meDstBlendMode=GL_ZERO;
     921           0 :                 break;
     922             :             case rendering::CompositeOperation::UNDER:
     923             :                 // FALLTHROUGH intended - but correct?!
     924             :             case rendering::CompositeOperation::DESTINATION:
     925           0 :                 o_action.meSrcBlendMode=GL_ZERO;
     926           0 :                 o_action.meDstBlendMode=GL_ONE;
     927           0 :                 break;
     928             :             case rendering::CompositeOperation::INSIDE:
     929           0 :                 o_action.meSrcBlendMode=GL_DST_ALPHA;
     930           0 :                 o_action.meDstBlendMode=GL_ZERO;
     931           0 :                 break;
     932             :             case rendering::CompositeOperation::INSIDE_REVERSE:
     933           0 :                 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
     934           0 :                 o_action.meDstBlendMode=GL_ZERO;
     935           0 :                 break;
     936             :             case rendering::CompositeOperation::OUTSIDE:
     937           0 :                 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
     938           0 :                 o_action.meDstBlendMode=GL_ONE;
     939           0 :                 break;
     940             :             case rendering::CompositeOperation::OUTSIDE_REVERSE:
     941           0 :                 o_action.meSrcBlendMode=GL_ZERO;
     942           0 :                 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
     943           0 :                 break;
     944             :             case rendering::CompositeOperation::ATOP:
     945           0 :                 o_action.meSrcBlendMode=GL_DST_ALPHA;
     946           0 :                 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
     947           0 :                 break;
     948             :             case rendering::CompositeOperation::ATOP_REVERSE:
     949           0 :                 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
     950           0 :                 o_action.meDstBlendMode=GL_SRC_ALPHA;
     951           0 :                 break;
     952             :             case rendering::CompositeOperation::XOR:
     953           0 :                 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
     954           0 :                 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
     955           0 :                 break;
     956             :             case rendering::CompositeOperation::ADD:
     957           0 :                 o_action.meSrcBlendMode=GL_ONE;
     958           0 :                 o_action.meDstBlendMode=GL_ONE;
     959           0 :                 break;
     960             :             case rendering::CompositeOperation::SATURATE:
     961           0 :                 o_action.meSrcBlendMode=GL_SRC_ALPHA_SATURATE;
     962           0 :                 o_action.meDstBlendMode=GL_SRC_ALPHA_SATURATE;
     963           0 :                 break;
     964             : 
     965             :             default:
     966           0 :                 ENSURE_OR_THROW( false, "CanvasHelper::setupGraphicsState: unexpected mode" );
     967             :                 break;
     968             :         }
     969             : 
     970           0 :         if (renderState.DeviceColor.getLength())
     971             :             o_action.maARGBColor =
     972           0 :                 mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0];
     973           0 :     }
     974             : 
     975           0 :     void CanvasHelper::flush() const
     976             :     {
     977           0 :     }
     978             : 
     979           0 :     bool CanvasHelper::renderRecordedActions() const
     980             :     {
     981           0 :         std::vector<Action>::const_iterator aCurr(mpRecordedActions->begin());
     982           0 :         const std::vector<Action>::const_iterator aEnd(mpRecordedActions->end());
     983           0 :         while( aCurr != aEnd )
     984             :         {
     985           0 :             if( !aCurr->maFunction( *this,
     986           0 :                                     aCurr->maTransform,
     987           0 :                                     aCurr->meSrcBlendMode,
     988           0 :                                     aCurr->meDstBlendMode,
     989           0 :                                     aCurr->maARGBColor,
     990           0 :                                     aCurr->maPolyPolys ) )
     991           0 :                 return false;
     992             : 
     993           0 :             ++aCurr;
     994             :         }
     995             : 
     996           0 :         return true;
     997             :     }
     998             : 
     999           0 :     size_t CanvasHelper::getRecordedActionCount() const
    1000             :     {
    1001           0 :         return mpRecordedActions->size();
    1002             :     }
    1003           0 : }
    1004             : 
    1005             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10