[Libreoffice-commits] core.git: 3 commits - basegfx/Library_basegfx.mk basegfx/source canvas/Library_oglcanvas.mk canvas/Module_canvas.mk canvas/source configure.ac cppcanvas/source include/basegfx include/cppcanvas include/sal offapi/com officecfg/registry Repository.mk sdext/source sd/source slideshow/source

Thorsten Behrens tbehrens at suse.com
Mon Oct 7 08:34:18 PDT 2013


 Repository.mk                                            |    1 
 basegfx/Library_basegfx.mk                               |    1 
 basegfx/source/polygon/b2dpolypolygontools.cxx           |  133 +
 basegfx/source/tools/numbertools.cxx                     |   61 
 canvas/Library_oglcanvas.mk                              |   69 
 canvas/Module_canvas.mk                                  |    6 
 canvas/source/cairo/cairo_canvashelper.hxx               |    1 
 canvas/source/directx/dx_bitmapcanvashelper.hxx          |    1 
 canvas/source/directx/dx_canvashelper.hxx                |    2 
 canvas/source/opengl/ogl_bitmapcanvashelper.cxx          |  101 +
 canvas/source/opengl/ogl_bitmapcanvashelper.hxx          |  103 +
 canvas/source/opengl/ogl_buffercontext.hxx               |   34 
 canvas/source/opengl/ogl_canvasbitmap.cxx                |   55 
 canvas/source/opengl/ogl_canvasbitmap.hxx                |   78 
 canvas/source/opengl/ogl_canvascustomsprite.cxx          |  261 +++
 canvas/source/opengl/ogl_canvascustomsprite.hxx          |  100 +
 canvas/source/opengl/ogl_canvasfont.cxx                  |   81 
 canvas/source/opengl/ogl_canvasfont.hxx                  |   68 
 canvas/source/opengl/ogl_canvashelper.cxx                | 1011 ++++++++++++
 canvas/source/opengl/ogl_canvashelper.hxx                |  238 ++
 canvas/source/opengl/ogl_canvastools.cxx                 |  139 +
 canvas/source/opengl/ogl_canvastools.hxx                 |   38 
 canvas/source/opengl/ogl_spritecanvas.cxx                |  195 ++
 canvas/source/opengl/ogl_spritecanvas.hxx                |  118 +
 canvas/source/opengl/ogl_spritedevicehelper.cxx          | 1249 +++++++++++++++
 canvas/source/opengl/ogl_spritedevicehelper.hxx          |  179 ++
 canvas/source/opengl/ogl_textlayout.cxx                  |  215 ++
 canvas/source/opengl/ogl_textlayout.hxx                  |   79 
 canvas/source/opengl/ogl_texturecache.cxx                |  124 +
 canvas/source/opengl/ogl_texturecache.hxx                |   64 
 canvas/source/opengl/ogl_tools.hxx                       |   31 
 canvas/source/opengl/oglcanvas.component                 |   16 
 canvas/source/tools/canvastools.cxx                      |   10 
 canvas/source/vcl/canvashelper.hxx                       |    1 
 configure.ac                                             |    2 
 cppcanvas/source/wrapper/implspritecanvas.cxx            |    4 
 cppcanvas/source/wrapper/implspritecanvas.hxx            |    4 
 include/basegfx/polygon/b2dpolypolygontools.hxx          |   20 
 include/basegfx/tools/tools.hxx                          |   25 
 include/cppcanvas/spritecanvas.hxx                       |    4 
 include/sal/log-areas.dox                                |    2 
 offapi/com/sun/star/rendering/XSpriteCanvas.idl          |   11 
 officecfg/registry/data/org/openoffice/Office/Canvas.xcu |    1 
 sd/source/ui/presenter/PresenterCanvas.cxx               |   11 
 sd/source/ui/presenter/PresenterCanvas.hxx               |    4 
 sd/source/ui/presenter/PresenterTextView.cxx             |    1 
 sd/source/ui/presenter/SlideRenderer.cxx                 |    1 
 sdext/source/presenter/PresenterSlideSorter.cxx          |    1 
 slideshow/source/engine/slideview.cxx                    |    9 
 slideshow/source/engine/transitions/slidechangebase.cxx  |    1 
 slideshow/source/engine/waitsymbol.cxx                   |   13 
 51 files changed, 4933 insertions(+), 44 deletions(-)

New commits:
commit e52f1bd7b34fc73f52aadf1d33efa6685a0b22e8
Author: Thorsten Behrens <tbehrens at suse.com>
Date:   Tue Jan 31 01:07:48 2012 +0100

    Add opengl canvas implementation.
    
    Adds opengl canvas implementation - display-list-based, all
    rendering done as textured geometry. Needs shader support.
    
    Currently compiles and works on Linux, Mac should be ~easy to
    add, win32 eventually.
    
    Change-Id: Ibf3eb88d6a36a91b2960a3a6320d708160e4fc14

diff --git a/Repository.mk b/Repository.mk
index 7e393d4..d306442 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -229,6 +229,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	$(if $(filter unx,$(GUIBASE)),desktop_detector) \
 	$(if $(DISABLE_SCRIPTING),,dlgprov) \
 	$(if $(ENABLE_DIRECTX),directx9canvas) \
+	$(if $(ENABLE_OPENGL),oglcanvas) \
 	drawinglayer \
 	editeng \
 	egi \
