summaryrefslogtreecommitdiff
path: root/canvas/source/cairo
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/cairo')
-rw-r--r--canvas/source/cairo/cairo_cachedbitmap.cxx90
-rw-r--r--canvas/source/cairo/cairo_cachedbitmap.hxx67
-rw-r--r--canvas/source/cairo/cairo_cairo.cxx64
-rw-r--r--canvas/source/cairo/cairo_cairo.hxx97
-rw-r--r--canvas/source/cairo/cairo_canvas.cxx195
-rw-r--r--canvas/source/cairo/cairo_canvas.hxx161
-rw-r--r--canvas/source/cairo/cairo_canvasbitmap.cxx286
-rw-r--r--canvas/source/cairo/cairo_canvasbitmap.hxx138
-rw-r--r--canvas/source/cairo/cairo_canvascustomsprite.cxx175
-rw-r--r--canvas/source/cairo/cairo_canvascustomsprite.hxx156
-rw-r--r--canvas/source/cairo/cairo_canvasfont.cxx193
-rw-r--r--canvas/source/cairo/cairo_canvasfont.hxx96
-rw-r--r--canvas/source/cairo/cairo_canvashelper.cxx1996
-rw-r--r--canvas/source/cairo/cairo_canvashelper.hxx335
-rw-r--r--canvas/source/cairo/cairo_canvashelper_text.cxx398
-rw-r--r--canvas/source/cairo/cairo_canvashelper_texturefill.cxx144
-rw-r--r--canvas/source/cairo/cairo_devicehelper.cxx302
-rw-r--r--canvas/source/cairo/cairo_devicehelper.hxx143
-rw-r--r--canvas/source/cairo/cairo_quartz_cairo.cxx347
-rw-r--r--canvas/source/cairo/cairo_quartz_cairo.hxx73
-rw-r--r--canvas/source/cairo/cairo_repainttarget.hxx60
-rw-r--r--canvas/source/cairo/cairo_services.cxx83
-rw-r--r--canvas/source/cairo/cairo_sprite.hxx71
-rw-r--r--canvas/source/cairo/cairo_spritecanvas.cxx232
-rw-r--r--canvas/source/cairo/cairo_spritecanvas.hxx174
-rw-r--r--canvas/source/cairo/cairo_spritecanvashelper.cxx544
-rw-r--r--canvas/source/cairo/cairo_spritecanvashelper.hxx147
-rw-r--r--canvas/source/cairo/cairo_spritedevicehelper.cxx201
-rw-r--r--canvas/source/cairo/cairo_spritedevicehelper.hxx95
-rw-r--r--canvas/source/cairo/cairo_spritehelper.cxx183
-rw-r--r--canvas/source/cairo/cairo_spritehelper.hxx115
-rw-r--r--canvas/source/cairo/cairo_spritesurface.hxx70
-rw-r--r--canvas/source/cairo/cairo_surfaceprovider.hxx82
-rw-r--r--canvas/source/cairo/cairo_textlayout.cxx656
-rw-r--r--canvas/source/cairo/cairo_textlayout.hxx120
-rw-r--r--canvas/source/cairo/cairo_win32_cairo.cxx325
-rw-r--r--canvas/source/cairo/cairo_win32_cairo.hxx70
-rw-r--r--canvas/source/cairo/cairo_xlib_cairo.cxx352
-rw-r--r--canvas/source/cairo/cairo_xlib_cairo.hxx106
-rw-r--r--canvas/source/cairo/cairocanvas.component37
-rw-r--r--canvas/source/cairo/exports.dxp2
-rw-r--r--canvas/source/cairo/makefile.mk140
42 files changed, 9321 insertions, 0 deletions
diff --git a/canvas/source/cairo/cairo_cachedbitmap.cxx b/canvas/source/cairo/cairo_cachedbitmap.cxx
new file mode 100644
index 000000000000..53b0bb02d76d
--- /dev/null
+++ b/canvas/source/cairo/cairo_cachedbitmap.cxx
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "cairo_cachedbitmap.hxx"
+#include "cairo_repainttarget.hxx"
+
+#include <com/sun/star/rendering/RepaintResult.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ CachedBitmap::CachedBitmap( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& rUsedViewState,
+ const rendering::RenderState& rUsedRenderState,
+ const uno::Reference< rendering::XCanvas >& rTarget ) :
+ CachedPrimitiveBase( rUsedViewState, rTarget, true ),
+ mpSurface( pSurface ),
+ maRenderState( rUsedRenderState )
+ {}
+
+ void SAL_CALL CachedBitmap::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpSurface.reset();
+ CachedPrimitiveBase::disposing();
+ }
+
+ ::sal_Int8 CachedBitmap::doRedraw( const rendering::ViewState& rNewState,
+ const rendering::ViewState& /*rOldState*/,
+ const uno::Reference< rendering::XCanvas >& rTargetCanvas,
+ bool bSameViewTransform )
+ {
+ ENSURE_OR_THROW( bSameViewTransform,
+ "CachedBitmap::doRedraw(): base called with changed view transform "
+ "(told otherwise during construction)" );
+
+ RepaintTarget* pTarget = dynamic_cast< RepaintTarget* >(rTargetCanvas.get());
+
+ ENSURE_OR_THROW( pTarget,
+ "CachedBitmap::redraw(): cannot cast target to RepaintTarget" );
+
+ if( !pTarget->repaint( mpSurface,
+ rNewState,
+ maRenderState ) )
+ {
+ // target failed to repaint
+ return rendering::RepaintResult::FAILED;
+ }
+
+ return rendering::RepaintResult::REDRAWN;
+ }
+}
diff --git a/canvas/source/cairo/cairo_cachedbitmap.hxx b/canvas/source/cairo/cairo_cachedbitmap.hxx
new file mode 100644
index 000000000000..a704a0d6c20f
--- /dev/null
+++ b/canvas/source/cairo/cairo_cachedbitmap.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CACHEDBITMAP_HXX
+#define _CAIROCANVAS_CACHEDBITMAP_HXX
+
+#include <canvas/base/cachedprimitivebase.hxx>
+
+#include "cairo_cairo.hxx"
+
+/* Definition of CachedBitmap class */
+
+namespace cairocanvas
+{
+ class CachedBitmap : public ::canvas::CachedPrimitiveBase
+ {
+ public:
+
+ /** Create an XCachedPrimitive for given GraphicObject
+ */
+ CachedBitmap( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& rUsedViewState,
+ const ::com::sun::star::rendering::RenderState& rUsedRenderState,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& rTarget );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ private:
+ virtual ::sal_Int8 doRedraw( const ::com::sun::star::rendering::ViewState& rNewState,
+ const ::com::sun::star::rendering::ViewState& rOldState,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& rTargetCanvas,
+ bool bSameViewTransform );
+
+
+ ::cairo::SurfaceSharedPtr mpSurface;
+ const ::com::sun::star::rendering::RenderState maRenderState;
+ };
+}
+
+#endif /* _CAIROCANVAS_CACHEDBITMAP_HXX */
diff --git a/canvas/source/cairo/cairo_cairo.cxx b/canvas/source/cairo/cairo_cairo.cxx
new file mode 100644
index 000000000000..f855a4f1700c
--- /dev/null
+++ b/canvas/source/cairo/cairo_cairo.cxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include "cairo_cairo.hxx"
+
+#ifdef WNT
+# include <tools/prewin.h>
+# include <windows.h>
+# include <tools/postwin.h>
+#endif
+
+#include <vcl/sysdata.hxx>
+#include <vcl/syschild.hxx>
+
+namespace cairo
+{
+/****************************************************************************************
+ * Platform independent part of surface backends for OpenOffice.org Cairo Canvas *
+ * For the rest of the functions (and the platform-specific derived *
+ * Surface classes), see platform specific cairo_<platform>_cairo.cxx *
+ ****************************************************************************************/
+
+ const SystemEnvData* GetSysData(const Window *pOutputWindow)
+ {
+ const SystemEnvData* pSysData = NULL;
+ // check whether we're a SysChild: have to fetch system data
+ // directly from SystemChildWindow, because the GetSystemData
+ // method is unfortunately not virtual
+ const SystemChildWindow* pSysChild = dynamic_cast< const SystemChildWindow* >( pOutputWindow );
+ if( pSysChild )
+ pSysData = pSysChild->GetSystemData();
+ else
+ pSysData = pOutputWindow->GetSystemData();
+ return pSysData;
+ }
+}
diff --git a/canvas/source/cairo/cairo_cairo.hxx b/canvas/source/cairo/cairo_cairo.hxx
new file mode 100644
index 000000000000..10832ac27be6
--- /dev/null
+++ b/canvas/source/cairo/cairo_cairo.hxx
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CAIRO_HXX
+#define _CAIROCANVAS_CAIRO_HXX
+
+#include <sal/config.h>
+#include <boost/shared_ptr.hpp>
+
+struct SystemEnvData;
+struct BitmapSystemData;
+struct SystemGraphicsData;
+class VirtualDevice;
+class OutputDevice;
+class Window;
+class Size;
+
+#include <cairo.h> //cannot be inside a namespace, otherwise Quartz fails to compile.
+
+namespace cairo {
+ typedef cairo_t Cairo;
+ typedef cairo_matrix_t Matrix;
+ typedef cairo_format_t Format;
+ typedef cairo_content_t Content;
+ typedef cairo_pattern_t Pattern;
+
+ typedef boost::shared_ptr<cairo_surface_t> CairoSurfaceSharedPtr;
+ typedef boost::shared_ptr<Cairo> CairoSharedPtr;
+
+ const SystemEnvData* GetSysData(const Window *pOutputWindow);
+
+ /** Cairo surface interface
+
+ For each cairo-supported platform, there's an implementation of
+ this interface
+ */
+ struct Surface
+ {
+ public:
+ virtual ~Surface() {}
+
+ // Query methods
+ virtual CairoSharedPtr getCairo() const = 0;
+ virtual CairoSurfaceSharedPtr getCairoSurface() const = 0;
+ virtual boost::shared_ptr<Surface> getSimilar( Content aContent, int width, int height ) const = 0;
+
+ /// factory for VirDev on this surface
+ virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const = 0;
+
+ /// Resize the surface (possibly destroying content)
+ virtual void Resize( int width, int height ) = 0;
+
+ /// Flush all pending output to surface
+ virtual void flush() const = 0;
+ };
+
+ typedef boost::shared_ptr<Surface> SurfaceSharedPtr;
+
+ /// Create Surface from given cairo surface
+ SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface );
+ /// Create surface with given dimensions
+ SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
+ int x, int y, int width, int height );
+ /// Create Surface for given bitmap data
+ SurfaceSharedPtr createBitmapSurface( const OutputDevice& rRefDevice,
+ const BitmapSystemData& rData,
+ const Size& rSize );
+
+ /// Check whether cairo will work on given window
+ bool IsCairoWorking( OutputDevice* );
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_canvas.cxx b/canvas/source/cairo/cairo_canvas.cxx
new file mode 100644
index 000000000000..54d04158c993
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvas.cxx
@@ -0,0 +1,195 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#ifdef WNT
+# include <tools/prewin.h>
+# include <windows.h>
+# include <tools/postwin.h>
+#endif
+
+#include <vcl/sysdata.hxx>
+
+#include "cairo_canvas.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ Canvas::Canvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void Canvas::initialize()
+ {
+ // #i64742# Only perform initialization when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ /* maArguments:
+ 0: ptr to creating instance (Window or VirtualDevice)
+ 1: SystemEnvData as a streamed Any (or empty for VirtualDevice)
+ 2: current bounds of creating instance
+ 3: bool, denoting always on top state for Window (always false for VirtualDevice)
+ 4: XWindow for creating Window (or empty for VirtualDevice)
+ 5: SystemGraphicsData as a streamed Any
+ */
+ VERBOSE_TRACE("Canvas created %p\n", this);
+
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER &&
+ maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
+ "Canvas::initialize: wrong number of arguments, or wrong types" );
+
+ // We expect a single Any here, containing a pointer to a valid
+ // VCL output device, on which to output (mostly needed for text)
+ sal_Int64 nPtr = 0;
+ maArguments[0] >>= nPtr;
+ OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
+
+ ENSURE_ARG_OR_THROW( pOutDev != NULL,
+ "Canvas::initialize: invalid OutDev pointer" );
+
+ awt::Rectangle aBounds;
+ maArguments[2] >>= aBounds;
+
+ uno::Sequence<sal_Int8> aSeq;
+ maArguments[5] >>= aSeq;
+
+ const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
+ if( !pSysData || !pSysData->nSize )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed SystemGraphicsData invalid!")),
+ NULL);
+
+ bool bHasXRender = IsCairoWorking(pOutDev);
+ ENSURE_ARG_OR_THROW( bHasXRender == true,
+ "SpriteCanvas::SpriteCanvas: No RENDER extension" );
+
+ // setup helper
+ maDeviceHelper.init( *this,
+ *pOutDev );
+
+ maCanvasHelper.init( basegfx::B2ISize(aBounds.Width, aBounds.Height),
+ *this, this );
+
+ // forward surface to render on to canvashelper
+ maCanvasHelper.setSurface(
+ maDeviceHelper.getSurface(),
+ false );
+
+ maArguments.realloc(0);
+ }
+
+ Canvas::~Canvas()
+ {
+ OSL_TRACE( "CairoCanvas destroyed" );
+ }
+
+ void SAL_CALL Canvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxComponentContext.clear();
+
+ // forward to parent
+ CanvasBaseT::disposing();
+ }
+
+ ::rtl::OUString SAL_CALL Canvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CANVAS_SERVICE_NAME ) );
+ }
+
+ bool Canvas::repaint( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return maCanvasHelper.repaint( pSurface, viewState, renderState );
+ }
+
+ SurfaceSharedPtr Canvas::getSurface()
+ {
+ return maDeviceHelper.getSurface();
+ }
+
+ SurfaceSharedPtr Canvas::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ return maDeviceHelper.createSurface( rSize, aContent );
+ }
+
+ SurfaceSharedPtr Canvas::createSurface( ::Bitmap& rBitmap )
+ {
+ SurfaceSharedPtr pSurface;
+
+ BitmapSystemData aData;
+ if( rBitmap.GetSystemData( aData ) ) {
+ const Size& rSize = rBitmap.GetSizePixel();
+
+ pSurface = maDeviceHelper.createSurface( aData, rSize );
+ }
+
+ return pSurface;
+ }
+
+ SurfaceSharedPtr Canvas::changeSurface( bool, bool )
+ {
+ // non-modifiable surface here
+ return SurfaceSharedPtr();
+ }
+
+ OutputDevice* Canvas::getOutputDevice()
+ {
+ return maDeviceHelper.getOutputDevice();
+ }
+}
diff --git a/canvas/source/cairo/cairo_canvas.hxx b/canvas/source/cairo/cairo_canvas.hxx
new file mode 100644
index 000000000000..bbcb89c54c7d
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvas.hxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CANVAS_HXX_
+#define _CAIROCANVAS_CANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <cppuhelper/compbase7.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/spritecanvasbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/bufferedgraphicdevicebase.hxx>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include "cairo_devicehelper.hxx"
+#include "cairo_repainttarget.hxx"
+#include "cairo_surfaceprovider.hxx"
+#include "cairo_spritecanvashelper.hxx"
+
+#define CANVAS_SERVICE_NAME "com.sun.star.rendering.Canvas.Cairo"
+#define CANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.Canvas.Cairo"
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::lang::XMultiServiceFactory,
+ ::com::sun::star::util::XUpdatable,
+ ::com::sun::star::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
+ typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase_Base >,
+ DeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBase_Base;
+
+ /** Mixin SurfaceProvider
+
+ Have to mixin the SurfaceProvider before deriving from
+ ::canvas::CanvasBase, as this template should already
+ implement some of those interface methods.
+
+ The reason why this appears kinda convoluted is the fact that
+ we cannot specify non-IDL types as WeakComponentImplHelperN
+ template args, and furthermore, don't want to derive
+ ::canvas::CanvasBase directly from
+ SurfaceProvider (because derivees of
+ ::canvas::CanvasBase have to explicitely forward the
+ XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS)
+ anyway).
+ */
+ class CanvasBaseSurfaceProvider_Base : public CanvasBase_Base,
+ public SurfaceProvider
+ {
+ };
+
+ typedef ::canvas::IntegerBitmapBase< CanvasBaseSurfaceProvider_Base,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBaseT;
+
+ /** Product of this component's factory.
+
+ The Canvas object combines the actual Window canvas with
+ the XGraphicDevice interface. This is because there's a
+ one-to-one relation between them, anyway, since each window
+ can have exactly one canvas and one associated
+ XGraphicDevice. And to avoid messing around with circular
+ references, this is implemented as one single object.
+ */
+ class Canvas : public CanvasBaseT,
+ public RepaintTarget
+ {
+ public:
+ Canvas( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Any >& aArguments,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ void initialize();
+
+ /// For resource tracking
+ ~Canvas();
+
+#if defined __SUNPRO_CC
+ using CanvasBaseT::disposing;
+#endif
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( Canvas, GraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // RepaintTarget
+ virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ // SurfaceProvider
+ virtual SurfaceSharedPtr getSurface();
+ virtual SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ virtual SurfaceSharedPtr createSurface( ::Bitmap& rBitmap );
+ virtual SurfaceSharedPtr changeSurface( bool bHasAlpha, bool bCopyContent );
+ virtual OutputDevice* getOutputDevice();
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ };
+
+ typedef ::rtl::Reference< Canvas > CanvasRef;
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx
new file mode 100644
index 000000000000..445839ca0127
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasbitmap.cxx
@@ -0,0 +1,286 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "cairo_canvasbitmap.hxx"
+
+#ifdef CAIRO_HAS_XLIB_SURFACE
+# include "cairo_xlib_cairo.hxx"
+#elif defined CAIRO_HAS_QUARTZ_SURFACE
+# include "cairo_quartz_cairo.hxx"
+#elif defined CAIRO_HAS_WIN32_SURFACE
+# include "cairo_win32_cairo.hxx"
+# include <cairo-win32.h>
+#else
+# error Native API needed.
+#endif
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+#ifdef CAIRO_HAS_WIN32_SURFACE
+namespace
+{
+ HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize )
+ {
+ // cant seem to retrieve HBITMAP from cairo. copy content then
+ HDC hScreenDC=GetDC(NULL);
+ HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
+ rSize.getX(),
+ rSize.getY() );
+
+ HDC hBmpDC = CreateCompatibleDC( 0 );
+ HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap );
+
+ BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(),
+ cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()),
+ 0, 0, SRCCOPY );
+
+ SelectObject( hBmpDC, hBmpOld );
+ DeleteDC( hBmpDC );
+
+ return hBmpBitmap;
+ }
+}
+#endif
+
+namespace cairocanvas
+{
+ CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize,
+ const SurfaceProviderRef& rSurfaceProvider,
+ rendering::XGraphicDevice* pDevice,
+ bool bHasAlpha ) :
+ mpSurfaceProvider( rSurfaceProvider ),
+ mpBufferSurface(),
+ mpBufferCairo(),
+ maSize(rSize),
+ mbHasAlpha(bHasAlpha)
+ {
+ ENSURE_OR_THROW( mpSurfaceProvider.is(),
+ "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
+
+ OSL_TRACE( "bitmap size: %dx%d", rSize.getX(), rSize.getY() );
+
+ mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
+ mpBufferCairo = mpBufferSurface->getCairo();
+
+ maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice );
+ maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha );
+
+ // clear bitmap to 100% transparent
+ maCanvasHelper.clear();
+ }
+
+ void SAL_CALL CanvasBitmap::disposing()
+ {
+ mpSurfaceProvider.clear();
+
+ mpBufferCairo.reset();
+ mpBufferSurface.reset();
+
+ // forward to parent
+ CanvasBitmap_Base::disposing();
+ }
+
+ SurfaceSharedPtr CanvasBitmap::getSurface()
+ {
+ return mpBufferSurface;
+ }
+
+ SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ return mpSurfaceProvider->createSurface(rSize,aContent);
+ }
+
+ SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap )
+ {
+ return mpSurfaceProvider->createSurface(rBitmap);
+ }
+
+ SurfaceSharedPtr CanvasBitmap::changeSurface( bool, bool )
+ {
+ // non-modifiable surface here
+ return SurfaceSharedPtr();
+ }
+
+ OutputDevice* CanvasBitmap::getOutputDevice()
+ {
+ return mpSurfaceProvider->getOutputDevice();
+ }
+
+ bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return maCanvasHelper.repaint( pSurface, viewState, renderState );
+ }
+
+ uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
+ {
+ uno::Any aRV( sal_Int32(0) );
+ // 0 ... get BitmapEx
+ // 1 ... get Pixbuf with bitmap RGB content
+ // 2 ... get Pixbuf with bitmap alpha mask
+ switch( nHandle )
+ {
+ case 0:
+ {
+ aRV = uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
+ break;
+ }
+ case 1:
+ {
+#ifdef CAIRO_HAS_XLIB_SURFACE
+ X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(mpBufferSurface.get());
+ OSL_ASSERT(pXlibSurface);
+ uno::Sequence< uno::Any > args( 3 );
+ args[0] = uno::Any( false ); // do not call XFreePixmap on it
+ args[1] = uno::Any( pXlibSurface->getPixmap()->mhDrawable );
+ args[2] = uno::Any( sal_Int32( pXlibSurface->getDepth() ) );
+
+ aRV = uno::Any( args );
+#elif defined CAIRO_HAS_QUARTZ_SURFACE
+ QuartzSurface* pQuartzSurface = dynamic_cast<QuartzSurface*>(mpBufferSurface.get());
+ OSL_ASSERT(pQuartzSurface);
+ uno::Sequence< uno::Any > args( 1 );
+ args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
+ aRV = uno::Any( args );
+#elif defined CAIRO_HAS_WIN32_SURFACE
+ // TODO(F2): check whether under all circumstances,
+ // the alpha channel is ignored here.
+ uno::Sequence< uno::Any > args( 1 );
+ args[1] = uno::Any( sal_Int64(surface2HBitmap(mpBufferSurface,maSize)) );
+
+ aRV = uno::Any( args );
+ // caller frees the bitmap
+#else
+# error Please define fast prop retrieval for your platform!
+#endif
+ break;
+ }
+ case 2:
+ {
+#ifdef CAIRO_HAS_XLIB_SURFACE
+ uno::Sequence< uno::Any > args( 3 );
+ SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
+ CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
+ X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(pAlphaSurface.get());
+ OSL_ASSERT(pXlibSurface);
+
+ // create RGB image (levels of gray) of alpha channel of original picture
+ cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pAlphaCairo.get() );
+ cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
+ cairo_paint( pAlphaCairo.get() );
+ pAlphaCairo.reset();
+
+ X11PixmapSharedPtr pPixmap = pXlibSurface->getPixmap();
+ args[0] = uno::Any( true );
+ args[1] = ::com::sun::star::uno::Any( pPixmap->mhDrawable );
+ args[2] = ::com::sun::star::uno::Any( sal_Int32( pXlibSurface->getDepth () ) );
+ pPixmap->clear(); // caller takes ownership of pixmap
+
+ // return pixmap and alphachannel pixmap - it will be used in BitmapEx
+ aRV = uno::Any( args );
+#elif defined CAIRO_HAS_QUARTZ_SURFACE
+ SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
+ CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
+ QuartzSurface* pQuartzSurface=dynamic_cast<QuartzSurface*>(pAlphaSurface.get());
+ OSL_ASSERT(pQuartzSurface);
+
+ // create RGB image (levels of gray) of alpha channel of original picture
+ cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pAlphaCairo.get() );
+ cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
+ cairo_paint( pAlphaCairo.get() );
+ pAlphaCairo.reset();
+
+ uno::Sequence< uno::Any > args( 1 );
+ args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
+ // return ??? and alphachannel ??? - it will be used in BitmapEx
+ aRV = uno::Any( args );
+#elif defined CAIRO_HAS_WIN32_SURFACE
+ SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
+ CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
+
+ // create RGB image (levels of gray) of alpha channel of original picture
+ cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pAlphaCairo.get() );
+ cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
+ cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
+ cairo_paint( pAlphaCairo.get() );
+ pAlphaCairo.reset();
+
+ // cant seem to retrieve HBITMAP from cairo. copy content then
+ uno::Sequence< uno::Any > args( 1 );
+ args[1] = uno::Any( sal_Int64(surface2HBitmap(pAlphaSurface,maSize)) );
+
+ aRV = uno::Any( args );
+ // caller frees the bitmap
+#else
+# error Please define fast prop retrieval for your platform!
+#endif
+ break;
+ }
+ }
+
+ return aRV;
+ }
+
+#define IMPLEMENTATION_NAME "CairoCanvas.CanvasBitmap"
+#define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
+
+ ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+}
diff --git a/canvas/source/cairo/cairo_canvasbitmap.hxx b/canvas/source/cairo/cairo_canvasbitmap.hxx
new file mode 100644
index 000000000000..5597a5ade004
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasbitmap.hxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CANVASBITMAP_HXX
+#define _CAIROCANVAS_CANVASBITMAP_HXX
+
+#include <cppuhelper/compbase4.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <comphelper/uno3.hxx>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <canvas/base/integerbitmapbase.hxx>
+
+#include "cairo_cairo.hxx"
+#include "cairo_canvashelper.hxx"
+#include "cairo_repainttarget.hxx"
+#include "cairo_spritecanvas.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::beans::XFastPropertySet > CanvasBitmapBase_Base;
+ class CanvasBitmapSpriteSurface_Base :
+ public ::canvas::BaseMutexHelper<CanvasBitmapBase_Base>,
+ public SurfaceProvider
+ {
+ };
+
+ typedef ::canvas::IntegerBitmapBase<
+ CanvasBitmapSpriteSurface_Base,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBitmap_Base;
+
+ class CanvasBitmap : public CanvasBitmap_Base,
+ public RepaintTarget
+ {
+ 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 ::basegfx::B2ISize& rSize,
+ const SurfaceProviderRef& rDevice,
+ ::com::sun::star::rendering::XGraphicDevice* pDevice,
+ bool bHasAlpha );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( CanvasBitmap, CanvasBitmapBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // SurfaceProvider
+ virtual SurfaceSharedPtr getSurface();
+ virtual SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ virtual SurfaceSharedPtr createSurface( ::Bitmap& rBitmap );
+ virtual SurfaceSharedPtr changeSurface( bool bHasAlpha, bool bCopyContent );
+ virtual OutputDevice* getOutputDevice();
+
+ // RepaintTarget
+ virtual bool repaint( const SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ // XFastPropertySet
+ // used to retrieve BitmapEx pointer or X Pixmap handles for this bitmap
+ // handle values have these meanings:
+ // 0 ... get pointer to BitmapEx
+ // 1 ... get X pixmap handle to rgb content
+ // 2 ... get X pitmap handle to alpha mask
+ // returned any contains either BitmapEx pointer or array of three Any value
+ // 1st a bool value: true - free the pixmap after used by XFreePixmap, false do nothing, the pixmap is used internally in the canvas
+ // 2nd the pixmap handle
+ // 3rd the pixmap depth
+ virtual ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setFastPropertyValue(sal_Int32, const ::com::sun::star::uno::Any&) throw (::com::sun::star::uno::RuntimeException) {}
+
+ private:
+ SurfaceProviderRef mpSurfaceProvider;
+ ::cairo::SurfaceSharedPtr mpBufferSurface;
+ ::cairo::CairoSharedPtr mpBufferCairo;
+
+ const ::basegfx::B2ISize maSize;
+ const bool mbHasAlpha;
+ };
+}
+
+#endif /* _CAIROCANVAS_CANVASBITMAP_HXX */
diff --git a/canvas/source/cairo/cairo_canvascustomsprite.cxx b/canvas/source/cairo/cairo_canvascustomsprite.cxx
new file mode 100644
index 000000000000..ad9a743da885
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvascustomsprite.cxx
@@ -0,0 +1,175 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+#include "cairo_canvascustomsprite.hxx"
+#include "cairo_spritecanvas.hxx"
+
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice ) :
+ mpSpriteCanvas( rRefDevice ),
+ maSize( ::canvas::tools::roundUp( rSpriteSize.Width ),
+ ::canvas::tools::roundUp( rSpriteSize.Height ) )
+ {
+ ENSURE_OR_THROW( rRefDevice.get(),
+ "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+ OSL_TRACE("sprite size: %d, %d",
+ ::canvas::tools::roundUp( rSpriteSize.Width ),
+ ::canvas::tools::roundUp( rSpriteSize.Height ));
+
+ mpBufferSurface = mpSpriteCanvas->createSurface( maSize );
+
+ maCanvasHelper.init( maSize,
+ *rRefDevice,
+ rRefDevice.get() );
+ maCanvasHelper.setSurface( mpBufferSurface, true );
+
+ maSpriteHelper.init( rSpriteSize,
+ rRefDevice );
+ maSpriteHelper.setSurface( mpBufferSurface );
+
+ // clear sprite to 100% transparent
+ maCanvasHelper.clear();
+ }
+
+ void SAL_CALL CanvasCustomSprite::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpSpriteCanvas.clear();
+ mpBufferSurface.reset();
+
+ // forward to parent
+ CanvasCustomSpriteBaseT::disposing();
+ }
+
+ void CanvasCustomSprite::redraw( const CairoSharedPtr& pCairo,
+ bool bBufferedUpdate ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ redraw( pCairo, maSpriteHelper.getPosPixel(), bBufferedUpdate );
+ }
+
+ void CanvasCustomSprite::redraw( const CairoSharedPtr& pCairo,
+ const ::basegfx::B2DPoint& rOrigOutputPos,
+ bool bBufferedUpdate ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maSpriteHelper.redraw( pCairo,
+ rOrigOutputPos,
+ mbSurfaceDirty,
+ bBufferedUpdate );
+
+ mbSurfaceDirty = false;
+ }
+
+ bool CanvasCustomSprite::repaint( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return maCanvasHelper.repaint( pSurface, viewState, renderState );
+ }
+
+ SurfaceSharedPtr CanvasCustomSprite::getSurface()
+ {
+ return mpBufferSurface;
+ }
+
+ SurfaceSharedPtr CanvasCustomSprite::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ return mpSpriteCanvas->createSurface(rSize,aContent);
+ }
+
+ SurfaceSharedPtr CanvasCustomSprite::createSurface( ::Bitmap& rBitmap )
+ {
+ return mpSpriteCanvas->createSurface(rBitmap);
+ }
+
+ SurfaceSharedPtr CanvasCustomSprite::changeSurface( bool bHasAlpha, bool bCopyContent )
+ {
+ if( !bHasAlpha && !bCopyContent )
+ {
+ OSL_TRACE("replacing sprite background surface");
+
+ mpBufferSurface = mpSpriteCanvas->createSurface( maSize, CAIRO_CONTENT_COLOR );
+ maSpriteHelper.setSurface( mpBufferSurface );
+
+ return mpBufferSurface;
+ }
+
+ return SurfaceSharedPtr();
+ }
+
+ OutputDevice* CanvasCustomSprite::getOutputDevice()
+ {
+ return mpSpriteCanvas->getOutputDevice();
+ }
+
+#define IMPLEMENTATION_NAME "CairoCanvas.CanvasCustomSprite"
+#define SERVICE_NAME "com.sun.star.rendering.CanvasCustomSprite"
+
+ ::rtl::OUString SAL_CALL CanvasCustomSprite::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+}
diff --git a/canvas/source/cairo/cairo_canvascustomsprite.hxx b/canvas/source/cairo/cairo_canvascustomsprite.hxx
new file mode 100644
index 000000000000..abebdc85d917
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvascustomsprite.hxx
@@ -0,0 +1,156 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CANVASCUSTOMSPRITE_HXX
+#define _CAIROCANVAS_CANVASCUSTOMSPRITE_HXX
+
+#include <cppuhelper/compbase4.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.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/basemutexhelper.hxx>
+#include <canvas/base/canvascustomspritebase.hxx>
+
+#include "cairo_sprite.hxx"
+#include "cairo_cairo.hxx"
+#include "cairo_canvashelper.hxx"
+#include "cairo_repainttarget.hxx"
+#include "cairo_spritehelper.hxx"
+#include "cairo_spritecanvas.hxx"
+
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::rendering::XCustomSprite,
+ ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::lang::XServiceInfo > CanvasCustomSpriteBase_Base;
+ /** Mixin Sprite
+
+ Have to mixin the Sprite interface before deriving from
+ ::canvas::CanvasCustomSpriteBase, as this template should
+ already implement some of those interface methods.
+
+ The reason why this appears kinda convoluted is the fact that
+ we cannot specify non-IDL types as WeakComponentImplHelperN
+ template args, and furthermore, don't want to derive
+ ::canvas::CanvasCustomSpriteBase directly from
+ ::canvas::Sprite (because derivees of
+ ::canvas::CanvasCustomSpriteBase have to explicitely forward
+ the XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS)
+ anyway). Basically, ::canvas::CanvasCustomSpriteBase should
+ remain a base class that provides implementation, not to
+ enforce any specific interface on its derivees.
+ */
+ class CanvasCustomSpriteSpriteBase_Base : public ::canvas::BaseMutexHelper< CanvasCustomSpriteBase_Base >,
+ public Sprite,
+ public SurfaceProvider
+ {
+ };
+
+ typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
+ SpriteHelper,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasCustomSpriteBaseT;
+
+ /* Definition of CanvasCustomSprite class */
+
+ class CanvasCustomSprite : public CanvasCustomSpriteBaseT,
+ public RepaintTarget
+ {
+ 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 );
+
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcount Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( CanvasCustomSprite, CanvasCustomSpriteBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ // Sprite
+ virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
+ bool bBufferedUpdate ) const;
+ virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
+ const ::basegfx::B2DPoint& rOrigOutputPos,
+ bool bBufferedUpdate ) const;
+
+ // RepaintTarget
+ virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ // SurfaceProvider
+ virtual SurfaceSharedPtr getSurface();
+ virtual SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ virtual SurfaceSharedPtr createSurface( ::Bitmap& rBitmap );
+ virtual SurfaceSharedPtr changeSurface( bool bHasAlpha, bool bCopyContent );
+ virtual OutputDevice* getOutputDevice();
+
+ private:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ SpriteCanvasRef mpSpriteCanvas;
+ ::cairo::SurfaceSharedPtr mpBufferSurface;
+ ::basegfx::B2ISize maSize;
+ };
+}
+
+#endif /* _CAIROCANVAS_CANVASCUSTOMSPRITE_HXX */
diff --git a/canvas/source/cairo/cairo_canvasfont.cxx b/canvas/source/cairo/cairo_canvasfont.cxx
new file mode 100644
index 000000000000..452280728151
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasfont.cxx
@@ -0,0 +1,193 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+
+#include <rtl/math.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <vcl/metric.hxx>
+#include <i18npool/mslangid.hxx>
+
+#include "cairo_canvasfont.hxx"
+#include "cairo_textlayout.hxx"
+
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ namespace
+ {
+ // Little helper to encapsulate locking into policy class
+ class LocalGuard
+ {
+ public:
+ LocalGuard() :
+ aGuard( Application::GetSolarMutex() )
+ {
+ }
+
+ /// To be compatible with CanvasBase mutex concept
+ LocalGuard( const ::osl::Mutex& ) :
+ aGuard( Application::GetSolarMutex() )
+ {
+ }
+
+ private:
+ ::vos::OGuard aGuard;
+ };
+ }
+
+ CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
+ const uno::Sequence< beans::PropertyValue >& /*rExtraFontProperties*/,
+ const geometry::Matrix2D& rFontMatrix,
+ const SurfaceProviderRef& rDevice ) :
+ CanvasFont_Base( m_aMutex ),
+ maFont( Font( rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ),
+ maFontRequest( rFontRequest ),
+ mpRefDevice( rDevice )
+ {
+ maFont->SetAlign( ALIGN_BASELINE );
+ maFont->SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ maFont->SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
+
+ // TODO(F2): improve panose->vclenum conversion
+ maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+ maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+
+ maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
+
+ // adjust to stretched/shrinked font
+ if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
+ {
+ OutputDevice* pOutDev( mpRefDevice->getOutputDevice() );
+
+ if( pOutDev )
+ {
+ const bool bOldMapState( pOutDev->IsMapModeEnabled() );
+ pOutDev->EnableMapMode(FALSE);
+
+ const Size aSize = pOutDev->GetFontMetric( *maFont ).GetSize();
+
+ const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+ double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+ if( !::basegfx::fTools::equalZero( fDividend) )
+ fStretch /= fDividend;
+
+ const long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+ maFont->SetWidth( nNewWidth );
+
+ pOutDev->EnableMapMode(bOldMapState);
+ }
+ }
+ }
+
+ void SAL_CALL CanvasFont::disposing()
+ {
+ LocalGuard aGuard;
+
+ mpRefDevice.clear();
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ LocalGuard aGuard;
+
+ if( !mpRefDevice.is() )
+ return uno::Reference< rendering::XTextLayout >(); // we're disposed
+
+ return new TextLayout( aText,
+ nDirection,
+ nRandomSeed,
+ Reference( this ),
+ mpRefDevice );
+ }
+
+ rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) throw (uno::RuntimeException)
+ {
+ LocalGuard aGuard;
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ LocalGuard aGuard;
+
+ // TODO(F1)
+ return rendering::FontMetrics();
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ LocalGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ LocalGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+#define IMPLEMENTATION_NAME "CairoCanvas::CanvasFont"
+#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"
+
+ ::rtl::OUString SAL_CALL CanvasFont::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasFont::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasFont::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+ ::Font CanvasFont::getVCLFont() const
+ {
+ return *maFont;
+ }
+}
diff --git a/canvas/source/cairo/cairo_canvasfont.hxx b/canvas/source/cairo/cairo_canvasfont.hxx
new file mode 100644
index 000000000000..9b59ca57fa52
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasfont.hxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CANVASFONT_HXX
+#define _CAIROCANVAS_CANVASFONT_HXX
+
+#include <comphelper/implementationreference.hxx>
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/rendering/FontRequest.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <vcl/font.hxx>
+
+#include <canvas/vclwrapper.hxx>
+
+#include "cairo_spritecanvas.hxx"
+
+#include <boost/utility.hpp>
+
+
+/* Definition of CanvasFont class */
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XCanvasFont,
+ ::com::sun::star::lang::XServiceInfo > CanvasFont_Base;
+
+ class CanvasFont : public ::comphelper::OBaseMutex,
+ public CanvasFont_Base,
+ private ::boost::noncopyable
+ {
+ public:
+ typedef ::comphelper::ImplementationReference<
+ CanvasFont,
+ ::com::sun::star::rendering::XCanvasFont > Reference;
+
+ 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& rFontMatrix,
+ const SurfaceProviderRef& rDevice );
+
+ /// 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);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ ::Font getVCLFont() const;
+
+ private:
+ ::canvas::vcltools::VCLObject<Font> maFont;
+ ::com::sun::star::rendering::FontRequest maFontRequest;
+ SurfaceProviderRef mpRefDevice;
+ };
+
+}
+
+#endif /* _CAIROCANVAS_CANVASFONT_HXX */
diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx
new file mode 100644
index 000000000000..60647d4f8224
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper.cxx
@@ -0,0 +1,1996 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+#include <rtl/instance.hxx>
+
+#include <com/sun/star/util/Endianness.hpp>
+#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 <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
+#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
+#include <com/sun/star/rendering/ColorSpaceType.hpp>
+#include <com/sun/star/rendering/ColorComponentTag.hpp>
+#include <com/sun/star/rendering/RenderingIntent.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/keystoplerp.hxx>
+#include <basegfx/tools/lerp.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <canvas/parametricpolypolygon.hxx>
+
+#include <vcl/canvastools.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+
+#include "cairo_spritecanvas.hxx"
+#include "cairo_cachedbitmap.hxx"
+#include "cairo_canvashelper.hxx"
+#include "cairo_canvasbitmap.hxx"
+
+#include <boost/tuple/tuple.hpp>
+#include <algorithm>
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ CanvasHelper::CanvasHelper() :
+ mpSurfaceProvider(NULL),
+ mpDevice(NULL),
+ mpVirtualDevice(),
+ mbHaveAlpha(),
+ mpCairo(),
+ mpSurface(),
+ maSize()
+ {
+ }
+
+ void CanvasHelper::disposing()
+ {
+ mpSurface.reset();
+ mpCairo.reset();
+ mpVirtualDevice.reset();
+ mpDevice = NULL;
+ mpSurfaceProvider = NULL;
+ }
+
+ void CanvasHelper::init( const ::basegfx::B2ISize& rSizePixel,
+ SurfaceProvider& rSurfaceProvider,
+ rendering::XGraphicDevice* pDevice )
+ {
+ maSize = rSizePixel;
+ mpSurfaceProvider = &rSurfaceProvider;
+ mpDevice = pDevice;
+ }
+
+ void CanvasHelper::setSize( const ::basegfx::B2ISize& rSize )
+ {
+ maSize = rSize;
+ }
+
+ void CanvasHelper::setSurface( const SurfaceSharedPtr& pSurface, bool bHasAlpha )
+ {
+ mbHaveAlpha = bHasAlpha;
+ mpVirtualDevice.reset();
+ mpSurface = pSurface;
+ mpCairo = pSurface->getCairo();
+ }
+
+ static void setColor( Cairo* pCairo,
+ const uno::Sequence<double>& rColor )
+ {
+ if( rColor.getLength() > 3 )
+ {
+ const double alpha = rColor[3];
+
+ cairo_set_source_rgba( pCairo,
+ alpha*rColor[0],
+ alpha*rColor[1],
+ alpha*rColor[2],
+ alpha );
+ }
+ else if( rColor.getLength() == 3 )
+ cairo_set_source_rgb( pCairo,
+ rColor[0],
+ rColor[1],
+ rColor[2] );
+ }
+
+ void CanvasHelper::useStates( const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ bool bSetColor )
+ {
+ Matrix aViewMatrix;
+ Matrix aRenderMatrix;
+ Matrix aCombinedMatrix;
+
+ cairo_matrix_init( &aViewMatrix,
+ viewState.AffineTransform.m00, viewState.AffineTransform.m10, viewState.AffineTransform.m01,
+ viewState.AffineTransform.m11, viewState.AffineTransform.m02, viewState.AffineTransform.m12);
+ cairo_matrix_init( &aRenderMatrix,
+ renderState.AffineTransform.m00, renderState.AffineTransform.m10, renderState.AffineTransform.m01,
+ renderState.AffineTransform.m11, renderState.AffineTransform.m02, renderState.AffineTransform.m12);
+ cairo_matrix_multiply( &aCombinedMatrix, &aRenderMatrix, &aViewMatrix);
+
+ if( viewState.Clip.is() ) {
+ OSL_TRACE ("view clip");
+
+ aViewMatrix.x0 = basegfx::fround( aViewMatrix.x0 );
+ aViewMatrix.y0 = basegfx::fround( aViewMatrix.y0 );
+ cairo_set_matrix( mpCairo.get(), &aViewMatrix );
+ doPolyPolygonPath( viewState.Clip, Clip );
+ }
+
+ aCombinedMatrix.x0 = basegfx::fround( aCombinedMatrix.x0 );
+ aCombinedMatrix.y0 = basegfx::fround( aCombinedMatrix.y0 );
+ cairo_set_matrix( mpCairo.get(), &aCombinedMatrix );
+
+ if( renderState.Clip.is() ) {
+ OSL_TRACE ("render clip BEGIN");
+
+ doPolyPolygonPath( renderState.Clip, Clip );
+ OSL_TRACE ("render clip END");
+ }
+
+ if( bSetColor )
+ setColor(mpCairo.get(),renderState.DeviceColor);
+
+ cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER );
+ switch( renderState.CompositeOperation )
+ {
+ case rendering::CompositeOperation::CLEAR:
+ compositingMode = CAIRO_OPERATOR_CLEAR;
+ break;
+ case rendering::CompositeOperation::SOURCE:
+ compositingMode = CAIRO_OPERATOR_SOURCE;
+ break;
+ case rendering::CompositeOperation::DESTINATION:
+ compositingMode = CAIRO_OPERATOR_DEST;
+ break;
+ case rendering::CompositeOperation::OVER:
+ compositingMode = CAIRO_OPERATOR_OVER;
+ break;
+ case rendering::CompositeOperation::UNDER:
+ compositingMode = CAIRO_OPERATOR_DEST;
+ break;
+ case rendering::CompositeOperation::INSIDE:
+ compositingMode = CAIRO_OPERATOR_IN;
+ break;
+ case rendering::CompositeOperation::INSIDE_REVERSE:
+ compositingMode = CAIRO_OPERATOR_OUT;
+ break;
+ case rendering::CompositeOperation::OUTSIDE:
+ compositingMode = CAIRO_OPERATOR_DEST_OVER;
+ break;
+ case rendering::CompositeOperation::OUTSIDE_REVERSE:
+ compositingMode = CAIRO_OPERATOR_DEST_OUT;
+ break;
+ case rendering::CompositeOperation::ATOP:
+ compositingMode = CAIRO_OPERATOR_ATOP;
+ break;
+ case rendering::CompositeOperation::ATOP_REVERSE:
+ compositingMode = CAIRO_OPERATOR_DEST_ATOP;
+ break;
+ case rendering::CompositeOperation::XOR:
+ compositingMode = CAIRO_OPERATOR_XOR;
+ break;
+ case rendering::CompositeOperation::ADD:
+ compositingMode = CAIRO_OPERATOR_ADD;
+ break;
+ case rendering::CompositeOperation::SATURATE:
+ compositingMode = CAIRO_OPERATOR_SATURATE;
+ break;
+ }
+ cairo_set_operator( mpCairo.get(), compositingMode );
+ }
+
+ void CanvasHelper::clear()
+ {
+ OSL_TRACE ("clear whole area: %d x %d", maSize.getX(), maSize.getY() );
+
+ if( mpCairo )
+ {
+ cairo_save( mpCairo.get() );
+
+ cairo_identity_matrix( mpCairo.get() );
+ // this does not really differ from all-zero, as cairo
+ // internally converts to premultiplied alpha. but anyway,
+ // this keeps it consistent with the other canvas impls
+ if( mbHaveAlpha )
+ cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 );
+ else
+ cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 );
+ cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
+
+ cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
+ cairo_fill( mpCairo.get() );
+
+ cairo_restore( mpCairo.get() );
+ }
+ }
+
+ void CanvasHelper::drawPoint( const rendering::XCanvas* ,
+ const geometry::RealPoint2D& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& )
+ {
+ }
+
+ void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& aStartPoint,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ cairo_set_line_width( mpCairo.get(), 1 );
+
+ useStates( viewState, renderState, true );
+
+ cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 );
+ cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
+ cairo_stroke( mpCairo.get() );
+
+ cairo_restore( mpCairo.get() );
+ }
+ }
+
+ void CanvasHelper::drawBezier( const rendering::XCanvas* ,
+ const geometry::RealBezierSegment2D& aBezierSegment,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ cairo_set_line_width( mpCairo.get(), 1 );
+
+ useStates( viewState, renderState, true );
+
+ cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 );
+ cairo_curve_to( mpCairo.get(),
+ aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5,
+ aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5,
+ aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
+ cairo_stroke( mpCairo.get() );
+
+ cairo_restore( mpCairo.get() );
+ }
+ }
+
+#define CANVASBITMAP_IMPLEMENTATION_NAME "CairoCanvas::CanvasBitmap"
+#define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon"
+
+
+ /** surfaceFromXBitmap Create a surface from XBitmap
+ * @param xBitmap bitmap image that will be used for the surface
+ * @param bHasAlpha will be set to true if resulting surface has alpha
+ *
+ * This is a helper function for the other surfaceFromXBitmap().
+ * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas.
+ *
+ * @return created surface or NULL
+ **/
+ static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() );
+ if( pBitmapImpl )
+ return pBitmapImpl->getSurface();
+
+ SurfaceProvider* pSurfaceProvider = dynamic_cast<SurfaceProvider*>( xBitmap.get() );
+ if( pSurfaceProvider )
+ return pSurfaceProvider->getSurface();
+
+ return SurfaceSharedPtr();
+ }
+
+ static ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ // TODO(F1): Add support for floating point bitmap formats
+ uno::Reference<rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap,
+ uno::UNO_QUERY_THROW);
+ ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap(xIntBmp);
+ if( !!aBmpEx )
+ return aBmpEx;
+
+ // TODO(F1): extract pixel from XBitmap interface
+ ENSURE_OR_THROW( false,
+ "bitmapExFromXBitmap(): could not extract BitmapEx" );
+
+ return ::BitmapEx();
+ }
+
+ static bool readAlpha( BitmapReadAccess* pAlphaReadAcc, long nY, const long nWidth, unsigned char* data, long nOff )
+ {
+ bool bIsAlpha = false;
+ long nX;
+ int nAlpha;
+ Scanline pReadScan;
+
+ nOff += 3;
+
+ switch( pAlphaReadAcc->GetScanlineFormat() ) {
+ case BMP_FORMAT_8BIT_TC_MASK:
+ pReadScan = pAlphaReadAcc->GetScanline( nY );
+ for( nX = 0; nX < nWidth; nX++ ) {
+ nAlpha = data[ nOff ] = 255 - ( *pReadScan++ );
+ if( nAlpha != 255 )
+ bIsAlpha = true;
+ nOff += 4;
+ }
+ break;
+ case BMP_FORMAT_8BIT_PAL:
+ pReadScan = pAlphaReadAcc->GetScanline( nY );
+ for( nX = 0; nX < nWidth; nX++ ) {
+ nAlpha = data[ nOff ] = 255 - ( pAlphaReadAcc->GetPaletteColor( *pReadScan++ ).GetBlue() );
+ if( nAlpha != 255 )
+ bIsAlpha = true;
+ nOff += 4;
+ }
+ break;
+ default:
+ OSL_TRACE( "fallback to GetColor for alpha - slow, format: %d", pAlphaReadAcc->GetScanlineFormat() );
+ for( nX = 0; nX < nWidth; nX++ ) {
+ nAlpha = data[ nOff ] = 255 - pAlphaReadAcc->GetColor( nY, nX ).GetBlue();
+ if( nAlpha != 255 )
+ bIsAlpha = true;
+ nOff += 4;
+ }
+ }
+
+ return bIsAlpha;
+ }
+
+
+ /** surfaceFromXBitmap Create a surface from XBitmap
+ * @param xBitmap bitmap image that will be used for the surface
+ * @param rDevice reference to the device into which we want to draw
+ * @param data will be filled with alpha data, if xBitmap is alpha/transparent image
+ * @param bHasAlpha will be set to true if resulting surface has alpha
+ *
+ * This function tries various methods for creating a surface from xBitmap. It also uses
+ * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha )
+ *
+ * @return created surface or NULL
+ **/
+ static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, const SurfaceProviderRef& rSurfaceProvider, unsigned char*& data, bool& bHasAlpha )
+ {
+ bHasAlpha = xBitmap->hasAlpha();
+ SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap );
+ if( pSurface )
+ data = NULL;
+ else
+ {
+ ::BitmapEx aBmpEx = bitmapExFromXBitmap(xBitmap);
+ ::Bitmap aBitmap = aBmpEx.GetBitmap();
+
+ // there's no pixmap for alpha bitmap. we might still
+ // use rgb pixmap and only access alpha pixels the
+ // slow way. now we just speedup rgb bitmaps
+ if( !aBmpEx.IsTransparent() && !aBmpEx.IsAlpha() ) {
+ pSurface = rSurfaceProvider->createSurface( aBitmap );
+ data = NULL;
+ bHasAlpha = false;
+ }
+
+ if( !pSurface ) {
+ AlphaMask aAlpha = aBmpEx.GetAlpha();
+
+ ::BitmapReadAccess* pBitmapReadAcc = aBitmap.AcquireReadAccess();
+ ::BitmapReadAccess* pAlphaReadAcc = NULL;
+ const long nWidth = pBitmapReadAcc->Width();
+ const long nHeight = pBitmapReadAcc->Height();
+ long nX, nY;
+ bool bIsAlpha = false;
+
+ if( aBmpEx.IsTransparent() || aBmpEx.IsAlpha() )
+ pAlphaReadAcc = aAlpha.AcquireReadAccess();
+
+ data = (unsigned char*) malloc( nWidth*nHeight*4 );
+
+ long nOff = 0;
+ ::Color aColor;
+ unsigned int nAlpha = 255;
+
+ for( nY = 0; nY < nHeight; nY++ ) {
+ ::Scanline pReadScan;
+
+ switch( pBitmapReadAcc->GetScanlineFormat() ) {
+ case BMP_FORMAT_8BIT_PAL:
+ pReadScan = pBitmapReadAcc->GetScanline( nY );
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff++ ];
+ else
+ nAlpha = data[ nOff++ ] = 255;
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = 255;
+#endif
+ aColor = pBitmapReadAcc->GetPaletteColor( *pReadScan++ );
+
+#ifdef OSL_BIGENDIAN
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 );
+#else
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 );
+ nOff++;
+#endif
+ }
+ break;
+ case BMP_FORMAT_24BIT_TC_BGR:
+ pReadScan = pBitmapReadAcc->GetScanline( nY );
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff ];
+ else
+ nAlpha = data[ nOff ] = 255;
+ data[ nOff + 3 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff + 2 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff + 1 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ nOff += 4;
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ nOff++;
+#endif
+ }
+ break;
+ case BMP_FORMAT_24BIT_TC_RGB:
+ pReadScan = pBitmapReadAcc->GetScanline( nY );
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff++ ];
+ else
+ nAlpha = data[ nOff++ ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 );
+ pReadScan += 3;
+ nOff++;
+#endif
+ }
+ break;
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ pReadScan = pBitmapReadAcc->GetScanline( nY );
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff++ ];
+ else
+ nAlpha = data[ nOff++ ] = pReadScan[ 3 ];
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 );
+ pReadScan += 4;
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = pReadScan[ 3 ];
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ pReadScan++;
+ nOff++;
+#endif
+ }
+ break;
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ pReadScan = pBitmapReadAcc->GetScanline( nY );
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff ++ ];
+ else
+ nAlpha = data[ nOff ++ ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 );
+ pReadScan++;
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 );
+ pReadScan += 4;
+ nOff++;
+#endif
+ }
+ break;
+ default:
+ OSL_TRACE( "fallback to GetColor - slow, format: %d", pBitmapReadAcc->GetScanlineFormat() );
+
+ if( pAlphaReadAcc )
+ if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) )
+ bIsAlpha = true;
+
+ for( nX = 0; nX < nWidth; nX++ ) {
+ aColor = pBitmapReadAcc->GetColor( nY, nX );
+
+ // cairo need premultiplied color values
+ // TODO(rodo) handle endianess
+#ifdef OSL_BIGENDIAN
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff++ ];
+ else
+ nAlpha = data[ nOff++ ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 );
+#else
+ if( pAlphaReadAcc )
+ nAlpha = data[ nOff + 3 ];
+ else
+ nAlpha = data[ nOff + 3 ] = 255;
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 );
+ data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 );
+ nOff ++;
+#endif
+ }
+ }
+ }
+
+ aBitmap.ReleaseAccess( pBitmapReadAcc );
+ if( pAlphaReadAcc )
+ aAlpha.ReleaseAccess( pAlphaReadAcc );
+
+ SurfaceSharedPtr pImageSurface = createSurface(
+ CairoSurfaceSharedPtr(
+ cairo_image_surface_create_for_data(
+ data,
+ bIsAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
+ nWidth, nHeight, nWidth*4 ),
+ &cairo_surface_destroy) );
+
+ // pSurface = rSurfaceProvider->getSurface( ::basegfx::B2ISize( nWidth, nHeight ), bIsAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
+ // Cairo* pTargetCairo = cairo_create( pSurface );
+ // cairo_set_source_surface( pTargetCairo, pImageSurface, 0, 0 );
+
+ // //if( !bIsAlpha )
+ // //cairo_set_operator( pTargetCairo, CAIRO_OPERATOR_SOURCE );
+
+ // cairo_paint( pTargetCairo );
+ // cairo_destroy( pTargetCairo );
+ // cairo_surface_destroy( pImageSurface );
+ pSurface = pImageSurface;
+
+ bHasAlpha = bIsAlpha;
+
+ OSL_TRACE("image: %d x %d alpha: %d alphaRead %p", nWidth, nHeight, bIsAlpha, pAlphaReadAcc);
+ }
+ }
+
+ return pSurface;
+ }
+
+ static void addColorStops( Pattern* pPattern, const uno::Sequence< uno::Sequence< double > >& rColors, const uno::Sequence< double >& rStops, bool bReverseStops = false )
+ {
+ float stop;
+ int i;
+
+ OSL_ASSERT( rColors.getLength() == rStops.getLength() );
+
+ for( i = 0; i < rColors.getLength(); i++ ) {
+ const uno::Sequence< double >& rColor( rColors[i] );
+ stop = bReverseStops ? 1 - rStops[i] : rStops[i];
+ if( rColor.getLength() == 3 )
+ cairo_pattern_add_color_stop_rgb( pPattern, stop, rColor[0], rColor[1], rColor[2] );
+ else if( rColor.getLength() == 4 ) {
+ double alpha = rColor[3];
+ // cairo expects premultiplied alpha
+ cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha );
+ }
+ }
+ }
+
+ static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha)
+ {
+ if( rLeft.getLength() == 3 )
+ {
+ uno::Sequence<double> aRes(3);
+ aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
+ aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
+ aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
+ return aRes;
+ }
+ else if( rLeft.getLength() == 4 )
+ {
+ uno::Sequence<double> aRes(4);
+ aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
+ aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
+ aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
+ aRes[3] = basegfx::tools::lerp(rLeft[3],rRight[3],fAlpha);
+ return aRes;
+ }
+
+ return uno::Sequence<double>();
+ }
+
+ static Pattern* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon& rPolygon )
+ {
+ Pattern* pPattern = NULL;
+ const ::canvas::ParametricPolyPolygon::Values aValues = rPolygon.getValues();
+ double x0, x1, y0, y1, cx, cy, r0, r1;
+
+// undef macros from vclenum.hxx which conflicts with GradientType enum values
+#undef GRADIENT_LINEAR
+#undef GRADIENT_ELLIPTICAL
+
+ switch( aValues.meType ) {
+ case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
+ x0 = 0;
+ y0 = 0;
+ x1 = 1;
+ y1 = 0;
+ pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 );
+ addColorStops( pPattern, aValues.maColors, aValues.maStops );
+ break;
+
+ case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
+ cx = 0;
+ cy = 0;
+ r0 = 0;
+ r1 = 1;
+
+ pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 );
+ addColorStops( pPattern, aValues.maColors, aValues.maStops, true );
+ break;
+ default:
+ break;
+ }
+
+ return pPattern;
+ }
+
+ static void doOperation( Operation aOperation,
+ Cairo* pCairo,
+ const uno::Sequence< rendering::Texture >* pTextures,
+ const SurfaceProviderRef& pDevice,
+ const basegfx::B2DRange& rBounds )
+ {
+ switch( aOperation ) {
+ case Fill:
+ /* TODO: multitexturing */
+ if( pTextures ) {
+ const ::com::sun::star::rendering::Texture& aTexture ( (*pTextures)[0] );
+ if( aTexture.Bitmap.is() ) {
+ unsigned char* data = NULL;
+ bool bHasAlpha = false;
+ SurfaceSharedPtr pSurface = surfaceFromXBitmap( (*pTextures)[0].Bitmap, pDevice, data, bHasAlpha );
+
+ if( pSurface ) {
+ cairo_pattern_t* pPattern;
+
+ cairo_save( pCairo );
+
+ ::com::sun::star::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform );
+ Matrix aScaleMatrix, aTextureMatrix, aScaledTextureMatrix;
+
+ cairo_matrix_init( &aTextureMatrix,
+ aTransform.m00, aTransform.m10, aTransform.m01,
+ aTransform.m11, aTransform.m02, aTransform.m12);
+
+ geometry::IntegerSize2D aSize = aTexture.Bitmap->getSize();
+
+ cairo_matrix_init_scale( &aScaleMatrix, 1.0/aSize.Width, 1.0/aSize.Height );
+ cairo_matrix_multiply( &aScaledTextureMatrix, &aTextureMatrix, &aScaleMatrix );
+ cairo_matrix_invert( &aScaledTextureMatrix );
+
+ // we don't care about repeat mode yet, so the workaround is disabled for now
+ pPattern = cairo_pattern_create_for_surface( pSurface->getCairoSurface().get() );
+
+ if( aTexture.RepeatModeX == rendering::TexturingMode::REPEAT &&
+ aTexture.RepeatModeY == rendering::TexturingMode::REPEAT )
+ {
+ cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_REPEAT );
+ }
+ else if ( aTexture.RepeatModeX == rendering::TexturingMode::NONE &&
+ aTexture.RepeatModeY == rendering::TexturingMode::NONE )
+ {
+ cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_NONE );
+ }
+ else if ( aTexture.RepeatModeX == rendering::TexturingMode::CLAMP &&
+ aTexture.RepeatModeY == rendering::TexturingMode::CLAMP )
+ {
+ cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_PAD );
+ }
+
+ aScaledTextureMatrix.x0 = basegfx::fround( aScaledTextureMatrix.x0 );
+ aScaledTextureMatrix.y0 = basegfx::fround( aScaledTextureMatrix.y0 );
+ cairo_pattern_set_matrix( pPattern, &aScaledTextureMatrix );
+
+ cairo_set_source( pCairo, pPattern );
+ if( !bHasAlpha )
+ cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE );
+ cairo_fill( pCairo );
+
+ cairo_restore( pCairo );
+
+ cairo_pattern_destroy( pPattern );
+ }
+
+ if( data )
+ free( data );
+ } else if( aTexture.Gradient.is() ) {
+ uno::Reference< lang::XServiceInfo > xRef( aTexture.Gradient, uno::UNO_QUERY );
+
+ OSL_TRACE( "gradient fill" );
+ if( xRef.is() &&
+ xRef->getImplementationName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME ) ) ) ) {
+ // TODO(Q1): Maybe use dynamic_cast here
+
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ OSL_TRACE( "known implementation" );
+
+ ::canvas::ParametricPolyPolygon* pPolyImpl = static_cast< ::canvas::ParametricPolyPolygon* >( aTexture.Gradient.get() );
+ ::com::sun::star::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform );
+ Matrix aTextureMatrix;
+
+ cairo_matrix_init( &aTextureMatrix,
+ aTransform.m00, aTransform.m10, aTransform.m01,
+ aTransform.m11, aTransform.m02, aTransform.m12);
+ if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR )
+ {
+ // no general path gradient yet in cairo; emulate then
+ cairo_save( pCairo );
+ cairo_clip( pCairo );
+
+ // fill bound rect with start color
+ cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(),
+ rBounds.getWidth(), rBounds.getHeight() );
+ setColor(pCairo,pPolyImpl->getValues().maColors[0]);
+ cairo_fill(pCairo);
+
+ cairo_transform( pCairo, &aTextureMatrix );
+
+ // longest line in gradient bound rect
+ const unsigned int nGradientSize(
+ static_cast<unsigned int>(
+ ::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) );
+
+ // typical number for pixel of the same color (strip size)
+ const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 );
+
+ // use at least three steps, and at utmost the number of color
+ // steps
+ const unsigned int nStepCount(
+ ::std::max(
+ 3U,
+ ::std::min(
+ nGradientSize / nStripSize,
+ 128U )) + 1 );
+
+ const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0];
+ basegfx::tools::KeyStopLerp aLerper(pPolyImpl->getValues().maStops);
+ for( unsigned int i=1; i<nStepCount; ++i )
+ {
+ const double fT( i/double(nStepCount) );
+
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
+ setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha));
+ cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT );
+ cairo_fill(pCairo);
+ }
+
+ cairo_restore( pCairo );
+ }
+ else
+ {
+ Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
+
+ if( pPattern ) {
+ OSL_TRACE( "filling with pattern" );
+
+ cairo_save( pCairo );
+
+ cairo_transform( pCairo, &aTextureMatrix );
+ cairo_set_source( pCairo, pPattern );
+ cairo_fill( pCairo );
+ cairo_restore( pCairo );
+
+ cairo_pattern_destroy( pPattern );
+ }
+ }
+ }
+ }
+ } else
+ cairo_fill( pCairo );
+ OSL_TRACE("fill");
+ break;
+ case Stroke:
+ cairo_stroke( pCairo );
+ OSL_TRACE("stroke");
+ break;
+ case Clip:
+ cairo_clip( pCairo );
+ OSL_TRACE("clip");
+ break;
+ }
+ }
+
+ static void clipNULL( Cairo *pCairo )
+ {
+ OSL_TRACE("clipNULL");
+ Matrix aOrigMatrix, aIdentityMatrix;
+
+ /* we set identity matrix here to overcome bug in cairo 0.9.2
+ where XCreatePixmap is called with zero width and height.
+
+ it also reaches faster path in cairo clipping code.
+ */
+ cairo_matrix_init_identity( &aIdentityMatrix );
+ cairo_get_matrix( pCairo, &aOrigMatrix );
+ cairo_set_matrix( pCairo, &aIdentityMatrix );
+
+ cairo_reset_clip( pCairo );
+ cairo_rectangle( pCairo, 0, 0, 1, 1 );
+ cairo_clip( pCairo );
+ cairo_rectangle( pCairo, 2, 0, 1, 1 );
+ cairo_clip( pCairo );
+
+ /* restore the original matrix */
+ cairo_set_matrix( pCairo, &aOrigMatrix );
+ }
+
+ void doPolyPolygonImplementation( ::basegfx::B2DPolyPolygon aPolyPolygon,
+ Operation aOperation,
+ Cairo* pCairo,
+ const uno::Sequence< rendering::Texture >* pTextures,
+ const SurfaceProviderRef& pDevice,
+ rendering::FillRule eFillrule )
+ {
+ if( pTextures )
+ ENSURE_ARG_OR_THROW( pTextures->getLength(),
+ "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
+
+ bool bOpToDo = false;
+ Matrix aOrigMatrix, aIdentityMatrix;
+ double nX, nY, nBX, nBY, nAX, nAY;
+
+ cairo_get_matrix( pCairo, &aOrigMatrix );
+ cairo_matrix_init_identity( &aIdentityMatrix );
+ cairo_set_matrix( pCairo, &aIdentityMatrix );
+
+ cairo_set_fill_rule( pCairo,
+ eFillrule == rendering::FillRule_EVEN_ODD ?
+ CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING );
+
+ for( sal_uInt32 nPolygonIndex = 0; nPolygonIndex < aPolyPolygon.count(); nPolygonIndex++ ) {
+ ::basegfx::B2DPolygon aPolygon( aPolyPolygon.getB2DPolygon( nPolygonIndex ) );
+ const sal_uInt32 nPointCount( aPolygon.count() );
+ // to correctly render closed curves, need to output first
+ // point twice (so output one additional point)
+ const sal_uInt32 nExtendedPointCount( nPointCount +
+ aPolygon.isClosed()*aPolygon.areControlPointsUsed() );
+
+ if( nPointCount > 1) {
+ bool bIsBezier = aPolygon.areControlPointsUsed();
+ bool bIsRectangle = ::basegfx::tools::isRectangle( aPolygon );
+ ::basegfx::B2DPoint aA, aB, aP;
+
+ for( sal_uInt32 j=0; j < nExtendedPointCount; j++ ) {
+ aP = aPolygon.getB2DPoint( j % nPointCount );
+
+ nX = aP.getX();
+ nY = aP.getY();
+ cairo_matrix_transform_point( &aOrigMatrix, &nX, &nY );
+
+ if( ! bIsBezier && (bIsRectangle || aOperation == Clip) ) {
+ nX = basegfx::fround( nX );
+ nY = basegfx::fround( nY );
+ }
+
+ if( aOperation == Stroke ) {
+ nX += 0.5;
+ nY += 0.5;
+ }
+
+ if( j==0 )
+ {
+ cairo_move_to( pCairo, nX, nY );
+ OSL_TRACE( "move to %f,%f", nX, nY );
+ }
+ else {
+ if( bIsBezier ) {
+ aA = aPolygon.getNextControlPoint( (j-1) % nPointCount );
+ aB = aPolygon.getPrevControlPoint( j % nPointCount );
+
+ nAX = aA.getX();
+ nAY = aA.getY();
+ nBX = aB.getX();
+ nBY = aB.getY();
+
+ if( aOperation == Stroke ) {
+ nAX += 0.5;
+ nAY += 0.5;
+ nBX += 0.5;
+ nBY += 0.5;
+ }
+ cairo_matrix_transform_point( &aOrigMatrix, &nAX, &nAY );
+ cairo_matrix_transform_point( &aOrigMatrix, &nBX, &nBY );
+ cairo_curve_to( pCairo, nAX, nAY, nBX, nBY, nX, nY );
+ } else {
+ cairo_line_to( pCairo, nX, nY );
+ OSL_TRACE( "line to %f,%f", nX, nY );
+ }
+ bOpToDo = true;
+ }
+ }
+
+ if( aPolygon.isClosed() )
+ cairo_close_path( pCairo );
+
+ if( aOperation == Fill && pTextures ) {
+ cairo_set_matrix( pCairo, &aOrigMatrix );
+ doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
+ cairo_set_matrix( pCairo, &aIdentityMatrix );
+ }
+ } else {
+ OSL_TRACE( "empty polygon for op: %d\n", aOperation );
+ if( aOperation == Clip ) {
+ clipNULL( pCairo );
+
+ return;
+ }
+ }
+ }
+ if( bOpToDo && ( aOperation != Fill || !pTextures ) )
+ doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
+
+ cairo_set_matrix( pCairo, &aOrigMatrix );
+
+ if( aPolyPolygon.count() == 0 && aOperation == Clip )
+ clipNULL( pCairo );
+ }
+
+ void CanvasHelper::doPolyPolygonPath( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ Operation aOperation,
+ bool bNoLineJoin,
+ const uno::Sequence< rendering::Texture >* pTextures,
+ Cairo* pCairo ) const
+ {
+ const ::basegfx::B2DPolyPolygon& rPolyPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
+
+ if( !pCairo )
+ pCairo = mpCairo.get();
+
+ if(bNoLineJoin && Stroke == aOperation)
+ {
+ // emulate rendering::PathJoinType::NONE by painting single edges
+ for(sal_uInt32 a(0); a < rPolyPoly.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(rPolyPoly.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(aCandidate.count());
+
+ if(nPointCount)
+ {
+ const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1: nPointCount);
+ basegfx::B2DPolygon aEdge;
+ aEdge.append(aCandidate.getB2DPoint(0));
+ aEdge.append(basegfx::B2DPoint(0.0, 0.0));
+
+ for(sal_uInt32 b(0); b < nEdgeCount; b++)
+ {
+ const sal_uInt32 nNextIndex((b + 1) % nPointCount);
+ aEdge.setB2DPoint(1, aCandidate.getB2DPoint(nNextIndex));
+ aEdge.setNextControlPoint(0, aCandidate.getNextControlPoint(b));
+ aEdge.setPrevControlPoint(1, aCandidate.getPrevControlPoint(nNextIndex));
+
+ doPolyPolygonImplementation( basegfx::B2DPolyPolygon(aEdge),
+ aOperation,
+ pCairo, pTextures,
+ mpSurfaceProvider,
+ xPolyPolygon->getFillRule() );
+
+ // prepare next step
+ aEdge.setB2DPoint(0, aEdge.getB2DPoint(1));
+ }
+ }
+ }
+ }
+ else
+ {
+ doPolyPolygonImplementation( rPolyPoly, aOperation,
+ pCairo, pTextures,
+ mpSurfaceProvider,
+ xPolyPolygon->getFillRule() );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
+
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ cairo_set_line_width( mpCairo.get(), 1 );
+
+ useStates( viewState, renderState, true );
+ doPolyPolygonPath( xPolyPolygon, Stroke );
+
+ cairo_restore( mpCairo.get() );
+ } else
+ OSL_TRACE ("CanvasHelper called after it was disposed");
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "drawPolyPolygon" );
+#endif
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::StrokeAttributes& strokeAttributes )
+ {
+ #ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+ #endif
+
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ useStates( viewState, renderState, true );
+
+ Matrix aMatrix;
+ double w = strokeAttributes.StrokeWidth, h = 0;
+ cairo_get_matrix( mpCairo.get(), &aMatrix );
+ cairo_matrix_transform_distance( &aMatrix, &w, &h );
+ cairo_set_line_width( mpCairo.get(), w );
+
+ cairo_set_miter_limit( mpCairo.get(), strokeAttributes.MiterLimit );
+
+ // FIXME: cairo doesn't handle end cap so far (rodo)
+ switch( strokeAttributes.StartCapType ) {
+ case rendering::PathCapType::BUTT:
+ cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_BUTT );
+ break;
+ case rendering::PathCapType::ROUND:
+ cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_ROUND );
+ break;
+ case rendering::PathCapType::SQUARE:
+ cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_SQUARE );
+ break;
+ }
+
+ bool bNoLineJoin(false);
+
+ switch( strokeAttributes.JoinType ) {
+ // cairo doesn't have join type NONE so we use MITER as it's pretty close
+ case rendering::PathJoinType::NONE:
+ bNoLineJoin = true;
+ case rendering::PathJoinType::MITER:
+ cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_MITER );
+ break;
+ case rendering::PathJoinType::ROUND:
+ cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_ROUND );
+ break;
+ case rendering::PathJoinType::BEVEL:
+ cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_BEVEL );
+ break;
+ }
+
+ if( strokeAttributes.DashArray.getLength() > 0 ) {
+ double* pDashArray = new double[ strokeAttributes.DashArray.getLength() ];
+ for( sal_Int32 i=0; i<strokeAttributes.DashArray.getLength(); i++ )
+ pDashArray[i]=strokeAttributes.DashArray[i];
+ cairo_set_dash( mpCairo.get(), pDashArray, strokeAttributes.DashArray.getLength(), 0 );
+ delete[] pDashArray;
+ }
+
+ // TODO(rodo) use LineArray of strokeAttributes
+
+ doPolyPolygonPath( xPolyPolygon, Stroke, bNoLineJoin );
+
+ cairo_restore( mpCairo.get() );
+ } else
+ OSL_TRACE ("CanvasHelper called after it was disposed");
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "strokePolyPolygon" );
+#endif
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* ,
+ 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* ,
+ 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* ,
+ 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* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ #ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+ #endif
+
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ useStates( viewState, renderState, true );
+ doPolyPolygonPath( xPolyPolygon, Fill );
+
+ cairo_restore( mpCairo.get() );
+ } else
+ OSL_TRACE ("CanvasHelper called after it was disposed");
+
+ #ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "fillPolyPolygon" );
+ #endif
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Sequence< rendering::Texture >& textures )
+ {
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ useStates( viewState, renderState, true );
+ doPolyPolygonPath( xPolyPolygon, Fill, false, &textures );
+
+ cairo_restore( mpCairo.get() );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* ,
+ 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::XCachedPrimitive > CanvasHelper::implDrawBitmapSurface( const rendering::XCanvas* pCanvas,
+ const SurfaceSharedPtr& pInputSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const geometry::IntegerSize2D& rSize,
+ bool bModulateColors,
+ bool bHasAlpha )
+ {
+ SurfaceSharedPtr pSurface=pInputSurface;
+ uno::Reference< rendering::XCachedPrimitive > rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
+ geometry::IntegerSize2D aBitmapSize = rSize;
+
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
+ cairo_clip( mpCairo.get() );
+
+ useStates( viewState, renderState, true );
+
+ // if( !bHasAlpha )
+ // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
+
+ Matrix aMatrix;
+
+ cairo_get_matrix( mpCairo.get(), &aMatrix );
+ if( ! ::rtl::math::approxEqual( aMatrix.xx, 1 ) &&
+ ! ::rtl::math::approxEqual( aMatrix.yy, 1 ) &&
+ ::rtl::math::approxEqual( aMatrix.x0, 0 ) &&
+ ::rtl::math::approxEqual( aMatrix.y0, 0 ) &&
+ basegfx::fround( rSize.Width * aMatrix.xx ) > 8 &&
+ basegfx::fround( rSize.Height* aMatrix.yy ) > 8 )
+ {
+ double dWidth, dHeight;
+
+ dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
+ dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
+ aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
+ aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
+
+ SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
+ ::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
+ bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
+ CairoSharedPtr pCairo = pScaledSurface->getCairo();
+
+ cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
+ // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
+ cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
+ cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
+ cairo_paint( pCairo.get() );
+
+ pSurface = pScaledSurface;
+
+ aMatrix.xx = aMatrix.yy = 1;
+ cairo_set_matrix( mpCairo.get(), &aMatrix );
+
+ rv = uno::Reference< rendering::XCachedPrimitive >(
+ new CachedBitmap( pSurface, viewState, renderState,
+ // cast away const, need to
+ // change refcount (as this is
+ // ~invisible to client code,
+ // still logically const)
+ const_cast< rendering::XCanvas* >(pCanvas)) );
+ }
+
+ if( !bHasAlpha && mbHaveAlpha )
+ {
+ double x, y, width, height;
+
+ x = y = 0;
+ width = aBitmapSize.Width;
+ height = aBitmapSize.Height;
+ cairo_matrix_transform_point( &aMatrix, &x, &y );
+ cairo_matrix_transform_distance( &aMatrix, &width, &height );
+
+ // in case the bitmap doesn't have alpha and covers whole area
+ // we try to change surface to plain rgb
+ OSL_TRACE ("chance to change surface to rgb, %f, %f, %f x %f (%d x %d)", x, y, width, height, maSize.getX(), maSize.getY() );
+ if( x <= 0 && y <= 0 && x + width >= maSize.getX() && y + height >= maSize.getY() )
+ {
+ OSL_TRACE ("trying to change surface to rgb");
+ if( mpSurfaceProvider ) {
+ SurfaceSharedPtr pNewSurface = mpSurfaceProvider->changeSurface( false, false );
+
+ if( pNewSurface )
+ setSurface( pNewSurface, false );
+
+ // set state to new mpCairo.get()
+ useStates( viewState, renderState, true );
+ // use the possibly modified matrix
+ cairo_set_matrix( mpCairo.get(), &aMatrix );
+ }
+ }
+ }
+
+ cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
+ if( !bHasAlpha &&
+ ::rtl::math::approxEqual( aMatrix.xx, 1 ) &&
+ ::rtl::math::approxEqual( aMatrix.yy, 1 ) &&
+ ::rtl::math::approxEqual( aMatrix.x0, 0 ) &&
+ ::rtl::math::approxEqual( aMatrix.y0, 0 ) )
+ cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_pattern_set_extend( cairo_get_source(mpCairo.get()), CAIRO_EXTEND_PAD );
+ cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height );
+ cairo_clip( mpCairo.get() );
+
+ if( bModulateColors )
+ cairo_paint_with_alpha( mpCairo.get(), renderState.DeviceColor[3] );
+ else
+ cairo_paint( mpCairo.get() );
+ cairo_restore( mpCairo.get() );
+ } else
+ OSL_TRACE ("CanvasHelper called after it was disposed");
+
+ return rv; // 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 )
+ {
+ #ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+ #endif
+
+ uno::Reference< rendering::XCachedPrimitive > rv;
+ unsigned char* data = NULL;
+ bool bHasAlpha = false;
+ SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
+ geometry::IntegerSize2D aSize = xBitmap->getSize();
+
+ if( pSurface ) {
+ rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, false, bHasAlpha );
+
+ if( data )
+ free( data );
+ } else
+ rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
+
+ #ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
+ #endif
+
+ return rv;
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
+
+ uno::Reference< rendering::XCachedPrimitive > rv;
+ unsigned char* data = NULL;
+ bool bHasAlpha = false;
+ SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
+ geometry::IntegerSize2D aSize = xBitmap->getSize();
+
+ if( pSurface ) {
+ rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, true, bHasAlpha );
+
+ if( data )
+ free( data );
+ } else
+ rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
+#endif
+
+ return rv;
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+ {
+ return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+ }
+
+ void CanvasHelper::copyRect( const rendering::XCanvas* ,
+ 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 CanvasHelper::getSize()
+ {
+ if( !mpSurfaceProvider )
+ geometry::IntegerSize2D(1, 1); // we're disposed
+
+ return ::basegfx::unotools::integerSize2DFromB2ISize( maSize );
+ }
+
+ uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
+ sal_Bool /*beFast*/ )
+ {
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
+
+ if( mpCairo ) {
+ return uno::Reference< rendering::XBitmap >( new CanvasBitmap( ::basegfx::B2ISize( ::canvas::tools::roundUp( newSize.Width ),
+ ::canvas::tools::roundUp( newSize.Height ) ),
+ mpSurfaceProvider, mpDevice, false ) );
+ } else
+ OSL_TRACE ("CanvasHelper called after it was disposed");
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "getScaledBitmap" );
+#endif
+
+ return uno::Reference< rendering::XBitmap >();
+ }
+
+ uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& aLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if( mpCairo ) {
+ aLayout = getMemoryLayout();
+
+ const sal_Int32 nWidth( rect.X2 - rect.X1 );
+ const sal_Int32 nHeight( rect.Y2 - rect.Y1 );
+ uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight );
+ sal_Int8* pData = aRes.getArray();
+ cairo_surface_t* pImageSurface = cairo_image_surface_create_for_data( (unsigned char *) pData,
+ CAIRO_FORMAT_ARGB32,
+ nWidth, nHeight, 4*nWidth );
+ cairo_t* pCairo = cairo_create( pImageSurface );
+ cairo_set_source_surface( pCairo, mpSurface->getCairoSurface().get(), -rect.X1, -rect.Y1);
+ cairo_paint( pCairo );
+ cairo_destroy( pCairo );
+ cairo_surface_destroy( pImageSurface );
+
+ aLayout.ScanLines = nHeight;
+ aLayout.ScanLineBytes = nWidth*4;
+ aLayout.ScanLineStride = aLayout.ScanLineBytes;
+
+ return aRes;
+ }
+
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ void CanvasHelper::setData( const uno::Sequence< sal_Int8 >& /*data*/,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& /*rect*/ )
+ {
+ }
+
+ void CanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& /*color*/,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& /*pos*/ )
+ {
+ }
+
+ uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& /*pos*/ )
+ {
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ uno::Reference< rendering::XBitmapPalette > CanvasHelper::getPalette()
+ {
+ // TODO(F1): Palette bitmaps NYI
+ return uno::Reference< rendering::XBitmapPalette >();
+ }
+
+ namespace
+ {
+ class CairoColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
+ {
+ private:
+ uno::Sequence< sal_Int8 > maComponentTags;
+ uno::Sequence< sal_Int32 > maBitCounts;
+
+ virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
+ {
+ return rendering::ColorSpaceType::RGB;
+ }
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
+ {
+ return maComponentTags;
+ }
+ virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
+ {
+ return rendering::RenderingIntent::PERCEPTUAL;
+ }
+ virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
+ {
+ return uno::Sequence< beans::PropertyValue >();
+ }
+ virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
+ const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+ {
+ // TODO(P3): if we know anything about target
+ // colorspace, this can be greatly sped up
+ uno::Sequence<rendering::ARGBColor> aIntermediate(
+ convertToARGB(deviceColor));
+ return targetColorSpace->convertFromARGB(aIntermediate);
+ }
+ virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const double* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::RGBColor > aRes(nLen/4);
+ rendering::RGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ const double fAlpha(pIn[3]);
+ if( fAlpha == 0.0 )
+ *pOut++ = rendering::RGBColor(0.0, 0.0, 0.0);
+ else
+ *pOut++ = rendering::RGBColor(pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const double* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ const double fAlpha(pIn[3]);
+ if( fAlpha == 0.0 )
+ *pOut++ = rendering::ARGBColor(0.0, 0.0, 0.0, 0.0);
+ else
+ *pOut++ = rendering::ARGBColor(fAlpha,pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const double* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = rendering::ARGBColor(pIn[3],pIn[2],pIn[1],pIn[1]);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::RGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< double > aRes(nLen*4);
+ double* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = pIn->Blue;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Red;
+ *pColors++ = 1.0;
+ ++pIn;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< double > aRes(nLen*4);
+ double* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = pIn->Alpha*pIn->Blue;
+ *pColors++ = pIn->Alpha*pIn->Green;
+ *pColors++ = pIn->Alpha*pIn->Red;
+ *pColors++ = pIn->Alpha;
+ ++pIn;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< double > aRes(nLen*4);
+ double* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = pIn->Blue;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Red;
+ *pColors++ = pIn->Alpha;
+ ++pIn;
+ }
+ return aRes;
+ }
+
+ // XIntegerBitmapColorSpace
+ virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
+ {
+ return 32;
+ }
+ virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
+ {
+ return maBitCounts;
+ }
+ virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
+ {
+ return util::Endianness::LITTLE;
+ }
+ virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
+ const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+ {
+ if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) )
+ {
+ const sal_Int8* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence<double> aRes(nLen);
+ double* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
+ *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
+ *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
+ *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
+ }
+ return aRes;
+ }
+ else
+ {
+ // TODO(P3): if we know anything about target
+ // colorspace, this can be greatly sped up
+ uno::Sequence<rendering::ARGBColor> aIntermediate(
+ convertIntegerToARGB(deviceColor));
+ return targetColorSpace->convertFromARGB(aIntermediate);
+ }
+ }
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
+ const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+ {
+ if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) )
+ {
+ // it's us, so simply pass-through the data
+ return deviceColor;
+ }
+ else
+ {
+ // TODO(P3): if we know anything about target
+ // colorspace, this can be greatly sped up
+ uno::Sequence<rendering::ARGBColor> aIntermediate(
+ convertIntegerToARGB(deviceColor));
+ return targetColorSpace->convertIntegerFromARGB(aIntermediate);
+ }
+ }
+ virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const sal_Int8* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::RGBColor > aRes(nLen/4);
+ rendering::RGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ const double fAlpha((sal_uInt8)pIn[3]);
+ if( fAlpha )
+ *pOut++ = rendering::RGBColor(
+ pIn[2]/fAlpha,
+ pIn[1]/fAlpha,
+ pIn[0]/fAlpha);
+ else
+ *pOut++ = rendering::RGBColor(0,0,0);
+ pIn += 4;
+ }
+ return aRes;
+ }
+
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const sal_Int8* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ const double fAlpha((sal_uInt8)pIn[3]);
+ if( fAlpha )
+ *pOut++ = rendering::ARGBColor(
+ fAlpha/255.0,
+ pIn[2]/fAlpha,
+ pIn[1]/fAlpha,
+ pIn[0]/fAlpha);
+ else
+ *pOut++ = rendering::ARGBColor(0,0,0,0);
+ pIn += 4;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const sal_Int8* pIn( deviceColor.getConstArray() );
+ const sal_Size nLen( deviceColor.getLength() );
+ ENSURE_ARG_OR_THROW2(nLen%4==0,
+ "number of channels no multiple of 4",
+ static_cast<rendering::XColorSpace*>(this), 0);
+
+ uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
+ rendering::ARGBColor* pOut( aRes.getArray() );
+ for( sal_Size i=0; i<nLen; i+=4 )
+ {
+ *pOut++ = rendering::ARGBColor(
+ vcl::unotools::toDoubleColor(pIn[3]),
+ vcl::unotools::toDoubleColor(pIn[2]),
+ vcl::unotools::toDoubleColor(pIn[1]),
+ vcl::unotools::toDoubleColor(pIn[0]));
+ pIn += 4;
+ }
+ return aRes;
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::RGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< sal_Int8 > aRes(nLen*4);
+ sal_Int8* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Green);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Red);
+ *pColors++ = 255;
+ ++pIn;
+ }
+ return aRes;
+ }
+
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< sal_Int8 > aRes(nLen*4);
+ sal_Int8* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ const double fAlpha(pIn->Alpha);
+ *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Blue);
+ *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Green);
+ *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Red);
+ *pColors++ = vcl::unotools::toByteColor(fAlpha);
+ ++pIn;
+ }
+ return aRes;
+ }
+ virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
+ const sal_Size nLen( rgbColor.getLength() );
+
+ uno::Sequence< sal_Int8 > aRes(nLen*4);
+ sal_Int8* pColors=aRes.getArray();
+ for( sal_Size i=0; i<nLen; ++i )
+ {
+ *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Green);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Red);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
+ ++pIn;
+ }
+ return aRes;
+ }
+
+ public:
+ CairoColorSpace() :
+ maComponentTags(4),
+ maBitCounts(4)
+ {
+ sal_Int8* pTags = maComponentTags.getArray();
+ sal_Int32* pBitCounts = maBitCounts.getArray();
+ pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
+ pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
+ pTags[2] = rendering::ColorComponentTag::RGB_RED;
+ pTags[3] = rendering::ColorComponentTag::PREMULTIPLIED_ALPHA;
+
+ pBitCounts[0] =
+ pBitCounts[1] =
+ pBitCounts[2] =
+ pBitCounts[3] = 8;
+ }
+ };
+
+ struct CairoColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
+ CairoColorSpaceHolder>
+ {
+ uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
+ {
+ return new CairoColorSpace();
+ }
+ };
+ }
+
+ rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout()
+ {
+ if( !mpCairo )
+ return rendering::IntegerBitmapLayout(); // we're disposed
+
+ const geometry::IntegerSize2D aSize(getSize());
+ rendering::IntegerBitmapLayout aLayout;
+
+ aLayout.ScanLines = aSize.Height;
+ aLayout.ScanLineBytes = aSize.Width*4;
+ aLayout.ScanLineStride = aLayout.ScanLineBytes;
+ aLayout.PlaneStride = 0;
+ aLayout.ColorSpace = CairoColorSpaceHolder::get();
+ aLayout.Palette.clear();
+ aLayout.IsMsbFirst = sal_False;
+
+ return aLayout;
+ }
+
+ void CanvasHelper::flush() const
+ {
+ }
+
+ bool CanvasHelper::hasAlpha() const
+ {
+ return mbHaveAlpha;
+ }
+
+ bool CanvasHelper::repaint( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ OSL_TRACE("CanvasHelper::repaint");
+
+ if( mpCairo ) {
+ cairo_save( mpCairo.get() );
+
+ cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
+ cairo_clip( mpCairo.get() );
+
+ useStates( viewState, renderState, true );
+
+ Matrix aMatrix;
+
+ cairo_get_matrix( mpCairo.get(), &aMatrix );
+ aMatrix.xx = aMatrix.yy = 1;
+ cairo_set_matrix( mpCairo.get(), &aMatrix );
+
+ // if( !bHasAlpha )
+ // cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
+
+ cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
+ cairo_paint( mpCairo.get() );
+ cairo_restore( mpCairo.get() );
+ }
+
+ return true;
+ }
+}
diff --git a/canvas/source/cairo/cairo_canvashelper.hxx b/canvas/source/cairo/cairo_canvashelper.hxx
new file mode 100644
index 000000000000..d89429b77a25
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper.hxx
@@ -0,0 +1,335 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_CANVASHELPER_HXX_
+#define _CAIROCANVAS_CANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <com/sun/star/rendering/XLinePolyPolygon2D.hpp>
+
+#include <boost/utility.hpp>
+
+#include "cairo_cairo.hxx"
+#include "cairo_surfaceprovider.hxx"
+
+class VirtualDevice;
+
+namespace basegfx {
+ class B2DPolyPolygon;
+}
+
+namespace cairocanvas
+{
+ class SpriteCanvas;
+
+ enum Operation {
+ Stroke,
+ Fill,
+ Clip
+ };
+
+ class CanvasHelper : private ::boost::noncopyable
+ {
+ public:
+ CanvasHelper();
+
+ /// Release all references
+ void disposing();
+
+ /** Initialize canvas helper
+
+ This method late-initializes the canvas helper, providing
+ it with the necessary device and size. 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 rSizePixel
+ Size of the output surface in pixel.
+
+ @param rDevice
+ Reference device this canvas is associated with
+
+ */
+ void init( const ::basegfx::B2ISize& rSizePixel,
+ SurfaceProvider& rSurfaceProvider,
+ ::com::sun::star::rendering::XGraphicDevice* pDevice );
+
+ void setSize( const ::basegfx::B2ISize& rSize );
+ void setSurface( const ::cairo::SurfaceSharedPtr& pSurface, bool bHasAlpha );
+
+ // 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,
+ 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 );
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::FontInfo >
+ queryAvailableFonts( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::rendering::FontInfo& aFilter,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue >& aFontProperties );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawText( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::rendering::StringContext& text,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& xFont,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ sal_Int8 textDirection );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawTextLayout( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XTextLayout >& layoutetText,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawBitmap( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawBitmapModulated( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >
+ getDevice();
+
+ // BitmapCanvasHelper functionality
+ // ================================
+
+ void copyRect( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ 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::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::uno::Reference< ::com::sun::star::rendering::XBitmapPalette > getPalette();
+
+ ::com::sun::star::rendering::IntegerBitmapLayout getMemoryLayout();
+
+ // Flush drawing queue to screen
+ void flush() const;
+
+ /** Called from XCanvas base classes, to notify that content
+ is _about_ to change
+ */
+ void modifying() {}
+
+ bool hasAlpha() const;
+
+ enum ColorType
+ {
+ LINE_COLOR, FILL_COLOR, TEXT_COLOR, IGNORE_COLOR
+ };
+
+ void doPolyPolygonPath( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ Operation aOperation,
+ bool bNoLineJoin = false,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::Texture >* pTextures=NULL,
+ ::cairo::Cairo* pCairo=NULL ) const;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ implDrawBitmapSurface(
+ const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::geometry::IntegerSize2D& rSize,
+ bool bModulateColors,
+ bool bHasAlpha );
+
+ bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ protected:
+ /** Surface provider
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for canvas. Provides us with
+ our output surface and associated functionality.
+ */
+ SurfaceProvider* mpSurfaceProvider;
+
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for spritecanvas.
+ */
+ ::com::sun::star::rendering::XGraphicDevice* mpDevice;
+
+ private:
+
+ boost::shared_ptr<VirtualDevice> mpVirtualDevice;
+
+ void useStates( const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ bool setColor );
+
+ /// When true, content is able to represent alpha
+ bool mbHaveAlpha;
+
+ CairoSharedPtr mpCairo;
+ SurfaceSharedPtr mpSurface;
+ ::basegfx::B2ISize maSize;
+ };
+
+ /// also needed from SpriteHelper
+ void doPolyPolygonImplementation( ::basegfx::B2DPolyPolygon aPolyPolygon,
+ Operation aOperation,
+ ::cairo::Cairo* pCairo,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::Texture >* pTextures,
+ const SurfaceProviderRef& pDevice,
+ ::com::sun::star::rendering::FillRule eFillrule );
+}
+
+#endif /* _CAIROCANVAS_CANVASHELPER_HXX_ */
diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx
new file mode 100644
index 000000000000..35310e1c078d
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper_text.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include "cairo_canvasfont.hxx"
+#include "cairo_textlayout.hxx"
+#include "cairo_canvashelper.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ enum ColorType
+ {
+ LINE_COLOR, FILL_COLOR, TEXT_COLOR, IGNORE_COLOR
+ };
+
+ uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* ,
+ const rendering::FontRequest& fontRequest,
+ const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+ const geometry::Matrix2D& fontMatrix )
+ {
+ return uno::Reference< rendering::XCanvasFont >( new CanvasFont( fontRequest, extraFontProperties, fontMatrix, mpSurfaceProvider ));
+ }
+
+ uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* ,
+ const rendering::FontInfo& /*aFilter*/,
+ const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
+ {
+ // TODO
+ return uno::Sequence< rendering::FontInfo >();
+ }
+
+ static bool
+ setupFontTransform( ::OutputDevice& rOutDev,
+ ::Point& o_rPoint,
+ ::Font& io_rVCLFont,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState )
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ rViewState,
+ rRenderState);
+
+ ::basegfx::B2DTuple aScale;
+ ::basegfx::B2DTuple aTranslate;
+ double nRotate, nShearX;
+
+ aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );
+
+ // query font metric _before_ tampering with width and height
+ if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) )
+ {
+ // retrieve true font width
+ const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetWidth() );
+
+ const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) );
+
+ if( !nScaledFontWidth )
+ {
+ // scale is smaller than one pixel - disable text
+ // output altogether
+ return false;
+ }
+
+ io_rVCLFont.SetWidth( nScaledFontWidth );
+ }
+
+ if( !::rtl::math::approxEqual(aScale.getY(), 1.0) )
+ {
+ const sal_Int32 nFontHeight( io_rVCLFont.GetHeight() );
+ io_rVCLFont.SetHeight( ::basegfx::fround(nFontHeight * aScale.getY()) );
+ }
+
+ io_rVCLFont.SetOrientation( static_cast< short >( ::basegfx::fround(-fmod(nRotate, 2*M_PI)*(1800.0/M_PI)) ) );
+
+ // TODO(F2): Missing functionality in VCL: shearing
+ o_rPoint.X() = ::basegfx::fround(aTranslate.getX());
+ o_rPoint.Y() = ::basegfx::fround(aTranslate.getY());
+
+ return true;
+ }
+
+ static int
+ setupOutDevState( OutputDevice& rOutDev,
+ const rendering::XCanvas* pOwner,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ ColorType eColorType )
+ {
+ ::canvas::tools::verifyInput( renderState,
+ BOOST_CURRENT_FUNCTION,
+ const_cast<rendering::XCanvas*>(pOwner), // only for refcount
+ 2,
+ eColorType == IGNORE_COLOR ? 0 : 3 );
+
+ int nTransparency(0);
+
+ // TODO(P2): Don't change clipping all the time, maintain current clip
+ // state and change only when update is necessary
+
+ // accumulate non-empty clips into one region
+ // ==========================================
+
+ Region aClipRegion;
+
+ if( viewState.Clip.is() )
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
+ viewState.Clip) );
+
+ if( aClipPoly.count() )
+ {
+ // setup non-empty clipping
+ ::basegfx::B2DHomMatrix aMatrix;
+ aClipPoly.transform(
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
+ viewState.AffineTransform ) );
+
+ aClipRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
+ }
+ }
+
+ if( renderState.Clip.is() )
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
+ renderState.Clip) );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ aClipPoly.transform(
+ ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
+ viewState,
+ renderState ) );
+
+ if( aClipPoly.count() )
+ {
+ // setup non-empty clipping
+ Region aRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
+
+ if( aClipRegion.IsEmpty() )
+ aClipRegion = aRegion;
+ else
+ aClipRegion.Intersect( aRegion );
+ }
+ else
+ {
+ // clip polygon is empty
+ aClipRegion.SetEmpty();
+ }
+ }
+
+ // setup accumulated clip region. Note that setting an
+ // empty clip region denotes "clip everything" on the
+ // OutputDevice (which is why we translate that into
+ // SetClipRegion() here). When both view and render clip
+ // are empty, aClipRegion remains default-constructed,
+ // i.e. empty, too.
+ if( aClipRegion.IsEmpty() )
+ {
+ rOutDev.SetClipRegion();
+ }
+ else
+ {
+ rOutDev.SetClipRegion( aClipRegion );
+ }
+
+ if( eColorType != IGNORE_COLOR )
+ {
+ Color aColor( COL_WHITE );
+
+ if( renderState.DeviceColor.getLength() > 2 )
+ {
+ aColor = ::vcl::unotools::stdColorSpaceSequenceToColor( renderState.DeviceColor );
+ }
+
+ // extract alpha, and make color opaque
+ // afterwards. Otherwise, OutputDevice won't draw anything
+ nTransparency = aColor.GetTransparency();
+ aColor.SetTransparency(0);
+
+ switch( eColorType )
+ {
+ case LINE_COLOR:
+ rOutDev.SetLineColor( aColor );
+ rOutDev.SetFillColor();
+
+ break;
+
+ case FILL_COLOR:
+ rOutDev.SetFillColor( aColor );
+ rOutDev.SetLineColor();
+
+ break;
+
+ case TEXT_COLOR:
+ rOutDev.SetTextColor( aColor );
+
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "CanvasHelper::setupOutDevState(): Unexpected color type");
+ break;
+ }
+ }
+
+ return nTransparency;
+ }
+
+ bool setupTextOutput( OutputDevice& rOutDev,
+ const rendering::XCanvas* pOwner,
+ ::Point& o_rOutPos,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Reference< rendering::XCanvasFont >& xFont )
+ {
+ setupOutDevState( rOutDev, pOwner, viewState, renderState, TEXT_COLOR );
+
+ ::Font aVCLFont;
+
+ CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
+
+ ENSURE_ARG_OR_THROW( pFont,
+ "CanvasHelper::setupTextOutput(): Font not compatible with this canvas" );
+
+ aVCLFont = pFont->getVCLFont();
+
+ Color aColor( COL_BLACK );
+
+ if( renderState.DeviceColor.getLength() > 2 )
+ {
+ aColor = ::vcl::unotools::stdColorSpaceSequenceToColor(renderState.DeviceColor );
+ }
+
+ // setup font color
+ aVCLFont.SetColor( aColor );
+ aVCLFont.SetFillColor( aColor );
+
+ // no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here.
+ if( !setupFontTransform( rOutDev, o_rOutPos, aVCLFont, viewState, renderState ) )
+ return false;
+
+ rOutDev.SetFont( aVCLFont );
+
+
+ return true;
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* pOwner,
+ const rendering::StringContext& text,
+ const uno::Reference< rendering::XCanvasFont >& xFont,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ sal_Int8 textDirection )
+ {
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
+
+ ENSURE_ARG_OR_THROW( xFont.is(),
+ "CanvasHelper::drawText(): font is NULL");
+
+ if( !mpVirtualDevice )
+ mpVirtualDevice = mpSurface->createVirtualDevice();
+
+ if( mpVirtualDevice )
+ {
+#if defined CAIRO_HAS_WIN32_SURFACE
+ // FIXME: Some kind of work-araound...
+ cairo_rectangle (mpSurface->getCairo().get(), 0, 0, 0, 0);
+ cairo_fill(mpSurface->getCairo().get());
+#endif
+ ::Point aOutpos;
+ if( !setupTextOutput( *mpVirtualDevice, pOwner, aOutpos, viewState, renderState, xFont ) )
+ return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary
+
+ // change text direction and layout mode
+ ULONG nLayoutMode(0);
+ switch( textDirection )
+ {
+ case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
+ nLayoutMode |= TEXT_LAYOUT_BIDI_LTR;
+ // FALLTHROUGH intended
+ case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
+ nLayoutMode |= TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG;
+ nLayoutMode |= TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ break;
+
+ case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
+ nLayoutMode |= TEXT_LAYOUT_BIDI_RTL;
+ // FALLTHROUGH intended
+ case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
+ nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG;
+ nLayoutMode |= TEXT_LAYOUT_TEXTORIGIN_RIGHT;
+ break;
+ }
+
+ // TODO(F2): alpha
+ mpVirtualDevice->SetLayoutMode( nLayoutMode );
+
+ OSL_TRACE(":cairocanvas::CanvasHelper::drawText(O,t,f,v,r,d): %s", ::rtl::OUStringToOString( text.Text.copy( text.StartPosition, text.Length ),
+ RTL_TEXTENCODING_UTF8 ).getStr());
+
+ TextLayout* pTextLayout = new TextLayout(text, textDirection, 0, CanvasFont::Reference(dynamic_cast< CanvasFont* >( xFont.get() )), mpSurfaceProvider);
+ pTextLayout->draw( mpSurface, *mpVirtualDevice, aOutpos, viewState, renderState );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* pOwner,
+ const uno::Reference< rendering::XTextLayout >& xLayoutedText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_ARG_OR_THROW( xLayoutedText.is(),
+ "CanvasHelper::drawTextLayout(): layout is NULL");
+
+ TextLayout* pTextLayout = dynamic_cast< TextLayout* >( xLayoutedText.get() );
+
+ if( pTextLayout )
+ {
+ if( !mpVirtualDevice )
+ mpVirtualDevice = mpSurface->createVirtualDevice();
+
+ if( mpVirtualDevice )
+ {
+#if defined CAIRO_HAS_WIN32_SURFACE
+ // FIXME: Some kind of work-araound...
+ cairo_rectangle( mpSurface->getCairo().get(), 0, 0, 0, 0);
+ cairo_fill(mpSurface->getCairo().get());
+#endif
+ // TODO(T3): Race condition. We're taking the font
+ // from xLayoutedText, and then calling draw() at it,
+ // without exclusive access. Move setupTextOutput(),
+ // e.g. to impltools?
+
+ ::Point aOutpos;
+ if( !setupTextOutput( *mpVirtualDevice, pOwner, aOutpos, viewState, renderState, xLayoutedText->getFont() ) )
+ return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary
+
+ // TODO(F2): What about the offset scalings?
+ pTextLayout->draw( mpSurface, *mpVirtualDevice, aOutpos, viewState, renderState );
+ }
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( false,
+ "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+}
diff --git a/canvas/source/cairo/cairo_canvashelper_texturefill.cxx b/canvas/source/cairo/cairo_canvashelper_texturefill.cxx
new file mode 100644
index 000000000000..ee8aff6980cf
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper_texturefill.cxx
@@ -0,0 +1,144 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+
+#include <tools/poly.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <utility>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "cairo_textlayout.hxx"
+#include "cairo_parametricpolypolygon.hxx"
+#include "cairo_canvashelper.hxx"
+#include "cairo_canvasbitmap.hxx"
+#include "cairo_impltools.hxx"
+#include "cairo_canvasfont.hxx"
+
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ namespace
+ {
+ bool textureFill( OutputDevice& rOutDev,
+ GraphicObject& rGraphic,
+ const ::Point& rPosPixel,
+ const ::Size& rNextTileX,
+ const ::Size& rNextTileY,
+ sal_Int32 nTilesX,
+ sal_Int32 nTilesY,
+ const ::Size& rTileSize,
+ const GraphicAttr& rAttr)
+ {
+ BOOL bRet( false );
+ Point aCurrPos;
+ int nX, nY;
+
+ for( nY=0; nY < nTilesY; ++nY )
+ {
+ aCurrPos.X() = rPosPixel.X() + nY*rNextTileY.Width();
+ aCurrPos.Y() = rPosPixel.Y() + nY*rNextTileY.Height();
+
+ for( nX=0; nX < nTilesX; ++nX )
+ {
+ // update return value. This method should return true, if
+ // at least one of the looped Draws succeeded.
+ bRet |= rGraphic.Draw( &rOutDev,
+ aCurrPos,
+ rTileSize,
+ &rAttr );
+
+ aCurrPos.X() += rNextTileX.Width();
+ aCurrPos.Y() += rNextTileX.Height();
+ }
+ }
+
+ return bRet;
+ }
+
+ inline sal_Int32 roundDown( const double& rVal )
+ {
+ return static_cast< sal_Int32 >( floor( rVal ) );
+ }
+
+ inline sal_Int32 roundUp( const double& rVal )
+ {
+ return static_cast< sal_Int32 >( ceil( rVal ) );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas& rCanvas,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Sequence< rendering::Texture >& textures )
+ {
+ ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillPolyPolygon(): polygon is NULL");
+ ENSURE_ARG_OR_THROW( textures.getLength(),
+ "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
+
+ cairo_save( mpCairo );
+
+ useStates( viewState, renderState, true );
+ mpTextures = &textures;
+ drawPolyPolygonPath( xPolyPolygon, Fill );
+ mpTextures = NULL;
+
+ cairo_restore( mpCairo );
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+}
diff --git a/canvas/source/cairo/cairo_devicehelper.cxx b/canvas/source/cairo/cairo_devicehelper.cxx
new file mode 100644
index 000000000000..70a5ea51c0ea
--- /dev/null
+++ b/canvas/source/cairo/cairo_devicehelper.cxx
@@ -0,0 +1,302 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include <vcl/canvastools.hxx>
+
+#include <tools/stream.hxx>
+
+#include "cairo_spritecanvas.hxx"
+#include "cairo_canvasbitmap.hxx"
+#include "cairo_devicehelper.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ DeviceHelper::DeviceHelper() :
+ mpSurfaceProvider( NULL ),
+ mpRefDevice( NULL ),
+ mpSurface()
+ {
+ }
+
+ void DeviceHelper::implInit( SurfaceProvider& rSurfaceProvider,
+ OutputDevice& rRefDevice )
+ {
+ mpSurfaceProvider = &rSurfaceProvider;
+ mpRefDevice = &rRefDevice;
+
+ // no own surface, this is handled by derived classes
+ }
+
+ void DeviceHelper::init( SurfaceProvider& rSurfaceProvider,
+ OutputDevice& rRefDevice )
+ {
+ implInit(rSurfaceProvider, rRefDevice);
+
+ OutputDevice* pOutDev=getOutputDevice();
+ mpSurface = cairo::createSurface( *pOutDev,
+ pOutDev->GetOutOffXPixel(),
+ pOutDev->GetOutOffYPixel(),
+ pOutDev->GetOutputWidthPixel(),
+ pOutDev->GetOutputHeightPixel() );
+ }
+
+ void DeviceHelper::disposing()
+ {
+ // release all references
+ mpSurface.reset();
+ mpRefDevice = NULL;
+ mpSurfaceProvider = NULL;
+ }
+
+ void DeviceHelper::setSize( const ::basegfx::B2ISize& rSize )
+ {
+ OSL_TRACE("DeviceHelper::setSize(): device size %d x %d", rSize.getX(), rSize.getY() );
+
+ if( !mpRefDevice )
+ return; // disposed
+
+ OutputDevice* pOutDev=getOutputDevice();
+
+#if defined (UNX) && !defined (QUARTZ)
+ // X11 only
+ if( mpSurface )
+ mpSurface->Resize( rSize.getX() + pOutDev->GetOutOffXPixel(),
+ rSize.getY() + pOutDev->GetOutOffYPixel() );
+ else
+#endif
+ mpSurface = cairo::createSurface(
+ *pOutDev,
+ pOutDev->GetOutOffXPixel(),
+ pOutDev->GetOutOffYPixel(),
+ rSize.getX(), rSize.getY() );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalResolution()
+ {
+ // Map a one-by-one millimeter box to pixel
+ const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
+ mpRefDevice->SetMapMode( MapMode(MAP_MM) );
+ const Size aPixelSize( mpRefDevice->LogicToPixel(Size(1,1)) );
+ mpRefDevice->SetMapMode( aOldMapMode );
+
+ return ::vcl::unotools::size2DFromSize( aPixelSize );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalSize()
+ {
+ if( !mpRefDevice )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ // Map the pixel dimensions of the output window to millimeter
+ const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
+ mpRefDevice->SetMapMode( MapMode(MAP_MM) );
+ const Size aLogSize( mpRefDevice->PixelToLogic(mpRefDevice->GetOutputSizePixel()) );
+ mpRefDevice->SetMapMode( aOldMapMode );
+
+ return ::vcl::unotools::size2DFromSize( aLogSize );
+ }
+
+ uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ // disposed?
+ if( !mpSurfaceProvider )
+ return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XLinePolyPolygon2D >(
+ new ::basegfx::unotools::UnoPolyPolygon(
+ ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
+ {
+ // disposed?
+ if( !mpSurfaceProvider )
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(
+ new ::basegfx::unotools::UnoPolyPolygon(
+ ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const geometry::IntegerSize2D& size )
+ {
+ // disposed?
+ if( !mpSurfaceProvider )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
+ SurfaceProviderRef(mpSurfaceProvider),
+ rDevice.get(),
+ false ));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const geometry::IntegerSize2D& size )
+ {
+ // disposed?
+ if( !mpSurfaceProvider )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
+ SurfaceProviderRef(mpSurfaceProvider),
+ rDevice.get(),
+ true ));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool DeviceHelper::hasFullScreenMode()
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ sal_Bool DeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ uno::Any DeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(false);
+ }
+
+ uno::Any DeviceHelper::getDeviceHandle() const
+ {
+ return uno::makeAny( reinterpret_cast< sal_Int64 >(mpRefDevice) );
+ }
+
+ uno::Any DeviceHelper::getSurfaceHandle() const
+ {
+ return uno::Any();
+ }
+
+ namespace
+ {
+ struct DeviceColorSpace: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
+ DeviceColorSpace>
+ {
+ uno::Reference<rendering::XColorSpace> operator()()
+ {
+ return vcl::unotools::createStandardColorSpace();
+ }
+ };
+ }
+
+ uno::Reference<rendering::XColorSpace> DeviceHelper::getColorSpace() const
+ {
+ // always the same
+ return DeviceColorSpace::get();
+ }
+
+ void DeviceHelper::dumpScreenContent() const
+ {
+ static sal_uInt32 nFilePostfixCount(0);
+
+ if( mpRefDevice )
+ {
+ String aFilename( String::CreateFromAscii("dbg_frontbuffer") );
+ aFilename += String::CreateFromInt32(nFilePostfixCount);
+ aFilename += String::CreateFromAscii(".bmp");
+
+ SvFileStream aStream( aFilename, STREAM_STD_READWRITE );
+
+ const ::Point aEmptyPoint;
+ bool bOldMap( mpRefDevice->IsMapModeEnabled() );
+ mpRefDevice->EnableMapMode( FALSE );
+ aStream << mpRefDevice->GetBitmap(aEmptyPoint,
+ mpRefDevice->GetOutputSizePixel());
+ mpRefDevice->EnableMapMode( bOldMap );
+
+ ++nFilePostfixCount;
+ }
+ }
+
+ SurfaceSharedPtr DeviceHelper::getSurface()
+ {
+ return mpSurface;
+ }
+
+ SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ if( mpSurface )
+ return mpSurface->getSimilar( aContent, rSize.getX(), rSize.getY() );
+
+ return SurfaceSharedPtr();
+ }
+
+ SurfaceSharedPtr DeviceHelper::createSurface( BitmapSystemData& rData, const Size& rSize )
+ {
+ if( mpRefDevice )
+ return createBitmapSurface( *mpRefDevice, rData, rSize );
+
+ return SurfaceSharedPtr();
+ }
+}
diff --git a/canvas/source/cairo/cairo_devicehelper.hxx b/canvas/source/cairo/cairo_devicehelper.hxx
new file mode 100644
index 000000000000..84c5a84926ca
--- /dev/null
+++ b/canvas/source/cairo/cairo_devicehelper.hxx
@@ -0,0 +1,143 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_DEVICEHELPER_HXX
+#define _CAIROCANVAS_DEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <boost/utility.hpp>
+
+#include <vcl/window.hxx>
+#include <vcl/bitmap.hxx>
+
+#include "cairo_cairo.hxx"
+#include "cairo_surfaceprovider.hxx"
+
+/* Definition of DeviceHelper class */
+
+struct SystemEnvData;
+class Window;
+
+namespace cairocanvas
+{
+ class Canvas;
+ class CanvasHelper;
+
+ class DeviceHelper : private ::boost::noncopyable
+ {
+ public:
+ DeviceHelper();
+
+ /** init helper
+
+ @param rCanvas
+ Owning canvas.
+
+ @param rRefDevice
+ Reference output device. Needed for resolution
+ calculations etc.
+ */
+ void init( SurfaceProvider& rSurfaceProvider,
+ OutputDevice& rRefDevice );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // XWindowGraphicDevice
+ ::com::sun::star::geometry::RealSize2D getPhysicalResolution();
+ ::com::sun::star::geometry::RealSize2D getPhysicalSize();
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XLinePolyPolygon2D > createCompatibleLinePolyPolygon(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& points );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBezierPolyPolygon2D > createCompatibleBezierPolyPolygon(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > >& points );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ sal_Bool hasFullScreenMode( );
+ sal_Bool enterFullScreenMode( sal_Bool bEnter );
+
+ ::com::sun::star::uno::Any isAccelerated() const;
+ ::com::sun::star::uno::Any getDeviceHandle() const;
+ ::com::sun::star::uno::Any getSurfaceHandle() const;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XColorSpace > getColorSpace() const;
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const;
+
+ OutputDevice* getOutputDevice() const { return mpRefDevice; }
+ const void* getSysData() { return mpSysData; }
+ ::cairo::SurfaceSharedPtr getSurface();
+ ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, ::cairo::Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ ::cairo::SurfaceSharedPtr createSurface( BitmapSystemData& rData, const Size& rSize );
+
+ protected:
+ /** init helper
+
+ @param rCanvas
+ Owning canvas.
+
+ @param rRefDevice
+ Reference output device. Needed for resolution
+ calculations etc.
+ */
+ void implInit( SurfaceProvider& rSurfaceProvider,
+ OutputDevice& rRefDevice );
+ void setSize( const ::basegfx::B2ISize& rSize );
+
+ private:
+ /** Surface provider
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for canvas. Provides us with
+ our output surface and associated functionality.
+ */
+ SurfaceProvider* mpSurfaceProvider;
+
+ OutputDevice* mpRefDevice;
+ const void* mpSysData;
+ ::cairo::SurfaceSharedPtr mpSurface;
+ };
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_quartz_cairo.cxx b/canvas/source/cairo/cairo_quartz_cairo.cxx
new file mode 100644
index 000000000000..52626a0ae849
--- /dev/null
+++ b/canvas/source/cairo/cairo_quartz_cairo.cxx
@@ -0,0 +1,347 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#ifdef QUARTZ
+/************************************************************************
+ * Mac OS X/Quartz surface backend for OpenOffice.org Cairo Canvas *
+ ************************************************************************/
+
+#include <osl/diagnose.h>
+#include <vcl/sysdata.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/virdev.hxx>
+
+#include "cairo_cairo.hxx"
+
+#if defined CAIRO_HAS_QUARTZ_SURFACE
+
+#include "cairo_quartz_cairo.hxx"
+
+namespace cairo
+{
+ bool IsCairoWorking( OutputDevice* )
+ {
+ // trivially true for Mac
+ return true;
+ }
+
+ /**
+ * QuartzSurface::Surface: Create generic Canvas surface using given Cairo Surface
+ *
+ * @param pSurface Cairo Surface
+ *
+ * This constructor only stores data, it does no processing.
+ * It is used with e.g. cairo_image_surface_create_for_data()
+ * and QuartzSurface::getSimilar()
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ QuartzSurface::QuartzSurface( const CairoSurfaceSharedPtr& pSurface ) :
+ mpView(NULL),
+ mpSurface( pSurface )
+ {
+ // Necessary, context is lost otherwise
+ CGContextRetain( getCGContext() ); // == NULL for non-native surfaces
+ }
+
+ /**
+ * QuartzSurface::Surface: Create Canvas surface from Window reference.
+ * @param NSView
+ * @param x horizontal location of the new surface
+ * @param y vertical location of the new surface
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * pSysData contains the platform native Window reference.
+ * pSysData is used to create a surface on the Window
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ QuartzSurface::QuartzSurface( NSView* pView, int x, int y, int width, int height ) :
+ mpView(pView),
+ mpSurface()
+ {
+ OSL_TRACE("Canvas::cairo::Surface(NSView*, x:%d, y:%d, w:%d, h:%d): New Surface for window", x, y, width, height);
+
+ // on Mac OS X / Quartz we are not drawing directly to the screen, but via regular CGContextRef.
+ // The actual drawing to NSView (i.e. screen) is done in QuartzSurface::flush()
+
+ // HACK: currently initial size for windowsurface is 0x0, which is not possible for us.
+ if (width == 0 || height == 0) {
+ width = [mpView bounds].size.width;
+ height = [mpView bounds].size.height;
+ OSL_TRACE("Canvas::cairo::Surface(): BUG!! size is ZERO! fixing to %d x %d...", width, height);
+ }
+
+ // create a generic surface, NSView/Window is ARGB32.
+ mpSurface.reset(
+ cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, width, height),
+ &cairo_surface_destroy);
+
+ cairo_surface_set_device_offset( mpSurface.get(), x, y );
+ }
+
+ /**
+ * QuartzSurface::Surface: Create Canvas surface from CGContextRef.
+ * @param CGContext Native graphics context
+ * @param x horizontal location of the new surface
+ * @param y vertical location of the new surface
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ QuartzSurface::QuartzSurface( CGContextRef rContext, int x, int y, int width, int height ) :
+ mpView(NULL),
+ mpSurface()
+ {
+ OSL_TRACE("Canvas::cairo::Surface(CGContext:%p, x:%d, y:%d, w:%d, h:%d): New Surface.", rContext, x, y, width, height);
+ // create surface based on CGContext
+
+ // ensure kCGBitmapByteOrder32Host flag, otherwise Cairo breaks (we are practically always using CGBitmapContext)
+ OSL_ASSERT ((CGBitmapContextGetBitsPerPixel(rContext) != 32) ||
+ (CGBitmapContextGetBitmapInfo(rContext) & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Host);
+
+ mpSurface.reset(cairo_quartz_surface_create_for_cg_context(rContext, width, height),
+ &cairo_surface_destroy);
+
+ cairo_surface_set_device_offset( mpSurface.get(), x, y );
+
+ // Necessary, context is lost otherwise
+ CGContextRetain(rContext);
+ }
+
+
+ /**
+ * QuartzSurface::getCairo: Create Cairo (drawing object) for the Canvas surface
+ *
+ * @return new Cairo or NULL
+ **/
+ CairoSharedPtr QuartzSurface::getCairo() const
+ {
+ if (mpSurface.get()){
+ return CairoSharedPtr( cairo_create(mpSurface.get()),
+ &cairo_destroy );
+ } else {
+ return CairoSharedPtr();
+ }
+ }
+
+ /**
+ * QuartzSurface::getSimilar: Create new similar Canvas surface
+ * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * Creates a new Canvas surface. This normally creates platform native surface, even though
+ * generic function is used.
+ *
+ * Cairo surface from aContent (cairo_content_t)
+ *
+ * @return new surface or NULL
+ **/
+ SurfaceSharedPtr QuartzSurface::getSimilar( Content aContent, int width, int height ) const
+ {
+ return SurfaceSharedPtr(
+ new QuartzSurface(
+ CairoSurfaceSharedPtr(
+ cairo_surface_create_similar( mpSurface.get(), aContent, width, height ),
+ &cairo_surface_destroy )));
+ }
+
+ /**
+ * QuartzSurface::Resize: Resizes the Canvas surface.
+ * @param width new width of the surface
+ * @param height new height of the surface
+ *
+ * Only used on X11.
+ *
+ * @return The new surface or NULL
+ **/
+ void QuartzSurface::Resize( int width, int height )
+ {
+ OSL_ENSURE(false,"not supposed to be called!");
+ }
+
+
+ /**
+ * QuartzSurface::flush: Draw the data to screen
+ **/
+ void QuartzSurface::flush() const
+ {
+ // can only flush surfaces with NSView
+ if( !mpView ) return;
+
+ OSL_TRACE("Canvas::cairo::QuartzSurface::flush(): flush to NSView");
+
+ CGContextRef mrContext = getCGContext();
+
+ if (!mrContext) return;
+
+ [mpView lockFocus];
+
+ /**
+ * This code is using same screen update code as in VCL (esp. AquaSalGraphics::UpdateWindow() )
+ */
+ CGContextRef rViewContext = reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
+ CGImageRef xImage = CGBitmapContextCreateImage(mrContext);
+ CGContextDrawImage(rViewContext,
+ CGRectMake( 0, 0,
+ CGImageGetWidth(xImage),
+ CGImageGetHeight(xImage)),
+ xImage);
+ CGImageRelease( xImage );
+ CGContextFlush( rViewContext );
+
+ [mpView unlockFocus];
+ }
+
+ /**
+ * QuartzSurface::getDepth: Get the color depth of the Canvas surface.
+ *
+ * @return color depth
+ **/
+ int QuartzSurface::getDepth() const
+ {
+ if (mpSurface.get()) {
+ switch (cairo_surface_get_content (mpSurface.get())) {
+ case CAIRO_CONTENT_ALPHA: return 8; break;
+ case CAIRO_CONTENT_COLOR: return 24; break;
+ case CAIRO_CONTENT_COLOR_ALPHA: return 32; break;
+ }
+ }
+ OSL_TRACE("Canvas::cairo::QuartzSurface::getDepth(): ERROR - depth unspecified!");
+
+ return -1;
+ }
+
+ /**
+ * QuartzSurface::getCGContext: Get the native CGContextRef of the Canvas's cairo surface
+ *
+ * @return graphics context
+ **/
+ CGContextRef QuartzSurface::getCGContext() const
+ {
+ if (mpSurface.get())
+ return cairo_quartz_surface_get_cg_context(mpSurface.get());
+ else
+ return NULL;
+ }
+
+ /**
+ * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface
+ *
+ * @return The new virtual device
+ **/
+ boost::shared_ptr<VirtualDevice> QuartzSurface::createVirtualDevice() const
+ {
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.rCGContext = getCGContext();
+ return boost::shared_ptr<VirtualDevice>(
+ new VirtualDevice( &aSystemGraphicsData, getDepth() ));
+ }
+
+ /**
+ * cairo::createSurface: Create generic Canvas surface using given Cairo Surface
+ *
+ * @param rSurface Cairo Surface
+ *
+ * @return new Surface
+ */
+ SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
+ {
+ return SurfaceSharedPtr(new QuartzSurface(rSurface));
+ }
+
+ /**
+ * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice
+ *
+ * @param rSurface Cairo Surface
+ *
+ * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
+ *
+ * @return new Surface
+ */
+ SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
+ int x, int y, int width, int height )
+ {
+ SurfaceSharedPtr surf;
+
+ if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
+ {
+ const Window &rWindow = (const Window &) rRefDevice;
+ const SystemEnvData* pSysData = GetSysData(&rWindow);
+ if (pSysData)
+ surf = SurfaceSharedPtr(new QuartzSurface(pSysData->pView, x, y, width, height));
+ }
+ else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
+ {
+ SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData();
+
+ if (aSysData.rCGContext)
+ surf = SurfaceSharedPtr(new QuartzSurface(aSysData.rCGContext, x, y, width, height));
+ }
+ return surf;
+ }
+
+ /**
+ * cairo::createBitmapSurface: Create platfrom native Canvas surface from BitmapSystemData
+ * @param OutputDevice (not used)
+ * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
+ * @param rSize width and height of the new surface
+ *
+ * Create a surface based on image data on rData
+ *
+ * @return new surface or empty surface
+ **/
+ SurfaceSharedPtr createBitmapSurface( const OutputDevice& /* rRefDevice */,
+ const BitmapSystemData& rData,
+ const Size& rSize )
+ {
+ OSL_TRACE( "requested size: %d x %d available size: %d x %d",
+ rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
+
+ if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
+ {
+ CGContextRef rContext = (CGContextRef)rData.rImageContext;
+ OSL_TRACE("Canvas::cairo::createBitmapSurface(): New native image surface, context = %p.", rData.rImageContext);
+
+ return SurfaceSharedPtr(new QuartzSurface(rContext, 0, 0, rData.mnWidth, rData.mnHeight));
+ }
+ return SurfaceSharedPtr();
+ }
+
+} // namespace cairo
+
+#endif // CAIRO_HAS_QUARTZ_SURFACE
+
+#endif // QUARTZ
diff --git a/canvas/source/cairo/cairo_quartz_cairo.hxx b/canvas/source/cairo/cairo_quartz_cairo.hxx
new file mode 100644
index 000000000000..104016751293
--- /dev/null
+++ b/canvas/source/cairo/cairo_quartz_cairo.hxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_QUARTZ_CAIRO_HXX
+#define _CAIROCANVAS_QUARTZ_CAIRO_HXX
+
+#include "cairo_cairo.hxx"
+
+#include "premac.h"
+#include <Cocoa/Cocoa.h>
+#include <cairo-quartz.h>
+#include "postmac.h"
+
+namespace cairo {
+
+ class QuartzSurface : public Surface
+ {
+ NSView* mpView; // if NULL - bg surface
+ CairoSurfaceSharedPtr mpSurface;
+
+ public:
+ /// takes over ownership of passed cairo_surface
+ explicit QuartzSurface( const CairoSurfaceSharedPtr& pSurface );
+
+ /// create surface on subarea of given CGContext
+ explicit QuartzSurface( CGContextRef rContext, int x, int y, int width, int height );
+
+ /// create a offscreen surface for given NSView
+ QuartzSurface( NSView* pView, int x, int y, int width, int height );
+
+ // Surface interface
+ virtual CairoSharedPtr getCairo() const;
+ virtual CairoSurfaceSharedPtr getCairoSurface() const { return mpSurface; }
+ virtual SurfaceSharedPtr getSimilar( Content aContent, int width, int height ) const;
+
+ virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const;
+
+ virtual void Resize( int width, int height );
+
+ virtual void flush() const;
+
+ int getDepth() const;
+
+ CGContextRef getCGContext() const;
+
+ };
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_repainttarget.hxx b/canvas/source/cairo/cairo_repainttarget.hxx
new file mode 100644
index 000000000000..3e4d40f1efe7
--- /dev/null
+++ b/canvas/source/cairo/cairo_repainttarget.hxx
@@ -0,0 +1,60 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_REPAINTTARGET_HXX
+#define _CAIROCANVAS_REPAINTTARGET_HXX
+
+#ifndef _RTL_REF_HXX_
+#include <rtl/ref.hxx>
+#endif
+
+#include "cairo_cairo.hxx"
+
+using namespace ::cairo;
+
+namespace cairocanvas
+{
+ /* Definition of RepaintTarget interface */
+
+ /** Target interface for XCachedPrimitive implementations
+
+ This interface must be implemented on all canvas
+ implementations that hand out XCachedPrimitives
+ */
+ class RepaintTarget
+ {
+ public:
+ virtual ~RepaintTarget() {}
+
+ // call this when a bitmap is repainted
+ virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) = 0;
+ };
+}
+
+#endif /* _CAIROCANVAS_REPAINTTARGET_HXX */
diff --git a/canvas/source/cairo/cairo_services.cxx b/canvas/source/cairo/cairo_services.cxx
new file mode 100644
index 000000000000..a43b281c56bf
--- /dev/null
+++ b/canvas/source/cairo/cairo_services.cxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <algorithm>
+
+#include "cairo_canvas.hxx"
+#include "cairo_spritecanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_< Canvas, sdecl::with_args<true> > serviceImpl1(&initCanvas);
+ const sdecl::ServiceDecl cairoCanvasDecl(
+ serviceImpl1,
+ CANVAS_IMPLEMENTATION_NAME,
+ CANVAS_SERVICE_NAME );
+
+ static uno::Reference<uno::XInterface> initSpriteCanvas( SpriteCanvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_< SpriteCanvas, sdecl::with_args<true> > serviceImpl2(&initSpriteCanvas);
+ const sdecl::ServiceDecl cairoSpriteCanvasDecl(
+ serviceImpl2,
+ SPRITECANVAS_IMPLEMENTATION_NAME,
+ SPRITECANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS2(cairocanvas::cairoCanvasDecl, cairocanvas::cairoSpriteCanvasDecl)
diff --git a/canvas/source/cairo/cairo_sprite.hxx b/canvas/source/cairo/cairo_sprite.hxx
new file mode 100644
index 000000000000..8f5a0d2d3ddd
--- /dev/null
+++ b/canvas/source/cairo/cairo_sprite.hxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SPRITE_HXX
+#define _CAIROCANVAS_SPRITE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+#include "cairo_cairo.hxx"
+
+namespace cairocanvas
+{
+ /** Specialization of ::canvas::Sprite interface, to also provide
+ redraw methods.
+ */
+ class Sprite : public ::canvas::Sprite
+ {
+ public:
+
+ /** Redraw sprite at the stored position.
+
+ @param bBufferedUpdate
+ When true, the redraw does <em>not</em> happen directly on
+ the front buffer, but within a VDev. Used to speed up
+ drawing.
+ */
+ virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
+ bool bBufferedUpdate ) const = 0;
+
+ /** Redraw sprite at the given position.
+
+ @param rPos
+ Output position of the sprite. Overrides the sprite's own
+ output position.
+
+ @param bBufferedUpdate
+ When true, the redraw does <em>not</em> happen directly on
+ the front buffer, but within a VDev. Used to speed up
+ drawing.
+ */
+ virtual void redraw( const ::cairo::CairoSharedPtr& pCairo,
+ const ::basegfx::B2DPoint& rOrigOutputPos,
+ bool bBufferedUpdate ) const = 0;
+ };
+}
+
+#endif /* _CAIROCANVAS_SPRITE_HXX */
diff --git a/canvas/source/cairo/cairo_spritecanvas.cxx b/canvas/source/cairo/cairo_spritecanvas.cxx
new file mode 100644
index 000000000000..43911c1113d6
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvas.cxx
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "cairo_spritecanvas.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void SpriteCanvas::initialize()
+ {
+ VERBOSE_TRACE("CairoSpriteCanvas created %p\n", this);
+
+ // #i64742# Only call initialize when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ /* maArguments:
+ 0: ptr to creating instance (Window or VirtualDevice)
+ 1: SystemEnvData as a streamed Any (or empty for VirtualDevice)
+ 2: current bounds of creating instance
+ 3: bool, denoting always on top state for Window (always false for VirtualDevice)
+ 4: XWindow for creating Window (or empty for VirtualDevice)
+ 5: SystemGraphicsData as a streamed Any
+ */
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 4 &&
+ maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER &&
+ maArguments[4].getValueTypeClass() == uno::TypeClass_INTERFACE,
+ "CairoSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ awt::Rectangle aRect;
+ maArguments[2] >>= aRect;
+
+ sal_Bool bIsFullscreen( sal_False );
+ maArguments[3] >>= bIsFullscreen;
+
+ uno::Reference< awt::XWindow > xParentWindow;
+ maArguments[4] >>= xParentWindow;
+
+ Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
+ if( !pParentWindow )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Parent window not VCL window, or canvas out-of-process!")),
+ NULL);
+
+ bool bHasXRender = IsCairoWorking(pParentWindow);
+ ENSURE_ARG_OR_THROW( bHasXRender == true,
+ "CairoSpriteCanvas::SpriteCanvas: No RENDER extension" );
+
+ Size aPixelSize( pParentWindow->GetOutputSizePixel() );
+ const ::basegfx::B2ISize aSize( aPixelSize.Width(),
+ aPixelSize.Height() );
+
+ ENSURE_ARG_OR_THROW( pParentWindow != NULL,
+ "CairoSpriteCanvas::initialize: invalid Window pointer" );
+
+ // setup helper
+ maDeviceHelper.init( *pParentWindow,
+ *this,
+ aSize,
+ bIsFullscreen );
+
+ setWindow(uno::Reference<awt::XWindow2>(xParentWindow, uno::UNO_QUERY_THROW));
+
+ maCanvasHelper.init( maRedrawManager,
+ *this,
+ aSize );
+
+ maArguments.realloc(0);
+ }
+
+ void SAL_CALL SpriteCanvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxComponentContext.clear();
+
+ // forward to parent
+ SpriteCanvasBaseT::disposing();
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::showBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ return updateScreen( bUpdateAll );
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::switchBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ return updateScreen( bUpdateAll );
+ }
+
+ sal_Bool SAL_CALL SpriteCanvas::updateScreen( sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // avoid repaints on hidden window (hidden: not mapped to
+ // screen). Return failure, since the screen really has _not_
+ // been updated (caller should try again later)
+ return !mbIsVisible ? false : maCanvasHelper.updateScreen(
+ ::basegfx::unotools::b2IRectangleFromAwtRectangle(maBounds),
+ bUpdateAll,
+ mbSurfaceDirty);
+ }
+
+ ::rtl::OUString SAL_CALL SpriteCanvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SPRITECANVAS_SERVICE_NAME ) );
+ }
+
+ SurfaceSharedPtr SpriteCanvas::getSurface()
+ {
+ return maDeviceHelper.getBufferSurface();
+ }
+
+ SurfaceSharedPtr SpriteCanvas::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ return maDeviceHelper.createSurface( rSize, aContent );
+ }
+
+ SurfaceSharedPtr SpriteCanvas::createSurface( ::Bitmap& rBitmap )
+ {
+ BitmapSystemData aData;
+ if( rBitmap.GetSystemData( aData ) ) {
+ const Size& rSize = rBitmap.GetSizePixel();
+
+ return maDeviceHelper.createSurface( aData, rSize );
+ }
+
+ return SurfaceSharedPtr();
+ }
+
+ SurfaceSharedPtr SpriteCanvas::changeSurface( bool, bool )
+ {
+ // non-modifiable surface here
+ return SurfaceSharedPtr();
+ }
+
+ OutputDevice* SpriteCanvas::getOutputDevice()
+ {
+ return maDeviceHelper.getOutputDevice();
+ }
+
+ SurfaceSharedPtr SpriteCanvas::getBufferSurface()
+ {
+ return maDeviceHelper.getBufferSurface();
+ }
+
+ SurfaceSharedPtr SpriteCanvas::getWindowSurface()
+ {
+ return maDeviceHelper.getWindowSurface();
+ }
+
+ const ::basegfx::B2ISize& SpriteCanvas::getSizePixel()
+ {
+ return maDeviceHelper.getSizePixel();
+ }
+
+ void SpriteCanvas::setSizePixel( const ::basegfx::B2ISize& rSize )
+ {
+ maCanvasHelper.setSize( rSize );
+ // re-set background surface, in case it needed recreation
+ maCanvasHelper.setSurface( maDeviceHelper.getBufferSurface(),
+ false );
+ }
+
+ void SpriteCanvas::flush()
+ {
+ maDeviceHelper.flush();
+ }
+
+ bool SpriteCanvas::repaint( const SurfaceSharedPtr& pSurface,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return maCanvasHelper.repaint( pSurface, viewState, renderState );
+ }
+}
diff --git a/canvas/source/cairo/cairo_spritecanvas.hxx b/canvas/source/cairo/cairo_spritecanvas.hxx
new file mode 100644
index 000000000000..fcc0ae76839b
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvas.hxx
@@ -0,0 +1,174 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SPRITECANVAS_HXX_
+#define _CAIROCANVAS_SPRITECANVAS_HXX_
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <cppuhelper/compbase9.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/spritecanvasbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/bufferedgraphicdevicebase.hxx>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include "cairo_spritedevicehelper.hxx"
+#include "cairo_repainttarget.hxx"
+#include "cairo_surfaceprovider.hxx"
+#include "cairo_spritecanvashelper.hxx"
+
+#define SPRITECANVAS_SERVICE_NAME "com.sun.star.rendering.SpriteCanvas.Cairo"
+#define SPRITECANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.SpriteCanvas.Cairo"
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::lang::XMultiServiceFactory,
+ ::com::sun::star::rendering::XBufferController,
+ ::com::sun::star::awt::XWindowListener,
+ ::com::sun::star::util::XUpdatable,
+ ::com::sun::star::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > WindowGraphicDeviceBase_Base;
+ typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::BaseMutexHelper< WindowGraphicDeviceBase_Base >,
+ SpriteDeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > SpriteCanvasBase_Base;
+ /** Mixin SpriteSurface
+
+ Have to mixin the SpriteSurface before deriving from
+ ::canvas::SpriteCanvasBase, as this template should already
+ implement some of those interface methods.
+
+ The reason why this appears kinda convoluted is the fact that
+ we cannot specify non-IDL types as WeakComponentImplHelperN
+ template args, and furthermore, don't want to derive
+ ::canvas::SpriteCanvasBase directly from
+ ::canvas::SpriteSurface (because derivees of
+ ::canvas::SpriteCanvasBase have to explicitely forward the
+ XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS)
+ anyway). Basically, ::canvas::CanvasCustomSpriteBase should
+ remain a base class that provides implementation, not to
+ enforce any specific interface on its derivees.
+ */
+ class SpriteCanvasBaseSpriteSurface_Base : public SpriteCanvasBase_Base,
+ public ::canvas::SpriteSurface,
+ public SurfaceProvider
+ {
+ };
+
+ typedef ::canvas::SpriteCanvasBase< SpriteCanvasBaseSpriteSurface_Base,
+ SpriteCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > SpriteCanvasBaseT;
+
+ /** Product of this component's factory.
+
+ The SpriteCanvas object combines the actual Window canvas with
+ the XGraphicDevice interface. This is because there's a
+ one-to-one relation between them, anyway, since each window
+ can have exactly one canvas and one associated
+ XGraphicDevice. And to avoid messing around with circular
+ references, this is implemented as one single object.
+ */
+ class SpriteCanvas : public SpriteCanvasBaseT,
+ public RepaintTarget
+ {
+ public:
+ SpriteCanvas( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Any >& aArguments,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ void initialize();
+
+#if defined __SUNPRO_CC
+ using SpriteCanvasBaseT::disposing;
+#endif
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( SpriteCanvas, WindowGraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XBufferController (partial)
+ virtual ::sal_Bool SAL_CALL showBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL switchBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XSpriteCanvas (partial)
+ virtual sal_Bool SAL_CALL updateScreen( sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // SurfaceProvider
+ virtual SurfaceSharedPtr getSurface();
+ virtual SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ virtual SurfaceSharedPtr createSurface( ::Bitmap& rBitmap );
+ virtual SurfaceSharedPtr changeSurface( bool bHasAlpha, bool bCopyContent );
+ virtual OutputDevice* getOutputDevice();
+
+ // RepaintTarget
+ virtual bool repaint( const ::cairo::SurfaceSharedPtr& pSurface,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ SurfaceSharedPtr getWindowSurface();
+ SurfaceSharedPtr getBufferSurface();
+
+ const ::basegfx::B2ISize& getSizePixel();
+ void setSizePixel( const ::basegfx::B2ISize& rSize );
+ void flush();
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ };
+
+ typedef ::rtl::Reference< SpriteCanvas > SpriteCanvasRef;
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_spritecanvashelper.cxx b/canvas/source/cairo/cairo_spritecanvashelper.cxx
new file mode 100644
index 000000000000..bb4b44201043
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvashelper.cxx
@@ -0,0 +1,544 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/canvastools.hxx>
+
+#include <comphelper/scopeguard.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/cast.hpp>
+
+#include "cairo_spritecanvashelper.hxx"
+#include "cairo_canvascustomsprite.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ namespace
+ {
+ /** Sprite redraw at original position
+
+ Used to repaint the whole canvas (background and all
+ sprites)
+ */
+ void spriteRedraw( const CairoSharedPtr& pCairo,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ // downcast to derived cairocanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw( pCairo, true);
+ }
+
+ void repaintBackground( const CairoSharedPtr& pCairo,
+ const SurfaceSharedPtr& pBackgroundSurface,
+ const ::basegfx::B2DRange& rArea )
+ {
+ cairo_save( pCairo.get() );
+ cairo_rectangle( pCairo.get(), ceil( rArea.getMinX() ), ceil( rArea.getMinY() ),
+ floor( rArea.getWidth() ), floor( rArea.getHeight() ) );
+ cairo_clip( pCairo.get() );
+ cairo_set_source_surface( pCairo.get(), pBackgroundSurface->getCairoSurface().get(), 0, 0 );
+ cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pCairo.get() );
+ cairo_restore( pCairo.get() );
+ }
+
+ void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
+ const CairoSharedPtr& pCairo,
+ const ::basegfx::B2IRange& rArea )
+ {
+ // clip output to actual update region (otherwise a)
+ // wouldn't save much render time, and b) will clutter
+ // scrolled sprite content outside this area)
+ cairo_save( pCairo.get() );
+ cairo_rectangle( pCairo.get(), rArea.getMinX(), rArea.getMinY(),
+ sal::static_int_cast<sal_Int32>(rArea.getWidth()),
+ sal::static_int_cast<sal_Int32>(rArea.getHeight()) );
+ cairo_clip( pCairo.get() );
+
+ // repaint affected sprite directly to output device (at
+ // the actual screen output position)
+ // rendering directly to device buffer
+ ::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, false );
+
+ cairo_restore( pCairo.get() );
+ }
+
+ /** Repaint sprite at original position
+
+ Used for opaque updates, which render directly to the
+ device buffer.
+ */
+ void spriteRedrawStub( const CairoSharedPtr& pCairo,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ ::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, false );
+ }
+ }
+
+ /** Repaint sprite at given position
+
+ Used for generic update, which renders into device buffer.
+ */
+ void spriteRedrawStub2( const CairoSharedPtr& pCairo,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ ::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, true );;
+ }
+ }
+
+ /** Repaint sprite at original position
+
+ Used for opaque updates from scrollUpdate(), which render
+ directly to the front buffer.
+ */
+ void spriteRedrawStub3( const CairoSharedPtr& pCairo,
+ const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
+ {
+ const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
+
+ if( rSprite.is() )
+ ::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, false );
+ }
+ }
+
+ SpriteCanvasHelper::SpriteCanvasHelper() :
+ mpRedrawManager( NULL ),
+ mpOwningSpriteCanvas( NULL ),
+ mpCompositingSurface(),
+ maCompositingSurfaceSize()
+ {
+ }
+
+ void SpriteCanvasHelper::init( ::canvas::SpriteRedrawManager& rManager,
+ SpriteCanvas& rDevice,
+ const ::basegfx::B2ISize& rSize )
+ {
+ mpRedrawManager = &rManager;
+ mpOwningSpriteCanvas = &rDevice;
+
+ CanvasHelper::init( rSize, rDevice, &rDevice );
+ }
+
+ void SpriteCanvasHelper::disposing()
+ {
+ mpCompositingSurface.reset();
+ mpOwningSpriteCanvas = NULL;
+ mpRedrawManager = NULL;
+
+ // forward to base
+ CanvasHelper::disposing();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
+ const uno::Reference< rendering::XAnimation >& )
+ {
+ return uno::Reference< rendering::XAnimatedSprite >();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
+ const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/,
+ sal_Int8 /*interpolationMode*/ )
+ {
+ return uno::Reference< rendering::XAnimatedSprite >();
+ }
+
+ uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
+ {
+ if( !mpRedrawManager )
+ return uno::Reference< rendering::XCustomSprite >(); // we're disposed
+
+ return uno::Reference< rendering::XCustomSprite >(
+ new CanvasCustomSprite( spriteSize,
+ mpOwningSpriteCanvas ) );
+ }
+
+ uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite(
+ const uno::Reference< rendering::XSprite >& )
+ {
+ return uno::Reference< rendering::XSprite >();
+ }
+
+ sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRange& /*rCurrArea*/,
+ sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty )
+ {
+ if( !mpRedrawManager ||
+ !mpOwningSpriteCanvas ||
+ !mpOwningSpriteCanvas->getWindowSurface() ||
+ !mpOwningSpriteCanvas->getBufferSurface() )
+ {
+ return sal_False; // disposed, or otherwise dysfunctional
+ }
+
+ OSL_TRACE("SpriteCanvasHelper::updateScreen called");
+
+ const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
+
+ // force compositing surface to be available before using it
+ // inside forEachSpriteArea
+ SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
+ SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
+ CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
+ CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
+
+ // TODO(P1): Might be worthwile to track areas of background
+ // changes, too.
+ if( !bUpdateAll && !io_bSurfaceDirty )
+ {
+ // background has not changed, so we're free to optimize
+ // repaint to areas where a sprite has changed
+
+ // process each independent area of overlapping sprites
+ // separately.
+ mpRedrawManager->forEachSpriteArea( *this );
+ }
+ else
+ {
+ OSL_TRACE("SpriteCanvasHelper::updateScreen update ALL");
+
+ // background has changed, so we currently have no choice
+ // but repaint everything (or caller requested that)
+
+ cairo_rectangle( pCompositingCairo.get(), 0, 0, rSize.getX(), rSize.getY() );
+ cairo_clip( pCompositingCairo.get() );
+ cairo_save( pCompositingCairo.get() );
+ cairo_set_source_surface( pCompositingCairo.get(),
+ mpOwningSpriteCanvas->getBufferSurface()->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pCompositingCairo.get() );
+ cairo_restore( pCompositingCairo.get() );
+
+ // repaint all active sprites on top of background into
+ // VDev.
+ mpRedrawManager->forEachSprite(
+ ::boost::bind(
+ &spriteRedraw,
+ boost::cref(pCompositingCairo),
+ _1 ) );
+
+ // flush to screen
+ cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getX(), rSize.getY() );
+ cairo_clip( pWindowCairo.get() );
+ cairo_set_source_surface( pWindowCairo.get(),
+ pCompositingSurface->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pWindowCairo.get() );
+ }
+
+ // change record vector must be cleared, for the next turn of
+ // rendering and sprite changing
+ mpRedrawManager->clearChangeRecords();
+
+ io_bSurfaceDirty = false;
+
+ // commit to screen
+ mpOwningSpriteCanvas->flush();
+
+ return sal_True;
+ }
+
+ void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
+ {
+ if( mpOwningSpriteCanvas && mpCompositingSurface )
+ repaintBackground( mpCompositingSurface->getCairo(),
+ mpOwningSpriteCanvas->getBufferSurface(),
+ rUpdateRect );
+ }
+
+ void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
+ {
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBufferSurface(),
+ "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
+
+ OSL_TRACE("SpriteCanvasHelper::scrollUpdate called");
+
+ const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
+ const ::basegfx::B2IRange aOutputBounds( 0,0,
+ rSize.getX(),
+ rSize.getY() );
+
+ SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
+ SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
+ CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
+ CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
+
+ // round rectangles to integer pixel. Note: have to be
+ // extremely careful here, to avoid off-by-one errors for
+ // the destination area: otherwise, the next scroll update
+ // would copy pixel that are not supposed to be part of
+ // the sprite.
+ ::basegfx::B2IRange aSourceRect(
+ ::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) );
+ const ::basegfx::B2IRange& rDestRect(
+ ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
+ ::basegfx::B2IPoint aDestPos( rDestRect.getMinimum() );
+
+ ::std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
+
+ // TODO(E3): This is plain buggy (but copies the behaviour of
+ // the old Impress slideshow) - the scrolled area might
+ // actually lie _below_ another window!
+
+ // clip to output bounds (cannot properly scroll stuff
+ // _outside_ our screen area)
+ if( !::canvas::tools::clipScrollArea( aSourceRect,
+ aDestPos,
+ aUnscrollableAreas,
+ aOutputBounds ) )
+ {
+ // fully clipped scroll area: cannot simply scroll
+ // then. Perform normal opaque update (can use that, since
+ // one of the preconditions for scrollable update is
+ // opaque sprite content)
+
+ // repaint all affected sprites directly to output device
+ ::std::for_each( rUpdateArea.maComponentList.begin(),
+ rUpdateArea.maComponentList.end(),
+ ::boost::bind(
+ &spriteRedrawStub3,
+ boost::cref(pCompositingCairo),
+ _1 ) );
+ }
+ else
+ {
+ const ::basegfx::B2IVector aSourceUpperLeftPos( aSourceRect.getMinimum() );
+
+ // clip dest area (which must be inside rDestBounds)
+ ::basegfx::B2IRange aDestRect( rDestRect );
+ aDestRect.intersect( aOutputBounds );
+
+ cairo_save( pCompositingCairo.get() );
+ // scroll content in device back buffer
+ cairo_set_source_surface( pCompositingCairo.get(),
+ mpOwningSpriteCanvas->getBufferSurface()->getCairoSurface().get(),
+ aDestPos.getX() - aSourceUpperLeftPos.getX(),
+ aDestPos.getY() - aSourceUpperLeftPos.getY() );
+ cairo_rectangle( pCompositingCairo.get(),
+ aDestPos.getX(), aDestPos.getY(),
+ sal::static_int_cast<sal_Int32>(aDestRect.getWidth()),
+ sal::static_int_cast<sal_Int32>(aDestRect.getHeight()) );
+ cairo_clip( pCompositingCairo.get() );
+ cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pCompositingCairo.get() );
+ cairo_restore( pCompositingCairo.get() );
+
+ const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
+ aFirst( rUpdateArea.maComponentList.begin() );
+ ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
+ aSecond( aFirst ); ++aSecond;
+
+ ENSURE_OR_THROW( aFirst->second.getSprite().is(),
+ "VCLCanvas::scrollUpdate(): no sprite" );
+
+ // repaint uncovered areas from sprite. Need to actually
+ // clip here, since we're only repainting _parts_ of the
+ // sprite
+ ::std::for_each( aUnscrollableAreas.begin(),
+ aUnscrollableAreas.end(),
+ ::boost::bind( &opaqueUpdateSpriteArea,
+ ::boost::cref(aFirst->second.getSprite()),
+ boost::cref(pCompositingCairo),
+ _1 ) );
+ }
+
+ // repaint uncovered areas from backbuffer - take the
+ // _rounded_ rectangles from above, to have the update
+ // consistent with the scroll above.
+ ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
+ ::basegfx::computeSetDifference( aUncoveredAreas,
+ rUpdateArea.maTotalBounds,
+ ::basegfx::B2DRange( rDestRect ) );
+ ::std::for_each( aUncoveredAreas.begin(),
+ aUncoveredAreas.end(),
+ ::boost::bind( &repaintBackground,
+ boost::cref(pCompositingCairo),
+ boost::cref(mpOwningSpriteCanvas->getBufferSurface()),
+ _1 ) );
+
+ cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getX(), rSize.getY() );
+ cairo_clip( pWindowCairo.get() );
+ cairo_set_source_surface( pWindowCairo.get(),
+ pCompositingSurface->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pWindowCairo.get() );
+ }
+
+ void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBufferSurface(),
+ "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
+
+ OSL_TRACE("SpriteCanvasHelper::opaqueUpdate called");
+
+ const ::basegfx::B2ISize& rDeviceSize = mpOwningSpriteCanvas->getSizePixel();
+
+ SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rDeviceSize);
+ SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
+ CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
+ CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
+
+ cairo_rectangle( pCompositingCairo.get(), 0, 0, rDeviceSize.getX(), rDeviceSize.getY() );
+ cairo_clip( pCompositingCairo.get() );
+
+ ::basegfx::B2DVector aPos( ceil( rTotalArea.getMinX() ), ceil( rTotalArea.getMinY() ) );
+ ::basegfx::B2DVector aSize( floor( rTotalArea.getMaxX() - aPos.getX() ), floor( rTotalArea.getMaxY() - aPos.getY() ) );
+
+ cairo_rectangle( pCompositingCairo.get(), aPos.getX(), aPos.getY(), aSize.getX(), aSize.getY() );
+ cairo_clip( pCompositingCairo.get() );
+
+ // repaint all affected sprites directly to output device
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::boost::bind(
+ &spriteRedrawStub,
+ boost::cref(pCompositingCairo),
+ _1 ) );
+
+ // flush to screen
+ cairo_rectangle( pWindowCairo.get(), 0, 0, rDeviceSize.getX(), rDeviceSize.getY() );
+ cairo_clip( pWindowCairo.get() );
+ cairo_rectangle( pWindowCairo.get(), aPos.getX(), aPos.getY(), aSize.getX(), aSize.getY() );
+ cairo_clip( pWindowCairo.get() );
+ cairo_set_source_surface( pWindowCairo.get(),
+ pCompositingSurface->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pWindowCairo.get() );
+ }
+
+ void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rRequestedArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ // TODO
+ OSL_TRACE("SpriteCanvasHelper::genericUpdate called");
+
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBufferSurface(),
+ "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
+
+ // limit size of update VDev to target outdev's size
+ const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel();
+
+ SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
+ SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
+ CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
+ CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
+
+ // round output position towards zero. Don't want to truncate
+ // a fraction of a sprite pixel... Clip position at origin,
+ // otherwise, truncation of size below might leave visible
+ // areas uncovered by VDev.
+ const Point aOutputPosition(
+ ::std::max( sal_Int32( 0 ),
+ static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
+ ::std::max( sal_Int32( 0 ),
+ static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
+ // round output size towards +infty. Don't want to truncate a
+ // fraction of a sprite pixel... Limit size of VDev to output
+ // device's area.
+ const Size aOutputSize(
+ ::std::min( rSize.getX(),
+ ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X()) ),
+ ::std::min( rSize.getY(),
+ ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y()) ) );
+
+ cairo_rectangle( pCompositingCairo.get(), aOutputPosition.X(), aOutputPosition.Y(), aOutputSize.Width(), aOutputSize.Height() );
+ cairo_clip( pCompositingCairo.get() );
+
+ // paint background
+ cairo_save( pCompositingCairo.get() );
+ cairo_set_source_surface( pCompositingCairo.get(),
+ mpOwningSpriteCanvas->getBufferSurface()->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pCompositingCairo.get() );
+ cairo_restore( pCompositingCairo.get() );
+
+ // repaint all affected sprites on top of background into
+ // VDev.
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::boost::bind( &spriteRedrawStub2,
+ boost::cref(pCompositingCairo),
+ _1 ) );
+
+ // flush to screen
+ cairo_rectangle( pWindowCairo.get(), aOutputPosition.X(), aOutputPosition.Y(), aOutputSize.Width(), aOutputSize.Height() );
+ cairo_clip( pWindowCairo.get() );
+ cairo_set_source_surface( pWindowCairo.get(),
+ pCompositingSurface->getCairoSurface().get(),
+ 0, 0 );
+ cairo_set_operator( pWindowCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_paint( pWindowCairo.get() );
+ }
+
+ ::cairo::SurfaceSharedPtr SpriteCanvasHelper::getCompositingSurface( const ::basegfx::B2ISize& rNeededSize )
+ {
+ if( rNeededSize.getX() < maCompositingSurfaceSize.getX() ||
+ rNeededSize.getY() < maCompositingSurfaceSize.getY() )
+ {
+ // need to give buffer more size
+ mpCompositingSurface.reset();
+ }
+
+ if( !mpCompositingSurface )
+ {
+ mpCompositingSurface =
+ mpOwningSpriteCanvas->getWindowSurface()->getSimilar(
+ CAIRO_CONTENT_COLOR,
+ rNeededSize.getX(), rNeededSize.getY() );
+ maCompositingSurfaceSize = rNeededSize;
+ }
+
+ return mpCompositingSurface;
+ }
+}
diff --git a/canvas/source/cairo/cairo_spritecanvashelper.hxx b/canvas/source/cairo/cairo_spritecanvashelper.hxx
new file mode 100644
index 000000000000..2adc245fe4e1
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvashelper.hxx
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SPRITECANVASHELPER_HXX_
+#define _CAIROCANVAS_SPRITECANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <canvas/spriteredrawmanager.hxx>
+
+#include "cairo_cairo.hxx"
+#include "cairo_canvashelper.hxx"
+
+namespace basegfx
+{
+ class B2IRange;
+}
+
+namespace cairocanvas
+{
+ class SpriteCanvas;
+
+ class SpriteCanvasHelper : public CanvasHelper
+ {
+ public:
+ SpriteCanvasHelper();
+
+ void init( ::canvas::SpriteRedrawManager& rManager,
+ SpriteCanvas& rOwningSpriteCanvas,
+ const ::basegfx::B2ISize& rSize );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // XSpriteCanvas
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XAnimatedSprite > createSpriteFromAnimation(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimation >& animation );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XAnimatedSprite > createSpriteFromBitmaps(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > >& animationBitmaps,
+ sal_Int8 interpolationMode );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCustomSprite > createCustomSprite(
+ const ::com::sun::star::geometry::RealSize2D& spriteSize );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSprite > createClonedSprite(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite >& original );
+
+ /** Actually perform the screen update
+
+ @param rCurrArea
+ Current window area in absolute screen coordinates
+
+ @param bUpdateAll
+ sal_True, if everything must be updated, not only changed
+ sprites
+
+ @param io_bSurfaceDirty
+ In/out parameter, whether backbuffer surface is dirty (if
+ yes, we're performing a full update, anyway)
+ */
+ sal_Bool updateScreen( const ::basegfx::B2IRange& rCurrArea,
+ sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty );
+
+
+ // SpriteRedrawManager functor calls
+ // -------------------------------------------------
+
+ /** Gets called for simple background repaints
+ */
+ void backgroundPaint( const ::basegfx::B2DRange& rUpdateRect );
+
+ /** Gets called when area can be handled by scrolling.
+
+ Called method must copy screen content from rMoveStart to
+ rMoveEnd, and restore the background in the uncovered
+ areas.
+
+ @param rMoveStart
+ Source rect of the scroll
+
+ @param rMoveEnd
+ Dest rect of the scroll
+
+ @param rUpdateArea
+ All info necessary, should rMoveStart be partially or
+ fully outside the outdev
+ */
+ void scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
+
+ void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
+
+ void genericUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
+
+ private:
+ ::cairo::SurfaceSharedPtr getCompositingSurface( const ::basegfx::B2ISize& rNeededSize );
+
+ /// Set from the SpriteCanvas: instance coordinating sprite redraw
+ ::canvas::SpriteRedrawManager* mpRedrawManager;
+
+ /// Set from the init method. used to generate sprites
+ SpriteCanvas* mpOwningSpriteCanvas;
+
+ /// a temporary surface used to composite the frontbuffer image
+ ::cairo::SurfaceSharedPtr mpCompositingSurface;
+ ::basegfx::B2ISize maCompositingSurfaceSize;
+ };
+}
+
+#endif /* _CAIROCANVAS_SPRITECANVASHELPER_HXX_ */
+
diff --git a/canvas/source/cairo/cairo_spritedevicehelper.cxx b/canvas/source/cairo/cairo_spritedevicehelper.cxx
new file mode 100644
index 000000000000..ef345cd60eaf
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritedevicehelper.cxx
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include <vcl/syschild.hxx>
+#include <vcl/canvastools.hxx>
+
+#include "cairo_spritecanvas.hxx"
+#include "cairo_canvasbitmap.hxx"
+#include "cairo_devicehelper.hxx"
+#include "cairo_cairo.hxx"
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+
+ SpriteDeviceHelper::SpriteDeviceHelper() :
+ mpSpriteCanvas( NULL ),
+ mpBufferSurface(),
+ maSize(),
+ mbFullScreen( false )
+ {}
+
+ void SpriteDeviceHelper::init( Window& rOutputWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const ::basegfx::B2ISize& rSize,
+ bool bFullscreen )
+ {
+ DeviceHelper::init(rSpriteCanvas,
+ rOutputWindow);
+
+ mpSpriteCanvas = &rSpriteCanvas;
+ mbFullScreen = bFullscreen;
+
+ setSize( rSize );
+ }
+
+ void SpriteDeviceHelper::disposing()
+ {
+ // release all references
+ mpBufferSurface.reset();
+ mpSpriteCanvas = NULL;
+ }
+
+ ::sal_Int32 SpriteDeviceHelper::createBuffers( ::sal_Int32 /*nBuffers*/ )
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ return 1;
+ }
+
+ void SpriteDeviceHelper::destroyBuffers()
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ }
+
+ ::sal_Bool SpriteDeviceHelper::showBuffer( bool, ::sal_Bool )
+ {
+ OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
+ return sal_False;
+ }
+
+ ::sal_Bool SpriteDeviceHelper::switchBuffer( bool, ::sal_Bool )
+ {
+ OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
+ return sal_False;
+ }
+
+ uno::Any SpriteDeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(true);
+ }
+
+ uno::Any SpriteDeviceHelper::getDeviceHandle() const
+ {
+ return DeviceHelper::getDeviceHandle();
+ }
+
+ uno::Any SpriteDeviceHelper::getSurfaceHandle() const
+ {
+ return DeviceHelper::getSurfaceHandle();
+ }
+
+ void SpriteDeviceHelper::setSize( const ::basegfx::B2ISize& rSize )
+ {
+ OSL_TRACE("SpriteDeviceHelper::setSize(): device size %d x %d", rSize.getX(), rSize.getY() );
+
+ if( !mpSpriteCanvas )
+ return; // disposed
+
+ DeviceHelper::setSize(rSize);
+
+ if( mpBufferSurface && maSize != rSize )
+ mpBufferSurface.reset();
+ if( !mpBufferSurface )
+ mpBufferSurface = getWindowSurface()->getSimilar(
+ CAIRO_CONTENT_COLOR,
+ rSize.getX(), rSize.getY() );
+
+ if( maSize != rSize )
+ maSize = rSize;
+
+ mpSpriteCanvas->setSizePixel( maSize );
+ }
+
+ const ::basegfx::B2ISize& SpriteDeviceHelper::getSizePixel()
+ {
+ return maSize;
+ }
+
+ void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
+ {
+ setSize( ::basegfx::B2ISize(rBounds.Width, rBounds.Height) );
+ }
+
+ SurfaceSharedPtr SpriteDeviceHelper::getSurface()
+ {
+ return mpBufferSurface;
+ }
+
+ SurfaceSharedPtr SpriteDeviceHelper::getBufferSurface()
+ {
+ return mpBufferSurface;
+ }
+
+ SurfaceSharedPtr SpriteDeviceHelper::getWindowSurface()
+ {
+ return DeviceHelper::getSurface();
+ }
+
+ SurfaceSharedPtr SpriteDeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
+ {
+ if( mpBufferSurface )
+ return mpBufferSurface->getSimilar( aContent, rSize.getX(), rSize.getY() );
+
+ return SurfaceSharedPtr();
+ }
+
+ SurfaceSharedPtr SpriteDeviceHelper::createSurface( BitmapSystemData& rData, const Size& rSize )
+ {
+ if( getOutputDevice() )
+ return createBitmapSurface( *getOutputDevice(), rData, rSize );
+
+ return SurfaceSharedPtr();
+ }
+
+
+ /** SpriteDeviceHelper::flush Flush the platform native window
+ *
+ * Flushes the window by using the internally stored mpSysData.
+ *
+ **/
+ void SpriteDeviceHelper::flush()
+ {
+ SurfaceSharedPtr pWinSurface=getWindowSurface();
+ if( pWinSurface )
+ pWinSurface->flush();
+ }
+}
diff --git a/canvas/source/cairo/cairo_spritedevicehelper.hxx b/canvas/source/cairo/cairo_spritedevicehelper.hxx
new file mode 100644
index 000000000000..3e46014f28b0
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritedevicehelper.hxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SPRITEDEVICEHELPER_HXX
+#define _CAIROCANVAS_SPRITEDEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <boost/utility.hpp>
+
+#include <vcl/window.hxx>
+#include <vcl/bitmap.hxx>
+
+#include "cairo_cairo.hxx"
+#include "cairo_devicehelper.hxx"
+
+/* Definition of DeviceHelper class */
+
+namespace cairocanvas
+{
+ class SpriteCanvas;
+ class SpriteCanvasHelper;
+
+ class SpriteDeviceHelper : public DeviceHelper
+ {
+ public:
+ SpriteDeviceHelper();
+
+ void init( Window& rOutputWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const ::basegfx::B2ISize& rSize,
+ bool bFullscreen );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // XWindowGraphicDevice
+ ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
+ void destroyBuffers( );
+ ::sal_Bool showBuffer( bool, ::sal_Bool );
+ ::sal_Bool switchBuffer( bool, ::sal_Bool bUpdateAll );
+
+ ::com::sun::star::uno::Any isAccelerated() const;
+ ::com::sun::star::uno::Any getDeviceHandle() const;
+ ::com::sun::star::uno::Any getSurfaceHandle() const;
+
+ void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
+ void setSize( const ::basegfx::B2ISize& rSize );
+
+ ::cairo::SurfaceSharedPtr getSurface();
+ ::cairo::SurfaceSharedPtr getBufferSurface();
+ ::cairo::SurfaceSharedPtr getWindowSurface();
+ ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, ::cairo::Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
+ ::cairo::SurfaceSharedPtr createSurface( BitmapSystemData& rData, const Size& rSize );
+ const ::basegfx::B2ISize& getSizePixel();
+ void flush();
+
+ private:
+ /// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
+ SpriteCanvas* mpSpriteCanvas;
+
+ ::cairo::SurfaceSharedPtr mpBufferSurface;
+
+ ::basegfx::B2ISize maSize;
+ bool mbFullScreen;
+ };
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_spritehelper.cxx b/canvas/source/cairo/cairo_spritehelper.cxx
new file mode 100644
index 000000000000..a3ba84648f3b
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritehelper.cxx
@@ -0,0 +1,183 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
+
+#include "cairo_canvascustomsprite.hxx"
+#include "cairo_spritehelper.hxx"
+
+#include <memory>
+
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ SpriteHelper::SpriteHelper() :
+ mpSpriteCanvas(),
+ mpBufferSurface(),
+ mbTextureDirty(true)
+ {}
+
+ void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rSpriteCanvas )
+ {
+ ENSURE_OR_THROW( rSpriteCanvas.get(),
+ "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
+
+ mpSpriteCanvas = rSpriteCanvas;
+ mbTextureDirty = true;
+
+ // also init base class
+ CanvasCustomSpriteHelper::init( rSpriteSize,
+ rSpriteCanvas.get() );
+ }
+
+ void SpriteHelper::setSurface( const SurfaceSharedPtr& pBufferSurface )
+ {
+ mpBufferSurface = pBufferSurface;
+ }
+
+ void SpriteHelper::disposing()
+ {
+ mpBufferSurface.reset();
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteHelper::disposing();
+ }
+
+ void SpriteHelper::redraw( const CairoSharedPtr& pCairo,
+ const ::basegfx::B2DPoint& rPos,
+ bool& /*io_bSurfacesDirty*/,
+ bool /*bBufferedUpdate*/ ) const
+ {
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
+
+ const double fAlpha( getAlpha() );
+ const ::basegfx::B2DHomMatrix aTransform( getTransformation() );
+
+ if( isActive() && !::basegfx::fTools::equalZero( fAlpha ) ) {
+ OSL_TRACE ("CanvasCustomSprite::redraw called");
+ if( pCairo ) {
+ basegfx::B2DVector aSize = getSizePixel();
+ cairo_save( pCairo.get() );
+
+ double fX, fY;
+
+ fX = rPos.getX();
+ fY = rPos.getY();
+
+ if( !aTransform.isIdentity() ) {
+ cairo_matrix_t aMatrix, aInverseMatrix;
+ cairo_matrix_init( &aMatrix,
+ aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ),
+ aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) );
+
+ aMatrix.x0 = basegfx::fround( aMatrix.x0 );
+ aMatrix.y0 = basegfx::fround( aMatrix.y0 );
+
+ cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 );
+ cairo_matrix_invert( &aInverseMatrix );
+ cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY );
+
+ cairo_set_matrix( pCairo.get(), &aMatrix );
+ }
+
+ fX = basegfx::fround( fX );
+ fY = basegfx::fround( fY );
+
+ cairo_matrix_t aOrigMatrix;
+ cairo_get_matrix( pCairo.get(), &aOrigMatrix );
+ cairo_translate( pCairo.get(), fX, fY );
+
+ if( getClip().is() )
+ {
+ const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() );
+
+ ::basegfx::B2DPolyPolygon aClipPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
+ rClip ));
+
+ doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(),
+ NULL, SurfaceProviderRef(mpSpriteCanvas.get()),
+ rClip->getFillRule() );
+ }
+
+ OSL_TRACE ("aSize %f x %f position: %f,%f", aSize.getX(), aSize.getY(), fX, fY );
+ cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) );
+ cairo_clip( pCairo.get() );
+ cairo_set_matrix( pCairo.get(), &aOrigMatrix );
+
+ if( isContentFullyOpaque() )
+ cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
+ cairo_set_source_surface( pCairo.get(),
+ mpBufferSurface->getCairoSurface().get(),
+ fX, fY );
+ if( ::rtl::math::approxEqual( fAlpha, 1.0 ) )
+ cairo_paint( pCairo.get() );
+ else
+ cairo_paint_with_alpha( pCairo.get(), fAlpha );
+
+ cairo_restore( pCairo.get() );
+ }
+ }
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "sprite redraw" );
+#endif
+ }
+
+ ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
+ {
+ return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPoly);
+ }
+}
diff --git a/canvas/source/cairo/cairo_spritehelper.hxx b/canvas/source/cairo/cairo_spritehelper.hxx
new file mode 100644
index 000000000000..0d770e25003e
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritehelper.hxx
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SPRITEHELPER_HXX
+#define _CAIROCANVAS_SPRITEHELPER_HXX
+
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+
+#include <canvas/base/canvascustomspritehelper.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include "cairo_spritecanvas.hxx"
+
+
+namespace cairocanvas
+{
+ /* Definition of SpriteHelper class */
+
+ /** Helper class for canvas sprites.
+
+ This class implements all sprite-related functionality, like
+ that available on the XSprite interface.
+ */
+ class SpriteHelper : public ::canvas::CanvasCustomSpriteHelper
+ {
+ public:
+ /** Create sprite helper
+ */
+ SpriteHelper();
+
+ /** Late-init the sprite helper
+
+ @param rSpriteSize
+ Size of the sprite
+
+ @param rSpriteCanvas
+ Sprite canvas this sprite is part of. Object stores
+ ref-counted reference to it, thus, don't forget to pass on
+ disposing()!
+
+ @param rDevice
+ DX device to use
+
+ @param rSpriteSurface
+ The surface of the sprite (not the DX texture, but the
+ persistent target of content rendering)
+
+ @param bShowSpriteBounds
+ When true, little debug bound rects for sprites are shown
+ */
+ void init( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rSpriteCanvas );
+
+ void disposing();
+
+ void setSurface( const ::cairo::SurfaceSharedPtr& pBufferSurface );
+
+ /** Repaint sprite content to associated sprite canvas
+
+ @param rPos
+ Output position (sprite's own position is disregarded)
+
+ @param io_bSurfacesDirty
+ When true, the referenced sprite surfaces (backBuffer and
+ backBufferMask) have been modified since last call.
+
+ @param bBufferedUpdate
+ When true, the redraw does <em>not</em> happen directly on
+ the front buffer, but within a VDev. Used to speed up
+ drawing.
+ */
+ void redraw( const ::cairo::CairoSharedPtr& pCairo,
+ const ::basegfx::B2DPoint& rPos,
+ bool& bSurfacesDirty,
+ bool bBufferedUpdate ) const;
+
+ private:
+ virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPoly ) const;
+
+
+ SpriteCanvasRef mpSpriteCanvas;
+ ::cairo::SurfaceSharedPtr mpBufferSurface;
+ mutable bool mbTextureDirty; // when true, texture needs update
+ };
+}
+
+#endif /* _CAIROCANVAS_SPRITEHELPER_HXX */
diff --git a/canvas/source/cairo/cairo_spritesurface.hxx b/canvas/source/cairo/cairo_spritesurface.hxx
new file mode 100644
index 000000000000..343d51e5d816
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritesurface.hxx
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _VCLCANVAS_SPRITESURFACE_HXX
+#define _VCLCANVAS_SPRITESURFACE_HXX
+
+#include <sal/config.h>
+
+#include "cairo_sprite.hxx"
+
+class Point;
+class Size;
+class Rectangle;
+
+namespace cairocanvas
+{
+ /* Definition of SpriteSurface interface */
+
+ class SpriteSurface
+ {
+ public:
+ virtual ~SpriteSurface() {}
+
+ // call this when XSprite::show() is called
+ virtual void showSprite( const Sprite::ImplRef& sprite ) = 0;
+
+ // call this when XSprite::hide() is called
+ virtual void hideSprite( const Sprite::ImplRef& sprite ) = 0;
+
+ // call this when XSprite::move() is called
+ virtual void moveSprite( const Sprite::ImplRef& sprite,
+ const Point& rOldPos,
+ const Point& rNewPos,
+ const Size& rSpriteSize ) = 0;
+
+ // call this when some part of your sprite has changed. That
+ // includes show/hide´, i.e. for show, both showSprite and
+ // updateSprite must be called.
+ virtual void updateSprite( const Sprite::ImplRef& sprite,
+ const Point& rPos,
+ const Rectangle& rUpdateArea ) = 0;
+
+ };
+}
+
+#endif /* _VCLCANVAS_SPRITESURFACE_HXX */
diff --git a/canvas/source/cairo/cairo_surfaceprovider.hxx b/canvas/source/cairo/cairo_surfaceprovider.hxx
new file mode 100644
index 000000000000..a6ec53be333f
--- /dev/null
+++ b/canvas/source/cairo/cairo_surfaceprovider.hxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_SURFACEPROVIDER_HXX
+#define _CAIROCANVAS_SURFACEPROVIDER_HXX
+
+#include <rtl/ref.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+
+#include "cairo_cairo.hxx"
+
+using namespace ::cairo;
+
+class OutputDevice;
+class Bitmap;
+
+namespace cairocanvas
+{
+ class Bitmap;
+
+ /* Definition of RepaintTarget interface */
+
+ /** Target interface for XCachedPrimitive implementations
+
+ This interface must be implemented on all canvas
+ implementations that hand out XCachedPrimitives
+ */
+ class SurfaceProvider : public ::com::sun::star::uno::XInterface
+ {
+ public:
+ virtual ~SurfaceProvider() {}
+
+ /** Query surface from this provider
+
+ This should return the default surface to render on.
+ */
+ virtual SurfaceSharedPtr getSurface() = 0;
+
+ /// create new surface in given size
+ virtual SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize,
+ Content aContent = CAIRO_CONTENT_COLOR_ALPHA ) = 0;
+ /// create new surface from given bitmap
+ virtual SurfaceSharedPtr createSurface( ::Bitmap& rBitmap ) = 0;
+
+ /** convert surface between alpha and non-alpha
+ channel. returns new surface on success, NULL otherwise
+ */
+ virtual SurfaceSharedPtr changeSurface( bool bHasAlpha, bool bCopyContent ) = 0;
+
+ /** Provides the underlying vcl outputdevice this surface renders on
+ */
+ virtual OutputDevice* getOutputDevice() = 0;
+ };
+
+ typedef ::rtl::Reference< SurfaceProvider > SurfaceProviderRef;
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx
new file mode 100644
index 000000000000..d0873b63f5f0
--- /dev/null
+++ b/canvas/source/cairo/cairo_textlayout.cxx
@@ -0,0 +1,656 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <math.h>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/metric.hxx>
+#include <vcl/virdev.hxx>
+
+#ifdef WNT
+#include <tools/prewin.h>
+#include <windows.h>
+#include <tools/postwin.h>
+#ifdef max
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+#endif
+#include <vcl/sysdata.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/scoped_array.hpp>
+
+#include "cairo_textlayout.hxx"
+#include "cairo_spritecanvas.hxx"
+
+#ifdef CAIRO_HAS_QUARTZ_SURFACE
+# include "cairo_quartz_cairo.hxx"
+#elif defined CAIRO_HAS_WIN32_SURFACE
+# include "cairo_win32_cairo.hxx"
+# include <cairo-win32.h>
+#elif defined CAIRO_HAS_XLIB_SURFACE
+# include "cairo_xlib_cairo.hxx"
+# include <cairo-ft.h>
+#else
+# error Native API needed.
+#endif
+
+using namespace ::cairo;
+using namespace ::com::sun::star;
+
+namespace cairocanvas
+{
+ namespace
+ {
+ void setupLayoutMode( OutputDevice& rOutDev,
+ sal_Int8 nTextDirection )
+ {
+ // TODO(P3): avoid if already correctly set
+ ULONG nLayoutMode;
+ switch( nTextDirection )
+ {
+ default:
+ nLayoutMode = 0;
+ break;
+ case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
+ nLayoutMode = TEXT_LAYOUT_BIDI_LTR;
+ break;
+ case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
+ nLayoutMode = TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG;
+ break;
+ case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
+ nLayoutMode = TEXT_LAYOUT_BIDI_RTL;
+ break;
+ case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
+ nLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG;
+ break;
+ }
+
+ // set calculated layout mode. Origin is always the left edge,
+ // as required at the API spec
+ rOutDev.SetLayoutMode( nLayoutMode | TEXT_LAYOUT_TEXTORIGIN_LEFT );
+ }
+ }
+
+ TextLayout::TextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 /*nRandomSeed*/,
+ const CanvasFont::Reference& rFont,
+ const SurfaceProviderRef& rRefDevice ) :
+ TextLayout_Base( m_aMutex ),
+ maText( aText ),
+ maLogicalAdvancements(),
+ mpFont( rFont ),
+ mpRefDevice( rRefDevice ),
+ mnTextDirection( nDirection )
+ {
+ }
+
+ TextLayout::~TextLayout()
+ {
+ }
+
+ void SAL_CALL TextLayout::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpFont.reset();
+ mpRefDevice.clear();
+ }
+
+ // XTextLayout
+ uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< geometry::RealRectangle2D >();
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< geometry::RealRectangle2D >();
+ }
+
+ uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maLogicalAdvancements;
+ }
+
+ void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if( aAdvancements.getLength() != maText.Length )
+ {
+ OSL_TRACE( "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
+ throw lang::IllegalArgumentException();
+ }
+
+ maLogicalAdvancements = aAdvancements;
+ }
+
+ geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ OutputDevice* pOutDev = mpRefDevice->getOutputDevice();
+ if( !pOutDev )
+ return geometry::RealRectangle2D();
+
+ VirtualDevice aVDev( *pOutDev );
+ aVDev.SetFont( mpFont->getVCLFont() );
+
+ // need metrics for Y offset, the XCanvas always renders
+ // relative to baseline
+ const ::FontMetric& aMetric( aVDev.GetFontMetric() );
+
+ setupLayoutMode( aVDev, mnTextDirection );
+
+ const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
+ const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
+
+ if( maLogicalAdvancements.getLength() )
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ maLogicalAdvancements[ maLogicalAdvancements.getLength()-1 ],
+ nBelowBaseline );
+ }
+ else
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ aVDev.GetTextWidth(
+ maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length) ),
+ nBelowBaseline );
+ }
+ }
+
+ double SAL_CALL TextLayout::justify( double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
+ double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::TextHit();
+ }
+
+ rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
+ sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::Caret();
+ }
+
+ sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nCaretAdvancement*/,
+ sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0;
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ double SAL_CALL TextLayout::getBaselineOffset( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ sal_Int8 SAL_CALL TextLayout::getMainTextDirection( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mnTextDirection;
+ }
+
+ uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFont.getRef();
+ }
+
+ rendering::StringContext SAL_CALL TextLayout::getText( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maText;
+ }
+
+ void TextLayout::useFont( Cairo* pCairo )
+ {
+ rendering::FontRequest aFontRequest = mpFont->getFontRequest();
+ rendering::FontInfo aFontInfo = aFontRequest.FontDescription;
+
+ cairo_select_font_face( pCairo, ::rtl::OUStringToOString( aFontInfo.FamilyName, RTL_TEXTENCODING_UTF8 ), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL );
+ cairo_set_font_size( pCairo, aFontRequest.CellSize );
+ }
+
+ /** TextLayout:draw
+ *
+ * This function uses the "toy" api of the cairo library
+ *
+ **/
+ bool TextLayout::draw( Cairo* pCairo )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::rtl::OUString aSubText = maText.Text.copy( maText.StartPosition, maText.Length );
+ ::rtl::OString aUTF8String = ::rtl::OUStringToOString( aSubText, RTL_TEXTENCODING_UTF8 );
+
+ cairo_save( pCairo );
+ /* move to 0, 0 as cairo_show_text advances current point and current point is not restored by cairo_restore.
+ before we were depending on unmodified current point which I believed was preserved by save/restore */
+ cairo_move_to( pCairo, 0, 0 );
+ useFont( pCairo );
+ cairo_show_text( pCairo, aUTF8String );
+ cairo_restore( pCairo );
+
+ return true;
+ }
+
+
+ /**
+ * TextLayout::isCairoRenderable
+ *
+ * Features currenly not supported by Cairo (VCL rendering is used as fallback):
+ * - vertical glyphs
+ *
+ * @return true, if text/font can be rendered with cairo
+ **/
+ bool TextLayout::isCairoRenderable(SystemFontData aSysFontData) const
+ {
+#if defined UNX && !defined QUARTZ
+ // is font usable?
+ if (!aSysFontData.nFontId) return false;
+#endif
+
+ // vertical glyph rendering is not supported in cairo for now
+ if (aSysFontData.bVerticalCharacterType) {
+ OSL_TRACE(":cairocanvas::TextLayout::isCairoRenderable(): ***************** VERTICAL CHARACTER STYLE!!! ****************");
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * TextLayout::draw
+ *
+ * Cairo-based text rendering. Draw text directly on the cairo surface with cairo fonts.
+ * Avoid using VCL VirtualDevices for that, bypassing VCL DrawText functions, when possible
+ *
+ * Note: some text effects are not rendered due to lacking generic canvas or cairo canvas
+ * implementation. See issues 92657, 92658, 92659, 92660, 97529
+ *
+ * @return true, if successful
+ **/
+ bool TextLayout::draw( SurfaceSharedPtr& pSurface,
+ OutputDevice& rOutDev,
+ const Point& rOutpos,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ SystemTextLayoutData aSysLayoutData;
+#if (defined CAIRO_HAS_WIN32_SURFACE) && (OSL_DEBUG_LEVEL > 1)
+ LOGFONTW logfont;
+#endif
+ setupLayoutMode( rOutDev, mnTextDirection );
+
+ // TODO(P2): cache that
+ ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
+
+ if( maLogicalAdvancements.getLength() )
+ {
+ setupTextOffsets( aOffsets.get(), maLogicalAdvancements, viewState, renderState );
+
+ // TODO(F3): ensure correct length and termination for DX
+ // array (last entry _must_ contain the overall width)
+ }
+
+ aSysLayoutData = rOutDev.GetSysTextLayoutData(rOutpos, maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length),
+ maLogicalAdvancements.getLength() ? aOffsets.get() : NULL);
+
+ // The ::GetSysTextLayoutData(), i.e. layouting of text to glyphs can change the font being used.
+ // The fallback checks need to be done after final font is known.
+ if (!isCairoRenderable(aSysLayoutData.aSysFontData)) // VCL FALLBACKS
+ {
+ OSL_TRACE(":cairocanvas::TextLayout::draw(S,O,p,v,r): VCL FALLBACK %s%s%s%s - %s",
+ maLogicalAdvancements.getLength() ? "ADV " : "",
+ aSysLayoutData.aSysFontData.bAntialias ? "AA " : "",
+ aSysLayoutData.aSysFontData.bFakeBold ? "FB " : "",
+ aSysLayoutData.aSysFontData.bFakeItalic ? "FI " : "",
+ ::rtl::OUStringToOString( maText.Text.copy( maText.StartPosition, maText.Length ),
+ RTL_TEXTENCODING_UTF8 ).getStr());
+
+ if (maLogicalAdvancements.getLength()) // VCL FALLBACK - with glyph advances
+ {
+ rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets.get(),
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
+ return true;
+ }
+ else // VCL FALLBACK - without advances
+ {
+ rOutDev.DrawText( rOutpos, maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
+ return true;
+ }
+ }
+
+ if (aSysLayoutData.rGlyphData.empty()) return false; //??? false?
+
+ /**
+ * Setup platform independent glyph vector into cairo-based glyphs vector.
+ **/
+
+ // setup glyphs
+ std::vector<cairo_glyph_t> cairo_glyphs;
+ cairo_glyphs.reserve( 256 );
+
+ for( int nStart = 0; nStart < (int) aSysLayoutData.rGlyphData.size(); nStart++ )
+ {
+ cairo_glyph_t aGlyph;
+ SystemGlyphData systemGlyph = aSysLayoutData.rGlyphData.at(nStart);
+ aGlyph.index = systemGlyph.index;
+#ifdef CAIRO_HAS_WIN32_SURFACE
+ // Cairo requires standard glyph indexes (ETO_GLYPH_INDEX), while vcl/win/* uses ucs4 chars.
+ // Convert to standard indexes
+ aGlyph.index = cairo::ucs4toindex((unsigned int) aGlyph.index, aSysLayoutData.aSysFontData.hFont);
+#endif
+ aGlyph.x = systemGlyph.x;
+ aGlyph.y = systemGlyph.y;
+ cairo_glyphs.push_back(aGlyph);
+ }
+
+ if (cairo_glyphs.empty()) return true; //true or false??
+
+ /**
+ * Setup font
+ **/
+ cairo_font_face_t* font_face = NULL;
+
+#ifdef CAIRO_HAS_QUARTZ_SURFACE
+ // TODO: use cairo_quartz_font_face_create_for_cgfont(cgFont)
+ // when CGFont (Mac OS X 10.5 API) is provided by the AQUA VCL backend.
+ font_face = cairo_quartz_font_face_create_for_atsu_font_id((ATSUFontID) aSysLayoutData.aSysFontData.aATSUFontID);
+
+#elif defined CAIRO_HAS_WIN32_SURFACE
+ #if (OSL_DEBUG_LEVEL > 1)
+ GetObjectW( aSysLayoutData.aSysFontData.hFont, sizeof(logfont), &logfont );
+ #endif
+ // Note: cairo library uses logfont fallbacks when lfEscapement, lfOrientation and lfWidth are not zero.
+ // VCL always has non-zero value for lfWidth
+ font_face = cairo_win32_font_face_create_for_hfont(aSysLayoutData.aSysFontData.hFont);
+
+#elif defined CAIRO_HAS_XLIB_SURFACE
+ font_face = cairo_ft_font_face_create_for_ft_face((FT_Face)aSysLayoutData.aSysFontData.nFontId,
+ aSysLayoutData.aSysFontData.nFontFlags);
+#else
+# error Native API needed.
+#endif
+
+ CairoSharedPtr pSCairo = pSurface->getCairo();
+
+ cairo_set_font_face( pSCairo.get(), font_face);
+
+ // create default font options. cairo_get_font_options() does not retrieve the surface defaults,
+ // only what has been set before with cairo_set_font_options()
+ cairo_font_options_t* options = cairo_font_options_create();
+ if (aSysLayoutData.aSysFontData.bAntialias) {
+ // CAIRO_ANTIALIAS_GRAY provides more similar result to VCL Canvas,
+ // so we're not using CAIRO_ANTIALIAS_SUBPIXEL
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
+ }
+ cairo_set_font_options( pSCairo.get(), options);
+
+ // Font color
+ Color mTextColor = rOutDev.GetTextColor();
+ cairo_set_source_rgb(pSCairo.get(),
+ mTextColor.GetRed()/255.0,
+ mTextColor.GetGreen()/255.0,
+ mTextColor.GetBlue()/255.0);
+
+ // Font rotation and scaling
+ cairo_matrix_t m;
+ Font aFont = rOutDev.GetFont();
+ FontMetric aMetric( rOutDev.GetFontMetric(aFont) );
+ long nWidth = 0;
+
+ // width calculation is deep magic and platform/font dependant.
+ // width == 0 means no scaling, and usually width == height means the same.
+ // Other values mean horizontal scaling (narrow or stretching)
+ // see issue #101566
+
+ //proper scale calculation across platforms
+ if (aFont.GetWidth() == 0) {
+ nWidth = aFont.GetHeight();
+ } else {
+ // any scaling needs to be relative to the platform-dependent definition
+ // of height of the font
+ nWidth = aFont.GetWidth() * aFont.GetHeight() / aMetric.GetHeight();
+ }
+
+ cairo_matrix_init_identity(&m);
+
+ if (aSysLayoutData.orientation) cairo_matrix_rotate(&m, (3600 - aSysLayoutData.orientation) * M_PI / 1800.0);
+
+ cairo_matrix_scale(&m, nWidth, aFont.GetHeight());
+
+ //faux italics
+ if (aSysLayoutData.aSysFontData.bFakeItalic) m.xy = -m.xx * 0x6000L / 0x10000L;
+
+ cairo_set_font_matrix(pSCairo.get(), &m);
+
+ OSL_TRACE("\r\n:cairocanvas::TextLayout::draw(S,O,p,v,r): Size:(%d,%d), W:%d->%d, Pos (%d,%d), G(%d,%d,%d) %s%s%s%s || Name:%s - %s",
+ aFont.GetWidth(),
+ aFont.GetHeight(),
+ aMetric.GetWidth(),
+ nWidth,
+ (int) rOutpos.X(),
+ (int) rOutpos.Y(),
+ cairo_glyphs[0].index, cairo_glyphs[1].index, cairo_glyphs[2].index,
+ maLogicalAdvancements.getLength() ? "ADV " : "",
+ aSysLayoutData.aSysFontData.bAntialias ? "AA " : "",
+ aSysLayoutData.aSysFontData.bFakeBold ? "FB " : "",
+ aSysLayoutData.aSysFontData.bFakeItalic ? "FI " : "",
+#if (defined CAIRO_HAS_WIN32_SURFACE) && (OSL_DEBUG_LEVEL > 1)
+ ::rtl::OUStringToOString( reinterpret_cast<const sal_Unicode*> (logfont.lfFaceName), RTL_TEXTENCODING_UTF8 ).getStr(),
+#else
+ ::rtl::OUStringToOString( aFont.GetName(), RTL_TEXTENCODING_UTF8 ).getStr(),
+#endif
+ ::rtl::OUStringToOString( maText.Text.copy( maText.StartPosition, maText.Length ),
+ RTL_TEXTENCODING_UTF8 ).getStr()
+ );
+
+ cairo_show_glyphs(pSCairo.get(), &cairo_glyphs[0], cairo_glyphs.size());
+
+ //faux bold
+ if (aSysLayoutData.aSysFontData.bFakeBold) {
+ double bold_dx = 0.5 * sqrt( 0.7 * aFont.GetHeight() );
+ int total_steps = 2 * ((int) (bold_dx + 0.5));
+
+ // loop to draw the text for every half pixel of displacement
+ for (int nSteps = 0; nSteps < total_steps; nSteps++) {
+ for(int nGlyphIdx = 0; nGlyphIdx < (int) cairo_glyphs.size(); nGlyphIdx++) {
+ cairo_glyphs[nGlyphIdx].x += bold_dx * nSteps / total_steps;
+ }
+ cairo_show_glyphs(pSCairo.get(), &cairo_glyphs[0], cairo_glyphs.size());
+ }
+ OSL_TRACE(":cairocanvas::TextLayout::draw(S,O,p,v,r): FAKEBOLD - dx:%d", (int) bold_dx);
+ }
+
+ cairo_restore( pSCairo.get() );
+ cairo_font_face_destroy(font_face);
+ return true;
+ }
+
+
+ namespace
+ {
+ class OffsetTransformer
+ {
+ public:
+ OffsetTransformer( const ::basegfx::B2DHomMatrix& rMat ) :
+ maMatrix( rMat )
+ {
+ }
+
+ sal_Int32 operator()( const double& rOffset )
+ {
+ // This is an optimization of the normal rMat*[x,0]
+ // transformation of the advancement vector (in x
+ // direction), followed by a length calculation of the
+ // resulting vector: advancement' =
+ // ||rMat*[x,0]||. Since advancements are vectors, we
+ // can ignore translational components, thus if [x,0],
+ // it follows that rMat*[x,0]=[x',0] holds. Thus, we
+ // just have to calc the transformation of the x
+ // component.
+
+ // TODO(F2): Handle non-horizontal advancements!
+ return ::basegfx::fround( hypot(maMatrix.get(0,0)*rOffset,
+ maMatrix.get(1,0)*rOffset) );
+ }
+
+ private:
+ ::basegfx::B2DHomMatrix maMatrix;
+ };
+ }
+
+ void TextLayout::setupTextOffsets( sal_Int32* outputOffsets,
+ const uno::Sequence< double >& inputOffsets,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState ) const
+ {
+ ENSURE_OR_THROW( outputOffsets!=NULL,
+ "TextLayout::setupTextOffsets offsets NULL" );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ viewState,
+ renderState);
+
+ // fill integer offsets
+ ::std::transform( const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray(),
+ const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray()+inputOffsets.getLength(),
+ outputOffsets,
+ OffsetTransformer( aMatrix ) );
+ }
+
+#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
+#define IMPLEMENTATION_NAME "CairoCanvas::TextLayout"
+
+ ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+}
diff --git a/canvas/source/cairo/cairo_textlayout.hxx b/canvas/source/cairo/cairo_textlayout.hxx
new file mode 100644
index 000000000000..6e14907c01bb
--- /dev/null
+++ b/canvas/source/cairo/cairo_textlayout.hxx
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_TEXTLAYOUT_HXX
+#define _CAIROCANVAS_TEXTLAYOUT_HXX
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XTextLayout.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include <vcl/outdev.hxx>
+
+#include <boost/utility.hpp>
+
+#include "cairo_cairo.hxx"
+#include "cairo_canvasfont.hxx"
+
+
+/* Definition of TextLayout class */
+
+namespace cairocanvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XTextLayout,
+ ::com::sun::star::lang::XServiceInfo > TextLayout_Base;
+
+ class TextLayout : public ::comphelper::OBaseMutex,
+ public TextLayout_Base,
+ private ::boost::noncopyable
+ {
+ public:
+ TextLayout( const ::com::sun::star::rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed,
+ const CanvasFont::Reference& rFont,
+ const SurfaceProviderRef& rRefDevice );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XTextLayout
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > > SAL_CALL queryTextShapes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealRectangle2D > SAL_CALL queryInkMeasures( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealRectangle2D > SAL_CALL queryMeasures( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL queryLogicalAdvancements( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL applyLogicalAdvancements( const ::com::sun::star::uno::Sequence< double >& aAdvancements ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::geometry::RealRectangle2D SAL_CALL queryTextBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL justify( double nSize ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL combinedJustify( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > >& aNextLayouts, double nSize ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::TextHit SAL_CALL getTextHit( const ::com::sun::star::geometry::RealPoint2D& aHitPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::Caret SAL_CALL getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL getBaselineOffset( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int8 SAL_CALL getMainTextDirection( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > SAL_CALL getFont( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::StringContext SAL_CALL getText( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ bool draw( ::cairo::Cairo* pCairo );
+ bool draw( SurfaceSharedPtr& pSurface,
+ OutputDevice& rOutDev,
+ const Point& rOutpos,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) const;
+
+ void setupTextOffsets( sal_Int32* outputOffsets,
+ const ::com::sun::star::uno::Sequence< double >& inputOffsets,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) const;
+
+ protected:
+ ~TextLayout(); // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ private:
+ ::com::sun::star::rendering::StringContext maText;
+ ::com::sun::star::uno::Sequence< double > maLogicalAdvancements;
+ CanvasFont::Reference mpFont;
+ SurfaceProviderRef mpRefDevice;
+ sal_Int8 mnTextDirection;
+
+ void useFont( ::cairo::Cairo* pCairo );
+ bool isCairoRenderable(SystemFontData aSysFontData) const;
+ };
+
+}
+
+#endif /* _CAIROCANVAS_TEXTLAYOUT_HXX */
diff --git a/canvas/source/cairo/cairo_win32_cairo.cxx b/canvas/source/cairo/cairo_win32_cairo.cxx
new file mode 100644
index 000000000000..d0d6558c2fdd
--- /dev/null
+++ b/canvas/source/cairo/cairo_win32_cairo.cxx
@@ -0,0 +1,325 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#ifdef WNT
+/************************************************************************
+ * Win32 surface backend for OpenOffice.org Cairo Canvas *
+ ************************************************************************/
+
+#include <tools/prewin.h>
+#include <windows.h>
+#include <tools/postwin.h>
+
+#include <osl/diagnose.h>
+#include <vcl/bitmap.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/sysdata.hxx>
+
+#include "cairo_win32_cairo.hxx"
+
+#ifdef CAIRO_HAS_WIN32_SURFACE
+
+namespace cairo
+{
+
+#include <cairo-win32.h>
+
+ bool IsCairoWorking( OutputDevice* )
+ {
+ // trivially true for Windows
+ return true;
+ }
+
+ /**
+ * Surface::Surface: Create generic Canvas surface using given Cairo Surface
+ *
+ * @param pSurface Cairo Surface
+ *
+ * This constructor only stores data, it does no processing.
+ * It is used with e.g. cairo_image_surface_create_for_data()
+ * and Surface::getSimilar()
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ Win32Surface::Win32Surface( const CairoSurfaceSharedPtr& pSurface ) :
+ mpSurface( pSurface )
+ {}
+
+ /**
+ * Surface::Surface: Create Canvas surface from Window reference.
+ * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * @param x horizontal location of the new surface
+ * @param y vertical location of the new surface
+ *
+ * pSysData contains the platform native Window reference.
+ * pSysData is used to create a surface on the Window
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ Win32Surface::Win32Surface( HDC hDC, int x, int y) :
+ mpSurface(
+ cairo_win32_surface_create(hDC),
+ &cairo_surface_destroy)
+ {
+ cairo_surface_set_device_offset( mpSurface.get(), x, y );
+ }
+
+ /**
+ * Surface::Surface: Create platfrom native Canvas surface from BitmapSystemData
+ * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
+ *
+ * Create a surface based on image data on pBmpData
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ Win32Surface::Win32Surface( const BitmapSystemData& rBmpData ) :
+ mpSurface()
+ {
+ OSL_ASSERT(rBmpData.pDIB == NULL);
+
+ if(rBmpData.pDIB != NULL) {
+ // So just leave mpSurface to NULL, little else we can do at
+ // this stage. Hopefully the Win32 patch to
+ // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&,
+ // const Size&) will catch the cases where this
+ // constructor would be called with a DIB bitmap, and we
+ // will never get here. At least it worked for Ballmer.ppt.
+ }
+ else
+ {
+ HDC hDC = CreateCompatibleDC(NULL);
+ void* hOrigBitmap;
+ OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC);
+ hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB );
+ if(hOrigBitmap == NULL)
+ OSL_TRACE ("SelectObject failed: %d", GetLastError ());
+ mpSurface.reset(
+ cairo_win32_surface_create(hDC),
+ &cairo_surface_destroy);
+ }
+ }
+
+ /**
+ * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface
+ *
+ * @return new Cairo or NULL
+ **/
+ CairoSharedPtr Win32Surface::getCairo() const
+ {
+ return CairoSharedPtr( cairo_create(mpSurface.get()),
+ &cairo_destroy );
+ }
+
+ /**
+ * Surface::getSimilar: Create new similar Canvas surface
+ * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * Creates a new Canvas surface. This normally creates platform native surface, even though
+ * generic function is used.
+ *
+ * Cairo surface from aContent (cairo_content_t)
+ *
+ * @return new surface or NULL
+ **/
+ SurfaceSharedPtr Win32Surface::getSimilar( Content aContent, int width, int height ) const
+ {
+ return SurfaceSharedPtr(
+ new Win32Surface(
+ CairoSurfaceSharedPtr(
+ cairo_surface_create_similar( mpSurface.get(), aContent, width, height ),
+ &cairo_surface_destroy )));
+ }
+
+ /**
+ * Surface::Resize: Resizes the Canvas surface.
+ * @param width new width of the surface
+ * @param height new height of the surface
+ *
+ * Only used on X11.
+ *
+ * @return The new surface or NULL
+ **/
+ void Win32Surface::Resize( int /*width*/, int /*height*/ )
+ {
+ OSL_ENSURE(false,"not supposed to be called!");
+ }
+
+ void Win32Surface::flush() const
+ {
+ GdiFlush();
+ }
+
+ /**
+ * Surface::getDepth: Get the color depth of the Canvas surface.
+ *
+ * @return color depth
+ **/
+ int Win32Surface::getDepth() const
+ {
+ if (mpSurface) {
+ switch (cairo_surface_get_content (mpSurface.get())) {
+ case CAIRO_CONTENT_ALPHA: return 8; break;
+ case CAIRO_CONTENT_COLOR: return 24; break;
+ case CAIRO_CONTENT_COLOR_ALPHA: return 32; break;
+ }
+ }
+ OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!");
+ return -1;
+ }
+
+
+ /**
+ * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface
+ *
+ * @return The new virtual device
+ **/
+ boost::shared_ptr<VirtualDevice> Win32Surface::createVirtualDevice() const
+ {
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() );
+
+ return boost::shared_ptr<VirtualDevice>(
+ new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) ));
+ }
+
+
+ /**
+ * cairo::createSurface: Create generic Canvas surface using given Cairo Surface
+ *
+ * @param rSurface Cairo Surface
+ *
+ * @return new Surface
+ */
+ SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
+ {
+ return SurfaceSharedPtr(new Win32Surface(rSurface));
+ }
+
+
+ /**
+ * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice
+ *
+ * @param rSurface Cairo Surface
+ *
+ * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
+ *
+ * @return new Surface
+ */
+ SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
+ int x, int y, int /* width */, int /* height */)
+ {
+ SurfaceSharedPtr surf;
+
+ if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
+ {
+ const Window &rWindow = (const Window &) rRefDevice;
+ const SystemEnvData* pSysData = GetSysData(&rWindow);
+ if (pSysData && pSysData->hWnd)
+ surf = SurfaceSharedPtr(new Win32Surface(GetDC((HWND) pSysData->hWnd), x, y));
+ }
+ else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
+ {
+ SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData();
+ if (aSysData.hDC)
+ surf = SurfaceSharedPtr(new Win32Surface((HDC) aSysData.hDC, x, y));
+ }
+ return surf;
+ }
+
+
+ /**
+ * cairo::createBitmapSurface: Create platfrom native Canvas surface from BitmapSystemData
+ * @param OutputDevice (not used)
+ * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
+ * @param rSize width and height of the new surface
+ *
+ * Create a surface based on image data on rData
+ *
+ * @return new surface or empty surface
+ **/
+ SurfaceSharedPtr createBitmapSurface( const OutputDevice& /* rRefDevice */,
+ const BitmapSystemData& rData,
+ const Size& rSize )
+ {
+ OSL_TRACE( "requested size: %d x %d available size: %d x %d",
+ rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
+
+ if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
+ return SurfaceSharedPtr(new Win32Surface( rData ));
+ else
+ return SurfaceSharedPtr();
+ }
+
+
+ /**
+ * cairo::ucs4toindex: Convert ucs4 char to glyph index
+ * @param ucs4 an ucs4 char
+ * @param hfont current font
+ *
+ * @return true if successful
+ **/
+ unsigned long ucs4toindex(unsigned int ucs4, HFONT hfont)
+ {
+ wchar_t unicode[2];
+ WORD glyph_index;
+ HDC hdc = NULL;
+ int i = 0;
+
+ hdc = CreateCompatibleDC (NULL);
+
+ if (!hdc) return 0;
+ if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
+ DeleteDC (hdc);
+ return 0;
+ }
+
+ SelectObject (hdc, hfont);
+ SetMapMode (hdc, MM_TEXT);
+
+ unicode[0] = ucs4;
+ unicode[1] = 0;
+ if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
+ glyph_index = 0;
+ }
+
+ DeleteDC (hdc);
+ return glyph_index;
+ }
+
+
+} // namespace cairo
+
+#endif // CAIRO_HAS_WIN32_SURFACE
+
+#endif // WNT
diff --git a/canvas/source/cairo/cairo_win32_cairo.hxx b/canvas/source/cairo/cairo_win32_cairo.hxx
new file mode 100644
index 000000000000..3b083d28e748
--- /dev/null
+++ b/canvas/source/cairo/cairo_win32_cairo.hxx
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_WIN32_CAIRO_HXX
+#define _CAIROCANVAS_WIN32_CAIRO_HXX
+
+#ifdef WNT
+# include <tools/prewin.h>
+# include <windows.h>
+# include <tools/postwin.h>
+#endif
+
+#include "cairo_cairo.hxx"
+
+namespace cairo {
+
+ class Win32Surface : public Surface
+ {
+ CairoSurfaceSharedPtr mpSurface;
+
+ public:
+ /// takes over ownership of passed cairo_surface
+ explicit Win32Surface( const CairoSurfaceSharedPtr& pSurface );
+ /// create surface on subarea of given drawable
+ Win32Surface( HDC hDC, int x, int y );
+ /// create surface for given bitmap data
+ Win32Surface( const BitmapSystemData& rBmpData );
+
+ // Surface interface
+ virtual CairoSharedPtr getCairo() const;
+ virtual CairoSurfaceSharedPtr getCairoSurface() const { return mpSurface; }
+ virtual SurfaceSharedPtr getSimilar( Content aContent, int width, int height ) const;
+
+ virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const;
+
+ virtual void Resize( int width, int height );
+
+ virtual void flush() const;
+
+ int getDepth() const;
+ };
+
+ unsigned long ucs4toindex(unsigned int ucs4, HFONT hfont);
+}
+
+#endif
diff --git a/canvas/source/cairo/cairo_xlib_cairo.cxx b/canvas/source/cairo/cairo_xlib_cairo.cxx
new file mode 100644
index 000000000000..823ad05e426f
--- /dev/null
+++ b/canvas/source/cairo/cairo_xlib_cairo.cxx
@@ -0,0 +1,352 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <tools/prex.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/Xlib.h>
+#include <tools/postx.h>
+
+#include "cairo_xlib_cairo.hxx"
+
+#include <vcl/sysdata.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/virdev.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+namespace cairo
+{
+
+#include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
+
+ // TODO(F3): svp headless case!
+
+ bool IsCairoWorking( OutputDevice* pOutDev )
+ {
+ if( !pOutDev )
+ return false;
+
+ Display* pDisplay = (Display*)pOutDev->GetSystemGfxData().pDisplay;
+ int nDummy;
+ return XQueryExtension( pDisplay, "RENDER", &nDummy, &nDummy, &nDummy );
+ }
+
+ X11SysData::X11SysData() :
+ pDisplay(NULL),
+ hDrawable(0),
+ pVisual(NULL),
+ nScreen(0),
+ nDepth(-1),
+ aColormap(-1),
+ pRenderFormat(NULL)
+ {}
+
+ X11SysData::X11SysData( const SystemGraphicsData& pSysDat ) :
+ pDisplay(pSysDat.pDisplay),
+ hDrawable(pSysDat.hDrawable),
+ pVisual(pSysDat.pVisual),
+ nScreen(pSysDat.nScreen),
+ nDepth(pSysDat.nDepth),
+ aColormap(pSysDat.aColormap),
+ pRenderFormat(pSysDat.pRenderFormat)
+ {}
+
+ X11SysData::X11SysData( const SystemEnvData& pSysDat ) :
+ pDisplay(pSysDat.pDisplay),
+ hDrawable(pSysDat.aWindow),
+ pVisual(pSysDat.pVisual),
+ nScreen(pSysDat.nScreen),
+ nDepth(pSysDat.nDepth),
+ aColormap(pSysDat.aColormap),
+ pRenderFormat(NULL)
+ {}
+
+ X11Pixmap::~X11Pixmap()
+ {
+ if( mpDisplay && mhDrawable )
+ XFreePixmap( (Display*)mpDisplay, mhDrawable );
+ }
+
+ /**
+ * Surface::Surface: Create Canvas surface with existing data
+ * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * @param pSurface Cairo surface
+ *
+ * pSysData contains the platform native Drawable reference
+ * This constructor only stores data, it does no processing.
+ * It is used by e.g. Surface::getSimilar()
+ *
+ * Set the mpSurface as pSurface
+ **/
+ X11Surface::X11Surface( const X11SysData& rSysData,
+ const X11PixmapSharedPtr& rPixmap,
+ const CairoSurfaceSharedPtr& pSurface ) :
+ maSysData(rSysData),
+ mpPixmap(rPixmap),
+ mpSurface(pSurface)
+ {}
+
+ /**
+ * Surface::Surface: Create generic Canvas surface using given Cairo Surface
+ *
+ * @param pSurface Cairo Surface
+ *
+ * This constructor only stores data, it does no processing.
+ * It is used with e.g. cairo_image_surface_create_for_data()
+ * Unlike other constructors, mpSysData is set to NULL
+ *
+ * Set the mpSurface as pSurface
+ **/
+ X11Surface::X11Surface( const CairoSurfaceSharedPtr& pSurface ) :
+ maSysData(),
+ mpPixmap(),
+ mpSurface(pSurface)
+ {}
+
+ /**
+ * Surface::Surface: Create Canvas surface from Window reference.
+ * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * @param x horizontal location of the new surface
+ * @param y vertical location of the new surface
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * pSysData contains the platform native Window reference.
+ *
+ * pSysData is used to create a surface on the Window
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ X11Surface::X11Surface( const X11SysData& rSysData, int x, int y, int width, int height ) :
+ maSysData(rSysData),
+ mpPixmap(),
+ mpSurface(
+ cairo_xlib_surface_create( (Display*)rSysData.pDisplay,
+ rSysData.hDrawable,
+ (Visual*)rSysData.pVisual,
+ width + x, height + y ),
+ &cairo_surface_destroy)
+ {
+ cairo_surface_set_device_offset(mpSurface.get(), x, y );
+ }
+
+ /**
+ * Surface::Surface: Create platfrom native Canvas surface from BitmapSystemData
+ * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
+ * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * The pBmpData provides the imagedata that the created surface should contain.
+ *
+ * Set the mpSurface to the new surface or NULL
+ **/
+ X11Surface::X11Surface( const X11SysData& rSysData,
+ const BitmapSystemData& rData ) :
+ maSysData( rSysData ),
+ mpPixmap(),
+ mpSurface(
+ cairo_xlib_surface_create( (Display*)rSysData.pDisplay,
+ (Drawable)rData.aPixmap,
+ (Visual*) rSysData.pVisual,
+ rData.mnWidth, rData.mnHeight ),
+ &cairo_surface_destroy)
+ {
+ }
+
+ /**
+ * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface
+ *
+ * @return new Cairo or NULL
+ **/
+ CairoSharedPtr X11Surface::getCairo() const
+ {
+ return CairoSharedPtr( cairo_create(mpSurface.get()),
+ &cairo_destroy );
+ }
+
+ /**
+ * Surface::getSimilar: Create new similar Canvas surface
+ * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
+ * @param width width of the new surface
+ * @param height height of the new surface
+ *
+ * Creates a new Canvas surface. This normally creates platform native surface, even though
+ * generic function is used.
+ *
+ * Cairo surface from aContent (cairo_content_t)
+ *
+ * @return new surface or NULL
+ **/
+ SurfaceSharedPtr X11Surface::getSimilar( Content aContent, int width, int height ) const
+ {
+ Pixmap hPixmap;
+
+ if( maSysData.pDisplay && maSysData.hDrawable )
+ {
+ XRenderPictFormat* pFormat;
+ int nFormat;
+
+ switch (aContent)
+ {
+ case CAIRO_CONTENT_ALPHA:
+ nFormat = PictStandardA8;
+ break;
+ case CAIRO_CONTENT_COLOR:
+ nFormat = PictStandardRGB24;
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ default:
+ nFormat = PictStandardARGB32;
+ break;
+ }
+
+ pFormat = XRenderFindStandardFormat( (Display*)maSysData.pDisplay, nFormat );
+ hPixmap = XCreatePixmap( (Display*)maSysData.pDisplay, maSysData.hDrawable,
+ width > 0 ? width : 1, height > 0 ? height : 1,
+ pFormat->depth );
+
+ X11SysData aSysData(maSysData);
+ aSysData.pRenderFormat = pFormat;
+ return SurfaceSharedPtr(
+ new X11Surface( aSysData,
+ X11PixmapSharedPtr(
+ new X11Pixmap(hPixmap, maSysData.pDisplay)),
+ CairoSurfaceSharedPtr(
+ cairo_xlib_surface_create_with_xrender_format(
+ (Display*)maSysData.pDisplay,
+ hPixmap,
+ ScreenOfDisplay((Display *)maSysData.pDisplay, maSysData.nScreen),
+ pFormat, width, height ),
+ &cairo_surface_destroy) ));
+ }
+ else
+ return SurfaceSharedPtr(
+ new X11Surface( maSysData,
+ X11PixmapSharedPtr(),
+ CairoSurfaceSharedPtr(
+ cairo_surface_create_similar( mpSurface.get(), aContent, width, height ),
+ &cairo_surface_destroy )));
+ }
+
+ boost::shared_ptr<VirtualDevice> X11Surface::createVirtualDevice() const
+ {
+ SystemGraphicsData aSystemGraphicsData;
+
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDrawable = getDrawable();
+ aSystemGraphicsData.pRenderFormat = getRenderFormat();
+
+ return boost::shared_ptr<VirtualDevice>(
+ new VirtualDevice( &aSystemGraphicsData, getDepth() ));
+ }
+
+ /**
+ * Surface::Resize: Resizes the Canvas surface.
+ * @param width new width of the surface
+ * @param height new height of the surface
+ *
+ * Only used on X11.
+ *
+ * @return The new surface or NULL
+ **/
+ void X11Surface::Resize( int width, int height )
+ {
+ cairo_xlib_surface_set_size( mpSurface.get(), width, height );
+ }
+
+ void X11Surface::flush() const
+ {
+ XSync( (Display*)maSysData.pDisplay, false );
+ }
+
+ /**
+ * Surface::getDepth: Get the color depth of the Canvas surface.
+ *
+ * @return color depth
+ **/
+ int X11Surface::getDepth() const
+ {
+ if( maSysData.pRenderFormat )
+ return ((XRenderPictFormat*) maSysData.pRenderFormat)->depth;
+
+ return -1;
+ }
+
+ SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
+ {
+ return SurfaceSharedPtr(new X11Surface(rSurface));
+ }
+
+ static X11SysData getSysData( const Window& rWindow )
+ {
+ const SystemEnvData* pSysData = GetSysData(&rWindow);
+
+ if( !pSysData )
+ return X11SysData();
+ else
+ return X11SysData(*pSysData);
+ }
+
+ static X11SysData getSysData( const VirtualDevice& rVirDev )
+ {
+ return X11SysData( rVirDev.GetSystemGfxData() );
+ }
+
+ SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
+ int x, int y, int width, int height )
+ {
+ if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
+ return SurfaceSharedPtr(new X11Surface(getSysData((const Window&)rRefDevice),
+ x,y,width,height));
+ else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
+ return SurfaceSharedPtr(new X11Surface(getSysData((const VirtualDevice&)rRefDevice),
+ x,y,width,height));
+ else
+ return SurfaceSharedPtr();
+ }
+
+ SurfaceSharedPtr createBitmapSurface( const OutputDevice& rRefDevice,
+ const BitmapSystemData& rData,
+ const Size& rSize )
+ {
+ OSL_TRACE( "requested size: %d x %d available size: %d x %d",
+ rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
+ if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
+ {
+ if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
+ return SurfaceSharedPtr(new X11Surface(getSysData((const Window&)rRefDevice), rData ));
+ else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
+ return SurfaceSharedPtr(new X11Surface(getSysData((const VirtualDevice&)rRefDevice), rData ));
+ }
+
+ return SurfaceSharedPtr();
+ }
+}
diff --git a/canvas/source/cairo/cairo_xlib_cairo.hxx b/canvas/source/cairo/cairo_xlib_cairo.hxx
new file mode 100644
index 000000000000..aa5cfa67a2b6
--- /dev/null
+++ b/canvas/source/cairo/cairo_xlib_cairo.hxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CAIROCANVAS_XLIB_CAIRO_HXX
+#define _CAIROCANVAS_XLIB_CAIRO_HXX
+
+#include "cairo_cairo.hxx"
+
+struct SystemEnvData;
+struct SystemGraphicsData;
+
+namespace cairo {
+
+ /// Holds all X11-output relevant data
+ struct X11SysData
+ {
+ X11SysData();
+ explicit X11SysData( const SystemGraphicsData& );
+ explicit X11SysData( const SystemEnvData& );
+
+ void* pDisplay; // the relevant display connection
+ long hDrawable; // a drawable
+ void* pVisual; // the visual in use
+ int nScreen; // the current screen of the drawable
+ int nDepth; // depth of said visual
+ long aColormap; // the colormap being used
+ void* pRenderFormat; // render format for drawable
+ };
+
+ /// RAII wrapper for a pixmap
+ struct X11Pixmap
+ {
+ void* mpDisplay; // the relevant display connection
+ long mhDrawable; // a drawable
+
+ X11Pixmap( long hDrawable, void* pDisplay ) :
+ mpDisplay(pDisplay),
+ mhDrawable(hDrawable)
+ {}
+
+ ~X11Pixmap();
+
+ void clear() { mpDisplay=NULL; mhDrawable=0; }
+ };
+
+ typedef boost::shared_ptr<X11Pixmap> X11PixmapSharedPtr;
+
+ class X11Surface : public Surface
+ {
+ const X11SysData maSysData;
+ X11PixmapSharedPtr mpPixmap;
+ CairoSurfaceSharedPtr mpSurface;
+
+ X11Surface( const X11SysData& rSysData, const X11PixmapSharedPtr& rPixmap, const CairoSurfaceSharedPtr& pSurface );
+
+ public:
+ /// takes over ownership of passed cairo_surface
+ explicit X11Surface( const CairoSurfaceSharedPtr& pSurface );
+ /// create surface on subarea of given drawable
+ X11Surface( const X11SysData& rSysData, int x, int y, int width, int height );
+ /// create surface for given bitmap data
+ X11Surface( const X11SysData& rSysData, const BitmapSystemData& rBmpData );
+
+ // Surface interface
+ virtual CairoSharedPtr getCairo() const;
+ virtual CairoSurfaceSharedPtr getCairoSurface() const { return mpSurface; }
+ virtual SurfaceSharedPtr getSimilar( Content aContent, int width, int height ) const;
+
+ virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const;
+
+ virtual void Resize( int width, int height );
+
+ virtual void flush() const;
+
+ int getDepth() const;
+ X11PixmapSharedPtr getPixmap() const { return mpPixmap; }
+ void* getRenderFormat() const { return maSysData.pRenderFormat; }
+ long getDrawable() const { return mpPixmap ? mpPixmap->mhDrawable : maSysData.hDrawable; }
+ };
+}
+
+#endif
diff --git a/canvas/source/cairo/cairocanvas.component b/canvas/source/cairo/cairocanvas.component
new file mode 100644
index 000000000000..126ad2b44ee1
--- /dev/null
+++ b/canvas/source/cairo/cairocanvas.component
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--**********************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+**********************************************************************-->
+
+<component loader="com.sun.star.loader.SharedLibrary"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.rendering.Canvas.Cairo">
+ <service name="com.sun.star.rendering.Canvas.Cairo"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.rendering.SpriteCanvas.Cairo">
+ <service name="com.sun.star.rendering.SpriteCanvas.Cairo"/>
+ </implementation>
+</component>
diff --git a/canvas/source/cairo/exports.dxp b/canvas/source/cairo/exports.dxp
new file mode 100644
index 000000000000..f0e1c69934bc
--- /dev/null
+++ b/canvas/source/cairo/exports.dxp
@@ -0,0 +1,2 @@
+component_getImplementationEnvironment
+component_getFactory
diff --git a/canvas/source/cairo/makefile.mk b/canvas/source/cairo/makefile.mk
new file mode 100644
index 000000000000..040acd9ade8f
--- /dev/null
+++ b/canvas/source/cairo/makefile.mk
@@ -0,0 +1,140 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=canvas
+TARGET=cairocanvas
+TARGETTYPE=GUI
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Nothing to do if we're compiling with --disable-cairo -----------
+.IF "$(ENABLE_CAIRO)" != "TRUE"
+@all:
+ @echo "Building without cairo support..."
+.ELSE
+# --- X11 Mac build currently doesn't work with cairo -----------
+.IF "$(OS)" == "MACOSX" && "$(GUIBASE)" == "unx"
+@all:
+ @echo "Cannot build cairocanvas with X11..."
+.ENDIF
+.ENDIF
+
+# --- Common ----------------------------------------------------------
+
+
+.IF "$(SYSTEM_CAIRO)" == "YES"
+CFLAGS+=$(CAIRO_CFLAGS)
+.ELSE
+CFLAGS+=-I$(SOLARINCDIR)/cairo
+.ENDIF
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+.IF "$(L10N_framework)"==""
+SLOFILES = $(SLO)$/cairo_cachedbitmap.obj \
+ $(SLO)$/cairo_cairo.obj \
+ $(SLO)$/cairo_canvas.obj \
+ $(SLO)$/cairo_canvasbitmap.obj \
+ $(SLO)$/cairo_canvascustomsprite.obj \
+ $(SLO)$/cairo_canvasfont.obj \
+ $(SLO)$/cairo_canvashelper.obj \
+ $(SLO)$/cairo_canvashelper_text.obj \
+ $(SLO)$/cairo_devicehelper.obj \
+ $(SLO)$/cairo_services.obj \
+ $(SLO)$/cairo_spritecanvas.obj \
+ $(SLO)$/cairo_spritecanvashelper.obj \
+ $(SLO)$/cairo_spritedevicehelper.obj \
+ $(SLO)$/cairo_spritehelper.obj \
+ $(SLO)$/cairo_textlayout.obj
+
+SHL1TARGET=$(TARGET).uno
+
+SHL1STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(TOOLSLIB) $(I18NISOLANGLIB)
+
+.IF "$(GUI)"=="UNX"
+
+.IF "$(SYSTEM_CAIRO)" == "YES"
+SHL1STDLIBS+= $(CAIRO_LIBS)
+.ELSE
+SHL1STDLIBS+= -lcairo -lpixman-1
+.ENDIF
+
+.IF "$(GUIBASE)"=="aqua"
+# native Mac OS X (Quartz)
+SLOFILES+= $(SLO)$/cairo_quartz_cairo.obj
+CFLAGSCXX+=$(OBJCXXFLAGS)
+.ELSE # "$(GUIBASE)"=="aqua"
+
+# Xlib
+SLOFILES+= $(SLO)$/cairo_xlib_cairo.obj
+SHL1STDLIBS+= -lfontconfig -lX11 -lXrender $(FREETYPE_LIBS)
+CFLAGS+=$(FREETYPE_CFLAGS)
+
+.ENDIF # "$(GUIBASE)"=="aqua"
+
+.ELSE # "$(GUI)"=="UNX"
+
+.IF "$(GUI)"=="WNT"
+SLOFILES+= $(SLO)$/cairo_win32_cairo.obj
+.IF "$(COM)"=="GCC"
+SHL1STDLIBS+= -lcairo
+.ELSE
+SHL1STDLIBS+= cairo.lib
+.ENDIF
+SHL1STDLIBS+= $(GDI32LIB) $(MSIMG32LIB)
+.ENDIF
+
+.ENDIF # "$(GUI)"=="UNX"
+
+SHL1IMPLIB=i$(TARGET)
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1VERSIONMAP=$(SOLARENV)/src/component.map
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+.ENDIF
+# ==========================================================================
+
+.INCLUDE : target.mk
+
+ALLTAR : $(MISC)/cairocanvas.component
+
+$(MISC)/cairocanvas.component .ERRREMOVE : \
+ $(SOLARENV)/bin/createcomponent.xslt cairocanvas.component
+ $(XSLTPROC) --nonet --stringparam uri \
+ '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \
+ $(SOLARENV)/bin/createcomponent.xslt cairocanvas.component