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

Generated by: LCOV version 1.10