diff --git a/canvas/Library_oglcanvas.mk b/canvas/Library_oglcanvas.mk
new file mode 100644
index 0000000..fca6996
--- /dev/null
+++ b/canvas/Library_oglcanvas.mk
@@ -0,0 +1,69 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,oglcanvas))
+
+$(eval $(call gb_Library_set_componentfile,oglcanvas,canvas/source/opengl/oglcanvas))
+
+$(eval $(call gb_Library_use_sdk_api,oglcanvas))
+
+$(eval $(call gb_Library_use_libraries,oglcanvas,\
+	sal \
+	cppu \
+	basegfx \
+	cppuhelper \
+	comphelper \
+	vcl \
+	tk \
+	tl \
+	i18nlangtag \
+	canvastools \
+	$(gb_UWINAPI) \
+))
+
+$(eval $(call gb_Library_add_exception_objects,oglcanvas,\
+	canvas/source/opengl/ogl_bitmapcanvashelper \
+	canvas/source/opengl/ogl_canvasbitmap \
+	canvas/source/opengl/ogl_canvascustomsprite \
+	canvas/source/opengl/ogl_canvasfont \
+	canvas/source/opengl/ogl_canvashelper \
+	canvas/source/opengl/ogl_canvastools \
+	canvas/source/opengl/ogl_spritecanvas \
+	canvas/source/opengl/ogl_spritedevicehelper \
+	canvas/source/opengl/ogl_textlayout \
+	canvas/source/opengl/ogl_texturecache \
+))
+
+$(eval $(call gb_Library_use_externals,oglcanvas,\
+	boost_headers \
+))
+
+ifeq ($(strip $(OS)),MACOSX)
+$(eval $(call gb_Library_use_system_darwin_frameworks,oglcanvas,\
+    Cocoa \
+    GLUT \
+    OpenGL \
+))
+
+else ifeq ($(strip $(OS)),WNT)
+$(eval $(call gb_Library_use_system_win32_libs,oglcanvas,\
+    gdi32 \
+    glu32 \
+    opengl32 \
+))
+
+else
+$(eval $(call gb_Library_add_libs,oglcanvas,\
+    -lGL \
+    -lGLU \
+    -lX11 \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/canvas/Module_canvas.mk b/canvas/Module_canvas.mk
index 0bc364e..510cb98 100644
--- a/canvas/Module_canvas.mk
+++ b/canvas/Module_canvas.mk
@@ -32,6 +32,12 @@ $(eval $(call gb_Module_add_targets,canvas,\
 ))
 endif
 
+ifeq ($(ENABLE_OPENGL),TRUE)
+$(eval $(call gb_Module_add_targets,canvas,\
+	Library_oglcanvas \
+))
+endif
+
 ifneq ($(ENABLE_DIRECTX),)
 $(eval $(call gb_Module_add_targets,canvas,\
 	Library_directx9canvas \
diff --git a/canvas/source/opengl/ogl_bitmapcanvashelper.cxx b/canvas/source/opengl/ogl_bitmapcanvashelper.cxx
new file mode 100644
index 0000000..1d132cb
--- /dev/null
+++ b/canvas/source/opengl/ogl_bitmapcanvashelper.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ogl_bitmapcanvashelper.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+
+using namespace ::com::sun::star;
+
+namespace oglcanvas
+{
+    BitmapCanvasHelper::BitmapCanvasHelper()
+    {}
+
+    void BitmapCanvasHelper::disposing()
+    {
+        CanvasHelper::disposing();
+    }
+
+    void BitmapCanvasHelper::init( rendering::XGraphicDevice&     rDevice,
+                                   SpriteDeviceHelper&            rDeviceHelper,
+                                   const geometry::IntegerSize2D& rSize )
+    {
+        maSize = rSize;
+        CanvasHelper::init(rDevice,rDeviceHelper);
+    }
+
+    void BitmapCanvasHelper::copyRect( const rendering::XCanvas*                            /*pCanvas*/,
+                                       const uno::Reference< rendering::XBitmapCanvas >&    /*sourceCanvas*/,
+                                       const geometry::RealRectangle2D&                     /*sourceRect*/,
+                                       const rendering::ViewState&                          /*sourceViewState*/,
+                                       const rendering::RenderState&                        /*sourceRenderState*/,
+                                       const geometry::RealRectangle2D&                     /*destRect*/,
+                                       const rendering::ViewState&                          /*destViewState*/,
+                                       const rendering::RenderState&                        /*destRenderState*/ )
+    {
+        // TODO(F2): copyRect NYI
+    }
+
+    geometry::IntegerSize2D BitmapCanvasHelper::getSize()
+    {
+        return maSize;
+    }
+
+    uno::Reference< rendering::XBitmap > BitmapCanvasHelper::getScaledBitmap( const geometry::RealSize2D& /*newSize*/,
+                                                                              sal_Bool                    /*beFast*/ )
+    {
+        // TODO(F1):
+        return uno::Reference< rendering::XBitmap >();
+    }
+
+    uno::Sequence< sal_Int8 > BitmapCanvasHelper::getData( rendering::IntegerBitmapLayout&     /*bitmapLayout*/,
+                                                           const geometry::IntegerRectangle2D& /*rect*/ )
+    {
+        // TODO(F2): NYI - and improbable to ever be
+        return uno::Sequence< sal_Int8 >();
+    }
+
+    void BitmapCanvasHelper::setData( const uno::Sequence< sal_Int8 >&      /*data*/,
+                                      const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+                                      const geometry::IntegerRectangle2D&   /*rect*/ )
+    {
+        // TODO(F2): NYI - and improbable to ever be
+    }
+
+    void BitmapCanvasHelper::setPixel( const uno::Sequence< sal_Int8 >&       /*color*/,
+                                       const rendering::IntegerBitmapLayout&  /*bitmapLayout*/,
+                                       const geometry::IntegerPoint2D&        /*pos*/ )
+    {
+        // TODO(F2): NYI - and improbable to ever be
+    }
+
+    uno::Sequence< sal_Int8 > BitmapCanvasHelper::getPixel( rendering::IntegerBitmapLayout&   /*bitmapLayout*/,
+                                                            const geometry::IntegerPoint2D&   /*pos*/ )
+    {
+        // TODO(F2): NYI - and improbable to ever be
+        return uno::Sequence< sal_Int8 >();
+    }
+
+    rendering::IntegerBitmapLayout BitmapCanvasHelper::getMemoryLayout()
+    {
+        return ::canvas::tools::getStdMemoryLayout(getSize());
+    }
+
+    bool BitmapCanvasHelper::hasAlpha() const
+    {
+        return true;
+    }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_bitmapcanvashelper.hxx b/canvas/source/opengl/ogl_bitmapcanvashelper.hxx
new file mode 100644
index 0000000..50781c3
--- /dev/null
+++ b/canvas/source/opengl/ogl_bitmapcanvashelper.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_BITMAPCANVASHELPER_HXX_
+#define OGL_BITMAPCANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+#include "ogl_canvashelper.hxx"
+
+
+namespace oglcanvas
+{
+    /** Helper class for basic canvas functionality. */
+    class BitmapCanvasHelper : public CanvasHelper
+    {
+    public:
+        BitmapCanvasHelper();
+
+        /// Release all references
+        void disposing();
+
+        /** Initialize canvas helper
+
+            This method late-initializes the canvas helper, providing
+            it with the necessary device and output objects. Note that
+            the CanvasHelper does <em>not</em> take ownership of the
+            passed rDevice reference, nor does it perform any
+            reference counting. Thus, to prevent the reference counted
+            SpriteCanvas object from deletion, the user of this class
+            is responsible for holding ref-counted references itself!
+
+            @param rDevice
+            Reference device this canvas is associated with
+
+         */
+        void init( ::com::sun::star::rendering::XGraphicDevice&     rDevice,
+                   SpriteDeviceHelper&                              rDeviceHelper,
+                   const ::com::sun::star::geometry::IntegerSize2D& rSize );
+
+        // BitmapCanvasHelper functionality
+        // ================================
+
+        void copyRect( const ::com::sun::star::rendering::XCanvas*          rCanvas,
+                       const ::com::sun::star::uno::Reference<
+                            ::com::sun::star::rendering::XBitmapCanvas >&   sourceCanvas,
+                       const ::com::sun::star::geometry::RealRectangle2D&   sourceRect,
+                       const ::com::sun::star::rendering::ViewState&        sourceViewState,
+                       const ::com::sun::star::rendering::RenderState&      sourceRenderState,
+                       const ::com::sun::star::geometry::RealRectangle2D&   destRect,
+                       const ::com::sun::star::rendering::ViewState&        destViewState,
+                       const ::com::sun::star::rendering::RenderState&      destRenderState );
+
+        ::com::sun::star::geometry::IntegerSize2D getSize();
+
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > queryBitmapCanvas();
+
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap >
+            getScaledBitmap( const ::com::sun::star::geometry::RealSize2D&  newSize,
+                             sal_Bool                                               beFast );
+
+        ::com::sun::star::uno::Sequence< sal_Int8 >
+            getData( ::com::sun::star::rendering::IntegerBitmapLayout&      bitmapLayout,
+                     const ::com::sun::star::geometry::IntegerRectangle2D&  rect );
+
+        void setData( const ::com::sun::star::uno::Sequence< sal_Int8 >&        data,
+                      const ::com::sun::star::rendering::IntegerBitmapLayout&   bitmapLayout,
+                      const ::com::sun::star::geometry::IntegerRectangle2D&     rect );
+
+        void setPixel( const ::com::sun::star::uno::Sequence< sal_Int8 >&       color,
+                       const ::com::sun::star::rendering::IntegerBitmapLayout&  bitmapLayout,
+                       const ::com::sun::star::geometry::IntegerPoint2D&        pos );
+
+        ::com::sun::star::uno::Sequence< sal_Int8 >
+            getPixel( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+                      const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+        ::com::sun::star::rendering::IntegerBitmapLayout getMemoryLayout();
+
+        bool hasAlpha() const;
+
+    private:
+        ::com::sun::star::geometry::IntegerSize2D maSize;
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_buffercontext.hxx b/canvas/source/opengl/ogl_buffercontext.hxx
new file mode 100644
index 0000000..b996412
--- /dev/null
+++ b/canvas/source/opengl/ogl_buffercontext.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_BUFFERCONTEXT_HXX_
+#define OGL_BUFFERCONTEXT_HXX_
+
+#include <sal/config.h>
+#include <boost/shared_ptr.hpp>
+
+namespace oglcanvas
+{
+    struct IBufferContext
+    {
+        virtual ~IBufferContext() {}
+
+        /// start render to buffer. changes gl current context
+        virtual bool startBufferRendering() = 0;
+
+        /// end render to buffer. switches to window context, and selects rendered texture
+        virtual bool endBufferRendering() = 0;
+    };
+
+    typedef ::boost::shared_ptr<IBufferContext> IBufferContextSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvasbitmap.cxx b/canvas/source/opengl/ogl_canvasbitmap.cxx
new file mode 100644
index 0000000..d78baf5
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvasbitmap.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ogl_canvasbitmap.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+
+using namespace ::com::sun::star;
+
+namespace oglcanvas
+{
+    CanvasBitmap::CanvasBitmap( const geometry::IntegerSize2D& rSize,
+                                const SpriteCanvasRef&         rDevice,
+                                SpriteDeviceHelper&            rDeviceHelper,
+                                bool                           bHasAlpha ) :
+        mpDevice( rDevice ),
+        mbHasAlpha( bHasAlpha )
+    {
+        ENSURE_OR_THROW( mpDevice.is(),
+                         "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
+
+        maCanvasHelper.init( *mpDevice.get(), rDeviceHelper, rSize );
+    }
+
+    CanvasBitmap::CanvasBitmap( const CanvasBitmap& rSrc ) :
+        mpDevice( rSrc.mpDevice ),
+        mbHasAlpha( rSrc.mbHasAlpha )
+    {
+        maCanvasHelper = rSrc.maCanvasHelper;
+    }
+
+    void SAL_CALL CanvasBitmap::disposeThis()
+    {
+        mpDevice.clear();
+
+        // forward to parent
+        CanvasBitmapBaseT::disposeThis();
+    }
+
+    bool CanvasBitmap::renderRecordedActions() const
+    {
+        return maCanvasHelper.renderRecordedActions();
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvasbitmap.hxx b/canvas/source/opengl/ogl_canvasbitmap.hxx
new file mode 100644
index 0000000..b874bde
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvasbitmap.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_CANVASBITMAP_HXX
+#define OGL_CANVASBITMAP_HXX
+
+#include <cppuhelper/compbase2.hxx>
+
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/base/disambiguationhelper.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include "ogl_bitmapcanvashelper.hxx"
+#include "ogl_spritecanvas.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace oglcanvas
+{
+    typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XBitmapCanvas,
+                                              ::com::sun::star::rendering::XIntegerBitmap > CanvasBitmapBase_Base;
+    typedef ::canvas::IntegerBitmapBase<
+        ::canvas::DisambiguationHelper< CanvasBitmapBase_Base >,
+        BitmapCanvasHelper,
+        ::osl::MutexGuard,
+        ::cppu::OWeakObject >                          CanvasBitmapBaseT;
+
+    class CanvasBitmap : public CanvasBitmapBaseT
+    {
+    public:
+        /** Create a canvas bitmap for the given surface
+
+            @param rSize
+            Size of the bitmap
+
+            @param rDevice
+            Reference device, with which bitmap should be compatible
+         */
+        CanvasBitmap( const ::com::sun::star::geometry::IntegerSize2D& rSize,
+                      const SpriteCanvasRef&                           rDevice,
+                      SpriteDeviceHelper&                              rDeviceHelper,
+                      bool                                             bHasAlpha );
+
+        /** Create verbatim copy (including all recorded actions)
+         */
+        CanvasBitmap( const CanvasBitmap& rSrc );
+
+        /// Dispose all internal references
+        virtual void disposeThis();
+
+        /** Write out recorded actions
+         */
+        bool renderRecordedActions() const;
+
+    private:
+        /** MUST hold here, too, since CanvasHelper only contains a
+            raw pointer (without refcounting)
+        */
+        SpriteCanvasRef mpDevice;
+        bool            mbHasAlpha;
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvascustomsprite.cxx b/canvas/source/opengl/ogl_canvascustomsprite.cxx
new file mode 100644
index 0000000..7c08671
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvascustomsprite.cxx
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ogl_canvascustomsprite.hxx"
+#include "ogl_canvastools.hxx"
+#include "ogl_tools.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/verifyinput.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h>
+
+
+using namespace ::com::sun::star;
+
+namespace oglcanvas
+{
+    CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+                                            const SpriteCanvasRef&                        rRefDevice,
+                                            SpriteDeviceHelper&                           rDeviceHelper ) :
+        mpSpriteCanvas( rRefDevice ),
+        maSize(rSpriteSize),
+        mxClip(),
+        maTransformation(),
+        maPosition(),
+        mfAlpha(0.0),
+        mfPriority(0.0)
+    {
+        ENSURE_OR_THROW( rRefDevice.get(),
+                         "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+        ::canvas::tools::setIdentityAffineMatrix2D(maTransformation);
+        maCanvasHelper.init( *rRefDevice.get(),
+                             rDeviceHelper );
+    }
+
+    void SAL_CALL CanvasCustomSprite::disposeThis()
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        mpSpriteCanvas.clear();
+
+        // forward to parent
+        CanvasCustomSpriteBaseT::disposeThis();
+    }
+
+    void SAL_CALL CanvasCustomSprite::setAlpha( double alpha ) throw (lang::IllegalArgumentException,
+                                                                      uno::RuntimeException)
+    {
+        canvas::tools::verifyRange( alpha, 0.0, 1.0 );
+
+        ::osl::MutexGuard aGuard( m_aMutex );
+        mfAlpha = alpha;
+    }
+
+    void SAL_CALL CanvasCustomSprite::move( const geometry::RealPoint2D&  aNewPos,
+                                            const rendering::ViewState&   viewState,
+                                            const rendering::RenderState& renderState ) throw (lang::IllegalArgumentException,
+                                                                                               uno::RuntimeException)
+    {
+        canvas::tools::verifyArgs(aNewPos, viewState, renderState,
+                                  BOOST_CURRENT_FUNCTION,
+                                  static_cast< ::cppu::OWeakObject* >(this));
+
+        ::osl::MutexGuard aGuard( m_aMutex );
+        ::basegfx::B2DHomMatrix aTransform;
+        ::canvas::tools::mergeViewAndRenderTransform(aTransform,
+                                                     viewState,
+                                                     renderState);
+
+        // convert position to device pixel
+        maPosition = ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos);
+        maPosition *= aTransform;
+    }
+
+    void SAL_CALL CanvasCustomSprite::transform( const geometry::AffineMatrix2D& aTransformation ) throw (lang::IllegalArgumentException,
+                                                                                                          uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+        maTransformation = aTransformation;
+    }
+
+    void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip ) throw (uno::RuntimeException)
+    {
+        mxClip = xClip;
+    }
+
+    void SAL_CALL CanvasCustomSprite::setPriority( double nPriority ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+        mfPriority = nPriority;
+    }
+
+    void SAL_CALL CanvasCustomSprite::show() throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+        if( mpSpriteCanvas.is() )
+            mpSpriteCanvas->show(this);
+    }
+
+    void SAL_CALL CanvasCustomSprite::hide() throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+        if( mpSpriteCanvas.is() )
+            mpSpriteCanvas->hide(this);
+    }
+
+    uno::Reference< rendering::XCanvas > SAL_CALL CanvasCustomSprite::getContentCanvas() throw (uno::RuntimeException)
+    {
+        return this;
+    }
+
+    bool CanvasCustomSprite::renderSprite() const
+    {
+        if( ::basegfx::fTools::equalZero( mfAlpha ) )
+            return true;
+
+        TransformationPreserver aPreserver1;
+        const ::basegfx::B2IVector aSpriteSizePixel(
+            ::canvas::tools::roundUp( maSize.Width ),
+            ::canvas::tools::roundUp( maSize.Height ));
+
+        // translate sprite to output position
+        glTranslated(maPosition.getX(), maPosition.getY(), 0);
+
+        {
+            TransformationPreserver aPreserver2;
+
+            // apply sprite content transformation matrix
+            double aGLTransform[] =
+                {
+                    maTransformation.m00, maTransformation.m10, 0, 0,
+                    maTransformation.m01, maTransformation.m11, 0, 0,
+                    0,                    0,                    1, 0,
+                    maTransformation.m02, maTransformation.m12, 0, 1
+                };
+            glMultMatrixd(aGLTransform);
+
+            IBufferContextSharedPtr pBufferContext;
+            if( mfAlpha != 1.0 || mxClip.is() )
+            {
+                // drats. need to render to temp surface before, and then
+                // composite that to screen
+
+                // TODO(P3): buffer pbuffer, maybe even keep content
+                // (in a texture?)
+                pBufferContext=maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel);
+                pBufferContext->startBufferRendering();
+            }
+
+            // this ends up in pBufferContext, if that one's "current"
+            if( !maCanvasHelper.renderRecordedActions() )
+                return false;
+
+            if( pBufferContext )
+            {
+                // content ended up in background buffer - compose to
+                // screen now. Calls below switches us back to window
+                // context, and binds to generated, dynamic texture
+                pBufferContext->endBufferRendering();
+
+                glEnable(GL_TEXTURE_2D);
+                glTexParameteri(GL_TEXTURE_2D,
+                                GL_TEXTURE_MIN_FILTER,
+                                GL_NEAREST);
+                glTexParameteri(GL_TEXTURE_2D,
+                                GL_TEXTURE_MAG_FILTER,
+                                GL_NEAREST);
+                glEnable(GL_BLEND);
+                glBlendFunc(GL_SRC_ALPHA,
+                            GL_ONE_MINUS_SRC_ALPHA);
+
+                // blend against fixed vertex color; texture alpha is multiplied in
+                glColor4f(1,1,1,mfAlpha);
+
+                if( mxClip.is() )
+                {
+                    const double fWidth=maSize.Width;
+                    const double fHeight=maSize.Height;
+
+                    // TODO(P3): buffer triangulation
+                    const ::basegfx::B2DPolygon& rTriangulatedPolygon(
+                        ::basegfx::triangulator::triangulate(
+                            ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(mxClip)));
+
+                    basegfx::B2DPolygon rTriangleList(
+                        basegfx::tools::clipTriangleListOnRange(
+                            rTriangulatedPolygon,
+                            basegfx::B2DRange(
+                                0,0,
+                                aSpriteSizePixel.getX(),
+                                aSpriteSizePixel.getY())));
+
+                    glBegin(GL_TRIANGLES);
+                    for( sal_uInt32 i=0; i<rTriangulatedPolygon.count(); i++ )
+                    {
+                        const ::basegfx::B2DPoint& rPt( rTriangulatedPolygon.getB2DPoint(i) );
+                        const double s(rPt.getX()/fWidth);
+                        const double t(rPt.getY()/fHeight);
+                        glTexCoord2f(s,t); glVertex2d(rPt.getX(), rPt.getY());
+                    }
+                    glEnd();
+                }
+                else
+                {
+                    const double fWidth=maSize.Width/aSpriteSizePixel.getX();
+                    const double fHeight=maSize.Height/aSpriteSizePixel.getY();
+
+                    glBegin(GL_TRIANGLE_STRIP);
+                    glTexCoord2f(0,0);            glVertex2d(0,0);
+                    glTexCoord2f(0,fHeight);      glVertex2d(0, aSpriteSizePixel.getY());
+                    glTexCoord2f(fWidth,0);       glVertex2d(aSpriteSizePixel.getX(),0);
+                    glTexCoord2f(fWidth,fHeight); glVertex2d(aSpriteSizePixel.getX(),aSpriteSizePixel.getY());
+                    glEnd();
+                }
+
+                glBindTexture(GL_TEXTURE_2D, 0);
+                glDisable(GL_TEXTURE_2D);
+            }
+        }
+
+        glColor4f(1,0,0,1);
+        glBegin(GL_LINE_STRIP);
+        glVertex2d(-2,-2);
+        glVertex2d(-2,maSize.Height+4);
+        glVertex2d(maSize.Width+4,maSize.Height+4);
+        glVertex2d(maSize.Width+4,-2);
+        glVertex2d(-2,-2);
+        glVertex2d(maSize.Width+4,maSize.Height+4);
+        glEnd();
+
+        std::vector<double> aVec;
+        aVec.push_back(mfAlpha);
+        aVec.push_back(mfPriority);
+        aVec.push_back(maCanvasHelper.getRecordedActionCount());
+        renderOSD( aVec, 10 );
+
+        return true;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvascustomsprite.hxx b/canvas/source/opengl/ogl_canvascustomsprite.hxx
new file mode 100644
index 0000000..a96ce64
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvascustomsprite.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_CANVASCUSTOMSPRITE_HXX
+#define OGL_CANVASCUSTOMSPRITE_HXX
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <canvas/base/disambiguationhelper.hxx>
+
+#include "ogl_spritecanvas.hxx"
+#include "ogl_canvashelper.hxx"
+
+
+namespace oglcanvas
+{
+    typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XCustomSprite,
+                                              ::com::sun::star::rendering::XCanvas > CanvasCustomSpriteBase_Base;
+    typedef ::canvas::CanvasBase<
+         ::canvas::DisambiguationHelper< CanvasCustomSpriteBase_Base >,
+         CanvasHelper,
+         ::osl::MutexGuard,
+         ::cppu::OWeakObject >                          CanvasCustomSpriteBaseT;
+
+    /* Definition of CanvasCustomSprite class */
+
+    class CanvasCustomSprite : public CanvasCustomSpriteBaseT
+    {
+    public:
+        /** Create a custom sprite
+
+            @param rSpriteSize
+            Size of the sprite in pixel
+
+            @param rRefDevice
+            Associated output device
+
+            @param rSpriteCanvas
+            Target canvas
+
+            @param rDevice
+            Target DX device
+         */
+        CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D&   rSpriteSize,
+                            const SpriteCanvasRef&                          rRefDevice,
+                            SpriteDeviceHelper&                             rDeviceHelper );
+
+        virtual void disposeThis();
+
+        // XSprite
+        virtual void SAL_CALL setAlpha( double alpha ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL move( const ::com::sun::star::geometry::RealPoint2D&  aNewPos, const ::com::sun::star::rendering::ViewState&  viewState, const ::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL transform( const ::com::sun::star::geometry::AffineMatrix2D& aTransformation ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL clip( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& aClip ) throw (::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL setPriority( double nPriority ) throw (::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL show() throw (::com::sun::star::uno::RuntimeException);
+        virtual void SAL_CALL hide() throw (::com::sun::star::uno::RuntimeException);
+
+        // XCustomSprite
+        virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > SAL_CALL getContentCanvas() throw (::com::sun::star::uno::RuntimeException);
+
+        double getPriority() const { return mfPriority; }
+
+        /// Render sprite content at sprite position
+        bool renderSprite() const;
+
+    private:
+        /** MUST hold here, too, since CanvasHelper only contains a
+            raw pointer (without refcounting)
+        */
+        SpriteCanvasRef                              mpSpriteCanvas;
+        const ::com::sun::star::geometry::RealSize2D maSize;
+
+        ::com::sun::star::uno::Reference<
+            ::com::sun::star::rendering::XPolyPolygon2D > mxClip;
+        ::com::sun::star::geometry::AffineMatrix2D        maTransformation;
+        ::basegfx::B2DPoint                               maPosition;
+        double                                            mfAlpha;
+        double                                            mfPriority;
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvasfont.cxx b/canvas/source/opengl/ogl_canvasfont.cxx
new file mode 100644
index 0000000..d465919
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvasfont.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ogl_canvasfont.hxx"
+#include "ogl_textlayout.hxx"
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/PanoseWeight.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace oglcanvas
+{
+    CanvasFont::CanvasFont( const rendering::FontRequest&                   rFontRequest,
+                            const uno::Sequence< beans::PropertyValue >&    /*extraFontProperties*/,
+                            const geometry::Matrix2D&                       fontMatrix ) :
+        CanvasFontBaseT( m_aMutex ),
+        maFontRequest( rFontRequest ),
+        maFontMatrix( fontMatrix )
+    {
+    }
+
+    void SAL_CALL CanvasFont::disposing()
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+    }
+
+    uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText,
+                                                                                    sal_Int8                        nDirection,
+                                                                                    sal_Int64                       nRandomSeed ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) );
+    }
+
+    uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes(  ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        // TODO
+        return uno::Sequence< double >();
+    }
+
+    uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties(  ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        // TODO
+        return uno::Sequence< beans::PropertyValue >();
+    }
+
+    rendering::FontRequest SAL_CALL CanvasFont::getFontRequest(  ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        return maFontRequest;
+    }
+
+    rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics(  ) throw (uno::RuntimeException)
+    {
+        ::osl::MutexGuard aGuard( m_aMutex );
+
+        // TODO
+        return rendering::FontMetrics();
+    }
+
+    const ::com::sun::star::geometry::Matrix2D& CanvasFont::getFontMatrix() const
+    {
+        return maFontMatrix;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvasfont.hxx b/canvas/source/opengl/ogl_canvasfont.hxx
new file mode 100644
index 0000000..9a26297
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvasfont.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_CANVASFONT_HXX
+#define OGL_CANVASFONT_HXX
+
+#include <comphelper/implementationreference.hxx>
+
+#include <cppuhelper/compbase1.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <rtl/ref.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+
+/* Definition of CanvasFont class */
+
+namespace oglcanvas
+{
+    class SpriteCanvas;
+
+    typedef ::cppu::WeakComponentImplHelper1< ::com::sun::star::rendering::XCanvasFont > CanvasFontBaseT;
+
+    class CanvasFont : public ::comphelper::OBaseMutex,
+                       public CanvasFontBaseT,
+                       private ::boost::noncopyable
+    {
+    public:
+        typedef ::comphelper::ImplementationReference<
+            CanvasFont,
+            ::com::sun::star::rendering::XCanvasFont > ImplRef;
+
+        CanvasFont( const ::com::sun::star::rendering::FontRequest&                                     fontRequest,
+                    const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >&    extraFontProperties,
+                    const ::com::sun::star::geometry::Matrix2D&                                         fontMatrix );
+
+        /// Dispose all internal references
+        virtual void SAL_CALL disposing();
+
+        // XCanvasFont
+        virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > SAL_CALL createTextLayout( const ::com::sun::star::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (::com::sun::star::uno::RuntimeException);
+        virtual ::com::sun::star::rendering::FontRequest SAL_CALL getFontRequest(  ) throw (::com::sun::star::uno::RuntimeException);
+        virtual ::com::sun::star::rendering::FontMetrics SAL_CALL getFontMetrics(  ) throw (::com::sun::star::uno::RuntimeException);
+        virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getAvailableSizes(  ) throw (::com::sun::star::uno::RuntimeException);
+        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getExtraFontProperties(  ) throw (::com::sun::star::uno::RuntimeException);
+
+        const ::com::sun::star::geometry::Matrix2D& getFontMatrix() const;
+
+    private:
+        ::com::sun::star::rendering::FontRequest    maFontRequest;
+        ::com::sun::star::geometry::Matrix2D        maFontMatrix;
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvashelper.cxx b/canvas/source/opengl/ogl_canvashelper.cxx
new file mode 100644
index 0000000..ae349b9
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvashelper.cxx
@@ -0,0 +1,1011 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#define GL_GLEXT_PROTOTYPES
+
+#include "ogl_canvashelper.hxx"
+
+#include <rtl/crc.h>
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/RepaintResult.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/font.hxx>
+
+#include "ogl_canvasfont.hxx"
+#include "ogl_canvastools.hxx"
+#include "ogl_canvasbitmap.hxx"
+#include "ogl_spritecanvas.hxx"
+#include "ogl_texturecache.hxx"
+#include "ogl_tools.hxx"
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h>
+
+#include <boost/scoped_array.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace oglcanvas
+{
+    /* Concepts:
+       =========
+
+       This OpenGL canvas implementation tries to keep all render
+       output as high-level as possible, i.e. geometry data and
+       externally-provided bitmaps. Therefore, calls at the
+       XCanvas-interfaces are not immediately transformed into colored
+       pixel inside some GL buffer, but are retained simply with their
+       call parameters. Only after XSpriteCanvas::updateScreen() has
+       been called, this all gets transferred to the OpenGL subsystem
+       and converted to a visible scene. The big advantage is, this
+       makes sprite modifications practically zero-overhead, and saves
+       a lot on texture memory (compared to the directx canvas, which
+       immediately dumps every render call into a texture).
+
+       The drawback, of course, is that complex images churn a lot of
+       GPU cycles on every re-rendering.
+
+       For the while, I'll be using immediate mode, i.e. transfer data
+       over and over again to the OpenGL subsystem. Alternatively,
+       there are display lists, which at least keep the data on the
+       server, or even better, vertex buffers, which copy geometry
+       data over en bloc.
+
+       Next todo: put polygon geometry into vertex buffer (LRU cache
+       necessary?) - or, rather, buffer objects! prune entries older
+       than one updateScreen() call)
+
+       Text: http://www.opengl.org/resources/features/fontsurvey/
+     */
+
+    struct CanvasHelper::Action
+    {
+        ::basegfx::B2DHomMatrix         maTransform;
+        GLenum                          meSrcBlendMode;
+        GLenum                          meDstBlendMode;
+        rendering::ARGBColor            maARGBColor;
+        ::basegfx::B2DPolyPolygonVector maPolyPolys;
+
+        ::boost::function6< bool,
+                            const CanvasHelper&,
+                            const ::basegfx::B2DHomMatrix&,
+                            GLenum,
+                            GLenum,
+                            const rendering::ARGBColor&,
+                            const ::basegfx::B2DPolyPolygonVector& > maFunction;
+    };
+
+    namespace
+    {
+        bool lcl_drawPoint( const CanvasHelper&              /*rHelper*/,
+                            const ::basegfx::B2DHomMatrix&   rTransform,
+                            GLenum                           eSrcBlend,
+                            GLenum                           eDstBlend,
+                            const rendering::ARGBColor&      rColor,
+                            const geometry::RealPoint2D&     rPoint )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            glBegin(GL_POINTS);
+            glVertex2d(rPoint.X, rPoint.Y);
+            glEnd();
+
+            return true;
+        }
+
+        bool lcl_drawLine( const CanvasHelper&              /*rHelper*/,
+                           const ::basegfx::B2DHomMatrix&   rTransform,
+                           GLenum                           eSrcBlend,
+                           GLenum                           eDstBlend,
+                           const rendering::ARGBColor&      rColor,
+                           const geometry::RealPoint2D&     rStartPoint,
+                           const geometry::RealPoint2D&     rEndPoint )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            glBegin(GL_LINES);
+            glVertex2d(rStartPoint.X, rStartPoint.Y);
+            glVertex2d(rEndPoint.X, rEndPoint.Y);
+            glEnd();
+
+            return true;
+        }
+
+        bool lcl_drawPolyPolygon( const CanvasHelper&                    /*rHelper*/,
+                                  const ::basegfx::B2DHomMatrix&         rTransform,
+                                  GLenum                                 eSrcBlend,
+                                  GLenum                                 eDstBlend,
+                                  const rendering::ARGBColor&            rColor,
+                                  const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
+            const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
+            while( aCurr != aEnd )
+                renderPolyPolygon(*aCurr++);
+
+            return true;
+        }
+
+        bool lcl_fillPolyPolygon( const CanvasHelper&                    /*rHelper*/,
+                                  const ::basegfx::B2DHomMatrix&         rTransform,
+                                  GLenum                                 eSrcBlend,
+                                  GLenum                                 eDstBlend,
+                                  const rendering::ARGBColor&            rColor,
+                                  const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
+            const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
+            while( aCurr != aEnd )
+            {
+                glBegin(GL_TRIANGLES);
+                renderComplexPolyPolygon(*aCurr++);
+                glEnd();
+            }
+
+            return true;
+        }
+
+        bool lcl_fillGradientPolyPolygon( const CanvasHelper&                            rHelper,
+                                          const ::basegfx::B2DHomMatrix&                 rTransform,
+                                          GLenum                                         eSrcBlend,
+                                          GLenum                                         eDstBlend,
+                                          const ::canvas::ParametricPolyPolygon::Values& rValues,
+                                          const rendering::Texture&                      rTexture,
+                                          const ::basegfx::B2DPolyPolygonVector&         rPolyPolygons )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
+
+            // convert to weird canvas textur coordinate system (not
+            // [0,1]^2, but path coordinate system)
+            ::basegfx::B2DHomMatrix aTextureTransform;
+            ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+                                                            rTexture.AffineTransform );
+            ::basegfx::B2DRange aBounds;
+            ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
+            const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
+            while( aCurr != aEnd )
+                aBounds.expand(::basegfx::tools::getRange(*aCurr++));
+            aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
+            aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
+
+            const sal_Int32 nNumCols=rValues.maColors.getLength();
+            uno::Sequence< rendering::ARGBColor > aColors(nNumCols);
+            rendering::ARGBColor* const pColors=aColors.getArray();
+            rendering::ARGBColor* pCurrCol=pColors;
+            for( sal_Int32 i=0; i<nNumCols; ++i )
+                *pCurrCol++ = rHelper.getDevice()->getDeviceColorSpace()->convertToARGB(rValues.maColors[i])[0];
+
+            OSL_ASSERT(nNumCols == rValues.maStops.getLength());
+
+            switch( rValues.meType )
+            {
+                case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
+                    rHelper.getDeviceHelper()->useLinearGradientShader(pColors,
+                                                                       rValues.maStops,
+                                                                       aTextureTransform);
+                    break;
+
+                case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
+                    rHelper.getDeviceHelper()->useRadialGradientShader(pColors,
+                                                                       rValues.maStops,
+                                                                       aTextureTransform);
+                    break;
+
+                case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
+                    rHelper.getDeviceHelper()->useRectangularGradientShader(pColors,
+                                                                            rValues.maStops,
+                                                                            aTextureTransform);
+                    break;
+
+                default:
+                    ENSURE_OR_THROW( false,
+                                      "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case" );
+            }
+
+
+            aCurr=rPolyPolygons.begin();
+            while( aCurr != aEnd )
+            {
+                glBegin(GL_TRIANGLES);
+                renderComplexPolyPolygon(*aCurr++);
+                glEnd();
+            }
+
+            glUseProgram(0);
+            glLoadIdentity();
+            glMatrixMode(GL_MODELVIEW);
+
+            return true;
+        }
+
+        bool lcl_drawOwnBitmap( const CanvasHelper&              /*rHelper*/,
+                                const ::basegfx::B2DHomMatrix&   rTransform,
+                                GLenum                           eSrcBlend,
+                                GLenum                           eDstBlend,
+                                const rendering::ARGBColor&      rColor,
+                                const CanvasBitmap&              rBitmap )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            return rBitmap.renderRecordedActions();
+        }
+
+        bool lcl_drawGenericBitmap( const CanvasHelper&              rHelper,
+                                    const ::basegfx::B2DHomMatrix&   rTransform,
+                                    GLenum                           eSrcBlend,
+                                    GLenum                           eDstBlend,
+                                    const rendering::ARGBColor&      rColor,
+                                    const geometry::IntegerSize2D&   rPixelSize,
+                                    const uno::Sequence<sal_Int8>&   rPixelData,
+                                    sal_uInt32                       nPixelCrc32 )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rColor);
+
+            const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
+                rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
+
+            glBindTexture(GL_TEXTURE_2D, nTexId);
+            glEnable(GL_TEXTURE_2D);
+            glTexParameteri(GL_TEXTURE_2D,
+                            GL_TEXTURE_MIN_FILTER,
+                            GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D,
+                            GL_TEXTURE_MAG_FILTER,
+                            GL_NEAREST);
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA,
+                        GL_ONE_MINUS_SRC_ALPHA);
+
+            // blend against fixed vertex color; texture alpha is multiplied in
+            glColor4f(1,1,1,1);
+
+            glBegin(GL_TRIANGLE_STRIP);
+            glTexCoord2f(0,0); glVertex2d(0,0);
+            glTexCoord2f(0,1); glVertex2d(0, rPixelSize.Height);
+            glTexCoord2f(1,0); glVertex2d(rPixelSize.Width,0);
+            glTexCoord2f(1,1); glVertex2d(rPixelSize.Width,rPixelSize.Height);
+            glEnd();
+
+            glBindTexture(GL_TEXTURE_2D, 0);
+            glDisable(GL_TEXTURE_2D);
+
+            return true;
+        }
+
+        bool lcl_fillTexturedPolyPolygon( const CanvasHelper&                    rHelper,
+                                          const ::basegfx::B2DHomMatrix&         rTransform,
+                                          GLenum                                 eSrcBlend,
+                                          GLenum                                 eDstBlend,
+                                          const rendering::Texture&              rTexture,
+                                          const geometry::IntegerSize2D&         rPixelSize,
+                                          const uno::Sequence<sal_Int8>&         rPixelData,
+                                          sal_uInt32                             nPixelCrc32,
+                                          const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
+        {
+            TransformationPreserver aPreserver;
+            setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
+
+            const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
+                rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
+
+            glBindTexture(GL_TEXTURE_2D, nTexId);
+            glEnable(GL_TEXTURE_2D);
+            glTexParameteri(GL_TEXTURE_2D,
+                            GL_TEXTURE_MIN_FILTER,
+                            GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D,
+                            GL_TEXTURE_MAG_FILTER,
+                            GL_NEAREST);
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA,
+                        GL_ONE_MINUS_SRC_ALPHA);
+
+            // convert to weird canvas textur coordinate system (not
+            // [0,1]^2, but path coordinate system)
+            ::basegfx::B2DHomMatrix aTextureTransform;
+            ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+                                                            rTexture.AffineTransform );
+            ::basegfx::B2DRange aBounds;
+            ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
+            const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
+            while( aCurr != aEnd )
+                aBounds.expand(::basegfx::tools::getRange(*aCurr++));
+            aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
+            aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
+            aTextureTransform.invert();
+
+            glMatrixMode(GL_TEXTURE);
+            double aTexTransform[] =
+                {
+                    aTextureTransform.get(0,0), aTextureTransform.get(1,0), 0, 0,
+                    aTextureTransform.get(0,1), aTextureTransform.get(1,1), 0, 0,
+                    0,                          0,                          1, 0,
+                    aTextureTransform.get(0,2), aTextureTransform.get(1,2), 0, 1
+                };
+            glLoadMatrixd(aTexTransform);
+
+            // blend against fixed vertex color; texture alpha is multiplied in
+            glColor4f(1,1,1,rTexture.Alpha);
+
+            aCurr=rPolyPolygons.begin();
+            while( aCurr != aEnd )
+            {
+                glBegin(GL_TRIANGLES);
+                renderComplexPolyPolygon(*aCurr++);
+                glEnd();
+            }
+
+            glLoadIdentity();
+            glMatrixMode(GL_MODELVIEW);
+
+            glBindTexture(GL_TEXTURE_2D, 0);
+            glDisable(GL_TEXTURE_2D);
+
+            return true;
+        }
+    }
+
+    CanvasHelper::CanvasHelper() :
+        mpDevice( NULL ),
+        mpRecordedActions()
+    {}
+
+    CanvasHelper::~CanvasHelper()
+    {}
+
+    CanvasHelper& CanvasHelper::operator=( const CanvasHelper& rSrc )
+    {
+        mpDevice = rSrc.mpDevice;
+        mpDeviceHelper = rSrc.mpDeviceHelper;
+        mpRecordedActions = rSrc.mpRecordedActions;
+        return *this;
+    }
+
+    void CanvasHelper::disposing()
+    {
+        RecordVectorT aThrowaway;
+        mpRecordedActions.swap( aThrowaway );
+        mpDevice = NULL;
+        mpDeviceHelper = NULL;
+    }
+
+    void CanvasHelper::init( rendering::XGraphicDevice& rDevice,
+                             SpriteDeviceHelper& rDeviceHelper )
+    {
+        mpDevice = &rDevice;
+        mpDeviceHelper = &rDeviceHelper;
+    }
+
+    void CanvasHelper::clear()
+    {
+        mpRecordedActions->clear();
+    }
+
+    void CanvasHelper::drawPoint( const rendering::XCanvas*     /*pCanvas*/,
+                                  const geometry::RealPoint2D&  aPoint,
+                                  const rendering::ViewState&   viewState,
+                                  const rendering::RenderState& renderState )
+    {
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maFunction = ::boost::bind(&lcl_drawPoint,
+                                            _1,_2,_3,_4,_5,
+                                            aPoint);
+        }
+    }
+
+    void CanvasHelper::drawLine( const rendering::XCanvas*      /*pCanvas*/,
+                                 const geometry::RealPoint2D&   aStartPoint,
+                                 const geometry::RealPoint2D&   aEndPoint,
+                                 const rendering::ViewState&    viewState,
+                                 const rendering::RenderState&  renderState )
+    {
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maFunction = ::boost::bind(&lcl_drawLine,
+                                            _1,_2,_3,_4,_5,
+                                            aStartPoint,aEndPoint);
+        }
+    }
+
+    void CanvasHelper::drawBezier( const rendering::XCanvas*            /*pCanvas*/,
+                                   const geometry::RealBezierSegment2D& aBezierSegment,
+                                   const geometry::RealPoint2D&         aEndPoint,
+                                   const rendering::ViewState&          viewState,
+                                   const rendering::RenderState&        renderState )
+    {
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+
+            // TODO(F2): subdivide&render whole curve
+            rAct.maFunction = ::boost::bind(&lcl_drawLine,
+                                            _1,_2,_3,_4,_5,
+                                            geometry::RealPoint2D(
+                                                aBezierSegment.Px,
+                                                aBezierSegment.Py),
+                                            aEndPoint);
+        }
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
+                                                                                 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+                                                                                 const rendering::ViewState&                        viewState,
+                                                                                 const rendering::RenderState&                      renderState )
+    {
+        ENSURE_OR_THROW( xPolyPolygon.is(),
+                          "CanvasHelper::drawPolyPolygon: polygon is NULL");
+
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maPolyPolys.push_back(
+                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
+            rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
+
+            rAct.maFunction = &lcl_drawPolyPolygon;
+        }
+
+        // TODO(P1): Provide caching here.
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas*                            /*pCanvas*/,
+                                                                                   const uno::Reference< rendering::XPolyPolygon2D >&   xPolyPolygon,
+                                                                                   const rendering::ViewState&                          viewState,
+                                                                                   const rendering::RenderState&                        renderState,
+                                                                                   const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
+    {
+        ENSURE_OR_THROW( xPolyPolygon.is(),
+                          "CanvasHelper::strokePolyPolygon: polygon is NULL");
+
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maPolyPolys.push_back(
+                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
+            rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
+
+            // TODO(F3): fallback to drawPolyPolygon currently
+            rAct.maFunction = &lcl_drawPolyPolygon;
+        }
+
+        // TODO(P1): Provide caching here.
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas*                            /*pCanvas*/,
+                                                                                           const uno::Reference< rendering::XPolyPolygon2D >&   /*xPolyPolygon*/,
+                                                                                           const rendering::ViewState&                          /*viewState*/,
+                                                                                           const rendering::RenderState&                        /*renderState*/,
+                                                                                           const uno::Sequence< rendering::Texture >&           /*textures*/,
+                                                                                           const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
+    {
+        // TODO
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas*                           /*pCanvas*/,
+                                                                                                const uno::Reference< rendering::XPolyPolygon2D >&  /*xPolyPolygon*/,
+                                                                                                const rendering::ViewState&                         /*viewState*/,
+                                                                                                const rendering::RenderState&                       /*renderState*/,
+                                                                                                const uno::Sequence< rendering::Texture >&          /*textures*/,
+                                                                                                const uno::Reference< geometry::XMapping2D >&       /*xMapping*/,
+                                                                                                const rendering::StrokeAttributes&                  /*strokeAttributes*/ )
+    {
+        // TODO
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XPolyPolygon2D >   CanvasHelper::queryStrokeShapes( const rendering::XCanvas*                            /*pCanvas*/,
+                                                                                   const uno::Reference< rendering::XPolyPolygon2D >&   /*xPolyPolygon*/,
+                                                                                   const rendering::ViewState&                          /*viewState*/,
+                                                                                   const rendering::RenderState&                        /*renderState*/,
+                                                                                   const rendering::StrokeAttributes&                   /*strokeAttributes*/ )
+    {
+        // TODO
+        return uno::Reference< rendering::XPolyPolygon2D >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
+                                                                                 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+                                                                                 const rendering::ViewState&                        viewState,
+                                                                                 const rendering::RenderState&                      renderState )
+    {
+        ENSURE_OR_THROW( xPolyPolygon.is(),
+                          "CanvasHelper::fillPolyPolygon: polygon is NULL");
+
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maPolyPolys.push_back(
+                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
+            rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
+
+            rAct.maFunction = &lcl_fillPolyPolygon;
+        }
+
+        // TODO(P1): Provide caching here.
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas*                          /*pCanvas*/,
+                                                                                         const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+                                                                                         const rendering::ViewState&                        viewState,
+                                                                                         const rendering::RenderState&                      renderState,
+                                                                                         const uno::Sequence< rendering::Texture >&         textures )
+    {
+        ENSURE_OR_THROW( xPolyPolygon.is(),
+                          "CanvasHelper::fillPolyPolygon: polygon is NULL");
+
+        if( mpDevice )
+        {
+            mpRecordedActions->push_back( Action() );
+            Action& rAct=mpRecordedActions->back();
+
+            setupGraphicsState( rAct, viewState, renderState );
+            rAct.maPolyPolys.push_back(
+                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
+            rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
+
+            // TODO(F1): Multi-texturing
+            if( textures[0].Gradient.is() )
+            {
+                // try to cast XParametricPolyPolygon2D reference to
+                // our implementation class.
+                ::canvas::ParametricPolyPolygon* pGradient =
+                      dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
+
+                if( pGradient )
+                {
+                    // copy state from Gradient polypoly locally
+                    // (given object might change!)
+                    const ::canvas::ParametricPolyPolygon::Values& rValues(
+                        pGradient->getValues() );
+
+                    rAct.maFunction = ::boost::bind(&lcl_fillGradientPolyPolygon,
+                                                    _1,_2,_3,_4,
+                                                    rValues,
+                                                    textures[0],
+                                                    _6);
+                }
+                else
+                {
+                    // TODO(F1): The generic case is missing here
+                    ENSURE_OR_THROW( false,
+                                      "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered" );
+                }
+            }
+            else if( textures[0].Bitmap.is() )
+            {
+                // own bitmap?
+                CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(textures[0].Bitmap.get());
+                if( pOwnBitmap )
+                {
+                    // TODO(F2): own texture bitmap
+                }
+                else
+                {
+                    // TODO(P3): Highly inefficient - simply copies pixel data
+
+                    uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
+                        textures[0].Bitmap,
+                        uno::UNO_QUERY);
+                    if( xIntegerBitmap.is() )
+                    {
+                        const geometry::IntegerSize2D aSize=xIntegerBitmap->getSize();
+                        rendering::IntegerBitmapLayout aLayout;
+                        uno::Sequence<sal_Int8> aPixelData=
+                            xIntegerBitmap->getData(
+                                aLayout,
+                                geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
+
+                        // force-convert color to ARGB8888 int color space
+                        uno::Sequence<sal_Int8> aARGBBytes(
+                            aLayout.ColorSpace->convertToIntegerColorSpace(
+                                aPixelData,
+                                canvas::tools::getStdColorSpace()));
+
+                        rAct.maFunction = ::boost::bind(&lcl_fillTexturedPolyPolygon,
+                                                        _1,_2,_3,_4,
+                                                        textures[0],
+                                                        aSize,
+                                                        aARGBBytes,
+                                                        rtl_crc32(0,
+                                                                  aARGBBytes.getConstArray(),
+                                                                  aARGBBytes.getLength()),
+                                                        _6);
+                    }
+                    // TODO(F1): handle non-integer case
+                }
+            }
+        }
+
+        // TODO(P1): Provide caching here.
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas*                             /*pCanvas*/,
+                                                                                              const uno::Reference< rendering::XPolyPolygon2D >&    /*xPolyPolygon*/,
+                                                                                              const rendering::ViewState&                           /*viewState*/,
+                                                                                              const rendering::RenderState&                         /*renderState*/,
+                                                                                              const uno::Sequence< rendering::Texture >&            /*textures*/,
+                                                                                              const uno::Reference< geometry::XMapping2D >&         /*xMapping*/ )
+    {
+        // TODO
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas*                    /*pCanvas*/,
+                                                                       const rendering::FontRequest&                fontRequest,
+                                                                       const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+                                                                       const geometry::Matrix2D&                    fontMatrix )
+    {
+        if( mpDevice )
+            return uno::Reference< rendering::XCanvasFont >(
+                    new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
+
+        return uno::Reference< rendering::XCanvasFont >();
+    }
+
+    uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas*                       /*pCanvas*/,
+                                                                            const rendering::FontInfo&                      /*aFilter*/,
+                                                                            const uno::Sequence< beans::PropertyValue >&    /*aFontProperties*/ )
+    {
+        // TODO
+        return uno::Sequence< rendering::FontInfo >();
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas*                         /*pCanvas*/,
+                                                                          const rendering::StringContext&                   /*text*/,
+                                                                          const uno::Reference< rendering::XCanvasFont >&   /*xFont*/,
+                                                                          const rendering::ViewState&                       /*viewState*/,
+                                                                          const rendering::RenderState&                     /*renderState*/,
+                                                                          sal_Int8                                          /*textDirection*/ )
+    {
+        // TODO - but not used from slideshow
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas*                       /*pCanvas*/,
+                                                                                const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+                                                                                const rendering::ViewState&                     viewState,
+                                                                                const rendering::RenderState&                   renderState )
+    {
+        ENSURE_OR_THROW( xLayoutetText.is(),
+                          "CanvasHelper::drawTextLayout: text is NULL");
+
+        if( mpDevice )
+        {
+            VirtualDevice aVDev;
+            aVDev.EnableOutput(false);
+
+            CanvasFont* pFont=dynamic_cast<CanvasFont*>(xLayoutetText->getFont().get());
+            const rendering::StringContext& rTxt=xLayoutetText->getText();
+            if( pFont && rTxt.Length )
+            {
+                // create the font
+                const rendering::FontRequest& rFontRequest = pFont->getFontRequest();
+                const geometry::Matrix2D&     rFontMatrix = pFont->getFontMatrix();
+                ::Font aFont(
+                    rFontRequest.FontDescription.FamilyName,
+                    rFontRequest.FontDescription.StyleName,
+                    Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
+
+                aFont.SetAlign( ALIGN_BASELINE );
+                aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+                aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==util::TriState_YES) ? true : false );
+                aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+                aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+
+                // adjust to stretched font
+                if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
+                {
+                    const Size aSize = aVDev.GetFontMetric( aFont ).GetSize();
+                    const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+                    double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+                    if( !::basegfx::fTools::equalZero( fDividend) )
+                        fStretch /= fDividend;
+
+                    const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+                    aFont.SetWidth( nNewWidth );
+                }
+
+                // set font
+                aVDev.SetFont(aFont);
+
+                mpRecordedActions->push_back( Action() );
+                Action& rAct=mpRecordedActions->back();
+
+                setupGraphicsState( rAct, viewState, renderState );
+
+                // handle custom spacing, if there
+                uno::Sequence<double> aLogicalAdvancements=xLayoutetText->queryLogicalAdvancements();
+                if( aLogicalAdvancements.getLength() )
+                {
+                    // create the DXArray
+                    const sal_Int32 nLen( aLogicalAdvancements.getLength() );
+                    ::boost::scoped_array<sal_Int32> pDXArray( new sal_Int32[nLen] );
+                    for( sal_Int32 i=0; i<nLen; ++i )
+                        pDXArray[i] = basegfx::fround( aLogicalAdvancements[i] );
+
+                    // get the glyphs
+                    aVDev.GetTextOutlines(rAct.maPolyPolys,
+                                          rTxt.Text,
+                                          0,
+                                          (xub_StrLen)rTxt.StartPosition,
+                                          (xub_StrLen)rTxt.Length,
+                                          true,
+                                          0,
+                                          pDXArray.get() );
+                }
+                else
+                {
+                    // get the glyphs
+                    aVDev.GetTextOutlines(rAct.maPolyPolys,
+                                          rTxt.Text,
+                                          0,
+                                          (xub_StrLen)rTxt.StartPosition,
+                                          (xub_StrLen)rTxt.Length );
+                }
+
+                // own copy, for thread safety
+                std::for_each(rAct.maPolyPolys.begin(),
+                              rAct.maPolyPolys.end(),
+                              ::boost::mem_fn(&::basegfx::B2DPolyPolygon::makeUnique));
+
+                rAct.maFunction = &lcl_fillPolyPolygon;
+            }
+        }
+
+        // TODO
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas*                   /*pCanvas*/,
+                                                                            const uno::Reference< rendering::XBitmap >& xBitmap,
+                                                                            const rendering::ViewState&                 viewState,
+                                                                            const rendering::RenderState&               renderState )
+    {
+        ENSURE_OR_THROW( xBitmap.is(),
+                          "CanvasHelper::drawBitmap: bitmap is NULL");
+
+        if( mpDevice )
+        {
+            // own bitmap?
+            CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(xBitmap.get());
+            if( pOwnBitmap )
+            {
+                // insert as transformed copy of bitmap action vector -
+                // during rendering, this gets rendered into a temporary
+                // buffer, and then composited to the front
+                mpRecordedActions->push_back( Action() );
+                Action& rAct=mpRecordedActions->back();
+
+                setupGraphicsState( rAct, viewState, renderState );
+                rAct.maFunction = ::boost::bind(&lcl_drawOwnBitmap,
+                                                _1,_2,_3,_4,_5,
+                                                *pOwnBitmap);
+            }
+            else
+            {
+                // TODO(P3): Highly inefficient - simply copies pixel data
+
+                uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
+                    xBitmap, uno::UNO_QUERY);
+                if( xIntegerBitmap.is() )
+                {
+                    const geometry::IntegerSize2D aSize=xBitmap->getSize();
+                    rendering::IntegerBitmapLayout aLayout;
+                    uno::Sequence<sal_Int8> aPixelData=
+                        xIntegerBitmap->getData(
+                            aLayout,
+                            geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
+
+                    // force-convert color to ARGB8888 int color space
+                    uno::Sequence<sal_Int8> aARGBBytes(
+                        aLayout.ColorSpace->convertToIntegerColorSpace(
+                            aPixelData,
+                            canvas::tools::getStdColorSpace()));
+
+                    mpRecordedActions->push_back( Action() );
+                    Action& rAct=mpRecordedActions->back();
+
+                    setupGraphicsState( rAct, viewState, renderState );
+                    rAct.maFunction = ::boost::bind(&lcl_drawGenericBitmap,
+                                                    _1,_2,_3,_4,_5,
+                                                    aSize, aARGBBytes,
+                                                    rtl_crc32(0,
+                                                              aARGBBytes.getConstArray(),
+                                                              aARGBBytes.getLength()));
+                }
+                // TODO(F1): handle non-integer case
+            }
+        }
+
+        // TODO(P1): Provide caching here.
+        return uno::Reference< rendering::XCachedPrimitive >(NULL);
+    }
+
+    uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas*                      pCanvas,
+                                                                                     const uno::Reference< rendering::XBitmap >&    xBitmap,
+                                                                                     const rendering::ViewState&                    viewState,
+                                                                                     const rendering::RenderState&                  renderState )
+    {
+        // TODO(F3): remove this wart altogether
+        return drawBitmap(pCanvas, xBitmap, viewState, renderState);
+    }
+
+    uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+    {
+        return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+    }
+
+    void CanvasHelper::setupGraphicsState( Action&                       o_action,
+                                           const rendering::ViewState&   viewState,
+                                           const rendering::RenderState& renderState )
+    {
+        ENSURE_OR_THROW( mpDevice,
+                          "CanvasHelper::setupGraphicsState: reference device invalid" );
+
+        // TODO(F3): clipping
+        // TODO(P2): think about caching transformations between canvas calls
+
+        // setup overall transform only now. View clip above was
+        // relative to view transform
+        ::basegfx::B2DHomMatrix aTransform;
+        ::canvas::tools::mergeViewAndRenderTransform(o_action.maTransform,
+                                                     viewState,
+                                                     renderState);
+        // setup compositing - mapping courtesy David Reveman
+        // (glitz_operator.c)
+        switch( renderState.CompositeOperation )
+        {
+            case rendering::CompositeOperation::OVER:
+                o_action.meSrcBlendMode=GL_ONE;
+                o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
+                break;
+            case rendering::CompositeOperation::CLEAR:
+                o_action.meSrcBlendMode=GL_ZERO;
+                o_action.meDstBlendMode=GL_ZERO;
+                break;
+            case rendering::CompositeOperation::SOURCE:
+                o_action.meSrcBlendMode=GL_ONE;
+                o_action.meDstBlendMode=GL_ZERO;
+                break;
+            case rendering::CompositeOperation::UNDER:
+                // FALLTHROUGH intended - but correct?!
+            case rendering::CompositeOperation::DESTINATION:
+                o_action.meSrcBlendMode=GL_ZERO;
+                o_action.meDstBlendMode=GL_ONE;
+                break;
+            case rendering::CompositeOperation::INSIDE:
+                o_action.meSrcBlendMode=GL_DST_ALPHA;
+                o_action.meDstBlendMode=GL_ZERO;
+                break;
+            case rendering::CompositeOperation::INSIDE_REVERSE:
+                o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
+                o_action.meDstBlendMode=GL_ZERO;
+                break;
+            case rendering::CompositeOperation::OUTSIDE:
+                o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
+                o_action.meDstBlendMode=GL_ONE;
+                break;
+            case rendering::CompositeOperation::OUTSIDE_REVERSE:
+                o_action.meSrcBlendMode=GL_ZERO;
+                o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
+                break;
+            case rendering::CompositeOperation::ATOP:
+                o_action.meSrcBlendMode=GL_DST_ALPHA;
+                o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
+                break;
+            case rendering::CompositeOperation::ATOP_REVERSE:
+                o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
+                o_action.meDstBlendMode=GL_SRC_ALPHA;
+                break;
+            case rendering::CompositeOperation::XOR:
+                o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA;
+                o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA;
+                break;
+            case rendering::CompositeOperation::ADD:
+                o_action.meSrcBlendMode=GL_ONE;
+                o_action.meDstBlendMode=GL_ONE;
+                break;
+            case rendering::CompositeOperation::SATURATE:
+                o_action.meSrcBlendMode=GL_SRC_ALPHA_SATURATE;
+                o_action.meDstBlendMode=GL_SRC_ALPHA_SATURATE;
+                break;
+
+            default:
+                ENSURE_OR_THROW( false, "CanvasHelper::setupGraphicsState: unexpected mode" );
+                break;
+        }
+
+        o_action.maARGBColor =
+            mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0];
+    }
+
+    void CanvasHelper::flush() const
+    {
+    }
+
+    bool CanvasHelper::renderRecordedActions() const
+    {
+        std::vector<Action>::const_iterator aCurr(mpRecordedActions->begin());
+        const std::vector<Action>::const_iterator aEnd(mpRecordedActions->end());
+        while( aCurr != aEnd )
+        {
+            if( !aCurr->maFunction( *this,
+                                    aCurr->maTransform,
+                                    aCurr->meSrcBlendMode,
+                                    aCurr->meDstBlendMode,
+                                    aCurr->maARGBColor,
+                                    aCurr->maPolyPolys ) )
+                return false;
+
+            ++aCurr;
+        }
+
+        return true;
+    }
+
+    size_t CanvasHelper::getRecordedActionCount() const
+    {
+        return mpRecordedActions->size();
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/opengl/ogl_canvashelper.hxx b/canvas/source/opengl/ogl_canvashelper.hxx
new file mode 100644
index 0000000..b7280ac
--- /dev/null
+++ b/canvas/source/opengl/ogl_canvashelper.hxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OGL_CANVASHELPER_HXX_
+#define OGL_CANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include <o3tl/cow_wrapper.hxx>
+#include <vector>
+
+namespace oglcanvas
+{
+    class SpriteDeviceHelper;
+
+    /** Helper class for basic canvas functionality. */
+    class CanvasHelper
+    {
+    public:
+        CanvasHelper();
+
+        // outline because of incomplete type Action
+        ~CanvasHelper();
+        CanvasHelper& operator=( const CanvasHelper& );
+
+        /// Release all references
+        void disposing();
+
+        /** Initialize canvas helper
+
+            This method late-initializes the canvas helper, providing
+            it with the necessary device and output objects. Note that
+            the CanvasHelper does <em>not</em> take ownership of the
+            passed rDevice reference, nor does it perform any
+            reference counting. Thus, to prevent the reference counted
+            SpriteCanvas object from deletion, the user of this class
+            is responsible for holding ref-counted references itself!
+
+            @param rDevice
+            Reference device this canvas is associated with
+
+         */
+        void init( ::com::sun::star::rendering::XGraphicDevice& rDevice,
+                   SpriteDeviceHelper& rDeviceHelper );
+
+        // CanvasHelper functionality
+        // ==========================
+
+        // XCanvas (only providing, not implementing the
+        // interface. Also note subtle method parameter differences)
+        void clear();
+        void drawPoint( const ::com::sun::star::rendering::XCanvas*     pCanvas,
+                        const ::com::sun::star::geometry::RealPoint2D&  aPoint,
+                        const ::com::sun::star::rendering::ViewState&   viewState,
+                        const ::com::sun::star::rendering::RenderState& renderState );
+        void drawLine( const ::com::sun::star::rendering::XCanvas*      pCanvas,
+                       const ::com::sun::star::geometry::RealPoint2D&   aStartPoint,
+                       const ::com::sun::star::geometry::RealPoint2D&   aEndPoint,
+                       const ::com::sun::star::rendering::ViewState&    viewState,
+                       const ::com::sun::star::rendering::RenderState&  renderState );
+        void drawBezier( const ::com::sun::star::rendering::XCanvas*            pCanvas,
+                         const ::com::sun::star::geometry::RealBezierSegment2D& aBezierSegment,
+                         const ::com::sun::star::geometry::RealPoint2D&         aEndPoint,
+                         const ::com::sun::star::rendering::ViewState&          viewState,
+                         const ::com::sun::star::rendering::RenderState&        renderState );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            drawPolyPolygon( const ::com::sun::star::rendering::XCanvas*            pCanvas,
+                             const ::com::sun::star::uno::Reference<
+                                    ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                             const ::com::sun::star::rendering::ViewState&          viewState,
+                             const ::com::sun::star::rendering::RenderState&        renderState );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            strokePolyPolygon( const ::com::sun::star::rendering::XCanvas*          pCanvas,
+                               const ::com::sun::star::uno::Reference<
+                                    ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                               const ::com::sun::star::rendering::ViewState&        viewState,
+                               const ::com::sun::star::rendering::RenderState&      renderState,
+                               const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            strokeTexturedPolyPolygon( const ::com::sun::star::rendering::XCanvas*          pCanvas,
+                                       const ::com::sun::star::uno::Reference<
+                                            ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                                       const ::com::sun::star::rendering::ViewState&        viewState,
+                                       const ::com::sun::star::rendering::RenderState&      renderState,
+                                       const ::com::sun::star::uno::Sequence<
+                                            ::com::sun::star::rendering::Texture >&         textures,
+                                       const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            strokeTextureMappedPolyPolygon( const ::com::sun::star::rendering::XCanvas*             pCanvas,
+                                            const ::com::sun::star::uno::Reference<
+                                                    ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                                            const ::com::sun::star::rendering::ViewState&           viewState,
+                                            const ::com::sun::star::rendering::RenderState&         renderState,
+                                            const ::com::sun::star::uno::Sequence<
+                                                    ::com::sun::star::rendering::Texture >&         textures,
+                                            const ::com::sun::star::uno::Reference<
+                                                    ::com::sun::star::geometry::XMapping2D >&       xMapping,
+                                            const ::com::sun::star::rendering::StrokeAttributes&    strokeAttributes );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >
+            queryStrokeShapes( const ::com::sun::star::rendering::XCanvas*          pCanvas,
+                               const ::com::sun::star::uno::Reference<
+                                    ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                               const ::com::sun::star::rendering::ViewState&        viewState,
+                               const ::com::sun::star::rendering::RenderState&      renderState,
+                               const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            fillPolyPolygon( const ::com::sun::star::rendering::XCanvas*            pCanvas,
+                             const ::com::sun::star::uno::Reference<
+                                    ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                             const ::com::sun::star::rendering::ViewState&          viewState,
+                             const ::com::sun::star::rendering::RenderState&        renderState );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            fillTexturedPolyPolygon( const ::com::sun::star::rendering::XCanvas*            pCanvas,
+                                     const ::com::sun::star::uno::Reference<
+                                            ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                                     const ::com::sun::star::rendering::ViewState&          viewState,
+                                     const ::com::sun::star::rendering::RenderState&        renderState,
+                                     const ::com::sun::star::uno::Sequence<
+                                            ::com::sun::star::rendering::Texture >&         textures );
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+            fillTextureMappedPolyPolygon( const ::com::sun::star::rendering::XCanvas*           pCanvas,
+                                          const ::com::sun::star::uno::Reference<
+                                                ::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
+                                          const ::com::sun::star::rendering::ViewState&         viewState,
+                                          const ::com::sun::star::rendering::RenderState&       renderState,
+                                          const ::com::sun::star::uno::Sequence<
+                                                ::com::sun::star::rendering::Texture >&         textures,
+                                          const ::com::sun::star::uno::Reference<
+                                                ::com::sun::star::geometry::XMapping2D >&       xMapping );
+
+        ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > SAL_CALL
+            createFont( const ::com::sun::star::rendering::XCanvas*             pCanvas,

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list