summaryrefslogtreecommitdiff
path: root/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'canvas')
-rw-r--r--canvas/inc/canvas/base/basemutexhelper.hxx72
-rw-r--r--canvas/inc/canvas/base/bitmapcanvasbase.hxx137
-rw-r--r--canvas/inc/canvas/base/bufferedgraphicdevicebase.hxx286
-rw-r--r--canvas/inc/canvas/base/cachedprimitivebase.hxx125
-rw-r--r--canvas/inc/canvas/base/canvasbase.hxx486
-rw-r--r--canvas/inc/canvas/base/canvascustomspritebase.hxx280
-rw-r--r--canvas/inc/canvas/base/canvascustomspritehelper.hxx296
-rw-r--r--canvas/inc/canvas/base/doublebitmapbase.hxx154
-rw-r--r--canvas/inc/canvas/base/floatbitmapbase.hxx158
-rw-r--r--canvas/inc/canvas/base/graphicdevicebase.hxx394
-rw-r--r--canvas/inc/canvas/base/integerbitmapbase.hxx154
-rw-r--r--canvas/inc/canvas/base/sprite.hxx122
-rw-r--r--canvas/inc/canvas/base/spritecanvasbase.hxx205
-rw-r--r--canvas/inc/canvas/base/spritesurface.hxx76
-rw-r--r--canvas/inc/canvas/canvastools.hxx664
-rw-r--r--canvas/inc/canvas/debug.hxx68
-rw-r--r--canvas/inc/canvas/elapsedtime.hxx185
-rw-r--r--canvas/inc/canvas/parametricpolypolygon.hxx175
-rw-r--r--canvas/inc/canvas/prioritybooster.hxx68
-rw-r--r--canvas/inc/canvas/propertysethelper.hxx164
-rw-r--r--canvas/inc/canvas/rendering/bitmap.hxx323
-rw-r--r--canvas/inc/canvas/rendering/icachedprimitive.hxx69
-rw-r--r--canvas/inc/canvas/rendering/icolorbuffer.hxx97
-rw-r--r--canvas/inc/canvas/rendering/irendermodule.hxx152
-rw-r--r--canvas/inc/canvas/rendering/isurface.hxx91
-rw-r--r--canvas/inc/canvas/rendering/isurfaceproxy.hxx116
-rw-r--r--canvas/inc/canvas/rendering/isurfaceproxymanager.hxx82
-rw-r--r--canvas/inc/canvas/spriteredrawmanager.hxx437
-rw-r--r--canvas/inc/canvas/vclwrapper.hxx152
-rw-r--r--canvas/inc/canvas/verbosetrace.hxx41
-rw-r--r--canvas/inc/canvas/verifyinput.hxx723
-rw-r--r--canvas/inc/makefile.mk47
-rw-r--r--canvas/inc/pch/precompiled_canvas.cxx31
-rw-r--r--canvas/inc/pch/precompiled_canvas.hxx34
-rw-r--r--canvas/overview.txt50
-rw-r--r--canvas/prj/build.lst10
-rw-r--r--canvas/prj/d.lst26
-rw-r--r--canvas/source/cairo/cairo_cachedbitmap.cxx93
-rw-r--r--canvas/source/cairo/cairo_cachedbitmap.hxx70
-rw-r--r--canvas/source/cairo/cairo_cairo.cxx67
-rw-r--r--canvas/source/cairo/cairo_cairo.hxx100
-rw-r--r--canvas/source/cairo/cairo_canvas.cxx198
-rw-r--r--canvas/source/cairo/cairo_canvas.hxx164
-rw-r--r--canvas/source/cairo/cairo_canvasbitmap.cxx289
-rw-r--r--canvas/source/cairo/cairo_canvasbitmap.hxx141
-rw-r--r--canvas/source/cairo/cairo_canvascustomsprite.cxx178
-rw-r--r--canvas/source/cairo/cairo_canvascustomsprite.hxx159
-rw-r--r--canvas/source/cairo/cairo_canvasfont.cxx180
-rw-r--r--canvas/source/cairo/cairo_canvasfont.hxx99
-rw-r--r--canvas/source/cairo/cairo_canvashelper.cxx1999
-rw-r--r--canvas/source/cairo/cairo_canvashelper.hxx338
-rw-r--r--canvas/source/cairo/cairo_canvashelper_text.cxx401
-rw-r--r--canvas/source/cairo/cairo_canvashelper_texturefill.cxx147
-rw-r--r--canvas/source/cairo/cairo_devicehelper.cxx305
-rw-r--r--canvas/source/cairo/cairo_devicehelper.hxx146
-rw-r--r--canvas/source/cairo/cairo_quartz_cairo.cxx350
-rw-r--r--canvas/source/cairo/cairo_quartz_cairo.hxx76
-rw-r--r--canvas/source/cairo/cairo_repainttarget.hxx61
-rw-r--r--canvas/source/cairo/cairo_services.cxx86
-rw-r--r--canvas/source/cairo/cairo_sprite.hxx74
-rw-r--r--canvas/source/cairo/cairo_spritecanvas.cxx235
-rw-r--r--canvas/source/cairo/cairo_spritecanvas.hxx177
-rw-r--r--canvas/source/cairo/cairo_spritecanvashelper.cxx547
-rw-r--r--canvas/source/cairo/cairo_spritecanvashelper.hxx149
-rw-r--r--canvas/source/cairo/cairo_spritedevicehelper.cxx204
-rw-r--r--canvas/source/cairo/cairo_spritedevicehelper.hxx98
-rw-r--r--canvas/source/cairo/cairo_spritehelper.cxx186
-rw-r--r--canvas/source/cairo/cairo_spritehelper.hxx118
-rw-r--r--canvas/source/cairo/cairo_spritesurface.hxx73
-rw-r--r--canvas/source/cairo/cairo_surfaceprovider.hxx85
-rw-r--r--canvas/source/cairo/cairo_textlayout.cxx699
-rw-r--r--canvas/source/cairo/cairo_textlayout.hxx123
-rw-r--r--canvas/source/cairo/cairo_win32_cairo.cxx330
-rw-r--r--canvas/source/cairo/cairo_win32_cairo.hxx73
-rw-r--r--canvas/source/cairo/cairo_xlib_cairo.cxx355
-rw-r--r--canvas/source/cairo/cairo_xlib_cairo.hxx109
-rw-r--r--canvas/source/cairo/exports.dxp3
-rw-r--r--canvas/source/cairo/makefile.mk132
-rw-r--r--canvas/source/directx/dx_5rm.cxx2286
-rw-r--r--canvas/source/directx/dx_9rm.cxx1366
-rw-r--r--canvas/source/directx/dx_bitmap.cxx221
-rw-r--r--canvas/source/directx/dx_bitmap.hxx96
-rw-r--r--canvas/source/directx/dx_bitmapcanvashelper.cxx249
-rw-r--r--canvas/source/directx/dx_bitmapcanvashelper.hxx139
-rw-r--r--canvas/source/directx/dx_bitmapprovider.hxx48
-rw-r--r--canvas/source/directx/dx_canvas.cxx258
-rw-r--r--canvas/source/directx/dx_canvas.hxx178
-rw-r--r--canvas/source/directx/dx_canvasbitmap.cxx280
-rw-r--r--canvas/source/directx/dx_canvasbitmap.hxx107
-rw-r--r--canvas/source/directx/dx_canvascustomsprite.cxx126
-rw-r--r--canvas/source/directx/dx_canvascustomsprite.hxx142
-rw-r--r--canvas/source/directx/dx_canvasfont.cxx183
-rw-r--r--canvas/source/directx/dx_canvasfont.hxx107
-rw-r--r--canvas/source/directx/dx_canvashelper.cxx817
-rw-r--r--canvas/source/directx/dx_canvashelper.hxx260
-rw-r--r--canvas/source/directx/dx_canvashelper_texturefill.cxx630
-rw-r--r--canvas/source/directx/dx_config.cxx179
-rw-r--r--canvas/source/directx/dx_config.hxx92
-rw-r--r--canvas/source/directx/dx_devicehelper.cxx239
-rw-r--r--canvas/source/directx/dx_devicehelper.hxx124
-rw-r--r--canvas/source/directx/dx_gdiplususer.cxx84
-rw-r--r--canvas/source/directx/dx_gdiplususer.hxx58
-rw-r--r--canvas/source/directx/dx_graphicsprovider.hxx56
-rw-r--r--canvas/source/directx/dx_ibitmap.hxx73
-rw-r--r--canvas/source/directx/dx_impltools.cxx671
-rw-r--r--canvas/source/directx/dx_impltools.hxx145
-rw-r--r--canvas/source/directx/dx_linepolypolygon.cxx68
-rw-r--r--canvas/source/directx/dx_linepolypolygon.hxx59
-rw-r--r--canvas/source/directx/dx_rendermodule.hxx93
-rw-r--r--canvas/source/directx/dx_sprite.hxx54
-rw-r--r--canvas/source/directx/dx_spritecanvas.cxx214
-rw-r--r--canvas/source/directx/dx_spritecanvas.hxx158
-rw-r--r--canvas/source/directx/dx_spritecanvashelper.cxx385
-rw-r--r--canvas/source/directx/dx_spritecanvashelper.hxx164
-rw-r--r--canvas/source/directx/dx_spritedevicehelper.cxx262
-rw-r--r--canvas/source/directx/dx_spritedevicehelper.hxx117
-rw-r--r--canvas/source/directx/dx_spritehelper.cxx219
-rw-r--r--canvas/source/directx/dx_spritehelper.hxx114
-rw-r--r--canvas/source/directx/dx_surfacebitmap.cxx806
-rw-r--r--canvas/source/directx/dx_surfacebitmap.hxx150
-rw-r--r--canvas/source/directx/dx_surfacegraphics.cxx88
-rw-r--r--canvas/source/directx/dx_surfacegraphics.hxx48
-rw-r--r--canvas/source/directx/dx_textlayout.cxx283
-rw-r--r--canvas/source/directx/dx_textlayout.hxx118
-rw-r--r--canvas/source/directx/dx_textlayout_drawhelper.cxx322
-rw-r--r--canvas/source/directx/dx_textlayout_drawhelper.hxx89
-rw-r--r--canvas/source/directx/dx_vcltools.cxx526
-rw-r--r--canvas/source/directx/dx_vcltools.hxx67
-rw-r--r--canvas/source/directx/dx_winstuff.hxx227
-rw-r--r--canvas/source/directx/exports.dxp3
-rw-r--r--canvas/source/directx/makefile.mk219
-rw-r--r--canvas/source/factory/cf_service.cxx555
-rw-r--r--canvas/source/factory/makefile.mk56
-rw-r--r--canvas/source/null/exports.dxp3
-rw-r--r--canvas/source/null/makefile.mk70
-rw-r--r--canvas/source/null/null_canvasbitmap.cxx87
-rw-r--r--canvas/source/null/null_canvasbitmap.hxx95
-rw-r--r--canvas/source/null/null_canvascustomsprite.cxx108
-rw-r--r--canvas/source/null/null_canvascustomsprite.hxx139
-rw-r--r--canvas/source/null/null_canvasfont.cxx124
-rw-r--r--canvas/source/null/null_canvasfont.hxx98
-rw-r--r--canvas/source/null/null_canvashelper.cxx339
-rw-r--r--canvas/source/null/null_canvashelper.hxx276
-rw-r--r--canvas/source/null/null_devicehelper.cxx242
-rw-r--r--canvas/source/null/null_devicehelper.hxx110
-rw-r--r--canvas/source/null/null_spritecanvas.cxx169
-rw-r--r--canvas/source/null/null_spritecanvas.hxx152
-rw-r--r--canvas/source/null/null_spritecanvashelper.cxx134
-rw-r--r--canvas/source/null/null_spritecanvashelper.hxx138
-rw-r--r--canvas/source/null/null_spritehelper.cxx100
-rw-r--r--canvas/source/null/null_spritehelper.hxx108
-rw-r--r--canvas/source/null/null_textlayout.cxx264
-rw-r--r--canvas/source/null/null_textlayout.hxx110
-rw-r--r--canvas/source/null/null_usagecounter.hxx79
-rw-r--r--canvas/source/null/sprite.hxx50
-rw-r--r--canvas/source/simplecanvas/exports.dxp3
-rw-r--r--canvas/source/simplecanvas/makefile.mk63
-rw-r--r--canvas/source/simplecanvas/simplecanvasimpl.cxx403
-rw-r--r--canvas/source/tools/cachedprimitivebase.cxx115
-rw-r--r--canvas/source/tools/canvascustomspritehelper.cxx499
-rw-r--r--canvas/source/tools/canvastools.cxx1047
-rw-r--r--canvas/source/tools/canvastools.flt3
-rw-r--r--canvas/source/tools/elapsedtime.cxx227
-rw-r--r--canvas/source/tools/imagecachedprimitive.hxx60
-rw-r--r--canvas/source/tools/makefile.mk91
-rw-r--r--canvas/source/tools/page.cxx155
-rw-r--r--canvas/source/tools/page.hxx160
-rw-r--r--canvas/source/tools/pagemanager.cxx225
-rw-r--r--canvas/source/tools/pagemanager.hxx97
-rw-r--r--canvas/source/tools/parametricpolypolygon.cxx293
-rw-r--r--canvas/source/tools/prioritybooster.cxx86
-rw-r--r--canvas/source/tools/propertysethelper.cxx190
-rw-r--r--canvas/source/tools/spriteredrawmanager.cxx523
-rw-r--r--canvas/source/tools/surface.cxx498
-rw-r--r--canvas/source/tools/surface.hxx165
-rw-r--r--canvas/source/tools/surfaceproxy.cxx185
-rw-r--r--canvas/source/tools/surfaceproxy.hxx137
-rw-r--r--canvas/source/tools/surfaceproxymanager.cxx89
-rw-r--r--canvas/source/tools/surfacerect.hxx138
-rw-r--r--canvas/source/tools/verifyinput.cxx929
-rw-r--r--canvas/source/vcl/backbuffer.cxx74
-rw-r--r--canvas/source/vcl/backbuffer.hxx70
-rw-r--r--canvas/source/vcl/bitmapbackbuffer.cxx167
-rw-r--r--canvas/source/vcl/bitmapbackbuffer.hxx106
-rw-r--r--canvas/source/vcl/cachedbitmap.cxx107
-rw-r--r--canvas/source/vcl/cachedbitmap.hxx81
-rw-r--r--canvas/source/vcl/canvas.cxx164
-rw-r--r--canvas/source/vcl/canvas.hxx134
-rw-r--r--canvas/source/vcl/canvasbitmap.cxx147
-rw-r--r--canvas/source/vcl/canvasbitmap.hxx132
-rw-r--r--canvas/source/vcl/canvasbitmaphelper.cxx570
-rw-r--r--canvas/source/vcl/canvasbitmaphelper.hxx132
-rw-r--r--canvas/source/vcl/canvascustomsprite.cxx200
-rw-r--r--canvas/source/vcl/canvascustomsprite.hxx136
-rw-r--r--canvas/source/vcl/canvasfont.cxx191
-rw-r--r--canvas/source/vcl/canvasfont.hxx103
-rw-r--r--canvas/source/vcl/canvashelper.cxx1431
-rw-r--r--canvas/source/vcl/canvashelper.hxx347
-rw-r--r--canvas/source/vcl/canvashelper_texturefill.cxx1185
-rw-r--r--canvas/source/vcl/devicehelper.cxx245
-rw-r--r--canvas/source/vcl/devicehelper.hxx106
-rw-r--r--canvas/source/vcl/exports.dxp3
-rw-r--r--canvas/source/vcl/impltools.cxx547
-rw-r--r--canvas/source/vcl/impltools.hxx205
-rw-r--r--canvas/source/vcl/makefile.mk85
-rw-r--r--canvas/source/vcl/outdevprovider.hxx64
-rw-r--r--canvas/source/vcl/repainttarget.hxx66
-rw-r--r--canvas/source/vcl/services.cxx93
-rw-r--r--canvas/source/vcl/sprite.hxx74
-rw-r--r--canvas/source/vcl/spritecanvas.cxx181
-rw-r--r--canvas/source/vcl/spritecanvas.hxx175
-rw-r--r--canvas/source/vcl/spritecanvashelper.cxx721
-rw-r--r--canvas/source/vcl/spritecanvashelper.hxx181
-rw-r--r--canvas/source/vcl/spritedevicehelper.cxx161
-rw-r--r--canvas/source/vcl/spritedevicehelper.hxx85
-rw-r--r--canvas/source/vcl/spritehelper.cxx446
-rw-r--r--canvas/source/vcl/spritehelper.hxx124
-rw-r--r--canvas/source/vcl/textlayout.cxx499
-rw-r--r--canvas/source/vcl/textlayout.hxx118
-rw-r--r--canvas/source/vcl/windowoutdevholder.cxx60
-rw-r--r--canvas/source/vcl/windowoutdevholder.hxx69
-rw-r--r--canvas/workben/canvasdemo.cxx715
-rw-r--r--canvas/workben/makefile.mk37
223 files changed, 50758 insertions, 0 deletions
diff --git a/canvas/inc/canvas/base/basemutexhelper.hxx b/canvas/inc/canvas/base/basemutexhelper.hxx
new file mode 100644
index 000000000000..d53cd927aae2
--- /dev/null
+++ b/canvas/inc/canvas/base/basemutexhelper.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_BASEMUTEXHELPER_HXX
+#define INCLUDED_CANVAS_BASEMUTEXHELPER_HXX
+
+#include <osl/mutex.hxx>
+
+
+/* Definition of the BaseMutexHelper class */
+
+namespace canvas
+{
+ /** Base class, deriving from ::comphelper::OBaseMutex and
+ initializing its own baseclass with m_aMutex.
+
+ This is necessary to make the CanvasBase, GraphicDeviceBase,
+ etc. classes freely combinable - letting them perform this
+ initialization would prohibit deriving e.g. CanvasBase from
+ GraphicDeviceBase.
+ */
+ template< class Base > class BaseMutexHelper : public Base
+ {
+ public:
+ typedef Base BaseType;
+
+ /** Construct BaseMutexHelper
+
+ This method is the whole purpose of this template:
+ initializing a base class with the provided m_aMutex
+ member (the WeakComponentImplHelper templates need that,
+ as they require the lifetime of the mutex to extend
+ theirs).
+ */
+ BaseMutexHelper() :
+ BaseType( m_aMutex )
+ {
+ }
+
+protected:
+ mutable ::osl::Mutex m_aMutex;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_BASEMUTEXHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/bitmapcanvasbase.hxx b/canvas/inc/canvas/base/bitmapcanvasbase.hxx
new file mode 100644
index 000000000000..234de95b62bd
--- /dev/null
+++ b/canvas/inc/canvas/base/bitmapcanvasbase.hxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_BITMAPCANVASBASE_HXX
+#define INCLUDED_CANVAS_BITMAPCANVASBASE_HXX
+
+#include <canvas/base/canvasbase.hxx>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+
+namespace canvas
+{
+ /** Helper template to handle XBitmapCanvas method forwarding to
+ BitmapCanvasHelper
+
+ Use this helper to handle the XBitmapCanvas part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XBitmapCanvas should be among them (why
+ else would you use this template, then?). Base class must have
+ an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasBase for further contractual requirements towards
+ the CanvasHelper type, and some examples.
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class BitmapCanvasBase :
+ public CanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef CanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+
+ // XBitmapCanvas
+ virtual void SAL_CALL copyRect( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(sourceCanvas, sourceRect, sourceViewState, sourceRenderState,
+ destRect, destViewState, destRenderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.copyRect( this,
+ sourceCanvas,
+ sourceRect,
+ sourceViewState,
+ sourceRenderState,
+ destRect,
+ destViewState,
+ destRenderState );
+ }
+
+ // XBitmap
+ virtual ::com::sun::star::geometry::IntegerSize2D SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getSize();
+ }
+
+ virtual ::sal_Bool SAL_CALL hasAlpha( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.hasAlpha();
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > SAL_CALL getScaledBitmap( const ::com::sun::star::geometry::RealSize2D& newSize,
+ sal_Bool beFast ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getScaledBitmap( newSize, beFast );
+ }
+
+ };
+}
+
+#endif /* INCLUDED_CANVAS_BITMAPCANVASBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/bufferedgraphicdevicebase.hxx b/canvas/inc/canvas/base/bufferedgraphicdevicebase.hxx
new file mode 100644
index 000000000000..daaf985967fd
--- /dev/null
+++ b/canvas/inc/canvas/base/bufferedgraphicdevicebase.hxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_BUFFEREDGRAPHICDEVICEBASE_HXX
+#define INCLUDED_CANVAS_BUFFEREDGRAPHICDEVICEBASE_HXX
+
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XWindowListener.hpp>
+
+#include <canvas/canvastools.hxx>
+#include <canvas/base/graphicdevicebase.hxx>
+
+
+/* Definition of BufferedGraphicDeviceBase class */
+
+namespace canvas
+{
+ /** Helper template base class for XGraphicDevice implementations
+ on windows.
+
+ Use this base class if your target device is a
+ window. Additionally to GraphicDeviceBase, this template
+ provides an implementation of the awt::XWindowListener
+ interface, to receive notifications about state changes of the
+ associated window.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XGraphicDevice should be among them (why else
+ would you use this template, then?). Base class must have an
+ Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have). As the very least,
+ the base class must be derived from uno::XInterface, as some
+ error reporting mechanisms rely on that.
+
+ @tpl DeviceHelper
+ Device helper implementation for the backend in question. This
+ object will be held as a member of this template class, and
+ basically gets forwarded all XGraphicDevice API calls that
+ could not be handled generically.
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+ */
+ template< class Base,
+ class DeviceHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class BufferedGraphicDeviceBase :
+ public GraphicDeviceBase< Base, DeviceHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef GraphicDeviceBase< Base, DeviceHelper, Mutex, UnambiguousBase > BaseType;
+ typedef BufferedGraphicDeviceBase OurType;
+ typedef Mutex MutexType;
+
+ BufferedGraphicDeviceBase() :
+ mxWindow(),
+ maBounds(),
+ mbIsVisible( false ),
+ mbIsTopLevel( false )
+ {
+ BaseType::maPropHelper.addProperties( PropertySetHelper::MakeMap
+ ("Window",
+ boost::bind(&OurType::getXWindow,
+ this)));
+ }
+
+ // XGraphicDevice
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBufferController > SAL_CALL getBufferController( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return this;
+ }
+
+ // XBufferController
+ virtual ::sal_Int32 SAL_CALL createBuffers( ::sal_Int32 nBuffers ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyRange( nBuffers, (sal_Int32)1 );
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maDeviceHelper.createBuffers( nBuffers );
+ }
+
+ virtual void SAL_CALL destroyBuffers( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::maDeviceHelper.destroyBuffers();
+ }
+
+ virtual ::sal_Bool SAL_CALL showBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maDeviceHelper.showBuffer( mbIsVisible, bUpdateAll );
+ }
+
+ virtual ::sal_Bool SAL_CALL switchBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maDeviceHelper.switchBuffer( mbIsVisible, bUpdateAll );
+ }
+
+
+ /** Set corresponding canvas window
+
+ Use this method to set the window this canvas displays
+ on. Comes in handy when the canvas needs to adapt size or
+ output position to the changing window.
+
+ Whenever the bounds of the window change, <code>void
+ notifySizeUpdate( const awt::Rectangle& rBounds )</code>
+ is called, with rBounds the window bound rect relative to
+ the frame window.
+ */
+ void setWindow( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::awt::XWindow2 >& rWindow )
+ {
+ if( mxWindow.is() )
+ mxWindow->removeWindowListener( this );
+
+ mxWindow = rWindow;
+
+ if( mxWindow.is() )
+ {
+ mbIsVisible = mxWindow->isVisible();
+ mbIsTopLevel =
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTopWindow >(
+ mxWindow,
+ ::com::sun::star::uno::UNO_QUERY ).is();
+
+ maBounds = transformBounds( mxWindow->getPosSize() );
+ mxWindow->addWindowListener( this );
+ }
+ }
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow2 > getWindow() const
+ {
+ return mxWindow;
+ }
+
+ ::com::sun::star::uno::Any getXWindow() const
+ {
+ return ::com::sun::star::uno::makeAny(mxWindow);
+ }
+
+#if defined __SUNPRO_CC
+ using Base::disposing;
+#endif
+ virtual void SAL_CALL disposing()
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ if( mxWindow.is() )
+ {
+ mxWindow->removeWindowListener(this);
+ mxWindow.clear();
+ }
+
+ // pass on to base class
+ BaseType::disposing();
+ }
+
+ ::com::sun::star::awt::Rectangle transformBounds( const ::com::sun::star::awt::Rectangle& rBounds )
+ {
+ // notifySizeUpdate's bounds are relative to the toplevel
+ // window
+ if( !mbIsTopLevel )
+ return tools::getAbsoluteWindowRect(
+ rBounds,
+ mxWindow );
+ else
+ return ::com::sun::star::awt::Rectangle( 0,0,rBounds.Width,rBounds.Height );
+ }
+
+ void boundsChanged( const ::com::sun::star::awt::WindowEvent& e )
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ const ::com::sun::star::awt::Rectangle& rNewBounds(
+ transformBounds(
+ ::com::sun::star::awt::Rectangle( e.X,
+ e.Y,
+ e.Width,
+ e.Height )));
+
+ if( rNewBounds.X != maBounds.X ||
+ rNewBounds.Y != maBounds.Y ||
+ rNewBounds.Width != maBounds.Width ||
+ rNewBounds.Height != maBounds.Height )
+ {
+ maBounds = rNewBounds;
+ BaseType::maDeviceHelper.notifySizeUpdate( maBounds );
+ }
+ }
+
+ // XWindowListener
+ virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ if( Source.Source == mxWindow )
+ mxWindow.clear();
+ }
+
+ virtual void SAL_CALL windowResized( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ boundsChanged( e );
+ }
+
+ virtual void SAL_CALL windowMoved( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ boundsChanged( e );
+ }
+
+ virtual void SAL_CALL windowShown( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ mbIsVisible = true;
+ }
+
+ virtual void SAL_CALL windowHidden( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ mbIsVisible = false;
+ }
+
+ protected:
+ ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow2 > mxWindow;
+
+ /// Current bounds of the owning Window
+ ::com::sun::star::awt::Rectangle maBounds;
+
+ /// True, if the window this canvas is contained in, is visible
+ bool mbIsVisible;
+
+ private:
+ /// True, if the window this canvas is contained in, is a toplevel window
+ bool mbIsTopLevel;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_BUFFEREDGRAPHICDEVICEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/cachedprimitivebase.hxx b/canvas/inc/canvas/base/cachedprimitivebase.hxx
new file mode 100644
index 000000000000..e9ef09dff3f2
--- /dev/null
+++ b/canvas/inc/canvas/base/cachedprimitivebase.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_CACHEDPRIMITIVEBASE_HXX
+#define INCLUDED_CANVAS_CACHEDPRIMITIVEBASE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCachedPrimitive.hpp>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+
+/* Definition of CachedPrimitiveBase class */
+
+namespace canvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XCachedPrimitive,
+ ::com::sun::star::lang::XServiceInfo > CachedPrimitiveBase_Base;
+
+ /** Base class, providing common functionality for implementers of
+ the XCachedPrimitive interface.
+ */
+ class CachedPrimitiveBase : public CachedPrimitiveBase_Base,
+ public ::comphelper::OBaseMutex
+ {
+ public:
+
+ /** Create an XCachedPrimitive for given target canvas
+
+ @param rUsedViewState
+ The viewstate the original object was rendered with
+
+ @param rTarget
+ The target canvas the repaint should happen on.
+
+ @param bFailForChangedViewTransform
+ When true, derived classes will never receive doRedraw()
+ calls with dissimilar view transformations and
+ bSameViewTransform set to false. This is useful for cached
+ objects where re-transforming the generated output is not
+ desirable, e.g. for hinted font output.
+ */
+ CachedPrimitiveBase( const ::com::sun::star::rendering::ViewState& rUsedViewState,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& rTarget,
+ bool bFailForChangedViewTransform );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XCachedPrimitive
+ virtual ::sal_Int8 SAL_CALL redraw( const ::com::sun::star::rendering::ViewState& aState ) throw (::com::sun::star::lang::IllegalArgumentException, ::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);
+
+ protected:
+ ~CachedPrimitiveBase(); // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ private:
+ CachedPrimitiveBase( const CachedPrimitiveBase& );
+ CachedPrimitiveBase& operator=( const CachedPrimitiveBase& );
+
+ /** Actually perform the requested redraw.
+
+ Clients must override this method, instead of the public
+ redraw() one.
+
+ @param rNewState
+ The viewstate to redraw with
+
+ @param rOldState
+ The viewstate this cache object was created with.
+
+ @param rTargetCanvas
+ Target canvas to render to.
+
+ @param bSameViewTransform
+ When true, rNewState and rOldState have the same transformation.
+ */
+ 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 ) = 0;
+
+ ::com::sun::star::rendering::ViewState maUsedViewState;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > mxTarget;
+ const bool mbFailForChangedViewTransform;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_CACHEDPRIMITIVEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/canvasbase.hxx b/canvas/inc/canvas/base/canvasbase.hxx
new file mode 100644
index 000000000000..5af2201ab2b3
--- /dev/null
+++ b/canvas/inc/canvas/base/canvasbase.hxx
@@ -0,0 +1,486 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_CANVASBASE_HXX
+#define INCLUDED_CANVAS_CANVASBASE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <osl/mutex.hxx>
+#include <canvas/verifyinput.hxx>
+
+
+namespace canvas
+{
+ /** Helper template to handle XCanvas method forwarding to CanvasHelper
+
+ Use this helper to handle the XCanvas part of your
+ implementation. In theory, we could have provided CanvasHelper
+ and CanvasBase as a single template, but that would duplicate
+ a lot of code now residing in CanvasHelper only.
+
+ This template basically interposes itself between the full
+ interface you implement (i.e. not restricted to XCanvas. The
+ problem with UNO partial interface implementation actually is,
+ that you cannot do it the plain way, since deriving from a
+ common base subclass always introduces the whole set of pure
+ virtuals, that your baseclass helper just overrided) and your
+ implementation class. You then only have to implement the
+ functionality <em>besides</em> XCanvas.
+
+ <pre>
+ Example:
+ typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::rendering::XSpriteCanvas,
+ ::com::sun::star::lang::XInitialization,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::lang::XServiceName > CanvasBase_Base;
+ typedef ::canvas::internal::CanvasBase< CanvasBase_Base, CanvasHelper > ExampleCanvas_Base;
+
+ class ExampleCanvas : public ExampleCanvas_Base,
+ public SpriteSurface,
+ public RepaintTarget
+ {
+ };
+ </pre>
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XCanvas should be among them (why else
+ would you use this template, then?). Base class must have an
+ Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have). As the very least,
+ the base class must be derived from uno::XInterface, as some
+ error reporting mechanisms rely on that.
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question. This
+ object will be held as a member of this template class, and
+ basically gets forwarded all XCanvas API calls. Furthermore,
+ everytime the canvas API semantically changes the content of
+ the canvas, CanvasHelper::modifying() will get called
+ (<em>before</em> the actual modification takes place).
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class CanvasBase :
+ public Base
+ {
+ public:
+ typedef Base BaseType;
+ typedef CanvasHelper HelperType;
+ typedef Mutex MutexType;
+ typedef UnambiguousBase UnambiguousBaseType;
+
+ /** Create CanvasBase
+ */
+ CanvasBase() :
+ maCanvasHelper(),
+ mbSurfaceDirty( true )
+ {
+ }
+
+#if defined __SUNPRO_CC
+ using Base::disposing;
+#endif
+ virtual void SAL_CALL disposing()
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ maCanvasHelper.disposing();
+
+ // pass on to base class
+ BaseType::disposing();
+ }
+
+ // XCanvas
+ virtual void SAL_CALL clear() throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ maCanvasHelper.clear();
+ }
+
+ virtual void SAL_CALL drawPoint( const ::com::sun::star::geometry::RealPoint2D& aPoint,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aPoint, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ maCanvasHelper.drawPoint( this, aPoint, viewState, renderState );
+ }
+
+ virtual void SAL_CALL drawLine( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aStartPoint, aEndPoint, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ maCanvasHelper.drawLine( this, aStartPoint, aEndPoint, viewState, renderState );
+ }
+
+ virtual void SAL_CALL drawBezier( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aBezierSegment, aEndPoint, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ maCanvasHelper.drawBezier( this, aBezierSegment, aEndPoint, viewState, renderState );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.drawPolyPolygon( this, xPolyPolygon, viewState, renderState );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ strokePolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.strokePolyPolygon( this, xPolyPolygon, viewState, renderState, strokeAttributes );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ strokeTexturedPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.strokeTexturedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, strokeAttributes );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ strokeTextureMappedPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, textures, xMapping, strokeAttributes,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.strokeTextureMappedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, xMapping, strokeAttributes );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL
+ queryStrokeShapes( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.queryStrokeShapes( this, xPolyPolygon, viewState, renderState, strokeAttributes );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ fillPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.fillPolyPolygon( this, xPolyPolygon, viewState, renderState );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ fillTexturedPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, textures,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.fillTexturedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ fillTextureMappedPolyPolygon( 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 ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xPolyPolygon, viewState, renderState, textures, xMapping,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.fillTextureMappedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, xMapping );
+ }
+
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > SAL_CALL
+ createFont( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(fontRequest,
+ // dummy, to keep argPos in sync
+ fontRequest,
+ fontMatrix,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maCanvasHelper.createFont( this, fontRequest, extraFontProperties, fontMatrix );
+ }
+
+
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::FontInfo > SAL_CALL
+ queryAvailableFonts( const ::com::sun::star::rendering::FontInfo& aFilter,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aFontProperties ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aFilter,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maCanvasHelper.queryAvailableFonts( this, aFilter, aFontProperties );
+ }
+
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawText( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xFont, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+ tools::verifyRange( textDirection,
+ ::com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
+ ::com::sun::star::rendering::TextDirection::STRONG_RIGHT_TO_LEFT );
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.drawText( this, text, xFont, viewState, renderState, textDirection );
+ }
+
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawTextLayout( 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 ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(layoutetText, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.drawTextLayout( this, layoutetText, viewState, renderState );
+ }
+
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawBitmap( 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 ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xBitmap, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.drawBitmap( this, xBitmap, viewState, renderState );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawBitmapModulated( 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 ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xBitmap, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ mbSurfaceDirty = true;
+ maCanvasHelper.modifying();
+
+ return maCanvasHelper.drawBitmapModulated( this, xBitmap, viewState, renderState );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice > SAL_CALL
+ getDevice() throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maCanvasHelper.getDevice();
+ }
+
+ protected:
+ ~CanvasBase() {} // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ HelperType maCanvasHelper;
+ mutable bool mbSurfaceDirty;
+
+ private:
+ CanvasBase( const CanvasBase& );
+ CanvasBase& operator=( const CanvasBase& );
+ };
+}
+
+#endif /* INCLUDED_CANVAS_CANVASBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/canvascustomspritebase.hxx b/canvas/inc/canvas/base/canvascustomspritebase.hxx
new file mode 100644
index 000000000000..4d00e7b7a206
--- /dev/null
+++ b/canvas/inc/canvas/base/canvascustomspritebase.hxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_CANVASCUSTOMSPRITEBASE_HXX
+#define INCLUDED_CANVAS_CANVASCUSTOMSPRITEBASE_HXX
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/base/sprite.hxx>
+
+#include <boost/utility.hpp>
+
+
+namespace canvas
+{
+ /** Helper template to handle XCustomSprite method forwarding to
+ CanvasCustomSpriteHelper
+
+ Use this helper to handle the XCustomSprite part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XCustomSprite and Sprite should be among
+ them (why else would you use this template, then?). Base class
+ must have an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl SpriteHelper
+ Sprite helper implementation for the backend in question
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasCustomSpriteHelper for further contractual
+ requirements towards the SpriteHelper type, and some examples.
+ */
+ template< class Base,
+ class SpriteHelper,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class CanvasCustomSpriteBase :
+ public IntegerBitmapBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef IntegerBitmapBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+ typedef SpriteHelper SpriteHelperType;
+
+ CanvasCustomSpriteBase() :
+ maSpriteHelper()
+ {
+ }
+
+ /** Object is being disposed.
+
+ Called from the cppu helper base, to notify disposal of
+ this object. Already releases all internal references.
+
+ @derive when overriding this method in derived classes,
+ <em>always</em> call the base class' method!
+ */
+ virtual void SAL_CALL disposing()
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.disposing();
+
+ // pass on to base class
+ BaseType::disposing();
+ }
+
+ // XCanvas: selectively override base's methods here, for opacity tracking
+ virtual void SAL_CALL clear() throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.clearingContent( this );
+
+ // and forward to base class, which handles the actual rendering
+ return BaseType::clear();
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
+ drawBitmap( 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 ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(xBitmap, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.checkDrawBitmap( this, xBitmap, viewState, renderState );
+
+ // and forward to base class, which handles the actual rendering
+ return BaseType::drawBitmap( xBitmap,
+ viewState,
+ renderState );
+ }
+
+ // TODO(F3): If somebody uses the XIntegerBitmap methods to
+ // clear pixel (setting alpha != 1.0 there), or a compositing
+ // mode results in similar alpha, maSpriteHelper might
+ // errorneously report fully opaque sprites. Effectively, all
+ // render methods must be overridden here; or better,
+ // functionality provided at the baseclass.
+
+ // XSprite
+ virtual void SAL_CALL setAlpha( double alpha ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyRange( alpha, 0.0, 1.0 );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.setAlpha( this, alpha );
+ }
+
+ virtual void SAL_CALL move( const ::com::sun::star::geometry::RealPoint2D& aNewPos,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aNewPos, viewState, renderState,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.move( this, aNewPos, viewState, renderState );
+ }
+
+ virtual void SAL_CALL transform( const ::com::sun::star::geometry::AffineMatrix2D& aTransformation ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(aTransformation,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.transform( this, aTransformation );
+ }
+
+ virtual void SAL_CALL clip( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& aClip ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ // NULL xClip explicitely allowed here (to clear clipping)
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.clip( this, aClip );
+ }
+
+ virtual void SAL_CALL setPriority( double nPriority ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.setPriority( this, nPriority );
+ }
+
+ virtual void SAL_CALL show() throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.show( this );
+ }
+
+ virtual void SAL_CALL hide() throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maSpriteHelper.hide( this );
+ }
+
+ // XCustomSprite
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > SAL_CALL
+ getContentCanvas() throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return this;
+ }
+
+ // Sprite
+ virtual bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return maSpriteHelper.isAreaUpdateOpaque( rUpdateArea );
+ }
+
+ virtual bool isContentChanged() const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::mbSurfaceDirty;
+ }
+
+ virtual ::basegfx::B2DPoint getPosPixel() const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return maSpriteHelper.getPosPixel();
+ }
+
+ virtual ::basegfx::B2DVector getSizePixel() const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return maSpriteHelper.getSizePixel();
+ }
+
+ virtual ::basegfx::B2DRange getUpdateArea() const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return maSpriteHelper.getUpdateArea();
+ }
+
+ virtual double getPriority() const
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return maSpriteHelper.getPriority();
+ }
+
+ protected:
+ SpriteHelperType maSpriteHelper;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_CANVASCUSTOMSPRITEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/canvascustomspritehelper.hxx b/canvas/inc/canvas/base/canvascustomspritehelper.hxx
new file mode 100644
index 000000000000..e37e77c5ec61
--- /dev/null
+++ b/canvas/inc/canvas/base/canvascustomspritehelper.hxx
@@ -0,0 +1,296 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_CANVASCUSTOMSPRITEHELPER_HXX
+#define INCLUDED_CANVAS_CANVASCUSTOMSPRITEHELPER_HXX
+
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/base/spritesurface.hxx>
+
+
+namespace canvas
+{
+ /* Definition of CanvasCustomSpriteHelper class */
+
+ /** Base class for an XSprite helper implementation - to be used
+ in concert with CanvasCustomSpriteBase
+ */
+ class CanvasCustomSpriteHelper
+ {
+ public:
+ CanvasCustomSpriteHelper();
+ virtual ~CanvasCustomSpriteHelper() {}
+
+ /** Init helper
+
+ @param rSpriteSize
+ Requested size of the sprite, as passed to the
+ XSpriteCanvas::createCustomSprite() method
+
+ @param rOwningSpriteCanvas
+ The XSpriteCanvas this sprite is displayed on
+ */
+ void init( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteSurface::Reference& rOwningSpriteCanvas );
+
+ /** Object is being disposed, release all internal references
+
+ @derive when overriding this method in derived classes,
+ <em>always</em> call the base class' method!
+ */
+ void disposing();
+
+ // XCanvas
+ /// need to call this method for XCanvas::clear(), for opacity tracking
+ void clearingContent( const Sprite::Reference& rSprite );
+
+ /// need to call this method for XCanvas::drawBitmap(), for opacity tracking
+ void checkDrawBitmap( const Sprite::Reference& rSprite,
+ 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 );
+
+ // XSprite
+ void setAlpha( const Sprite::Reference& rSprite,
+ double alpha );
+ void move( const Sprite::Reference& rSprite,
+ const ::com::sun::star::geometry::RealPoint2D& aNewPos,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ void transform( const Sprite::Reference& rSprite,
+ const ::com::sun::star::geometry::AffineMatrix2D& aTransformation );
+ void clip( const Sprite::Reference& rSprite,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& aClip );
+ void setPriority( const Sprite::Reference& rSprite,
+ double nPriority );
+ void show( const Sprite::Reference& rSprite );
+ void hide( const Sprite::Reference& rSprite );
+
+ // Sprite
+ bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const;
+ ::basegfx::B2DPoint getPosPixel() const;
+ ::basegfx::B2DVector getSizePixel() const;
+ ::basegfx::B2DRange getUpdateArea() const;
+ double getPriority() const;
+
+ // redraw must be implemented by derived - non sensible default implementation
+ // void redraw( const Sprite::Reference& rSprite,
+ // const ::basegfx::B2DPoint& rPos ) const;
+
+
+ // Helper methods for derived classes
+ // ----------------------------------
+
+ /// Calc sprite update area from given raw sprite bounds
+ ::basegfx::B2DRange getUpdateArea( const ::basegfx::B2DRange& rUntransformedSpriteBounds ) const;
+
+ /// Calc update area for unclipped sprite content
+ ::basegfx::B2DRange getFullSpriteRect() const;
+
+ /** Returns true, if sprite content bitmap is fully opaque.
+
+ This does not take clipping or transformation into
+ account, but only denotes that the sprite bitmap's alpha
+ channel is all 1.0
+ */
+ bool isContentFullyOpaque() const { return mbIsContentFullyOpaque; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasAlphaChanged() const { return mbAlphaDirty; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasPositionChanged() const { return mbPositionDirty; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasTransformChanged() const { return mbTransformDirty; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasClipChanged() const { return mbClipDirty; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasPrioChanged() const { return mbPrioDirty; }
+
+ /// Returns true, if transformation has changed since last transformUpdated() call
+ bool hasVisibilityChanged() const { return mbVisibilityDirty; }
+
+ /// Retrieve current alpha value
+ double getAlpha() const { return mfAlpha; }
+
+ /// Retrieve current clip
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& getClip() const { return mxClipPoly; }
+
+ const ::basegfx::B2DHomMatrix& getTransformation() const { return maTransform; }
+
+ /// Retrieve current activation state
+ bool isActive() const { return mbActive; }
+
+ protected:
+ /** Notifies that caller is again in sync with current alph
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void alphaUpdated() const { mbAlphaDirty=false; }
+
+ /** Notifies that caller is again in sync with current position
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void positionUpdated() const { mbPositionDirty=false; }
+
+ /** Notifies that caller is again in sync with current transformation
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void transformUpdated() const { mbTransformDirty=false; }
+
+ /** Notifies that caller is again in sync with current clip
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void clipUpdated() const { mbClipDirty=false; }
+
+ /** Notifies that caller is again in sync with current priority
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void prioUpdated() const { mbPrioDirty=false; }
+
+ /** Notifies that caller is again in sync with current visibility
+
+ const, but modifies state visible to derived
+ classes. beware of passing this information to the
+ outside!
+ */
+ void visibilityUpdated() const { mbVisibilityDirty=false; }
+
+ private:
+ CanvasCustomSpriteHelper( const CanvasCustomSpriteHelper& );
+ CanvasCustomSpriteHelper& operator=( const CanvasCustomSpriteHelper& );
+
+ /** Called to convert an API polygon to a basegfx polygon
+
+ @derive Needs to be provided by backend-specific code
+ */
+ virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPoly ) const = 0;
+
+ /** Update clip information from current state
+
+ This method recomputes the maCurrClipBounds and
+ mbIsCurrClipRectangle members from the current clip and
+ transformation. IFF the clip changed from rectangular to
+ rectangular again, this method issues a sequence of
+ optimized SpriteSurface::updateSprite() calls.
+
+ @return true, if SpriteSurface::updateSprite() was already
+ called within this method.
+ */
+ bool updateClipState( const Sprite::Reference& rSprite );
+
+ // --------------------------------------------------------------------
+
+ /// Owning sprite canvas
+ SpriteSurface::Reference mpSpriteCanvas;
+
+ /** Currently active clip area.
+
+ This member is either empty, denoting that the current
+ clip shows the full sprite content, or contains a
+ rectangular subarea of the sprite, outside of which
+ the sprite content is fully clipped.
+
+ @see mbIsCurrClipRectangle
+ */
+ ::basegfx::B2DRange maCurrClipBounds;
+
+ // sprite state
+ ::basegfx::B2DPoint maPosition;
+ ::basegfx::B2DVector maSize;
+ ::basegfx::B2DHomMatrix maTransform;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D > mxClipPoly;
+ double mfPriority;
+ double mfAlpha;
+ bool mbActive; // true, if not hidden
+
+ /** If true, denotes that the current sprite clip is a true
+ rectangle, i.e. maCurrClipBounds <em>exactly</em>
+ describes the visible area of the sprite.
+
+ @see maCurrClipBounds
+ */
+ bool mbIsCurrClipRectangle;
+
+ /** Redraw speedup.
+
+ When true, this flag denotes that the current sprite
+ content is fully opaque, thus, that blits to the screen do
+ neither have to take alpha into account, nor prepare any
+ background for the sprite area.
+ */
+ mutable bool mbIsContentFullyOpaque;
+
+ /// True, iff mfAlpha has changed
+ mutable bool mbAlphaDirty;
+
+ /// True, iff maPosition has changed
+ mutable bool mbPositionDirty;
+
+ /// True, iff maTransform has changed
+ mutable bool mbTransformDirty;
+
+ /// True, iff mxClipPoly has changed
+ mutable bool mbClipDirty;
+
+ /// True, iff mnPriority has changed
+ mutable bool mbPrioDirty;
+
+ /// True, iff mbActive has changed
+ mutable bool mbVisibilityDirty;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_CANVASCUSTOMSPRITEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/doublebitmapbase.hxx b/canvas/inc/canvas/base/doublebitmapbase.hxx
new file mode 100644
index 000000000000..912ef2c193b4
--- /dev/null
+++ b/canvas/inc/canvas/base/doublebitmapbase.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_DOUBLEBITMAPBASE_HXX
+#define INCLUDED_CANVAS_DOUBLEBITMAPBASE_HXX
+
+#include <com/sun/star/rendering/XIeeeDoubleBitmap.hpp>
+#include <canvas/bitmapcanvasbase.hxx>
+
+
+namespace canvas
+{
+ /** Helper template to handle XIeeeDoubleBitmap method forwarding to
+ BitmapCanvasHelper
+
+ Use this helper to handle the XIeeeDoubleBitmap part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XIeeeDoubleBitmap should be among them (why
+ else would you use this template, then?). Base class must have
+ an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasBase for further contractual requirements towards
+ the CanvasHelper type, and some examples.
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class DoubleBitmapBase :
+ public BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+
+ // XIeeeDoubleBitmap
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getData( ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::rendering::VolatileContentDestroyedException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(rect, this);
+ verifyIndexRange(rect, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getData( bitmapLayout,
+ rect );
+ }
+
+ virtual void SAL_CALL setData( const ::com::sun::star::uno::Sequence< double >& data,
+ const ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(bitmapLayout, rect, this);
+ verifyIndexRange(rect, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setData( data, bitmapLayout, rect );
+ }
+
+ virtual void SAL_CALL setPixel( const ::com::sun::star::uno::Sequence< double >& color,
+ const ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(bitmapLayout, pos, this);
+ verifyIndexRange(pos, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setPixel( color, bitmapLayout, pos );
+ }
+
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getPixel( ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::rendering::VolatileContentDestroyedException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(pos, this);
+ verifyIndexRange(pos, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getPixel( bitmapLayout,
+ pos );
+ }
+
+ virtual ::com::sun::star::rendering::FloatingPointBitmapLayout SAL_CALL getMemoryLayout( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getMemoryLayout();
+ }
+ };
+}
+
+#endif /* INCLUDED_CANVAS_DOUBLEBITMAPBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/floatbitmapbase.hxx b/canvas/inc/canvas/base/floatbitmapbase.hxx
new file mode 100644
index 000000000000..b566697f87a3
--- /dev/null
+++ b/canvas/inc/canvas/base/floatbitmapbase.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_FLOATBITMAPBASE_HXX
+#define INCLUDED_CANVAS_FLOATBITMAPBASE_HXX
+
+#include <com/sun/star/rendering/XIeeeFloatBitmap.hpp>
+#include <canvas/bitmapcanvasbase.hxx>
+
+
+namespace canvas
+{
+ /** Helper template to handle XIeeeFloatBitmap method forwarding to
+ BitmapCanvasHelper
+
+ Use this helper to handle the XIeeeFloatBitmap part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XIeeeFloatBitmap should be among them (why
+ else would you use this template, then?). Base class must have
+ an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasBase for further contractual requirements towards
+ the CanvasHelper type, and some examples.
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class FloatBitmapBase :
+ public BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+
+ // XIeeeFloatBitmap
+ virtual ::com::sun::star::uno::Sequence< float > SAL_CALL getData( ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::rendering::VolatileContentDestroyedException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(rect,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ verifyIndexRange(rect, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getData( bitmapLayout,
+ rect );
+ }
+
+ virtual void SAL_CALL setData( const ::com::sun::star::uno::Sequence< float >& data,
+ const ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(bitmapLayout, rect,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ verifyIndexRange(rect, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setData( data, bitmapLayout, rect );
+ }
+
+ virtual void SAL_CALL setPixel( const ::com::sun::star::uno::Sequence< float >& color,
+ const ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(bitmapLayout, pos,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ verifyIndexRange(pos, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setPixel( color, bitmapLayout, pos );
+ }
+
+ virtual ::com::sun::star::uno::Sequence< float > SAL_CALL getPixel( ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::rendering::VolatileContentDestroyedException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ verifyInput(pos,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ verifyIndexRange(pos, getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getPixel( bitmapLayout,
+ pos );
+ }
+
+ virtual ::com::sun::star::rendering::FloatingPointBitmapLayout SAL_CALL getMemoryLayout( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getMemoryLayout();
+ }
+ };
+}
+
+#endif /* INCLUDED_CANVAS_FLOATBITMAPBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/graphicdevicebase.hxx b/canvas/inc/canvas/base/graphicdevicebase.hxx
new file mode 100644
index 000000000000..54c8fcde0665
--- /dev/null
+++ b/canvas/inc/canvas/base/graphicdevicebase.hxx
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_GRAPHICDEVICEBASE_HXX
+#define INCLUDED_CANVAS_GRAPHICDEVICEBASE_HXX
+
+#include <rtl/ref.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XColorSpace.hpp>
+
+#include <canvas/parametricpolypolygon.hxx>
+#include <canvas/propertysethelper.hxx>
+
+
+/* Definition of GraphicDeviceBase class */
+
+namespace canvas
+{
+ /** Helper template base class for XGraphicDevice implementations.
+
+ This base class provides partial implementations of the
+ XGraphicDevice-related interface, such as XColorSpace.
+
+ This template basically interposes itself between the full
+ interface you implement (i.e. not restricted to XGraphicDevice
+ etc.). The problem with UNO partial interface implementation
+ actually is, that you cannot do it the plain way, since
+ deriving from a common base subclass always introduces the
+ whole set of pure virtuals, that your baseclass helper just
+ overrided) and your implementation class. You then only have
+ to implement the functionality <em>besides</em>
+ XGraphicDevice. If you want to support the optional debug
+ XUpdatable interface, also add that to the base classes
+ (client code will call the corresponding update() method,
+ whenever a burst of animations is over).
+
+ <pre>
+ Example:
+ typedef ::cppu::WeakComponentImplHelper5< ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::rendering::XColorSpace,
+ ::com::sun::star::rendering::XPropertySet,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
+ typedef ::canvas::internal::GraphicDeviceBase< GraphicDeviceBase, DeviceHelper > ExampleDevice_Base;
+
+ class ExampleDevice : public ExampleDevice_Base
+ {
+ };
+ </pre>
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XGraphicDevice should be among them (why else
+ would you use this template, then?). Base class must have an
+ Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have). As the very least,
+ the base class must be derived from uno::XInterface, as some
+ error reporting mechanisms rely on that.
+
+ @tpl DeviceHelper
+ Device helper implementation for the backend in question. This
+ object will be held as a member of this template class, and
+ basically gets forwarded all XGraphicDevice API calls that
+ could not be handled generically.
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ BaseMutexHelper-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+ */
+ template< class Base,
+ class DeviceHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class GraphicDeviceBase :
+ public Base
+ {
+ public:
+ typedef Base BaseType;
+ typedef DeviceHelper DeviceHelperType;
+ typedef Mutex MutexType;
+ typedef UnambiguousBase UnambiguousBaseType;
+ typedef GraphicDeviceBase ThisType;
+
+ typedef ::rtl::Reference< GraphicDeviceBase > Reference;
+
+ GraphicDeviceBase() :
+ maDeviceHelper(),
+ maPropHelper(),
+ mbDumpScreenContent(false)
+ {
+ maPropHelper.initProperties( PropertySetHelper::MakeMap
+ ("HardwareAcceleration",
+ boost::bind(&DeviceHelper::isAccelerated,
+ boost::ref(maDeviceHelper)))
+ ("DeviceHandle",
+ boost::bind(&DeviceHelper::getDeviceHandle,
+ boost::ref(maDeviceHelper)))
+ ("SurfaceHandle",
+ boost::bind(&DeviceHelper::getSurfaceHandle,
+ boost::ref(maDeviceHelper)))
+ ("DumpScreenContent",
+ boost::bind(&ThisType::getDumpScreenContent,
+ this),
+ boost::bind(&ThisType::setDumpScreenContent,
+ this,
+ _1)));
+ }
+
+#if defined __SUNPRO_CC
+ using Base::disposing;
+#endif
+ virtual void SAL_CALL disposing()
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ maDeviceHelper.disposing();
+
+ // pass on to base class
+ cppu::WeakComponentImplHelperBase::disposing();
+ }
+
+ // XGraphicDevice
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBufferController > SAL_CALL getBufferController( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBufferController >();
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XColorSpace > SAL_CALL getDeviceColorSpace( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.getColorSpace();
+ }
+
+ virtual ::com::sun::star::geometry::RealSize2D SAL_CALL getPhysicalResolution( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.getPhysicalResolution();
+ }
+
+ virtual ::com::sun::star::geometry::RealSize2D SAL_CALL getPhysicalSize( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.getPhysicalSize();
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XLinePolyPolygon2D > SAL_CALL createCompatibleLinePolyPolygon( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& points ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createCompatibleLinePolyPolygon( this, points );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBezierPolyPolygon2D > SAL_CALL createCompatibleBezierPolyPolygon( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > >& points ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createCompatibleBezierPolyPolygon( this, points );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > SAL_CALL createCompatibleBitmap( const ::com::sun::star::geometry::IntegerSize2D& size ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyBitmapSize(size,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createCompatibleBitmap( this, size );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > SAL_CALL createVolatileBitmap( const ::com::sun::star::geometry::IntegerSize2D& size ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyBitmapSize(size,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createVolatileBitmap( this, size );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > SAL_CALL createCompatibleAlphaBitmap( const ::com::sun::star::geometry::IntegerSize2D& size ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyBitmapSize(size,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createCompatibleAlphaBitmap( this, size );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > SAL_CALL createVolatileAlphaBitmap( const ::com::sun::star::geometry::IntegerSize2D& size ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyBitmapSize(size,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< UnambiguousBaseType* >(this));
+
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.createVolatileAlphaBitmap( this, size );
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > SAL_CALL getParametricPolyPolygonFactory( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return this;
+ }
+
+ virtual ::sal_Bool SAL_CALL hasFullScreenMode( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.hasFullScreenMode();
+ }
+
+ virtual ::sal_Bool SAL_CALL enterFullScreenMode( ::sal_Bool bEnter ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ return maDeviceHelper.enterFullScreenMode( bEnter );
+ }
+
+ // XMultiServiceFactory
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
+ {
+ return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
+ ParametricPolyPolygon::create(this,
+ aServiceSpecifier,
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >()));
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::rtl::OUString& aServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
+ {
+ return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
+ ParametricPolyPolygon::create(this,
+ aServiceSpecifier,
+ Arguments));
+ }
+
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return ParametricPolyPolygon::getAvailableServiceNames();
+ }
+
+
+ // XUpdatable
+ virtual void SAL_CALL update() throw (com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+
+ if( mbDumpScreenContent )
+ maDeviceHelper.dumpScreenContent();
+ }
+
+
+ // XPropertySet
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() throw (::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ return maPropHelper.getPropertySetInfo();
+ }
+
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::beans::PropertyVetoException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ maPropHelper.setPropertyValue( aPropertyName, aValue );
+ }
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& aPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ return maPropHelper.getPropertyValue( aPropertyName );
+ }
+
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ maPropHelper.addPropertyChangeListener( aPropertyName,
+ xListener );
+ }
+
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ maPropHelper.removePropertyChangeListener( aPropertyName,
+ xListener );
+ }
+
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ maPropHelper.addVetoableChangeListener( aPropertyName,
+ xListener );
+ }
+
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ MutexType aGuard( BaseType::m_aMutex );
+ maPropHelper.removeVetoableChangeListener( aPropertyName,
+ xListener );
+ }
+
+ protected:
+ ~GraphicDeviceBase() {} // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ ::com::sun::star::uno::Any getDumpScreenContent() const
+ {
+ return ::com::sun::star::uno::makeAny( mbDumpScreenContent );
+ }
+
+ void setDumpScreenContent( const ::com::sun::star::uno::Any& rAny )
+ {
+ // TODO(Q1): this was mbDumpScreenContent =
+ // rAny.get<bool>(), only that gcc3.3 wouldn't eat it
+ rAny >>= mbDumpScreenContent;
+ }
+
+ DeviceHelperType maDeviceHelper;
+ PropertySetHelper maPropHelper;
+ bool mbDumpScreenContent;
+
+ private:
+ GraphicDeviceBase( const GraphicDeviceBase& );
+ GraphicDeviceBase& operator=( const GraphicDeviceBase& );
+ };
+}
+
+#endif /* INCLUDED_CANVAS_GRAPHICDEVICEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/integerbitmapbase.hxx b/canvas/inc/canvas/base/integerbitmapbase.hxx
new file mode 100644
index 000000000000..761ebcfb4d61
--- /dev/null
+++ b/canvas/inc/canvas/base/integerbitmapbase.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_INTEGERBITMAPBASE_HXX
+#define INCLUDED_CANVAS_INTEGERBITMAPBASE_HXX
+
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <canvas/base/bitmapcanvasbase.hxx>
+
+
+namespace canvas
+{
+ /** Helper template to handle XIntegerBitmap method forwarding to
+ BitmapCanvasHelper
+
+ Use this helper to handle the XIntegerBitmap part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XIntegerBitmap should be among them (why
+ else would you use this template, then?). Base class must have
+ an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasBase for further contractual requirements towards
+ the CanvasHelper type, and some examples.
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class IntegerBitmapBase :
+ public BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+
+ // XIntegerBitmap
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getData( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::rendering::VolatileContentDestroyedException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(rect,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ tools::verifyIndexRange(rect, BaseType::getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getData( bitmapLayout,
+ rect );
+ }
+
+ virtual void SAL_CALL setData( const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(bitmapLayout, rect,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ tools::verifyIndexRange(rect, BaseType::getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setData( data, bitmapLayout, rect );
+ }
+
+ virtual void SAL_CALL setPixel( const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(bitmapLayout, pos,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ tools::verifyIndexRange(pos, BaseType::getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ BaseType::mbSurfaceDirty = true;
+ BaseType::maCanvasHelper.modifying();
+
+ BaseType::maCanvasHelper.setPixel( color, bitmapLayout, pos );
+ }
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getPixel( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::rendering::VolatileContentDestroyedException, ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(pos,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ tools::verifyIndexRange(pos, BaseType::getSize() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getPixel( bitmapLayout,
+ pos );
+ }
+
+ virtual ::com::sun::star::rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.getMemoryLayout();
+ }
+ };
+}
+
+#endif /* INCLUDED_CANVAS_INTEGERBITMAPBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/sprite.hxx b/canvas/inc/canvas/base/sprite.hxx
new file mode 100644
index 000000000000..28c9be6a5d59
--- /dev/null
+++ b/canvas/inc/canvas/base/sprite.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SPRITE_HXX
+#define INCLUDED_CANVAS_SPRITE_HXX
+
+#include <rtl/ref.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+namespace basegfx
+{
+ class B2DPoint;
+ class B2DVector;
+ class B2DRange;
+}
+
+namespace canvas
+{
+ /* Definition of Sprite interface (as we mix with UNO here, has to
+ be XInterface - reference holders to a Sprite must be able to
+ control lifetime of reference target)
+ */
+
+ /** Helper interface to connect SpriteCanvas with various
+ sprite implementations.
+
+ This interface should be implemented from every sprite class,
+ as it provides essential repaint and update area facilitates.
+
+ @derive typically, each canvas implementation will derive
+ another interface from this one, that adds rendering
+ functionality (which, of course, is impossible here in a
+ generic way)
+ */
+ class Sprite : public ::com::sun::star::lang::XComponent
+ {
+ public:
+ typedef ::rtl::Reference< Sprite > Reference;
+
+ /** Query whether sprite update will fully cover the given area.
+
+ Use this method to determine whether any background
+ content (regardless of static or sprite) needs an update
+ before rendering this sprite.
+
+ @return true, if sprite redraw will fully overwrite given
+ area (and thus, the background need not be redrawn
+ beforehand).
+ */
+ virtual bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const = 0;
+
+ /** Query whether content has changed
+ */
+ virtual bool isContentChanged() const = 0;
+
+ /** Query position of the left, top pixel of the sprite
+ */
+ virtual ::basegfx::B2DPoint getPosPixel() const = 0;
+
+ /** Query size of the sprite in pixel.
+ */
+ virtual ::basegfx::B2DVector getSizePixel() const = 0;
+
+ /** Get area that is currently covered by the sprite
+
+ This area is already adapted to clipping, alpha and
+ transformation state of this sprite.
+ */
+ virtual ::basegfx::B2DRange getUpdateArea() const = 0;
+
+ /** Query sprite priority
+ */
+ virtual double getPriority() const = 0;
+ };
+
+ /** Functor providing a StrictWeakOrdering for sprite references
+ */
+ struct SpriteComparator
+ {
+ bool operator()( const Sprite::Reference& rLHS,
+ const Sprite::Reference& rRHS )
+ {
+ const double nPrioL( rLHS->getPriority() );
+ const double nPrioR( rRHS->getPriority() );
+
+ // if prios are equal, tie-break on ptr value
+ return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR;
+ }
+ };
+}
+
+#endif /* INCLUDED_CANVAS_SPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/spritecanvasbase.hxx b/canvas/inc/canvas/base/spritecanvasbase.hxx
new file mode 100644
index 000000000000..d44bf425d4de
--- /dev/null
+++ b/canvas/inc/canvas/base/spritecanvasbase.hxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SPRITECANVASBASE_HXX
+#define INCLUDED_CANVAS_SPRITECANVASBASE_HXX
+
+#include <rtl/ref.hxx>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/InterpolationMode.hpp>
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/spriteredrawmanager.hxx>
+
+
+namespace canvas
+{
+ /** Helper template to handle XIntegerBitmap method forwarding to
+ BitmapCanvasHelper
+
+ Use this helper to handle the XIntegerBitmap part of your
+ implementation.
+
+ @tpl Base
+ Base class to use, most probably one of the
+ WeakComponentImplHelperN templates with the appropriate
+ interfaces. At least XSpriteCanvas and SpriteSurface should be
+ among them (why else would you use this template, then?). Base
+ class must have an Base( const Mutex& ) constructor (like the
+ WeakComponentImplHelperN templates have).
+
+ @tpl CanvasHelper
+ Canvas helper implementation for the backend in question
+
+ @tpl Mutex
+ Lock strategy to use. Defaults to using the
+ OBaseMutex-provided lock. Everytime one of the methods is
+ entered, an object of type Mutex is created with m_aMutex as
+ the sole parameter, and destroyed again when the method scope
+ is left.
+
+ @tpl UnambiguousBase
+ Optional unambiguous base class for XInterface of Base. It's
+ sometimes necessary to specify this parameter, e.g. if Base
+ derives from multiple UNO interface (were each provides its
+ own version of XInterface, making the conversion ambiguous)
+
+ @see CanvasBase for further contractual requirements towards
+ the CanvasHelper type, and some examples.
+ */
+ template< class Base,
+ class CanvasHelper,
+ class Mutex=::osl::MutexGuard,
+ class UnambiguousBase=::com::sun::star::uno::XInterface > class SpriteCanvasBase :
+ public IntegerBitmapBase< Base, CanvasHelper, Mutex, UnambiguousBase >
+ {
+ public:
+ typedef IntegerBitmapBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType;
+ typedef ::rtl::Reference< SpriteCanvasBase > Reference;
+
+ SpriteCanvasBase() :
+ maRedrawManager()
+ {
+ }
+
+#if defined __SUNPRO_CC
+ using Base::disposing;
+#endif
+ virtual void SAL_CALL disposing()
+ {
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maRedrawManager.disposing();
+
+ // pass on to base class
+ BaseType::disposing();
+ }
+
+ // XSpriteCanvas
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimatedSprite > SAL_CALL createSpriteFromAnimation( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimation >& animation ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(animation,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.createSpriteFromAnimation(animation);
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimatedSprite > SAL_CALL createSpriteFromBitmaps( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > >& animationBitmaps,
+ sal_Int8 interpolationMode ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::rendering::VolatileContentDestroyedException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(animationBitmaps,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+ tools::verifyRange( interpolationMode,
+ ::com::sun::star::rendering::InterpolationMode::NEAREST_NEIGHBOR,
+ ::com::sun::star::rendering::InterpolationMode::BEZIERSPLINE4 );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.createSpriteFromBitmaps(animationBitmaps, interpolationMode);
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCustomSprite > SAL_CALL createCustomSprite( const ::com::sun::star::geometry::RealSize2D& spriteSize ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifySpriteSize(spriteSize,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.createCustomSprite(spriteSize);
+ }
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite > SAL_CALL createClonedSprite( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite >& original ) throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ tools::verifyArgs(original,
+ BOOST_CURRENT_FUNCTION,
+ static_cast< typename BaseType::UnambiguousBaseType* >(this));
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ return BaseType::maCanvasHelper.createClonedSprite(original);
+ }
+
+ // SpriteSurface
+ virtual void showSprite( const Sprite::Reference& rSprite )
+ {
+ OSL_ASSERT( rSprite.is() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maRedrawManager.showSprite( rSprite );
+ }
+
+ virtual void hideSprite( const Sprite::Reference& rSprite )
+ {
+ OSL_ASSERT( rSprite.is() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maRedrawManager.hideSprite( rSprite );
+ }
+
+ virtual void moveSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rOldPos,
+ const ::basegfx::B2DPoint& rNewPos,
+ const ::basegfx::B2DVector& rSpriteSize )
+ {
+ OSL_ASSERT( rSprite.is() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maRedrawManager.moveSprite( rSprite, rOldPos, rNewPos, rSpriteSize );
+ }
+
+ virtual void updateSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rUpdateArea )
+ {
+ OSL_ASSERT( rSprite.is() );
+
+ typename BaseType::MutexType aGuard( BaseType::m_aMutex );
+
+ maRedrawManager.updateSprite( rSprite, rPos, rUpdateArea );
+ }
+
+ protected:
+ SpriteRedrawManager maRedrawManager;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_SPRITECANVASBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/base/spritesurface.hxx b/canvas/inc/canvas/base/spritesurface.hxx
new file mode 100644
index 000000000000..cd66f4369581
--- /dev/null
+++ b/canvas/inc/canvas/base/spritesurface.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SPRITESURFACE_HXX
+#define INCLUDED_CANVAS_SPRITESURFACE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+namespace canvas
+{
+ /* Definition of the SpriteSurface interface */
+
+ /** Canvas surface containing sprites
+
+ Every canvas surface that contains sprites must implement this
+ interface, when employing the canvas base framework. The
+ methods provided here are used from the individual sprites to
+ notify the canvas about necessary screen updates.
+ */
+ class SpriteSurface : public ::com::sun::star::uno::XInterface
+ {
+ public:
+ typedef ::rtl::Reference< SpriteSurface > Reference;
+
+ /// Sprites should call this from XSprite::show()
+ virtual void showSprite( const Sprite::Reference& rSprite ) = 0;
+
+ /// Sprites should call this from XSprite::hide()
+ virtual void hideSprite( const Sprite::Reference& rSprite ) = 0;
+
+ /// Sprites should call this from XSprite::move()
+ virtual void moveSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rOldPos,
+ const ::basegfx::B2DPoint& rNewPos,
+ const ::basegfx::B2DVector& rSpriteSize ) = 0;
+
+ /** Sprites should call this when some part of the content has
+ changed.
+
+ That includes show/hide, i.e. for show, both showSprite()
+ and updateSprite() must be called.
+ */
+ virtual void updateSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rUpdateArea ) = 0;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_SPRITESURFACE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/canvastools.hxx b/canvas/inc/canvas/canvastools.hxx
new file mode 100644
index 000000000000..bd1b20edda8d
--- /dev/null
+++ b/canvas/inc/canvas/canvastools.hxx
@@ -0,0 +1,664 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_CANVASTOOLS_HXX
+#define INCLUDED_CANVAS_CANVASTOOLS_HXX
+
+#include <rtl/math.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include <string.h> // for strcmp
+#include <vector>
+#include <limits>
+#include <algorithm>
+
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DRange;
+ class B2IRange;
+ class B2IPoint;
+ class B2DPolyPolygon;
+}
+
+namespace com { namespace sun { namespace star { namespace geometry
+{
+ struct RealSize2D;
+ struct IntegerSize2D;
+ struct AffineMatrix2D;
+ struct Matrix2D;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct RenderState;
+ struct ViewState;
+ struct IntegerBitmapLayout;
+ class XCanvas;
+ struct Texture;
+ class XIntegerBitmapColorSpace;
+ class XPolyPolygon2D;
+
+ bool operator==( const RenderState& rLHS,
+ const RenderState& rRHS );
+
+ bool operator==( const ViewState& rLHS,
+ const ViewState& rRHS );
+} } } }
+
+namespace com { namespace sun { namespace star { namespace awt
+{
+ struct Rectangle;
+ class XWindow2;
+} } } }
+
+class Color;
+
+namespace canvas
+{
+ namespace tools
+ {
+ /** Compute the next highest power of 2 of a 32-bit value
+
+ Code devised by Sean Anderson, in good ole HAKMEM
+ tradition.
+
+ @return 1 << (lg(x - 1) + 1)
+ */
+ inline sal_uInt32 nextPow2( sal_uInt32 x )
+ {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+
+ return ++x;
+ }
+
+ /**
+ *
+ * Count the number of 1-bits of an n-bit value
+ *
+ */
+
+ // mickey's math tricks...
+ inline unsigned int pow2( unsigned int c ) { return 0x1 << c; }
+ inline unsigned int mask( unsigned int c ) { return ((unsigned int)(-1)) / (pow2(pow2(c)) + 1); }
+ inline unsigned int count( unsigned int x, unsigned int c ) { return ((x) & mask(c)) + (((x) >> (pow2(c))) & mask(c)); }
+ template<typename T>
+ inline unsigned int bitcount( T c ) {
+ unsigned int nByteIndex = 0;
+ unsigned int nNumBytes = sizeof(T)<<2;
+ do {
+ c=count(c,nByteIndex++);
+ nNumBytes >>= 1;
+ } while(nNumBytes);
+ return c;
+ }
+ inline sal_uInt32 bitcount32( sal_uInt32 c ) {
+ c=count(c,0);
+ c=count(c,1);
+ c=count(c,2);
+ c=count(c,3);
+ c=count(c,4);
+ return c;
+ }
+
+ /** Round given floating point value down to next integer
+ */
+ inline sal_Int32 roundDown( const double& rVal )
+ {
+ return static_cast< sal_Int32 >( floor( rVal ) );
+ }
+
+ /** Round given floating point value up to next integer
+ */
+ inline sal_Int32 roundUp( const double& rVal )
+ {
+ return static_cast< sal_Int32 >( ceil( rVal ) );
+ }
+
+ /** Create a RealSize2D with both coordinate values set to +infinity
+ */
+ ::com::sun::star::geometry::RealSize2D createInfiniteSize2D();
+
+
+ // View- and RenderState utilities
+ // ===================================================================
+
+ ::com::sun::star::rendering::RenderState&
+ initRenderState( ::com::sun::star::rendering::RenderState& renderState );
+
+ ::com::sun::star::rendering::ViewState&
+ initViewState( ::com::sun::star::rendering::ViewState& viewState );
+
+ ::basegfx::B2DHomMatrix&
+ getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
+ const ::com::sun::star::rendering::ViewState& viewState );
+
+ ::com::sun::star::rendering::ViewState&
+ setViewStateTransform( ::com::sun::star::rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::basegfx::B2DHomMatrix&
+ getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ ::com::sun::star::rendering::RenderState&
+ setRenderStateTransform( ::com::sun::star::rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::com::sun::star::rendering::ViewState&
+ appendToViewState( ::com::sun::star::rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::com::sun::star::rendering::RenderState&
+ appendToRenderState( ::com::sun::star::rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::com::sun::star::rendering::ViewState&
+ prependToViewState( ::com::sun::star::rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::com::sun::star::rendering::RenderState&
+ prependToRenderState( ::com::sun::star::rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& transform );
+
+ ::basegfx::B2DHomMatrix&
+ mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& transform,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ ::com::sun::star::rendering::ViewState&
+ mergeViewAndRenderState( ::com::sun::star::rendering::ViewState& resultViewState,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& xCanvas );
+
+
+ // Matrix utilities
+ // ===================================================================
+
+ ::com::sun::star::geometry::AffineMatrix2D&
+ setIdentityAffineMatrix2D( ::com::sun::star::geometry::AffineMatrix2D& matrix );
+
+ ::com::sun::star::geometry::Matrix2D&
+ setIdentityMatrix2D( ::com::sun::star::geometry::Matrix2D& matrix );
+
+
+ // Special utilities
+ // ===================================================================
+
+ /** Calc the bounding rectangle of a transformed rectangle.
+
+ The method applies the given transformation to the
+ specified input rectangle, and returns the bounding box of
+ the resulting output area.
+
+ @param o_Rect
+ Output rectangle
+
+ @param i_Rect
+ Input rectangle
+
+ @param i_Transformation
+ Transformation to apply to the input rectangle
+
+ @see calcRectToRectTransform()
+
+ @return a reference to the resulting rectangle
+ */
+ ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& o_Rect,
+ const ::basegfx::B2DRange& i_Rect,
+ const ::basegfx::B2DHomMatrix& i_Transformation );
+
+ /** Calc a transform that maps one rectangle on top of
+ another.
+
+ The method is a kissing cousin to
+ calcTransformedRectBounds(). It can be used to modify the
+ given transformation matrix, such that it transforms the
+ given input rectangle to the given output rectangle,
+ changing only translation and scale (if necessary). Thus,
+ if you've calculated an output rectangle via
+ calcTransformedRectBounds(), you can move and scale that
+ rectangle as you like, and have this method calculate the
+ required total transformation for it.
+
+ @param o_transform
+ Output parameter, to receive the resulting transformation
+ matrix.
+
+ @param i_destRect
+ Input parameter, specifies the requested destination
+ rectangle. The resulting transformation will exactly map
+ the source rectangle to the destination rectangle.
+
+ @param i_srcRect
+ Input parameter, specifies the original source
+ rectangle. The resulting transformation will exactly map
+ the source rectangle to the destination rectangle.
+
+ @param i_transformation
+ The original transformation matrix. This is changed with
+ translations and scalings (if necessary), to exactly map
+ the source rectangle to the destination rectangle.
+
+ @return a reference to the resulting transformation matrix
+
+ @see calcTransformedRectBounds()
+ */
+ ::basegfx::B2DHomMatrix& calcRectToRectTransform( ::basegfx::B2DHomMatrix& o_transform,
+ const ::basegfx::B2DRange& i_destRect,
+ const ::basegfx::B2DRange& i_srcRect,
+ const ::basegfx::B2DHomMatrix& i_transformation );
+
+ /** Calc a transform that maps the upper, left corner of a
+ rectangle to the origin.
+
+ The method is a specialized version of
+ calcRectToRectTransform(), mapping the input rectangle's
+ the upper, left corner to the origin, and leaving the size
+ untouched.
+
+ @param o_transform
+ Output parameter, to receive the resulting transformation
+ matrix.
+
+ @param i_srcRect
+ Input parameter, specifies the original source
+ rectangle. The resulting transformation will exactly map
+ the source rectangle's upper, left corner to the origin.
+
+ @param i_transformation
+ The original transformation matrix. This is changed with
+ translations (if necessary), to exactly map the source
+ rectangle to the origin.
+
+ @return a reference to the resulting transformation matrix
+
+ @see calcRectToRectTransform()
+ @see calcTransformedRectBounds()
+ */
+ ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
+ const ::basegfx::B2DRange& i_srcRect,
+ const ::basegfx::B2DHomMatrix& i_transformation );
+
+ /** Check whether a given rectangle is within another
+ transformed rectangle.
+
+ This method checks for polygonal containedness, i.e. the
+ transformed rectangle is not represented as an axis-alignd
+ rectangle anymore (like calcTransformedRectBounds()), but
+ polygonal. Thus, the insideness test is based on tight
+ bounds.
+
+ @param rContainedRect
+ This rectangle is checked, whether it is fully within the
+ transformed rTransformRect.
+
+ @param rTransformRect
+ This rectangle is transformed, and then checked whether it
+ fully contains rContainedRect.
+
+ @param rTransformation
+ This transformation is applied to rTransformRect
+ */
+ bool isInside( const ::basegfx::B2DRange& rContainedRect,
+ const ::basegfx::B2DRange& rTransformRect,
+ const ::basegfx::B2DHomMatrix& rTransformation );
+
+ /** Clip a scroll to the given bound rect
+
+ @param io_rSourceArea
+ Source area to scroll. The resulting clipped source area
+ is returned therein.
+
+ @param io_rDestPoint
+ Destination point of the scroll (upper, left corner of
+ rSourceArea after the scroll). The new, resulting
+ destination point is returned therein.q
+
+ @param o_ClippedAreas
+ Vector of rectangles in the <em>destination</em> area
+ coordinate system, which are clipped away from the source
+ area, and thus need extra updates (i.e. they are not
+ correctly copy from the scroll operation, since there was
+ no information about them in the source).
+
+ @param rBounds
+ Bounds to clip against.
+
+ @return false, if the resulting scroll area is empty
+ */
+ bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
+ const ::basegfx::B2IRange& rBounds );
+
+ /** Clip a blit between two differently surfaces.
+
+ This method clips source and dest rect for a clip between
+ two differently clipped surfaces, such that the resulting
+ blit rects are fully within both clip areas.
+
+ @param io_rSourceArea
+ Source area of the blit. Returned therein is the computed
+ clipped source area.
+
+ @param io_rDestPoint
+ Dest area of the blit. Returned therein is the computed
+ clipped dest area.
+
+ @param rSourceBounds
+ Clip bounds of the source surface
+
+ @param rDestBounds
+ Clip bounds of the dest surface
+
+ @return false, if the resulting blit is empty, i.e. fully
+ clipped away.
+ */
+ bool clipBlit( ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ const ::basegfx::B2IRange& rSourceBounds,
+ const ::basegfx::B2IRange& rDestBounds );
+
+ /** Return range of integer pixel, which will cover the sprite
+ given by the floating point range.
+
+ This method assumes that sprite sizes are always integer,
+ and that the sprite position (top, left edge of the
+ sprite) is rounded to the nearest integer before
+ rendering.
+
+ @param rRange
+ Input range. Values must be within the representable
+ bounds of sal_Int32
+
+ @return the integer range, which is covered by the sprite
+ given by rRange.
+ */
+ ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange );
+
+ /** Retrieve various internal properties of the actual canvas implementation.
+
+ This method retrieves a bunch of internal, implementation-
+ and platform-dependent values from the canvas
+ implementation. Among them are for example operating
+ system window handles. The actual layout and content of
+ the returned sequence is dependent on the component
+ implementation, undocumented and subject to change.
+
+ @param i_rxCanvas
+ Input parameter, the canvas representation for which the device information
+ is to be retrieveds
+
+ @param o_rxParams
+ Output parameter, the sequence of Anys that hold the device parameters. Layout is as described above
+
+ @return A reference to the resulting sequence of parameters
+ */
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& getDeviceInfo(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas >& i_rxCanvas,
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& o_rxParams );
+
+ /** Return a color space for a default RGBA integer format
+
+ Use this method for dead-simple bitmap implementations,
+ that map all their formats to 8888 RGBA color.
+ */
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XIntegerBitmapColorSpace> getStdColorSpace();
+
+ /** Return a memory layout for a default RGBA integer format
+
+ Use this method for dead-simple bitmap implementations,
+ that map all their formats to 8888 RGBA color.
+ */
+ ::com::sun::star::rendering::IntegerBitmapLayout getStdMemoryLayout(
+ const ::com::sun::star::geometry::IntegerSize2D& rBitmapSize );
+
+ /// Convert standard 8888 RGBA color to vcl color
+ ::Color stdIntSequenceToColor( const ::com::sun::star::uno::Sequence<sal_Int8>& rColor );
+
+ /// Convert standard 8888 RGBA color to vcl color
+ ::com::sun::star::uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor );
+
+ // Modeled closely after boost::numeric_cast, only that we
+ // issue some trace output here and throw a RuntimeException
+
+ /** Cast numeric value into another (numeric) data type
+
+ Apart from converting the numeric value, this template
+ also checks if any overflow, underflow, or sign
+ information is lost (if yes, it throws an
+ uno::RuntimeException.
+ */
+ template< typename Target, typename Source > inline Target numeric_cast( Source arg )
+ {
+ // typedefs abbreviating respective trait classes
+ typedef ::std::numeric_limits< Source > SourceLimits;
+ typedef ::std::numeric_limits< Target > TargetLimits;
+
+ if( ( arg<0 && !TargetLimits::is_signed) || // loosing the sign here
+ ( SourceLimits::is_signed && arg<TargetLimits::min()) || // underflow will happen
+ ( arg>TargetLimits::max() ) ) // overflow will happen
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ OSL_TRACE("numeric_cast detected data loss");
+#endif
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "numeric_cast detected data loss" )),
+ NULL );
+ }
+
+ return static_cast<Target>(arg);
+ }
+
+ ::com::sun::star::awt::Rectangle getAbsoluteWindowRect(
+ const ::com::sun::star::awt::Rectangle& rRect,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow2 >& xWin );
+
+ /** Retrieve for small bound marks around each corner of the given rectangle
+ */
+ ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange );
+
+ /** Calculate number of gradient "strips" to generate (takes
+ into account device resolution)
+
+ @param nColorSteps
+ Maximal integer difference between all color stops, needed
+ for smooth gradient color differences
+ */
+ int calcGradientStepCount( ::basegfx::B2DHomMatrix& rTotalTransform,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::rendering::Texture& texture,
+ int nColorSteps );
+
+ /** A very simplistic map for ASCII strings and arbitrary value
+ types.
+
+ This class internally references a constant, static array of
+ sorted MapEntries, and performs a binary search to look up
+ values for a given query string. Note that this map is static,
+ i.e. not meant to be extented at runtime.
+
+ @tpl ValueType
+ The value type this map should store, associated with an ASCII
+ string.
+ */
+ template< typename ValueType > class ValueMap
+ {
+ public:
+ struct MapEntry
+ {
+ const char* maKey;
+ ValueType maValue;
+ };
+
+ /** Create a ValueMap for the given array of MapEntries.
+
+ @param pMap
+ Pointer to a <em>static</em> array of MapEntries. Must
+ live longer than this object! Make absolutely sure that
+ the string entries passed via pMap are ASCII-only -
+ everything else might not yield correct string
+ comparisons, and thus will result in undefined behaviour.
+
+ @param nEntries
+ Number of entries for pMap
+
+ @param bCaseSensitive
+ Whether the map query should be performed case sensitive
+ or not. When bCaseSensitive is false, all MapEntry strings
+ must be lowercase!
+ */
+ ValueMap( const MapEntry* pMap,
+ ::std::size_t nEntries,
+ bool bCaseSensitive ) :
+ mpMap( pMap ),
+ mnEntries( nEntries ),
+ mbCaseSensitive( bCaseSensitive )
+ {
+#ifdef DBG_UTIL
+ // Ensure that map entries are sorted (and all lowercase, if this
+ // map is case insensitive)
+ const ::rtl::OString aStr( pMap->maKey );
+ if( !mbCaseSensitive &&
+ aStr != aStr.toAsciiLowerCase() )
+ {
+ OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
+ pMap->maKey);
+ OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
+ }
+
+ if( mnEntries > 1 )
+ {
+ for( ::std::size_t i=0; i<mnEntries-1; ++i, ++pMap )
+ {
+ if( !mapComparator(pMap[0], pMap[1]) &&
+ mapComparator(pMap[1], pMap[0]) )
+ {
+ OSL_TRACE("ValueMap::ValueMap(): Map is not sorted, keys %s and %s are wrong",
+ pMap[0].maKey,
+ pMap[1].maKey);
+ OSL_ENSURE( false,
+ "ValueMap::ValueMap(): Map is not sorted" );
+ }
+
+ const ::rtl::OString aStr2( pMap[1].maKey );
+ if( !mbCaseSensitive &&
+ aStr2 != aStr2.toAsciiLowerCase() )
+ {
+ OSL_TRACE("ValueMap::ValueMap(): Key %s is not lowercase",
+ pMap[1].maKey);
+ OSL_ENSURE( false, "ValueMap::ValueMap(): Key is not lowercase" );
+ }
+ }
+ }
+#endif
+ }
+
+ /** Lookup a value for the given query string
+
+ @param rName
+ The string to lookup. If the map was created with the case
+ insensitive flag, the lookup is performed
+ case-insensitive, otherwise, case-sensitive.
+
+ @param o_rResult
+ Output parameter, which receives the value associated with
+ the query string. If no value was found, the referenced
+ object is kept unmodified.
+
+ @return true, if a matching entry was found.
+ */
+ bool lookup( const ::rtl::OUString& rName,
+ ValueType& o_rResult ) const
+ {
+ // rName is required to contain only ASCII characters.
+ // TODO(Q1): Enforce this at upper layers
+ ::rtl::OString aKey( ::rtl::OUStringToOString( mbCaseSensitive ? rName : rName.toAsciiLowerCase(),
+ RTL_TEXTENCODING_ASCII_US ) );
+ MapEntry aSearchKey =
+ {
+ aKey.getStr(),
+ ValueType()
+ };
+
+ const MapEntry* pRes;
+ const MapEntry* pEnd = mpMap+mnEntries;
+ if( (pRes=::std::lower_bound( mpMap,
+ pEnd,
+ aSearchKey,
+ &mapComparator )) != pEnd )
+ {
+ // place to _insert before_ found - is it equal to
+ // the search key?
+ if( strcmp( pRes->maKey, aSearchKey.maKey ) == 0 )
+ {
+ // yep, correct entry found
+ o_rResult = pRes->maValue;
+ return true;
+ }
+ }
+
+ // not found
+ return false;
+ }
+
+ private:
+ static bool mapComparator( const MapEntry& rLHS,
+ const MapEntry& rRHS )
+ {
+ return strcmp( rLHS.maKey,
+ rRHS.maKey ) < 0;
+ }
+
+ const MapEntry* mpMap;
+ ::std::size_t mnEntries;
+ bool mbCaseSensitive;
+ };
+ }
+}
+
+#endif /* INCLUDED_CANVAS_CANVASTOOLS_HXX */
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/debug.hxx b/canvas/inc/canvas/debug.hxx
new file mode 100644
index 000000000000..5e81c6290c81
--- /dev/null
+++ b/canvas/inc/canvas/debug.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_DEBUG_HXX
+#define INCLUDED_CANVAS_DEBUG_HXX
+
+// shared_ptr debugging
+// --------------------
+
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+
+# include <sal/config.h>
+# include <boost/shared_ptr.hpp>
+
+::std::size_t find_unreachable_objects( bool );
+
+# ifdef VERBOSE
+# include <osl/diagnose.h>
+# define SHARED_PTR_LEFTOVERS(a) OSL_TRACE("%s\n%s: Unreachable objects still use %d bytes\n", \
+ BOOST_CURRENT_FUNCTION, a, \
+ find_unreachable_objects(true) )
+# else
+/** This macro shows how much memory is still used by shared_ptrs
+
+ Use this macro at places in the code where normally all shared_ptr
+ objects should have been deleted. You'll get the number of bytes
+ still contained in those objects, which quite possibly are prevented
+ from deletion by circular references.
+ */
+# define SHARED_PTR_LEFTOVERS(a) OSL_TRACE("%s\n%s: Unreachable objects still use %d bytes\n", \
+ BOOST_CURRENT_FUNCTION, a, \
+ find_unreachable_objects(false) )
+# endif
+
+#else
+
+# define SHARED_PTR_LEFTOVERS(a) ((void)0)
+
+#endif
+
+#endif // ! defined(INCLUDED_CANVAS_DEBUG_HXX)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/elapsedtime.hxx b/canvas/inc/canvas/elapsedtime.hxx
new file mode 100644
index 000000000000..2e8a9b69d202
--- /dev/null
+++ b/canvas/inc/canvas/elapsedtime.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ELAPSEDTIME_HXX
+#define INCLUDED_CANVAS_ELAPSEDTIME_HXX
+
+#include <sal/types.h>
+
+#include "boost/shared_ptr.hpp"
+
+namespace canvas
+{
+ namespace tools
+ {
+ /** Calculate elapsed time.
+
+ This class provides several time-measurement and
+ -management functions. In its simplest use-case, it
+ measures the time from its creation.
+ */
+ class ElapsedTime
+ {
+ public:
+ /** Create a new ElapsedTime object
+
+ The moment of construction starts the time
+ measurement. That means, a subsequent getElapsedTime()
+ call will return the time difference between object
+ creation and getElapsedTime() call.
+ */
+ ElapsedTime();
+
+ /** Creates a new ElapsedTime object based on another
+ timer.
+
+ The moment of construction starts the time
+ measurement. That means, a subsequent getElapsedTime()
+ call will return the time difference between object
+ creation and getElapsedTime() call. All time values
+ are not taken from the system's time base, but from
+ the provided timer.
+ */
+ ElapsedTime( ::boost::shared_ptr<ElapsedTime> const & pTimeBase );
+
+ /** Gets this timer's base timer.
+ */
+ ::boost::shared_ptr<ElapsedTime> const & getTimeBase() const;
+
+ /** Reset the time
+
+ The instance of the reset() call starts the time
+ measurement from scratch. That means, a subsequent
+ getElapsedTime() call will return the time difference
+ between reset() and getElapsedTime() call.
+ */
+ void reset();
+
+ /** Query the elapsed time
+
+ This method returns the elapsed time in seconds
+ between either the construction of this object, or the
+ last reset() call, if any (but see the time modulation
+ methods below, for means to modify the otherwise
+ continuous flow of time).
+
+ @return the elapsed time in seconds.
+ */
+ double getElapsedTime() const;
+
+ /** Pauses the running timer.
+
+ This method stops the time, as returned by this
+ object, until continueTimer() is called. During this
+ period, getElapsedTime() will always return the same
+ time value (i.e. the instant when pauseTimer() was
+ called).
+ */
+ void pauseTimer();
+
+ /** Continues the paused timer.
+
+ This method re-enables the time flow, that is, time
+ starts running again for clients calling
+ getElapsedTime(). The (subtle) difference to the
+ holdTimer/releaseTimer() methods below is, that there
+ is no perceived time 'jump' between the pauseTimer()
+ call and the continueTimer() call, i.e. the time
+ starts over with the same value it has stopped on
+ pauseTimer().
+ */
+ void continueTimer();
+
+ /** Adjusts the timer, hold and pause times.
+
+ This method modifies the time as returned by this
+ object by the specified amount. This affects the time
+ as returned by getElapsedTime(), regardless of the
+ mode (e.g. paused, or on hold).
+
+ @param fOffset
+ This value will be added to the current time, i.e. the
+ next call to getElapsedTime() (when performed
+ immediately) will be adjusted by fOffset.
+
+ @param bLimitToLastQueriedTime
+ Limits the given offset to the time that has been
+ taken via getElapsedTime()
+ */
+ void adjustTimer( double fOffset,
+ bool bLimitToLastQueriedTime = true );
+
+ /** Holds the current time.
+
+ This call makes the timer hold the current time
+ (e.g. getElapsedTime() will return the time when
+ holdTimer() was called), while the underlying time is
+ running on. When releaseTimer() is called, the time
+ will 'jump' to the then-current, underlying time. This
+ is equivalent to pressing the "interim time" button on
+ a stop watch, which shows this stopped time, while the
+ clock keeps running internally.
+ */
+ void holdTimer();
+
+ /** Releases a held timer.
+
+ After this call, the timer again returns the running
+ time on getElapsedTime().
+ */
+ void releaseTimer();
+
+ private:
+ static double getSystemTime();
+ double getCurrentTime() const;
+ double getElapsedTimeImpl() const; // does not set m_fLastQueriedTime
+
+ const ::boost::shared_ptr<ElapsedTime> m_pTimeBase;
+
+ /// To validate adjustTimer() calls with bLimitToLastQueriedTime=true
+ mutable double m_fLastQueriedTime;
+
+ /// Start time, from which the difference to the time base is returned
+ double m_fStartTime;
+
+ /// Instant, when last pause or hold started, relative to m_fStartTime
+ double m_fFrozenTime;
+
+ /// True, when in pause mode
+ bool m_bInPauseMode;
+
+ /// True, when in hold mode
+ bool m_bInHoldMode;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_CANVAS_ELAPSEDTIME_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/parametricpolypolygon.hxx b/canvas/inc/canvas/parametricpolypolygon.hxx
new file mode 100644
index 000000000000..97598ac46996
--- /dev/null
+++ b/canvas/inc/canvas/parametricpolypolygon.hxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_PARAMETRICPOLYPOLYGON_HXX
+#define INCLUDED_CANVAS_PARAMETRICPOLYPOLYGON_HXX
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XParametricPolyPolygon2D.hpp>
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+#include <boost/utility.hpp>
+
+namespace basegfx
+{
+ class B2DPolygon;
+ class B2DHomMatrix;
+}
+
+
+/* Definition of ParametricPolyPolygon class */
+
+namespace canvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XParametricPolyPolygon2D,
+ ::com::sun::star::lang::XServiceInfo > ParametricPolyPolygon_Base;
+
+ class ParametricPolyPolygon : public ::comphelper::OBaseMutex,
+ public ParametricPolyPolygon_Base,
+ private ::boost::noncopyable
+ {
+ public:
+ enum GradientType
+ {
+ GRADIENT_LINEAR,
+ GRADIENT_ELLIPTICAL,
+ GRADIENT_RECTANGULAR
+ };
+
+ /** Structure of defining values for the ParametricPolyPolygon
+
+ This is used to copy the state of the
+ ParametricPolyPolygon atomically.
+ */
+ struct Values
+ {
+ Values( const ::basegfx::B2DPolygon& rGradientPoly,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& rColors,
+ const ::com::sun::star::uno::Sequence< double >& rStops,
+ double nAspectRatio,
+ GradientType eType ) :
+ maGradientPoly( rGradientPoly ),
+ mnAspectRatio( nAspectRatio ),
+ maColors( rColors ),
+ maStops( rStops ),
+ meType( eType )
+ {
+ }
+
+ /// Polygonal gradient shape (ignored for linear and axial gradient)
+ const ::basegfx::B2DPolygon maGradientPoly;
+
+ /// Aspect ratio of gradient, affects scaling of innermost gradient polygon
+ const double mnAspectRatio;
+
+ /// Gradient colors
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > > maColors;
+
+ /// Gradient color stops
+ const ::com::sun::star::uno::Sequence< double > maStops;
+
+ /// Type of gradient to render (as e.g. linear grads are not represented by maGradientPoly)
+ const GradientType meType;
+ };
+
+ static ::com::sun::star::uno::Sequence< ::rtl::OUString > getAvailableServiceNames();
+ static ParametricPolyPolygon* create(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::rtl::OUString& rServiceName,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rArgs );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XParametricPolyPolygon2D
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL getOutline( double t ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getColor( double t ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getPointColor( const ::com::sun::star::geometry::RealPoint2D& point ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XColorSpace > SAL_CALL getColorSpace() 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);
+
+ /// Query all defining values of this object atomically
+ Values getValues() const;
+
+ protected:
+ ~ParametricPolyPolygon(); // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ private:
+ static ParametricPolyPolygon* createLinearHorizontalGradient( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops );
+ static ParametricPolyPolygon* createEllipticalGradient( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops,
+ double fAspect );
+ static ParametricPolyPolygon* createRectangularGradient( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops,
+ double fAspect );
+
+ /// Private, because objects can only be created from the static factories
+ ParametricPolyPolygon( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::basegfx::B2DPolygon& rGradientPoly,
+ GradientType eType,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops );
+ ParametricPolyPolygon( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::basegfx::B2DPolygon& rGradientPoly,
+ GradientType eType,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops,
+ double nAspectRatio );
+ ParametricPolyPolygon( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ GradientType eType,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
+ const ::com::sun::star::uno::Sequence< double >& stops );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice > mxDevice;
+
+ /// All defining values of this object
+ const Values maValues;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_PARAMETRICPOLYPOLYGON_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/prioritybooster.hxx b/canvas/inc/canvas/prioritybooster.hxx
new file mode 100644
index 000000000000..1839c015f75a
--- /dev/null
+++ b/canvas/inc/canvas/prioritybooster.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_PRIORITYBOOSTER_HXX
+#define INCLUDED_CANVAS_PRIORITYBOOSTER_HXX
+
+#include <sal/types.h>
+
+#include <memory>
+
+
+namespace canvas
+{
+ namespace tools
+ {
+ struct PriorityBooster_Impl;
+
+ /** Simplistic RAII object, to temporarily boost execution
+ priority for the current scope.
+ */
+ class PriorityBooster
+ {
+ public:
+ /** Create booster, with given priority delta
+
+ @param nDelta
+ Difference in execution priority. Positive values
+ increase prio, negative values decrease prio.
+ */
+ explicit PriorityBooster( sal_Int32 nDelta );
+ ~PriorityBooster();
+
+ private:
+ // also disables copy constructor and assignment operator
+ const ::std::auto_ptr< PriorityBooster_Impl > mpImpl;
+ };
+ }
+}
+
+#endif /* INCLUDED_CANVAS_PRIORITYBOOSTER_HXX */
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/propertysethelper.hxx b/canvas/inc/canvas/propertysethelper.hxx
new file mode 100644
index 000000000000..9daac32482c7
--- /dev/null
+++ b/canvas/inc/canvas/propertysethelper.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_PROPERTYSETHELPER_HXX
+#define INCLUDED_CANVAS_PROPERTYSETHELPER_HXX
+
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <canvas/canvastools.hxx>
+
+#include <boost/function.hpp>
+#include <vector>
+#include <memory>
+
+
+namespace canvas
+{
+ /** Really simplistic XPropertySet helper for properties.
+
+ This class provides easy access to properties, referenced via
+ ASCII strings. The name/property modification callbacks pairs
+ are passed into this class via a vector. Each time a property
+ is set or queried, the corresponding getter or setter callback
+ is called.
+
+ Use this class as a delegate for the corresponding
+ XPropertySet methods, and take care of UNO XInterface and lock
+ handling by yourself.
+
+ The core responsibility of this this class is the name/value
+ mapping for property sets.
+ */
+ class PropertySetHelper
+ {
+ public:
+ typedef boost::function0< ::com::sun::star::uno::Any > GetterType;
+ typedef boost::function1<void, const ::com::sun::star::uno::Any&> SetterType;
+ struct Callbacks
+ {
+ GetterType getter;
+ SetterType setter;
+ };
+ typedef tools::ValueMap< Callbacks > MapType;
+ typedef std::vector< MapType::MapEntry > InputMap;
+
+ class MakeMap : public InputMap
+ {
+ public:
+ MakeMap(const char* name,
+ const GetterType& getter,
+ const SetterType& setter)
+ {
+ MapType::MapEntry aEntry={name, {getter, setter}};
+ this->push_back(aEntry);
+ }
+ MakeMap(const char* name,
+ const GetterType& getter)
+ {
+ MapType::MapEntry aEntry={name, {getter, SetterType()}};
+ this->push_back(aEntry);
+ }
+ MakeMap& operator()(const char* name,
+ const GetterType& getter,
+ const SetterType& setter)
+ {
+ MapType::MapEntry aEntry={name, {getter, setter}};
+ this->push_back(aEntry);
+ return *this;
+ }
+ MakeMap& operator()(const char* name,
+ const GetterType& getter)
+ {
+ MapType::MapEntry aEntry={name, {getter, SetterType()}};
+ this->push_back(aEntry);
+ return *this;
+ }
+ };
+
+ /** Create helper with zero properties
+ */
+ PropertySetHelper();
+
+ /** Create helper with given name/value map
+ */
+ explicit PropertySetHelper( const InputMap& rMap );
+
+ /** Init helper with new name/value map
+
+ @param rMap
+ Vector of name/function pointers. Each name is offered as
+ a property, and reading/writing to this property is passed
+ on to the given function pointer.
+ */
+ void initProperties( const InputMap& rMap );
+
+ /** Add given properties to helper
+
+ @param rMap
+ Vector of name/function pointers. Each name is offered as
+ a property, and reading/writing to this property is passed
+ on to the given function pointer. These name/function
+ pairs are added to the already existing ones.
+ */
+ void addProperties( const InputMap& rMap );
+
+ /** Checks whether the given string corresponds to a valid
+ property name.
+
+ @return true, if the given name maps to a known property.
+ */
+ bool isPropertyName( const ::rtl::OUString& aPropertyName ) const;
+
+ /** Request the currently active map
+ */
+ const InputMap& getPropertyMap() const { return maMapEntries; }
+
+ // XPropertySet implementation
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > getPropertySetInfo() const;
+ void setPropertyValue( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Any& aValue );
+ ::com::sun::star::uno::Any getPropertyValue( const ::rtl::OUString& PropertyName ) const;
+ void addPropertyChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener );
+ void removePropertyChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener );
+ void addVetoableChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& xListener );
+ void removeVetoableChangeListener( const ::rtl::OUString& aPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& xListener );
+
+ private:
+ std::auto_ptr<MapType> mpMap;
+ InputMap maMapEntries;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_PROPERTYSETHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/bitmap.hxx b/canvas/inc/canvas/rendering/bitmap.hxx
new file mode 100644
index 000000000000..5fdb3ec8ecf4
--- /dev/null
+++ b/canvas/inc/canvas/rendering/bitmap.hxx
@@ -0,0 +1,323 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_BITMAP_HXX
+#define INCLUDED_CANVAS_BITMAP_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
+#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
+#include <com/sun/star/geometry/IntegerPoint2D.hpp>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/icachedprimitive.hxx>
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <vector>
+
+namespace basegfx
+{
+ class B2IVector;
+ class B2DPoint;
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+}
+
+namespace canvas
+{
+ class ImplBitmap;
+
+ /** Bitmap class, with XCanvas-like render interface.
+
+ This class provides a bitmap, that can be rendered into,
+ with an interface compatible to XCanvas. Furthermore, the
+ bitmaps held here can optionally be backed by (possibly
+ hw-accelerated) textures.
+ */
+ class Bitmap
+ {
+ public:
+ /** Create bitmap with given size
+
+ @param rSize
+ Size of the bitmap, in pixel
+
+ @param rMgr
+ SurfaceProxyManager, to use for HW acceleration
+
+ @param bWithAlpha
+ When true, the created bitmap will have an alpha channel,
+ false otherwise
+ */
+ Bitmap( const ::basegfx::B2IVector& rSize,
+ const ISurfaceProxyManagerSharedPtr& rMgr,
+ bool bWithAlpha );
+ ~Bitmap();
+
+ /// Query whether this bitmap contains alpha channel information
+ bool hasAlpha() const;
+
+ /// Query size of the bitmap in pixel
+ ::basegfx::B2IVector getSize() const;
+
+ ::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 );
+
+ /** Render the bitmap content to associated
+ SurfaceProxyManager's screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the bitmap content to associated
+ SurfaceProxyManager's screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rArea
+ Subset of the surface to render. Coordinate system are
+ surface area pixel, given area will be clipped to the
+ surface bounds.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the bitmap content to associated
+ SurfaceProxyManager's screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rClipPoly
+ Clip polygon for the surface. The clip polygon is also
+ subject to the output transformation.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Clear whole bitmap with given color.
+
+ This method sets every single pixel of the bitmap to the
+ specified color value.
+ */
+ void clear( const ::com::sun::star::uno::Sequence< double >& color );
+
+ void fillB2DPolyPolygon(
+ const ::basegfx::B2DPolyPolygon& rPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+
+ // High-level drawing operations (from the XCanvas interface)
+ // ==========================================================
+
+ /// See XCanvas interface
+ void drawPoint( const ::com::sun::star::geometry::RealPoint2D& aPoint,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ /// See XCanvas interface
+ void drawLine( 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 );
+ /// See XCanvas interface
+ void drawBezier( 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 );
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr drawPolyPolygon(
+ 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 );
+
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr strokePolyPolygon(
+ 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 );
+ /** See XCanvas interface
+
+ @param textureAnnotations
+ Vector of shared pointers to bitmap textures,
+ <em>corresponding</em> in indices to the textures
+ sequence. This is to decouple this interface from the
+ client's XBitmap-implementation class.
+ */
+ ICachedPrimitiveSharedPtr strokeTexturedPolyPolygon(
+ 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 ::std::vector< ::boost::shared_ptr<Bitmap> >& textureAnnotations,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ /** See XCanvas interface
+
+ @param textureAnnotations
+ Vector of shared pointers to bitmap textures,
+ <em>corresponding</em> in indices to the textures
+ sequence. This is to decouple this interface from the
+ client's XBitmap-implementation class.
+ */
+ ICachedPrimitiveSharedPtr strokeTextureMappedPolyPolygon(
+ 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 ::std::vector< ::boost::shared_ptr<Bitmap> >& textureAnnotations,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::geometry::XMapping2D >& xMapping,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr fillPolyPolygon(
+ 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 );
+ /** See XCanvas interface
+
+ @param textureAnnotations
+ Vector of shared pointers to bitmap textures,
+ <em>corresponding</em> in indices to the textures
+ sequence. This is to decouple this interface from the
+ client's XBitmap-implementation class.
+ */
+ ICachedPrimitiveSharedPtr fillTexturedPolyPolygon(
+ 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 ::std::vector< ::boost::shared_ptr<Bitmap> >& textureAnnotations );
+ /** See XCanvas interface
+
+ @param textureAnnotations
+ Vector of shared pointers to bitmap textures,
+ <em>corresponding</em> in indices to the textures
+ sequence. This is to decouple this interface from the
+ client's XBitmap-implementation class.
+ */
+ ICachedPrimitiveSharedPtr fillTextureMappedPolyPolygon(
+ 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 ::std::vector< ::boost::shared_ptr<Bitmap> >& textureAnnotations,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::geometry::XMapping2D >& xMapping );
+
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr drawBitmap(
+ 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 );
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr drawBitmap(
+ const ::boost::shared_ptr<Bitmap>& rImage,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr drawBitmapModulated(
+ 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 );
+ /// See XCanvas interface
+ ICachedPrimitiveSharedPtr drawBitmapModulated(
+ const ::boost::shared_ptr<Bitmap>& rImage,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ private:
+ friend class ImplBitmap;
+
+ const ::boost::scoped_ptr< ImplBitmap > mpImpl;
+ };
+
+ typedef ::boost::shared_ptr< Bitmap > BitmapSharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_BITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/icachedprimitive.hxx b/canvas/inc/canvas/rendering/icachedprimitive.hxx
new file mode 100644
index 000000000000..ff4a6c207f08
--- /dev/null
+++ b/canvas/inc/canvas/rendering/icachedprimitive.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ICACHEDPRIMITIVE_HXX
+#define INCLUDED_CANVAS_ICACHEDPRIMITIVE_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace basegfx
+{
+ class B2IRange;
+ class B2IPoint;
+}
+
+namespace canvas
+{
+ /** Objects with this interface are returned from every Bitmap
+ render operation.
+
+ These objects can be used to implement the
+ rendering::XCachedPrimitive interface, which in turn caches
+ render state and objects to facilitate quick redraws.
+ */
+ struct ICachedPrimitive
+ {
+ virtual ~ICachedPrimitive() {}
+
+ /** Redraw the primitive with the given view state
+
+ Note that the primitive will <em>always</em> be redrawn on
+ the bitmap it was created from.
+ */
+ virtual sal_Int8 redraw( const ::com::sun::star::rendering::ViewState& aState ) const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ICachedPrimitive > ICachedPrimitiveSharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_ICACHEDPRIMITIVE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/icolorbuffer.hxx b/canvas/inc/canvas/rendering/icolorbuffer.hxx
new file mode 100644
index 000000000000..cdb58c304a70
--- /dev/null
+++ b/canvas/inc/canvas/rendering/icolorbuffer.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ICOLORBUFFER_HXX
+#define INCLUDED_CANVAS_ICOLORBUFFER_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace canvas
+{
+ /** Interface for a raw memory pixel container
+
+ Use this interface to represent a surface of raw pixel (e.g. a
+ bitmap) to the canvas rendering framework.
+ */
+ struct IColorBuffer
+ {
+ /// The underlying pixel format for this buffer
+ enum Format
+ {
+ // 24-bit RGB pixel format, 8 bits per channel.
+ FMT_R8G8B8,
+
+ // 32-bit ARGB pixel format with alpha, 8 bits per channel.
+ FMT_A8R8G8B8,
+
+ // 32-bit RGB pixel format, 8 bits per channel.
+ FMT_X8R8G8B8,
+
+ // for enum to 32bit
+ FMT_UNKNOWN = static_cast<sal_uInt32>(-1)
+ };
+
+ virtual ~IColorBuffer() {}
+
+ /** Get a pointer to the raw memory bits of the pixel
+ */
+ virtual sal_uInt8* lock() const = 0;
+
+ /** unlock previous locked buffer
+ */
+ virtual void unlock() const = 0;
+
+ /** Get width in pixel
+ */
+ virtual sal_uInt32 getWidth() const = 0;
+
+ /** Get height in pixel
+ */
+ virtual sal_uInt32 getHeight() const = 0;
+
+ /** Offset, in bytes, between consecutive scan lines of the bitmap.
+ If the stride is positive, the bitmap is top-down.
+ If the stride is negative, the bitmap is bottom-up.
+ The returned value is only valid while the buffer is locked.
+ */
+ virtual sal_uInt32 getStride() const = 0;
+
+ /** Get format of the color buffer
+ */
+ virtual Format getFormat() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< IColorBuffer > IColorBufferSharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_ICOLORBUFFER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/irendermodule.hxx b/canvas/inc/canvas/rendering/irendermodule.hxx
new file mode 100644
index 000000000000..b3e470005e45
--- /dev/null
+++ b/canvas/inc/canvas/rendering/irendermodule.hxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_IRENDERMODULE_HXX
+#define INCLUDED_CANVAS_IRENDERMODULE_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+
+namespace basegfx
+{
+ class B2DRange;
+ class B2IRange;
+ class B2IVector;
+ class B2IPoint;
+}
+
+namespace canvas
+{
+ struct ISurface;
+
+ struct Vertex
+ {
+ float r,g,b,a;
+ float u,v;
+ float x,y,z;
+ };
+
+ /** Output module interface for backend render implementations.
+
+ Implement this interface for each operating system- or
+ library-specific rendering backend, which needs coupling with
+ the canvas rendering framework (which can be shared between
+ all backend implementations).
+ */
+ struct IRenderModule
+ {
+ /** Type of primitive passed to the render module via
+ pushVertex()
+ */
+ enum PrimitiveType
+ {
+ PRIMITIVE_TYPE_UNKNOWN,
+ PRIMITIVE_TYPE_TRIANGLE,
+ PRIMITIVE_TYPE_QUAD
+ };
+
+ virtual ~IRenderModule() {}
+
+ /// Lock rendermodule against concurrent access
+ virtual void lock() const = 0;
+
+ /// Unlock rendermodule for concurrent access
+ virtual void unlock() const = 0;
+
+ /** Maximal size of VRAM pages available
+
+ This is typically the maximum texture size of the
+ hardware, or some arbitrary limit if the backend is
+ software.
+ */
+ virtual ::basegfx::B2IVector getPageSize() = 0;
+
+ /** Create a (possibly hardware-accelerated) surface
+
+ @return a pointer to a surface, which is an abstraction of
+ a piece of (possibly hardware-accelerated) texture memory.
+ */
+ virtual ::boost::shared_ptr<ISurface> createSurface( const ::basegfx::B2IVector& surfaceSize ) = 0;
+
+ /** Begin rendering the given primitive.
+
+ Each beginPrimitive() call must be matched with an
+ endPrimitive() call.
+ */
+ virtual void beginPrimitive( PrimitiveType eType ) = 0;
+
+ /** Finish rendering a primitive.
+
+ Each beginPrimitive() call must be matched with an
+ endPrimitive() call.
+ */
+ virtual void endPrimitive() = 0;
+
+ /** Add given vertex to current primitive
+
+ After issuing a beginPrimitive(), each pushVertex() adds a
+ vertex to the active primitive.
+ */
+ virtual void pushVertex( const Vertex& vertex ) = 0;
+
+ /** Query error status
+
+ @returns true, if an error occured during primitive
+ construction.
+ */
+ virtual bool isError() = 0;
+ };
+
+ typedef ::boost::shared_ptr< IRenderModule > IRenderModuleSharedPtr;
+
+ /// Little RAII wrapper for guarding access to IRenderModule interface
+ class RenderModuleGuard : private ::boost::noncopyable
+ {
+ public:
+ explicit RenderModuleGuard( const IRenderModuleSharedPtr& rRenderModule ) :
+ mpRenderModule( rRenderModule )
+ {
+ mpRenderModule->lock();
+ }
+
+ ~RenderModuleGuard()
+ {
+ mpRenderModule->unlock();
+ }
+
+ private:
+ const IRenderModuleSharedPtr mpRenderModule;
+ };
+}
+
+#endif /* INCLUDED_CANVAS_IRENDERMODULE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/isurface.hxx b/canvas/inc/canvas/rendering/isurface.hxx
new file mode 100644
index 000000000000..7b08e2985fbc
--- /dev/null
+++ b/canvas/inc/canvas/rendering/isurface.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ISURFACE_HXX
+#define INCLUDED_CANVAS_ISURFACE_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace basegfx
+{
+ class B2IRange;
+ class B2IPoint;
+ class B2IVector;
+}
+
+namespace canvas
+{
+ struct IColorBuffer;
+
+ struct ISurface
+ {
+ virtual ~ISurface() {}
+
+ /** Select texture behind this interface to be the current one
+ for primitive output.
+ */
+ virtual bool selectTexture() = 0;
+
+ /** Tells wether the surface is valid or not
+ */
+ virtual bool isValid() = 0;
+
+ /** Update surface content from given IColorBuffer
+
+ This method updates the given subarea of the surface from
+ the given color buffer bits.
+
+ @param rDestPos
+ Position in the surface, where the subset update should
+ have its left, top edge
+
+ @param rSourceRect
+ Size and position of the rectangular subset update in the
+ source color buffer
+
+ @param rSource
+ Source bits to use for the update
+
+ @return true, if the update was successful
+ */
+ virtual bool update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ IColorBuffer& rSource ) = 0;
+
+ virtual ::basegfx::B2IVector getSize() = 0;
+ };
+
+ typedef ::boost::shared_ptr< ISurface > ISurfaceSharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_ISURFACE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/isurfaceproxy.hxx b/canvas/inc/canvas/rendering/isurfaceproxy.hxx
new file mode 100644
index 000000000000..998278a897f7
--- /dev/null
+++ b/canvas/inc/canvas/rendering/isurfaceproxy.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ISURFACEPROXY_HXX
+#define INCLUDED_CANVAS_ISURFACEPROXY_HXX
+
+#include <canvas/rendering/irendermodule.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+namespace basegfx
+{
+ class B2DRange;
+ class B2DPoint;
+ class B2DPolyPolygon;
+ class B2DHomMatrix;
+}
+
+namespace canvas
+{
+ struct ISurfaceProxy
+ {
+ virtual ~ISurfaceProxy() {}
+
+ /** Notify the proxy that the color buffer has changed
+ */
+ virtual void setColorBufferDirty() = 0;
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform ) = 0;
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rArea
+ Subset of the surface to render. Coordinate system are
+ surface area pixel, given area will be clipped to the
+ surface bounds.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform ) = 0;
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rClipPoly
+ Clip polygon for the surface. The clip polygon is also
+ subject to the output transformation.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ISurfaceProxy > ISurfaceProxySharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_ISURFACEPROXY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/rendering/isurfaceproxymanager.hxx b/canvas/inc/canvas/rendering/isurfaceproxymanager.hxx
new file mode 100644
index 000000000000..773592cd2d47
--- /dev/null
+++ b/canvas/inc/canvas/rendering/isurfaceproxymanager.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_ISURFACEPROXYMANAGER_HXX
+#define INCLUDED_CANVAS_ISURFACEPROXYMANAGER_HXX
+
+#include <canvas/rendering/irendermodule.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace canvas
+{
+ struct ISurfaceProxy;
+
+ /** Manager interface, which handles surface proxy objects.
+
+ Typically, each canvas instantiation has one
+ SurfaceProxyManager object, to handle their surfaces. Surfaces
+ itself are opaque objects, which encapsulate a framebuffer to
+ render upon, plus an optional (possibly accelerated) texture.
+ */
+ struct ISurfaceProxyManager
+ {
+ virtual ~ISurfaceProxyManager() {}
+
+ /** Create a surface proxy for a color buffer.
+
+ The whole idea is build around the concept that you create
+ some arbitrary buffer which contains the image data and
+ tell the texture manager about it. From there on you can
+ draw into this image using any kind of graphics api you
+ want. In the technical sense we allocate some space in
+ local videomemory or AGP memory which will be filled on
+ demand, which means if there exists any rendering
+ operation that needs to read from this memory location.
+ This method creates a logical hardware surface object
+ which uses the given color buffer as the image source.
+ Internally this texture may even be distributed to several
+ real hardware surfaces.
+ */
+ virtual ::boost::shared_ptr< ISurfaceProxy > createSurfaceProxy(
+ const IColorBufferSharedPtr& pBuffer ) const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ISurfaceProxyManager > ISurfaceProxyManagerSharedPtr;
+
+
+ /** Create a surface proxy for the given render module.
+ */
+ ISurfaceProxyManagerSharedPtr createSurfaceProxyManager( const IRenderModuleSharedPtr& rRenderModule );
+}
+
+#endif /* INCLUDED_CANVAS_ISURFACEPROXYMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/spriteredrawmanager.hxx b/canvas/inc/canvas/spriteredrawmanager.hxx
new file mode 100644
index 000000000000..c2eed8e0cf3a
--- /dev/null
+++ b/canvas/inc/canvas/spriteredrawmanager.hxx
@@ -0,0 +1,437 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
+#define INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
+
+#include <basegfx/range/b2dconnectedranges.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/base/spritesurface.hxx>
+
+#include <list>
+#include <vector>
+#include <algorithm>
+
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+
+
+/* Definition of SpriteRedrawManager class */
+
+namespace canvas
+{
+ /** This class manages smooth SpriteCanvas updates
+
+ Use this class to handle the ::canvas::SpriteSurface methods,
+ that track and process sprite update events. Recorded update
+ events are later grouped by connected areas (i.e. all sprites
+ that somehow overlap over a rectangular area are grouped
+ together); the forEachSpriteArea() method calls the passed
+ functor for each of those connected areas.
+
+ Note that, although this class generally works with IEEE
+ doubles, the calculation of connected areas happens in the
+ integer domain - it is generally expected that repaints can
+ only be divided at pixel boundaries, without causing visible
+ artifacts. Therefore, sprites that touch the same pixel (but
+ don't necessarily have the same floating point coordinates
+ there) will reside in a common sprite area and handled
+ together in the forEachSpriteArea functor call.
+ */
+ class SpriteRedrawManager : private ::boost::noncopyable
+ {
+ public:
+ /** Data container for the connected components list
+ */
+ class SpriteInfo
+ {
+ public:
+ ~SpriteInfo() {}
+
+ /** Create sprite info
+
+ @param rRef
+ Sprite this info represents (might be the NULL ref)
+
+ @param rTrueUpdateArea
+ True (un-rounded) update area this sprite has recorded
+
+ @param bNeedsUpdate
+ When false, this sprite is not a member of the change
+ record list. Thus, it only needs redraw if within the
+ update area of other, changed sprites.
+
+ @internal
+ */
+ SpriteInfo( const Sprite::Reference& rRef,
+ const ::basegfx::B2DRange& rTrueUpdateArea,
+ bool bNeedsUpdate ) :
+ mpSprite( rRef ),
+ maTrueUpdateArea( rTrueUpdateArea ),
+ mbNeedsUpdate( bNeedsUpdate ),
+ mbIsPureMove( false )
+ {
+ }
+
+ /** Create sprite info, specify move type
+
+ @param rRef
+ Sprite this info represents (might be the NULL ref)
+
+ @param rTrueUpdateArea
+ True (un-rounded) update area this sprite has recorded
+
+ @param bNeedsUpdate
+ When false, this sprite is not a member of the change
+ record list. Thus, it only needs redraw if within the
+ update area of other, changed sprites.
+
+ @param bIsPureMove
+ When true, this sprite is _only_ moved, no other
+ changes happened.
+
+ @internal
+ */
+ SpriteInfo( const Sprite::Reference& rRef,
+ const ::basegfx::B2DRange& rTrueUpdateArea,
+ bool bNeedsUpdate,
+ bool bIsPureMove ) :
+ mpSprite( rRef ),
+ maTrueUpdateArea( rTrueUpdateArea ),
+ mbNeedsUpdate( bNeedsUpdate ),
+ mbIsPureMove( bIsPureMove )
+ {
+ }
+
+ const Sprite::Reference& getSprite() const { return mpSprite; }
+
+ // #i61843# need to return by value here, to be used safely from bind
+ ::basegfx::B2DRange getUpdateArea() const { return maTrueUpdateArea; }
+ bool needsUpdate() const { return mbNeedsUpdate; }
+ bool isPureMove() const { return mbIsPureMove; }
+
+ private:
+ Sprite::Reference mpSprite;
+ ::basegfx::B2DRange maTrueUpdateArea;
+ bool mbNeedsUpdate;
+ bool mbIsPureMove;
+ };
+
+
+ /** Helper struct for SpriteTracer template
+
+ This struct stores change information to a sprite's visual
+ appearance (move, content updated, and the like).
+ */
+ struct SpriteChangeRecord
+ {
+ typedef enum{ none=0, move, update } ChangeType;
+
+ SpriteChangeRecord() :
+ meChangeType( none ),
+ mpAffectedSprite(),
+ maOldPos(),
+ maUpdateArea()
+ {
+ }
+
+ SpriteChangeRecord( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rOldPos,
+ const ::basegfx::B2DPoint& rNewPos,
+ const ::basegfx::B2DVector& rSpriteSize ) :
+ meChangeType( move ),
+ mpAffectedSprite( rSprite ),
+ maOldPos( rOldPos ),
+ maUpdateArea( rNewPos.getX(),
+ rNewPos.getY(),
+ rNewPos.getX() + rSpriteSize.getX(),
+ rNewPos.getY() + rSpriteSize.getY() )
+ {
+ }
+
+ SpriteChangeRecord( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rUpdateArea ) :
+ meChangeType( update ),
+ mpAffectedSprite( rSprite ),
+ maOldPos( rPos ),
+ maUpdateArea( rUpdateArea )
+ {
+ }
+
+ Sprite::Reference getSprite() const { return mpAffectedSprite; }
+
+ ChangeType meChangeType;
+ Sprite::Reference mpAffectedSprite;
+ ::basegfx::B2DPoint maOldPos;
+ ::basegfx::B2DRange maUpdateArea;
+ };
+
+ typedef ::std::vector< SpriteChangeRecord > VectorOfChangeRecords;
+ typedef ::std::list< Sprite::Reference > ListOfSprites;
+ typedef ::basegfx::B2DConnectedRanges< SpriteInfo > SpriteConnectedRanges;
+ typedef SpriteConnectedRanges::ComponentType AreaComponent;
+ typedef SpriteConnectedRanges::ConnectedComponents UpdateArea;
+ typedef ::std::vector< Sprite::Reference > VectorOfSprites;
+
+ SpriteRedrawManager();
+
+ /** Must be called when user of this object gets
+ disposed. Frees all internal references.
+ */
+ void disposing();
+
+ /** Functor, to be used from forEachSpriteArea
+ */
+ template< typename Functor > struct AreaUpdateCaller
+ {
+ AreaUpdateCaller( Functor& rFunc,
+ const SpriteRedrawManager& rManager ) :
+ mrFunc( rFunc ),
+ mrManager( rManager )
+ {
+ }
+
+ void operator()( const UpdateArea& rUpdateArea )
+ {
+ mrManager.handleArea( mrFunc, rUpdateArea );
+ }
+
+ Functor& mrFunc;
+ const SpriteRedrawManager& mrManager;
+ };
+
+ /** Call given functor for each sprite area that needs an
+ update.
+
+ This method calls the given functor for each update area
+ (calculated from the sprite change records).
+
+ @tpl Functor
+ Must provide the following four methods:
+ <pre>
+ void backgroundPaint( ::basegfx::B2DRange aUpdateRect );
+ void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart,
+ ::basegfx::B2DRange& o_rMoveEnd,
+ UpdateArea aUpdateArea );
+ 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 );
+ </pre>
+ The backgroundPaint() method is called to simply repaint
+ background content, the scrollUpdate() method is used to
+ scroll a given area, and paint background in the uncovered
+ areas, the opaqueUpdate() method is called when a sprite
+ can be painted in the given area without taking background
+ content into account, and finally, genericUpdate() is
+ called for complex updates, where first the background and
+ then all sprites consecutively have to be repainted.
+ */
+ template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const
+ {
+ SpriteConnectedRanges aUpdateAreas;
+
+ setupUpdateAreas( aUpdateAreas );
+
+ aUpdateAreas.forEachAggregate(
+ AreaUpdateCaller< Functor >( rFunc, *this ) );
+ }
+
+ /** Call given functor for each active sprite.
+
+ This method calls the given functor for each active
+ sprite, in the order of sprite priority.
+
+ @tpl Functor
+ Must provide a Functor::operator( Sprite::Reference& )
+ method.
+ */
+ template< typename Functor > void forEachSprite( const Functor& rFunc ) const
+ {
+ ::std::for_each( maSprites.begin(),
+ maSprites.end(),
+ rFunc );
+ }
+
+ /// Clear sprite change records (typically directly after a screen update)
+ void clearChangeRecords();
+
+ // SpriteSurface interface, is delegated to e.g. from SpriteCanvas
+ void showSprite( const Sprite::Reference& rSprite );
+ void hideSprite( const Sprite::Reference& rSprite );
+ void moveSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rOldPos,
+ const ::basegfx::B2DPoint& rNewPos,
+ const ::basegfx::B2DVector& rSpriteSize );
+ void updateSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rUpdateArea );
+
+ /** Internal, handles each distinct component for forEachAggregate()
+
+ The reason why this must be public is that it needs to be
+ accessible from the AreaUpdateCaller functor.
+
+ @internal
+ */
+ template< typename Functor > void handleArea( Functor& rFunc,
+ const UpdateArea& rUpdateArea ) const
+ {
+ // check whether this area contains changed sprites at all
+ // (if not, just ignore it)
+ if( areSpritesChanged( rUpdateArea ) )
+ {
+ // at least one of the sprites actually needs an
+ // update - process whole area.
+
+ // check whether this area could be handled special
+ // (background paint, direct update, scroll, etc.)
+ ::basegfx::B2DRange aMoveStart;
+ ::basegfx::B2DRange aMoveEnd;
+ if( rUpdateArea.maComponentList.empty() )
+ {
+ rFunc.backgroundPaint( rUpdateArea.maTotalBounds );
+ }
+ else
+ {
+ // cache number of sprites in this area (it's a
+ // list, and both isAreaUpdateScroll() and
+ // isAreaUpdateOpaque() need it).
+ const ::std::size_t nNumSprites(
+ rUpdateArea.maComponentList.size() );
+
+ if( isAreaUpdateScroll( aMoveStart,
+ aMoveEnd,
+ rUpdateArea,
+ nNumSprites ) )
+ {
+ rFunc.scrollUpdate( aMoveStart,
+ aMoveEnd,
+ rUpdateArea );
+ }
+ else
+ {
+ // potentially, more than a single sprite
+ // involved. Have to sort component lists for
+ // sprite prio.
+ VectorOfSprites aSortedUpdateSprites;
+ SpriteConnectedRanges::ComponentListType::const_iterator aCurr(
+ rUpdateArea.maComponentList.begin() );
+ const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
+ rUpdateArea.maComponentList.end() );
+ while( aCurr != aEnd )
+ {
+ const Sprite::Reference& rSprite( aCurr->second.getSprite() );
+ if( rSprite.is() )
+ aSortedUpdateSprites.push_back( rSprite );
+
+ ++aCurr;
+ }
+
+ ::std::sort( aSortedUpdateSprites.begin(),
+ aSortedUpdateSprites.end(),
+ SpriteComparator() );
+
+ if( isAreaUpdateOpaque( rUpdateArea,
+ nNumSprites ) )
+ {
+ rFunc.opaqueUpdate( rUpdateArea.maTotalBounds,
+ aSortedUpdateSprites );
+ }
+ else
+ {
+ rFunc.genericUpdate( rUpdateArea.maTotalBounds,
+ aSortedUpdateSprites );
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ /** Central method of this class. Calculates the set of
+ disjunct components that need an update.
+ */
+ void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const;
+
+ bool areSpritesChanged( const UpdateArea& rUpdateArea ) const;
+
+ bool isAreaUpdateNotOpaque( const ::basegfx::B2DRange& rUpdateRect,
+ const AreaComponent& rComponent ) const;
+
+ bool isAreaUpdateOpaque( const UpdateArea& rUpdateArea,
+ ::std::size_t nNumSprites ) const;
+
+ /** Check whether given update area can be handled by a simple
+ scroll
+
+ @param o_rMoveStart
+ Start rect of the move
+
+ @param o_rMoveEnd
+ End rect of the move. The content must be moved from start
+ to end rect
+
+ @param rUpdateArea
+ Area to check for scroll update optimization
+ */
+ bool isAreaUpdateScroll( ::basegfx::B2DRange& o_rMoveStart,
+ ::basegfx::B2DRange& o_rMoveEnd,
+ const UpdateArea& rUpdateArea,
+ ::std::size_t nNumSprites ) const;
+
+
+ ListOfSprites maSprites; // list of active
+ // sprite
+ // objects. this
+ // list is only
+ // used for full
+ // repaints,
+ // otherwise, we
+ // rely on the
+ // active sprites
+ // itself to notify
+ // us.
+
+ VectorOfChangeRecords maChangeRecords; // vector of
+ // sprites
+ // changes
+ // since last
+ // updateScreen()
+ // call
+ };
+}
+
+#endif /* INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/vclwrapper.hxx b/canvas/inc/canvas/vclwrapper.hxx
new file mode 100644
index 000000000000..d30667479f62
--- /dev/null
+++ b/canvas/inc/canvas/vclwrapper.hxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_VCLWRAPPER_HXX
+#define INCLUDED_CANVAS_VCLWRAPPER_HXX
+
+#include <osl/mutex.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+
+namespace canvas
+{
+ namespace vcltools
+ {
+ /** This helper template wraps VCL objects, and protects
+ object deletion with the Solar mutex. All other operations
+ are unprotected, this must be handled by client code.
+
+ The reason for this template is the fact that VCL objects
+ hold by value in uno::Reference-handled classes are
+ deleted without having the chance to get inbetween and
+ lock the solar mutex.
+
+ This template handles that problem transparently, the only
+ inconvenience is the fact that object member access now
+ has to be performed via operator->, since . is not
+ overloadable.
+
+ Otherwise, the template preserves the value semantics of
+ the wrapped object, that is, copy operations are performed
+ not by copying pointers, but by copying the underlying
+ object. This includes constness, i.e. on a const
+ VCLObject, only const methods of the wrapped object can be
+ called. Simply imagine this to be a value object of type
+ "template argument", with the only peculiarity that
+ member/method access is performed by operator-> instead of
+ the non-existing "operator.".
+ */
+ template< class _Wrappee > class VCLObject
+ {
+ public:
+ typedef _Wrappee Wrappee;
+
+ VCLObject() :
+ mpWrappee( new Wrappee() )
+ {
+ }
+
+ // no explicit here. VCLObjects should be freely
+ // constructible with Wrappees, and AFAIK there is no other
+ // implicit conversion path that could cause harm here
+ VCLObject( Wrappee* pWrappee ) :
+ mpWrappee( pWrappee )
+ {
+ }
+
+ // This object has value semantics, thus, forward copy
+ // to wrappee
+ VCLObject( const VCLObject& rOrig )
+ {
+ if( rOrig.mpWrappee )
+ mpWrappee = new Wrappee( *rOrig.mpWrappee );
+ else
+ mpWrappee = NULL;
+ }
+
+ // This object has value semantics, thus, forward copy
+ // to wrappee
+ VCLObject( const Wrappee& rOrig ) :
+ mpWrappee( new Wrappee( rOrig ) )
+ {
+ }
+
+ // This object has value semantics, thus, forward
+ // assignment to wrappee
+ VCLObject& operator=( const VCLObject& rhs )
+ {
+ if( mpWrappee )
+ {
+ if( rhs.mpWrappee )
+ *mpWrappee = *rhs.mpWrappee;
+ }
+ else
+ {
+ if( rhs.mpWrappee )
+ mpWrappee = new Wrappee( *rhs.mpWrappee );
+ }
+
+ return *this;
+ }
+
+ ~VCLObject()
+ {
+ // This here is the whole purpose of the template:
+ // protecting object deletion with the solar mutex
+ SolarMutexGuard aGuard;
+
+ if( mpWrappee )
+ delete mpWrappee;
+ }
+
+ Wrappee* operator->() { return mpWrappee; }
+ const Wrappee* operator->() const { return mpWrappee; }
+
+ Wrappee& operator*() { return *mpWrappee; }
+ const Wrappee& operator*() const { return *mpWrappee; }
+
+ Wrappee& get() { return *mpWrappee; }
+ const Wrappee& get() const { return *mpWrappee; }
+
+ void swap( VCLObject& rOther )
+ {
+ ::std::swap( mpWrappee, rOther.mpWrappee );
+ }
+
+ private:
+
+ Wrappee* mpWrappee;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_CANVAS_VCLWRAPPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/verbosetrace.hxx b/canvas/inc/canvas/verbosetrace.hxx
new file mode 100644
index 000000000000..aadfa0a40a53
--- /dev/null
+++ b/canvas/inc/canvas/verbosetrace.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_VERBOSETRACE_HXX
+#define INCLUDED_CANVAS_VERBOSETRACE_HXX
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+/// Wrap OSL_TRACE with a verbosity switch
+#define VERBOSE_TRACE OSL_TRACE
+#else
+#define VERBOSE_TRACE 1 ? ((void)0) : OSL_TRACE
+#endif
+
+#endif /* INCLUDED_CANVAS_VERBOSETRACE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/canvas/verifyinput.hxx b/canvas/inc/canvas/verifyinput.hxx
new file mode 100644
index 000000000000..748868ddba2b
--- /dev/null
+++ b/canvas/inc/canvas/verifyinput.hxx
@@ -0,0 +1,723 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_VERIFYINPUT_HXX
+#define INCLUDED_CANVAS_VERIFYINPUT_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/current_function.hpp>
+
+
+namespace com { namespace sun { namespace star { namespace geometry
+{
+ struct RealPoint2D;
+ struct RealSize2D;
+ struct RealBezierSegment2D;
+ struct RealRectangle2D;
+ struct AffineMatrix2D;
+ struct Matrix2D;
+ struct IntegerPoint2D;
+ struct IntegerSize2D;
+ struct IntegerRectangle2D;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct RenderState;
+ struct StrokeAttributes;
+ struct Texture;
+ struct ViewState;
+ struct IntegerBitmapLayout;
+ struct FloatingPointBitmapLayout;
+ struct FontRequest;
+ struct FontInfo;
+ class XCanvas;
+} } } }
+
+
+namespace canvas
+{
+ namespace tools
+ {
+
+ // Input checking facilities
+ // ===================================================================
+
+ // This header provides methods to check all common
+ // css::rendering::* method input parameters against
+ // compliance to the API specification.
+
+ /** Verify that the given transformation contains valid floating point
+ values.
+
+ @param rMatrix
+ Matrix to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::AffineMatrix2D& rMatrix,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given transformation contains valid floating point
+ values.
+
+ @param rMatrix
+ Matrix to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::Matrix2D& rMatrix,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given point contains valid floating point
+ values.
+
+ @param rPoint
+ Point to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::RealPoint2D& rPoint,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given size contains valid floating point
+ values.
+
+ @param rSize
+ Size to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::RealSize2D& rSize,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given bezier segment contains valid
+ floating point values.
+
+ @param rSegment
+ Segment to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::RealBezierSegment2D& rSegment,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given point contains valid floating point
+ values.
+
+ @param rPoint
+ Point to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::RealPoint2D& rPoint,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Verify that the given rectangle contains valid floating
+ point values.
+
+ @param rRect
+ Rect to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::geometry::RealRectangle2D& rRect,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for view state validity.
+
+ @param viewState
+ Viewstate to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::ViewState& viewState,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for render state validity.
+
+ @param renderState
+ Renderstate to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @param nMinColorComponents
+ Minimal number of color components available in
+ RenderState::DeviceColor
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::RenderState& renderState,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos,
+ sal_Int32 nMinColorComponents=0 );
+
+ /** Basic check for stroke attributes validity.
+
+ @param strokeAttributes
+ Attributes to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for texture validity.
+
+ @param texture
+ Texture to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::Texture& texture,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for bitmap layout validity.
+
+ @param bitmapLayout
+ Bitmap layout to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for bitmap layout validity.
+
+ @param bitmapLayout
+ Bitmap layout to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for font info validity.
+
+ @param fontInfo
+ Font info to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::FontInfo& fontInfo,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Basic check for font request validity.
+
+ @param fontRequest
+ Font request to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ void verifyInput( const ::com::sun::star::rendering::FontRequest& fontRequest,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos );
+
+ /** Templatized check for uno::Reference validity.
+
+ @param rRef
+ Reference to check against non-NILness
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ template< class Interface > void verifyInput(
+ const ::com::sun::star::uno::Reference< Interface >& rRef,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+ if( !rRef.is() )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw ::com::sun::star::lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": reference is NULL"),
+ xIf,
+ nArgPos );
+#else
+ throw ::com::sun::star::lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ /** Templatized check for content-of-sequence validity.
+
+ @param rSequence
+ Sequence of things to check
+
+ @param xIf
+ The interface that should be reported as the one
+ generating the exception.
+
+ @param nArgPos
+ Argument position on the call site (i.e. the position of
+ the argument, checked here, on the UNO interface
+ method. Counting starts at 0).
+
+ @throws an lang::IllegalArgumentException, if anything is wrong
+ */
+ template< typename SequenceContent > void verifyInput(
+ const ::com::sun::star::uno::Sequence< SequenceContent >& rSequence,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ const SequenceContent* pCurr = rSequence.getConstArray();
+ const SequenceContent* pEnd = pCurr + rSequence.getLength();
+ while( pCurr != pEnd )
+ verifyInput( *pCurr++, pStr, xIf, nArgPos );
+ }
+
+ /// Catch-all, to handle cases that DON'T need input checking (i.e. the Integer geometry ones)
+ template< typename T > void verifyInput( const T& /*rDummy*/,
+ const char* /*pStr*/,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& /*xIf*/,
+ ::sal_Int16 /*nArgPos*/ )
+ {
+ }
+
+ // TODO(Q2): Employ some template arglist magic here, to avoid
+ // this duplication of code...
+
+ template< typename Arg0 > void verifyArgs( const Arg0& rArg0,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ }
+
+ template< typename Arg0,
+ typename Arg1 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ }
+
+ template< typename Arg0,
+ typename Arg1,
+ typename Arg2 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const Arg2& rArg2,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ verifyInput( rArg2, pStr, xIf, 2 );
+ }
+
+ template< typename Arg0,
+ typename Arg1,
+ typename Arg2,
+ typename Arg3 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const Arg2& rArg2,
+ const Arg3& rArg3,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ verifyInput( rArg2, pStr, xIf, 2 );
+ verifyInput( rArg3, pStr, xIf, 3 );
+ }
+
+ template< typename Arg0,
+ typename Arg1,
+ typename Arg2,
+ typename Arg3,
+ typename Arg4 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const Arg2& rArg2,
+ const Arg3& rArg3,
+ const Arg4& rArg4,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ verifyInput( rArg2, pStr, xIf, 2 );
+ verifyInput( rArg3, pStr, xIf, 3 );
+ verifyInput( rArg4, pStr, xIf, 4 );
+ }
+
+ template< typename Arg0,
+ typename Arg1,
+ typename Arg2,
+ typename Arg3,
+ typename Arg4,
+ typename Arg5 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const Arg2& rArg2,
+ const Arg3& rArg3,
+ const Arg4& rArg4,
+ const Arg5& rArg5,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ verifyInput( rArg2, pStr, xIf, 2 );
+ verifyInput( rArg3, pStr, xIf, 3 );
+ verifyInput( rArg4, pStr, xIf, 4 );
+ verifyInput( rArg5, pStr, xIf, 5 );
+ }
+
+ template< typename Arg0,
+ typename Arg1,
+ typename Arg2,
+ typename Arg3,
+ typename Arg4,
+ typename Arg5,
+ typename Arg6 > void verifyArgs( const Arg0& rArg0,
+ const Arg1& rArg1,
+ const Arg2& rArg2,
+ const Arg3& rArg3,
+ const Arg4& rArg4,
+ const Arg5& rArg5,
+ const Arg6& rArg6,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf )
+ {
+ verifyInput( rArg0, pStr, xIf, 0 );
+ verifyInput( rArg1, pStr, xIf, 1 );
+ verifyInput( rArg2, pStr, xIf, 2 );
+ verifyInput( rArg3, pStr, xIf, 3 );
+ verifyInput( rArg4, pStr, xIf, 4 );
+ verifyInput( rArg5, pStr, xIf, 5 );
+ verifyInput( rArg6, pStr, xIf, 6 );
+ }
+
+
+ /** Range checker, which throws ::com::sun::star::lang::IllegalArgument exception, when
+ range is violated
+ */
+ template< typename NumType > inline void verifyRange( NumType arg, NumType lowerBound, NumType upperBound )
+ {
+ if( arg < lowerBound ||
+ arg > upperBound )
+ {
+ throw ::com::sun::star::lang::IllegalArgumentException();
+ }
+ }
+
+ /** Range checker, which throws ::com::sun::star::lang::IllegalArgument exception, when
+ range is violated
+
+ The checked range is half open, i.e. only bound by the specified value.
+
+ @param arg
+ Arg to check
+
+ @param bound
+ Bound to check against
+
+ @param bLowerBound
+ When true, given bound is the lower bound. When false,
+ given bound is the upper bound.
+ */
+ template< typename NumType > inline void verifyRange( NumType arg, NumType bound, bool bLowerBound=true )
+ {
+ if( (bLowerBound && arg < bound) ||
+ (!bLowerBound && arg > bound) )
+ {
+ throw ::com::sun::star::lang::IllegalArgumentException();
+ }
+ }
+
+ /** Range checker, which throws ::com::sun::star::lang::IndexOutOfBounds exception, when
+ index range is violated
+ */
+ template< typename NumType > inline void verifyIndexRange( NumType arg, NumType lowerBound, NumType upperBound )
+ {
+ if( arg < lowerBound ||
+ arg > upperBound )
+ {
+ throw ::com::sun::star::lang::IndexOutOfBoundsException();
+ }
+ }
+
+ /** Range checker, which throws ::com::sun::star::lang::IndexOutOfBounds exception, when
+ index range is violated
+
+ @param rect
+ Rect to verify
+
+ @param size
+ Given rectangle must be within ((0,0), (size.Width, size.Height))
+ */
+ void verifyIndexRange( const ::com::sun::star::geometry::IntegerRectangle2D& rect,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+
+ /** Range checker, which throws ::com::sun::star::lang::IndexOutOfBounds exception, when
+ index range is violated
+
+ @param pos
+ Position to verify
+
+ @param size
+ Given position must be within ((0,0), (size.Width, size.Height))
+ */
+ void verifyIndexRange( const ::com::sun::star::geometry::IntegerPoint2D& pos,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+
+ /** Range checker, which throws ::com::sun::star::lang::IndexOutOfBounds exception, when
+ the size is negative or null
+
+ @param size
+ Size to verify
+ */
+ void verifyBitmapSize( const ::com::sun::star::geometry::IntegerSize2D& size,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf );
+
+ /** Range checker, which throws ::com::sun::star::lang::IndexOutOfBounds exception, when
+ the size is negative or null
+
+ @param size
+ Size to verify
+ */
+ void verifySpriteSize( const ::com::sun::star::geometry::RealSize2D& size,
+ const char* pStr,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface >& xIf );
+ }
+}
+
+#endif /* INCLUDED_CANVAS_VERIFYINPUT_HXX */
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/makefile.mk b/canvas/inc/makefile.mk
new file mode 100644
index 000000000000..6a74668fd4cd
--- /dev/null
+++ b/canvas/inc/makefile.mk
@@ -0,0 +1,47 @@
+#*************************************************************************
+#
+# 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=inc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.IF "$(ENABLE_PCH)"!=""
+ALLTAR : \
+ $(SLO)$/precompiled.pch \
+ $(SLO)$/precompiled_ex.pch
+
+.ENDIF # "$(ENABLE_PCH)"!=""
+
diff --git a/canvas/inc/pch/precompiled_canvas.cxx b/canvas/inc/pch/precompiled_canvas.cxx
new file mode 100644
index 000000000000..ad3b242d4c3c
--- /dev/null
+++ b/canvas/inc/pch/precompiled_canvas.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_canvas.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/inc/pch/precompiled_canvas.hxx b/canvas/inc/pch/precompiled_canvas.hxx
new file mode 100644
index 000000000000..06d61119c733
--- /dev/null
+++ b/canvas/inc/pch/precompiled_canvas.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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): Generated on 2006-09-01 17:49:32.389803
+
+#ifdef PRECOMPILED_HEADERS
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/overview.txt b/canvas/overview.txt
new file mode 100644
index 000000000000..5d508b04bc45
--- /dev/null
+++ b/canvas/overview.txt
@@ -0,0 +1,50 @@
+The new OOo Canvas Framework
+============================
+
+The new OpenOffice.org canvas framework is the successor of the system
+GUI and graphics backend VCL. Basic functionality is available,
+supplying just as much features as necessary to provide a
+VCL-equivalent feature set (except proper BiDi/CTL support).
+
+For migration purposes, the new canvas and VCL will be shipped with
+OpenOffice.org for quite some time, allowing a step-by-step adaptation
+of the applications. Therefore, the canvas and VCL must somehow
+interoperate, since new code, using the canvas, typically is embedded
+in a VCL-based environment (for example, the OOo windows are still
+provided by VCL. To render into such a window via the canvas, a canvas
+must be constructable from a VCL window). Thus, essentially two new
+methods are provided at VCL's window, namely Window::GetCanvas() and
+Window::GetFullScreenCanvas(). Apart from that small link, canvas and
+VCL are completely separated.
+
+The canvas framework currently consists of the following two new
+CVS modules, /gsl/canvas and /gsl/cppcanvas. Additionally, a new
+generic graphics tooling is used (but not exclusively by the canvas,
+Armin's recent drawing layer fixups also make use of it), which
+resides in /graphics/basegfx. From these modules, six libraries are
+currently delivered, namely vclcanvas.uno.dll, javacanvas.jar,
+directxcanvas.uno.dll, canvastools680mi.dll, cppcanvas680mi.dll, and
+basegfx680mi.dll.
+
+
+The new OOo slideshow engine
+============================
+
+The new OpenOffice.org slideshow engine will replace the current
+Impress-embedded presentation framework with a fully independent UNO
+component, and it will be based on the new canvas. In its current
+state, it is able to provide a basic set of functionality, enabling
+the playback of simple presentations. It furthermore provides features
+like double-buffering, hardware-accelerated alpha-blending (currently
+not on all platforms) and anti-aliased rendering of all primitives.
+
+In a second step, this new slideshow engine will then be integrated
+with Impress model enhancements and extended PowerPoint import/export
+filters, to implement nearly all of PowerPoint's set of effects.
+
+The new slideshow engine is currently not accessible from the office
+UI, but included in the installations sets. Thus, other developers can
+start to use the new functionality, and base their own implementations
+on top of that. For the records, the respective UNO implementation of
+the slideshow resides in the slideshow.uno.dll library.
+
diff --git a/canvas/prj/build.lst b/canvas/prj/build.lst
new file mode 100644
index 000000000000..d75602dbe5f2
--- /dev/null
+++ b/canvas/prj/build.lst
@@ -0,0 +1,10 @@
+cv canvas : javaunohelper comphelper cppuhelper offuh unoil tools svtools vcl basegfx CAIRO:cairo NULL
+cv canvas usr1 - all cv_mkout NULL
+cv canvas\inc nmake - all cv_inc NULL
+cv canvas\source\tools nmake - all cv_tools cv_inc NULL
+cv canvas\source\vcl nmake - all cv_vcl cv_tools cv_inc NULL
+cv canvas\source\simplecanvas nmake - all cv_simplecanvas cv_tools cv_inc NULL
+cv canvas\source\cairo nmake - all cv_cairo cv_tools cv_inc NULL
+cv canvas\source\directx nmake - w cv_directx cv_tools cv_inc NULL
+cv canvas\source\null nmake - all cv_null cv_tools cv_inc NULL
+cv canvas\source\factory nmake - all cv_factory cv_inc NULL
diff --git a/canvas/prj/d.lst b/canvas/prj/d.lst
new file mode 100644
index 000000000000..986253a3b3e5
--- /dev/null
+++ b/canvas/prj/d.lst
@@ -0,0 +1,26 @@
+..\%__SRC%\bin\canvasto*.dll %_DEST%\bin%_EXT%\canvasto*.dll
+..\%__SRC%\bin\cairocan*.dll %_DEST%\bin%_EXT%\cairocan*.dll
+..\%__SRC%\bin\directx*.dll %_DEST%\bin%_EXT%\directx*.dll
+..\%__SRC%\bin\gdiplus*.dll %_DEST%\bin%_EXT%\gdiplus*.dll
+..\%__SRC%\bin\vclcanva*.dll %_DEST%\bin%_EXT%\vclcanva*.dll
+..\%__SRC%\bin\nullcanv*.dll %_DEST%\bin%_EXT%\nullcanv*.dll
+..\%__SRC%\bin\simpleca*.dll %_DEST%\bin%_EXT%\simpleca*.dll
+..\%__SRC%\bin\canvasfa*.dll %_DEST%\bin%_EXT%\canvasfa*.dll
+..\%__SRC%\lib\icanvastools.lib %_DEST%\lib%_EXT%\icanvastools.lib
+..\%__SRC%\lib\libcanvastools*.so %_DEST%\lib%_EXT%\
+..\%__SRC%\lib\cairocanvas.uno.so %_DEST%\lib%_EXT%\cairocanvas.uno.so
+..\%__SRC%\lib\vclcanvas.uno.so %_DEST%\lib%_EXT%\vclcanvas.uno.so
+..\%__SRC%\lib\nullcanvas.uno.so %_DEST%\lib%_EXT%\nullcanvas.uno.so
+..\%__SRC%\lib\simplecanvas.uno.so %_DEST%\lib%_EXT%\simplecanvas.uno.so
+..\%__SRC%\lib\canvasfactory.uno.so %_DEST%\lib%_EXT%\canvasfactory.uno.so
+..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
+..\%__SRC%\class\javacanvas.uno.jar %_DEST%\bin%_EXT%\javacanvas.uno.jar
+
+mkdir: %_DEST%\inc%_EXT%\canvas\base
+..\inc\canvas\base\*.hxx %_DEST%\inc%_EXT%\canvas\base\*.hxx
+
+mkdir: %_DEST%\inc%_EXT%\canvas\rendering
+..\inc\canvas\rendering\*.hxx %_DEST%\inc%_EXT%\canvas\rendering\*.hxx
+
+mkdir: %_DEST%\inc%_EXT%\canvas
+..\inc\canvas\*.hxx %_DEST%\inc%_EXT%\canvas\*.hxx
diff --git a/canvas/source/cairo/cairo_cachedbitmap.cxx b/canvas/source/cairo/cairo_cachedbitmap.cxx
new file mode 100644
index 000000000000..8203211363c8
--- /dev/null
+++ b/canvas/source/cairo/cairo_cachedbitmap.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_cachedbitmap.hxx b/canvas/source/cairo/cairo_cachedbitmap.hxx
new file mode 100644
index 000000000000..da945cb467b0
--- /dev/null
+++ b/canvas/source/cairo/cairo_cachedbitmap.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_cairo.cxx b/canvas/source/cairo/cairo_cairo.cxx
new file mode 100644
index 000000000000..71a9bb3f9b3e
--- /dev/null
+++ b/canvas/source/cairo/cairo_cairo.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_cairo.hxx b/canvas/source/cairo/cairo_cairo.hxx
new file mode 100644
index 000000000000..d468d28b4753
--- /dev/null
+++ b/canvas/source/cairo/cairo_cairo.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvas.cxx b/canvas/source/cairo/cairo_canvas.cxx
new file mode 100644
index 000000000000..8798751ecde1
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvas.cxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvas.hxx b/canvas/source/cairo/cairo_canvas.hxx
new file mode 100644
index 000000000000..163d2fc383aa
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvas.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx
new file mode 100644
index 000000000000..daad97cfa464
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasbitmap.cxx
@@ -0,0 +1,289 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvasbitmap.hxx b/canvas/source/cairo/cairo_canvasbitmap.hxx
new file mode 100644
index 000000000000..c61b6583bd91
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasbitmap.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvascustomsprite.cxx b/canvas/source/cairo/cairo_canvascustomsprite.cxx
new file mode 100644
index 000000000000..187c4d1c4462
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvascustomsprite.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvascustomsprite.hxx b/canvas/source/cairo/cairo_canvascustomsprite.hxx
new file mode 100644
index 000000000000..cad0eafc739f
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvascustomsprite.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvasfont.cxx b/canvas/source/cairo/cairo_canvasfont.cxx
new file mode 100644
index 000000000000..780951f18cf4
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasfont.cxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/rendering/PanoseProportion.hpp>
+
+#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
+{
+
+ 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->SetPitch(
+ rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
+ ? PITCH_FIXED : PITCH_VARIABLE);
+
+ 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()
+ {
+ SolarMutexGuard aGuard;
+
+ mpRefDevice.clear();
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard 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)
+ {
+ SolarMutexGuard aGuard;
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return rendering::FontMetrics();
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvasfont.hxx b/canvas/source/cairo/cairo_canvasfont.hxx
new file mode 100644
index 000000000000..e9394c0640ea
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvasfont.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx
new file mode 100644
index 000000000000..0294780bc9dc
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper.cxx
@@ -0,0 +1,1999 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvashelper.hxx b/canvas/source/cairo/cairo_canvashelper.hxx
new file mode 100644
index 000000000000..923df8d64f48
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper.hxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx
new file mode 100644
index 000000000000..0cc4713fcc60
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper_text.cxx
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_canvashelper_texturefill.cxx b/canvas/source/cairo/cairo_canvashelper_texturefill.cxx
new file mode 100644
index 000000000000..54d6139f8cb7
--- /dev/null
+++ b/canvas/source/cairo/cairo_canvashelper_texturefill.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_devicehelper.cxx b/canvas/source/cairo/cairo_devicehelper.cxx
new file mode 100644
index 000000000000..b0b6edde7d8c
--- /dev/null
+++ b/canvas/source/cairo/cairo_devicehelper.cxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_devicehelper.hxx b/canvas/source/cairo/cairo_devicehelper.hxx
new file mode 100644
index 000000000000..33bbb5beebf7
--- /dev/null
+++ b/canvas/source/cairo/cairo_devicehelper.hxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_quartz_cairo.cxx b/canvas/source/cairo/cairo_quartz_cairo.cxx
new file mode 100644
index 000000000000..d623d07dfebd
--- /dev/null
+++ b/canvas/source/cairo/cairo_quartz_cairo.cxx
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_quartz_cairo.hxx b/canvas/source/cairo/cairo_quartz_cairo.hxx
new file mode 100644
index 000000000000..a09ed918dce1
--- /dev/null
+++ b/canvas/source/cairo/cairo_quartz_cairo.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_repainttarget.hxx b/canvas/source/cairo/cairo_repainttarget.hxx
new file mode 100644
index 000000000000..f6b36fdcd783
--- /dev/null
+++ b/canvas/source/cairo/cairo_repainttarget.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+#include <rtl/ref.hxx>
+
+#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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_services.cxx b/canvas/source/cairo/cairo_services.cxx
new file mode 100644
index 000000000000..ba1e63f95703
--- /dev/null
+++ b/canvas/source/cairo/cairo_services.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_sprite.hxx b/canvas/source/cairo/cairo_sprite.hxx
new file mode 100644
index 000000000000..09146cd90fd4
--- /dev/null
+++ b/canvas/source/cairo/cairo_sprite.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritecanvas.cxx b/canvas/source/cairo/cairo_spritecanvas.cxx
new file mode 100644
index 000000000000..8267336c7c47
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvas.cxx
@@ -0,0 +1,235 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritecanvas.hxx b/canvas/source/cairo/cairo_spritecanvas.hxx
new file mode 100644
index 000000000000..ed27bd3d2ac0
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvas.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritecanvashelper.cxx b/canvas/source/cairo/cairo_spritecanvashelper.cxx
new file mode 100644
index 000000000000..ff0118f0c3e3
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvashelper.cxx
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritecanvashelper.hxx b/canvas/source/cairo/cairo_spritecanvashelper.hxx
new file mode 100644
index 000000000000..2bed2b2d6dc0
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritecanvashelper.hxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritedevicehelper.cxx b/canvas/source/cairo/cairo_spritedevicehelper.cxx
new file mode 100644
index 000000000000..5a8158aa3027
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritedevicehelper.cxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritedevicehelper.hxx b/canvas/source/cairo/cairo_spritedevicehelper.hxx
new file mode 100644
index 000000000000..a7a05150f245
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritedevicehelper.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritehelper.cxx b/canvas/source/cairo/cairo_spritehelper.cxx
new file mode 100644
index 000000000000..5a47aef1dc4a
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritehelper.cxx
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritehelper.hxx b/canvas/source/cairo/cairo_spritehelper.hxx
new file mode 100644
index 000000000000..10b7fdcf3f43
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritehelper.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_spritesurface.hxx b/canvas/source/cairo/cairo_spritesurface.hxx
new file mode 100644
index 000000000000..caebcface0db
--- /dev/null
+++ b/canvas/source/cairo/cairo_spritesurface.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_surfaceprovider.hxx b/canvas/source/cairo/cairo_surfaceprovider.hxx
new file mode 100644
index 000000000000..6164ef0f1f67
--- /dev/null
+++ b/canvas/source/cairo/cairo_surfaceprovider.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx
new file mode 100644
index 000000000000..d8de6c55e37e
--- /dev/null
+++ b/canvas/source/cairo/cairo_textlayout.cxx
@@ -0,0 +1,699 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 );
+ }
+
+ bool compareFallbacks(const SystemGlyphData&rA, const SystemGlyphData &rB)
+ {
+ return rA.fallbacklevel < rB.fallbacklevel;
+ }
+ }
+
+ 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);
+
+ // Sort them so that all glyphs on the same glyph fallback level are consecutive
+ std::sort(aSysLayoutData.rGlyphData.begin(), aSysLayoutData.rGlyphData.end(), compareFallbacks);
+ bool bCairoRenderable = true;
+
+ //Pull all the fonts we need to render the text
+ typedef std::pair<SystemFontData,int> FontLevel;
+ typedef std::vector<FontLevel> FontLevelVector;
+ FontLevelVector aFontData;
+ SystemGlyphDataVector::const_iterator aGlyphIter=aSysLayoutData.rGlyphData.begin();
+ const SystemGlyphDataVector::const_iterator aGlyphEnd=aSysLayoutData.rGlyphData.end();
+ for( ; aGlyphIter != aGlyphEnd; ++aGlyphIter )
+ {
+ if( aFontData.empty() || aGlyphIter->fallbacklevel != aFontData.back().second )
+ {
+ aFontData.push_back(FontLevel(rOutDev.GetSysFontData(aGlyphIter->fallbacklevel),
+ aGlyphIter->fallbacklevel));
+ if( !isCairoRenderable(aFontData.back().first) )
+ {
+ bCairoRenderable = false;
+ OSL_TRACE(":cairocanvas::TextLayout::draw(S,O,p,v,r): VCL FALLBACK %s%s%s%s - %s",
+ maLogicalAdvancements.getLength() ? "ADV " : "",
+ aFontData.back().first.bAntialias ? "AA " : "",
+ aFontData.back().first.bFakeBold ? "FB " : "",
+ aFontData.back().first.bFakeItalic ? "FI " : "",
+ ::rtl::OUStringToOString( maText.Text.copy( maText.StartPosition, maText.Length ),
+ RTL_TEXTENCODING_UTF8 ).getStr());
+ break;
+ }
+ }
+ }
+
+ // 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 (!bCairoRenderable) // VCL FALLBACKS
+ {
+ 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.
+ **/
+
+ // Loop through the fonts used and render the matching glyphs for each
+ FontLevelVector::const_iterator aFontDataIter = aFontData.begin();
+ const FontLevelVector::const_iterator aFontDataEnd = aFontData.end();
+ for( ; aFontDataIter != aFontDataEnd; ++aFontDataIter )
+ {
+ const SystemFontData &rSysFontData = aFontDataIter->first;
+
+ // setup glyphs
+ std::vector<cairo_glyph_t> cairo_glyphs;
+ cairo_glyphs.reserve( 256 );
+
+ aGlyphIter=aSysLayoutData.rGlyphData.begin();
+ for( ; aGlyphIter != aGlyphEnd; ++aGlyphIter )
+ {
+ SystemGlyphData systemGlyph = *aGlyphIter;
+ if( systemGlyph.fallbacklevel != aFontDataIter->second )
+ continue;
+
+ cairo_glyph_t aGlyph;
+ 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, rSysFontData.hFont);
+ #endif
+ aGlyph.x = systemGlyph.x;
+ aGlyph.y = systemGlyph.y;
+ cairo_glyphs.push_back(aGlyph);
+ }
+
+ if (cairo_glyphs.empty())
+ continue;
+
+ /**
+ * 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) rSysFontData.aATSUFontID);
+
+ #elif defined CAIRO_HAS_WIN32_SURFACE
+ #if (OSL_DEBUG_LEVEL > 1)
+ GetObjectW( rSysFontData.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(rSysFontData.hFont);
+
+ #elif defined CAIRO_HAS_XLIB_SURFACE
+ font_face = cairo_ft_font_face_create_for_ft_face((FT_Face)rSysFontData.nFontId,
+ rSysFontData.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 (rSysFontData.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 (rSysFontData.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 " : "",
+ rSysFontData.bAntialias ? "AA " : "",
+ rSysFontData.bFakeBold ? "FB " : "",
+ rSysFontData.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 (rSysFontData.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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_textlayout.hxx b/canvas/source/cairo/cairo_textlayout.hxx
new file mode 100644
index 000000000000..a2bcf4421e9f
--- /dev/null
+++ b/canvas/source/cairo/cairo_textlayout.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_win32_cairo.cxx b/canvas/source/cairo/cairo_win32_cairo.cxx
new file mode 100644
index 000000000000..d286604706c6
--- /dev/null
+++ b/canvas/source/cairo/cairo_win32_cairo.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#define _WIN32_WINNT 0x0500
+
+// 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_win32_cairo.hxx b/canvas/source/cairo/cairo_win32_cairo.hxx
new file mode 100644
index 000000000000..3ed001897024
--- /dev/null
+++ b/canvas/source/cairo/cairo_win32_cairo.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_xlib_cairo.cxx b/canvas/source/cairo/cairo_xlib_cairo.cxx
new file mode 100644
index 000000000000..a7df2f7d39fb
--- /dev/null
+++ b/canvas/source/cairo/cairo_xlib_cairo.cxx
@@ -0,0 +1,355 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/cairo_xlib_cairo.hxx b/canvas/source/cairo/cairo_xlib_cairo.hxx
new file mode 100644
index 000000000000..63d80dbf3f68
--- /dev/null
+++ b/canvas/source/cairo/cairo_xlib_cairo.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/cairo/exports.dxp b/canvas/source/cairo/exports.dxp
new file mode 100644
index 000000000000..9630d7e06768
--- /dev/null
+++ b/canvas/source/cairo/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory
diff --git a/canvas/source/cairo/makefile.mk b/canvas/source/cairo/makefile.mk
new file mode 100644
index 000000000000..b0ff10fe96b0
--- /dev/null
+++ b/canvas/source/cairo/makefile.mk
@@ -0,0 +1,132 @@
+#*************************************************************************
+#
+# 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
diff --git a/canvas/source/directx/dx_5rm.cxx b/canvas/source/directx/dx_5rm.cxx
new file mode 100644
index 000000000000..4adcb09de4cf
--- /dev/null
+++ b/canvas/source/directx/dx_5rm.cxx
@@ -0,0 +1,2286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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"
+
+#if DIRECTX_VERSION < 0x0900
+
+// Nvidia GeForce Go 6800 crashes with a bluescreen if we take the
+// maximum texture size, which would be twice as large. this behaviors
+// has only been observed on directx5.
+// This value is simply the maximum size for textures we request from
+// the system, it has absolutely nothing to do with the size of primitives
+// we're able to render, both concepts are totally independent from each other.
+#define MAX_TEXTURE_SIZE (2048)
+#define MIN_TEXTURE_SIZE (32)
+//#define FAKE_MAX_NUMBER_TEXTURES (2)
+//#define FAKE_MAX_TEXTURE_SIZE (512)
+
+//////////////////////////////////////////////////////////////////////////////////
+// includes
+//////////////////////////////////////////////////////////////////////////////////
+#include <vcl/syschild.hxx>
+#include <vcl/window.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/elapsedtime.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/isurface.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <tools/diagnose_ex.h>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#define COMPILE_MULTIMON_STUBS
+
+#include "dx_rendermodule.hxx"
+#include "dx_surfacegraphics.hxx"
+#include <vcl/sysdata.hxx>
+
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#include "dx_impltools.hxx"
+#include <malloc.h>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+#undef COMPILE_MULTIMON_STUBS
+
+#include <stdio.h>
+
+#define MONITOR_DEFAULTTONULL 0x00000000
+#define MONITOR_DEFAULTTOPRIMARY 0x00000001
+#define MONITOR_DEFAULTTONEAREST 0x00000002
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////////
+// 'dxcanvas' namespace
+//////////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ namespace
+ {
+ bool doBlit( const ::basegfx::B2IPoint& rDestPos,
+ IDirectDrawSurface& rOutSurface,
+ const ::basegfx::B2IRange& rSourceArea,
+ IDirectDrawSurface& rSourceSurface,
+ DDBLTFX* pBltFx,
+ bool bForceSoftware )
+ {
+ if( !bForceSoftware )
+ {
+ // blit surface to backbuffer
+ RECT aOutRect =
+ {
+ rDestPos.getX(),
+ rDestPos.getY(),
+ rDestPos.getX() + static_cast<sal_Int32>(rSourceArea.getWidth()),
+ rDestPos.getY() + static_cast<sal_Int32>(rSourceArea.getHeight()),
+ };
+ RECT aSourceRect =
+ {
+ rSourceArea.getMinX(),
+ rSourceArea.getMinY(),
+ rSourceArea.getMaxX(),
+ rSourceArea.getMaxY()
+ };
+
+ if( SUCCEEDED(rOutSurface.Blt( &aOutRect,
+ &rSourceSurface,
+ &aSourceRect,
+ DDBLT_WAIT,
+ pBltFx )) )
+ {
+ return true;
+ }
+ }
+
+ // failed, or forced to use SW copy. attempt manual copy.
+ bool bResult = false;
+
+ // lock source surface
+ DDSURFACEDESC aDescSrc;
+ rtl_fillMemory(&aDescSrc,sizeof(DDSURFACEDESC),0);
+ aDescSrc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwSrcFlags = DDLOCK_NOSYSLOCK|
+ DDLOCK_SURFACEMEMORYPTR|
+ DDLOCK_WAIT|
+ DDLOCK_READONLY;
+ if(SUCCEEDED(rSourceSurface.Lock(NULL,
+ &aDescSrc,
+ dwSrcFlags,
+ NULL)))
+ {
+ // lock destination surface
+ DDSURFACEDESC aDescDst;
+ rtl_fillMemory(&aDescDst,sizeof(DDSURFACEDESC),0);
+ aDescDst.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwDstFlags = DDLOCK_NOSYSLOCK|
+ DDLOCK_SURFACEMEMORYPTR|
+ DDLOCK_WAIT|
+ DDLOCK_WRITEONLY;
+ if(SUCCEEDED(rOutSurface.Lock(NULL,
+ &aDescDst,
+ dwDstFlags,
+ NULL)))
+ {
+ sal_uInt32 nSrcFormat;
+ nSrcFormat = ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRBitMask)<<8;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwGBitMask)<<4;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwBBitMask);
+
+ sal_uInt32 nDstFormat;
+ nDstFormat = ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRBitMask)<<8;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwGBitMask)<<4;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwBBitMask);
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ const sal_uInt32 nWidth( static_cast<sal_uInt32>(
+ rSourceArea.getWidth() ) );
+ const sal_uInt32 nHeight( static_cast<sal_uInt32>(
+ rSourceArea.getHeight() ) );
+
+ if((nSrcFormat == 0x8888) && (nDstFormat == 0x0565))
+ {
+ // medium range 8888 to 0565 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<1);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ sal_uInt32 srcPixel = *pSrcScanline++;
+ sal_uInt16 dstPixel;
+ dstPixel = (sal_uInt16)((srcPixel & 0x0000F8) >> 3);
+ dstPixel |= (srcPixel & 0x00FC00) >> 5;
+ dstPixel |= (srcPixel & 0xF80000) >> 8;
+ *pDstScanline++ = dstPixel;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+ else if((nSrcFormat == 0x8888) && (nDstFormat == 0x0888))
+ {
+ // medium range 8888 to 0888 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<2);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ *pDstScanline++ = (sal_uInt16)*pSrcScanline++;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+ else if((nSrcFormat == 0x8888) && (nDstFormat == 0x1555))
+ {
+ // medium range 8888 to 1555 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<1);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32*)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ sal_uInt32 srcPixel = *pSrcScanline++;
+ sal_uInt16 dstPixel;
+ dstPixel = (sal_uInt16)((srcPixel & 0x000000F8) >> 3);
+ dstPixel |= (srcPixel & 0x0000F800) >> 6;
+ dstPixel |= (srcPixel & 0x00F80000) >> 9;
+ dstPixel |= (srcPixel & 0x80000000) >> 16;
+ *pDstScanline++ = dstPixel;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+
+ // unlock destination surface
+ rOutSurface.Unlock(NULL);
+ }
+
+ // unlock source surface
+ rSourceSurface.Unlock(NULL);
+ }
+
+ return bResult;
+ }
+
+ void dumpSurface( const COMReference<IDirectDrawSurface> &pSurface, const char *szFilename )
+ {
+ if(!(pSurface.get()))
+ return;
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( FAILED(pSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ return;
+
+ const std::size_t dwBitmapSize(aSurfaceDesc.dwWidth*aSurfaceDesc.dwHeight*4);
+ sal_uInt8 *pBuffer = static_cast<sal_uInt8 *>(_alloca(dwBitmapSize));
+ if(pBuffer)
+ {
+ sal_uInt8 *pSource = reinterpret_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
+ sal_uInt8 *pDest = reinterpret_cast<sal_uInt8 *>(pBuffer);
+ const std::size_t dwDestPitch(aSurfaceDesc.dwWidth<<2);
+ pDest += aSurfaceDesc.dwHeight*dwDestPitch;
+ for(sal_uInt32 y=0; y<aSurfaceDesc.dwHeight; ++y)
+ {
+ pDest -= dwDestPitch;
+ rtl_copyMemory( pDest, pSource, dwDestPitch );
+ pSource += aSurfaceDesc.lPitch;
+ }
+
+ if(FILE *fp = fopen(szFilename,"wb"))
+ {
+ BITMAPINFOHEADER bitmapInfo;
+
+ bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.biWidth = aSurfaceDesc.dwWidth;
+ bitmapInfo.biHeight = aSurfaceDesc.dwHeight;
+ bitmapInfo.biPlanes = 1;
+ bitmapInfo.biBitCount = 32;
+ bitmapInfo.biCompression = BI_RGB;
+ bitmapInfo.biSizeImage = 0;
+ bitmapInfo.biXPelsPerMeter = 0;
+ bitmapInfo.biYPelsPerMeter = 0;
+ bitmapInfo.biClrUsed = 0;
+ bitmapInfo.biClrImportant = 0;
+
+ const std::size_t dwFileSize(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwBitmapSize);
+
+ BITMAPFILEHEADER header;
+ header.bfType = 'MB';
+ header.bfSize = dwFileSize;
+ header.bfReserved1 = 0;
+ header.bfReserved2 = 0;
+ header.bfOffBits = sizeof(BITMAPFILEHEADER) + bitmapInfo.biSize;
+
+ fwrite(&header,1,sizeof(BITMAPFILEHEADER),fp);
+ fwrite(&bitmapInfo,1,sizeof(BITMAPINFOHEADER),fp);
+ fwrite(pBuffer,1,dwBitmapSize,fp);
+
+ fclose(fp);
+ }
+ }
+
+ pSurface->Unlock(NULL);
+ }
+
+ void clearSurface( const COMReference<IDirectDrawSurface>& pSurface )
+ {
+ if(!(pSurface.is()))
+ return;
+
+ DDBLTFX aBltFx;
+
+ rtl_fillMemory( &aBltFx,
+ sizeof(DDBLTFX), 0 );
+ aBltFx.dwSize = sizeof(DDBLTFX);
+ aBltFx.dwFillColor = 0;
+
+ pSurface->Blt( NULL,
+ NULL,
+ NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT,
+ &aBltFx );
+ }
+
+ // Define struct for MonitorEntry
+ struct MonitorEntry
+ {
+ GUID mnGUID;
+ HMONITOR mhMonitor;
+ MONITORINFO maMonitorInfo;
+ };
+
+ // define type for MonitorList
+ typedef ::std::vector< MonitorEntry > MonitorList;
+
+ // Win32 system callback for DirectDrawEnumerateExA call
+ BOOL WINAPI EnumerateExA_Callback( GUID FAR* lpGUID,
+ LPSTR /*lpDriverDescription*/,
+ LPSTR /*lpDriverName*/,
+ LPVOID lpContext,
+ HMONITOR hMonitor )
+ {
+ if(lpGUID)
+ {
+ MonitorList* pMonitorList = (MonitorList*)lpContext;
+ MonitorEntry aEntry;
+
+ aEntry.mnGUID = *lpGUID;
+ aEntry.mhMonitor = hMonitor;
+ aEntry.maMonitorInfo.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfo( hMonitor,
+ &aEntry.maMonitorInfo );
+
+ pMonitorList->push_back(aEntry);
+ }
+
+ return DDENUMRET_OK;
+ }
+
+ void fillMonitorList( MonitorList& rMonitorList )
+ {
+ // Try to fill MonitorList. If neither lib or call to
+ // DirectDrawEnumerateExA does not exist, it's an old
+ // DX version (< 5.0), or system does not support
+ // multiple monitors.
+ HINSTANCE hInstance = LoadLibrary("ddraw.dll");
+
+ if(hInstance)
+ {
+ LPDIRECTDRAWENUMERATEEX lpDDEnumEx =
+ (LPDIRECTDRAWENUMERATEEX)GetProcAddress(hInstance,"DirectDrawEnumerateExA");
+
+ if(lpDDEnumEx)
+ lpDDEnumEx( (LPDDENUMCALLBACKEXA) EnumerateExA_Callback,
+ &rMonitorList,
+ DDENUM_ATTACHEDSECONDARYDEVICES );
+
+ FreeLibrary(hInstance);
+ }
+ }
+
+ IDirectDraw2* createDirectDraw( const MonitorList& rMonitorList,
+ MONITORINFO& rMonitorInfo,
+ HWND renderWindow )
+ {
+ GUID* gpSelectedDriverGUID = NULL;
+
+ // if we have multiple monitors, choose a gpSelectedDriverGUID from monitor list
+ HMONITOR hMonitor = MonitorFromWindow(renderWindow,
+ MONITOR_DEFAULTTONEAREST);
+
+ MonitorList::const_iterator aCurr = rMonitorList.begin();
+ const MonitorList::const_iterator aEnd = rMonitorList.end();
+ while( !gpSelectedDriverGUID && aCurr != aEnd )
+ {
+ if(hMonitor == aCurr->mhMonitor)
+ {
+ // This is the monitor we are running on
+ gpSelectedDriverGUID = const_cast<GUID*>(&aCurr->mnGUID);
+ rMonitorInfo = aCurr->maMonitorInfo;
+ }
+
+ ++aCurr;
+ }
+
+ IDirectDraw* pDirectDraw;
+ if( FAILED( DirectDrawCreate( gpSelectedDriverGUID, &pDirectDraw, NULL )))
+ return NULL;
+
+ IDirectDraw2* pDirectDraw2;
+ if( FAILED( pDirectDraw->QueryInterface( IID_IDirectDraw2, (LPVOID*)&pDirectDraw2 )))
+ return NULL;
+
+ // queryInterface bumped up the refcount, so release the
+ // reference to the original IDirectDraw interface.
+ pDirectDraw->Release();
+
+ return pDirectDraw2;
+ }
+
+ HRESULT WINAPI EnumTextureFormatsCallback( LPDDSURFACEDESC pSurfaceDesc,
+ LPVOID pContext )
+ {
+ // dirty cast of given context back to result ModeSelectContext
+ DDPIXELFORMAT* pResult = (DDPIXELFORMAT*)pContext;
+
+ if( pResult == NULL || pSurfaceDesc == NULL )
+ return DDENUMRET_CANCEL;
+
+ VERBOSE_TRACE( "EnumTextureFormatsCallback: advertised texture format has dwRGBBitCount %d, dwRBitMask %x, "
+ "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The format uses %s alpha.",
+ pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
+ pSurfaceDesc->ddpfPixelFormat.dwRBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwGBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwBBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwRGBAlphaBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
+
+ // Only accept RGB surfaces with alpha channel
+ if( (DDPF_ALPHAPIXELS | DDPF_RGB) ==
+ (pSurfaceDesc->ddpfPixelFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) )
+ {
+ // ignore formats with the DDPF_ALPHAPREMULT flag
+ if(!(pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT))
+ {
+ // take widest alpha channel available
+ if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth > pResult->dwAlphaBitDepth )
+ {
+ // take new format
+ rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
+ }
+ else if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth == pResult->dwAlphaBitDepth )
+ {
+ // tie-breaking: take highest bitcount
+ if( pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > pResult->dwRGBBitCount )
+ {
+ // take new format
+ rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
+ }
+ }
+ }
+ }
+
+ return DDENUMRET_OK;
+ }
+
+ class DXRenderModule;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** ISurface implemenation.
+
+ @attention holds the DXRenderModule via non-refcounted
+ reference! This is safe with current state of affairs, since
+ the canvas::PageManager holds surface and render module via
+ shared_ptr (and makes sure all surfaces are deleted before its
+ render module member goes out of scope).
+ */
+ class DXSurface : public canvas::ISurface
+ {
+ public:
+ DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize );
+ ~DXSurface();
+
+ virtual bool selectTexture();
+ virtual bool isValid();
+ virtual bool update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource );
+ virtual ::basegfx::B2IVector getSize();
+
+ private:
+ /// Guard local methods against concurrent acces to RenderModule
+ class ImplRenderModuleGuard : private ::boost::noncopyable
+ {
+ public:
+ explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule );
+ inline ~ImplRenderModuleGuard();
+
+ private:
+ DXRenderModule& mrRenderModule;
+ };
+
+ DXRenderModule& mrRenderModule;
+
+ COMReference<IDirectDrawSurface> mpSurface;
+ COMReference<IDirect3DTexture2> mpTexture;
+
+ ::basegfx::B2IVector maSize;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /// Default implementation of IDXRenderModule
+ class DXRenderModule : public IDXRenderModule
+ {
+ public:
+ explicit DXRenderModule( const ::Window& rWindow );
+
+ virtual void lock() const { maMutex.acquire(); }
+ virtual void unlock() const { maMutex.release(); }
+
+ virtual COMReference<IDirectDrawSurface>
+ createSystemMemorySurface( const ::basegfx::B2IVector& rSize );
+
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea );
+
+ virtual void resize( const ::basegfx::B2IRange& rect );
+ virtual HWND getHWND() const { return mhWnd; }
+ virtual void disposing();
+ virtual void screenShot();
+ virtual ::basegfx::B2IVector getPageSize();
+ virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize );
+ virtual void beginPrimitive( PrimitiveType eType );
+ virtual void endPrimitive();
+ virtual void pushVertex( const ::canvas::Vertex& vertex );
+ virtual bool isError();
+
+ const D3DDEVICEDESC& getDeviceDesc() const { return maDeviceDesc; }
+ const DDPIXELFORMAT& getTextureFormat() const { return maTextureFormat; }
+ COMReference<IDirectDraw2> getDirectDraw() { return mpDirectDraw; }
+ COMReference< IDirect3DDevice2 > getDevice() { return mpDirect3DDevice; }
+
+ void flushVertexCache();
+
+ struct ModeSelectContext
+ {
+ DDSURFACEDESC selectedDesc;
+ ::basegfx::B2ISize requestedSize;
+ };
+
+ /** Query actual size of the device
+
+ This is especially interesting for fullscreen devices
+ */
+ ::basegfx::B2ISize getFramebufferSize() const;
+
+ /** Query the amount of memory available for new surfaces
+
+ This might differ from getAvailableTextureMem()
+ @see getAvailableTextureMem()
+
+ @param bWithAGPMema
+ When true, returned value includes non-local,
+ i.e. AGP-able memory, too.
+
+ @return the amount of free surface mem
+ */
+ std::size_t getAvailableSurfaceMem( bool bWithAGPMem=true ) const;
+
+ /** Query the amount of memory available for new textures
+
+ This might differ from getAvailableSurfaceMem()
+ @see getAvailableSurfaceMem()
+
+ @param bWithAGPMema
+ When true, returned value includes non-local,
+ i.e. AGP-able memory, too.
+
+ @return the amount of free texture mem
+ */
+ std::size_t getAvailableTextureMem( bool bWithAGPMem=true ) const;
+
+ private:
+ bool queryCaps();
+ bool validateCaps();
+ bool setup3DDevice();
+ unsigned int getDisplayFormat() const;
+
+ void convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
+ ::basegfx::B2IRange& io_rDestArea );
+
+ void renderInfoText( const ::rtl::OUString& rStr,
+ const Gdiplus::PointF& rPos ) const;
+ void renderFPSCounter() const;
+ void renderMemAvailable() const;
+
+ bool create( const ::Window& rWindow );
+ bool validateMainSurfaces();
+
+ /** This object represents the DirectX state machine. In order
+ to serialize access to DirectX's global state, a global
+ mutex is required.
+ */
+ static ::osl::Mutex maMutex;
+
+ HWND mhWnd;
+ ::boost::scoped_ptr<SystemChildWindow> mpWindow;
+ ::basegfx::B2IVector maSize;
+
+ ModeSelectContext maSelectedFullscreenMode;
+ DDPIXELFORMAT maTextureFormat;
+
+ MONITORINFO maMonitorInfo; // monitor info for mpDirectDraw's monitor
+ COMReference<IDirectDraw2> mpDirectDraw;
+ COMReference<IDirectDrawSurface> mpPrimarySurface;
+ COMReference<IDirectDrawSurface> mpBackBufferSurface;
+
+ COMReference< IDirect3D2 > mpDirect3D;
+ COMReference< IDirect3DDevice2 > mpDirect3DDevice;
+
+ mutable ::canvas::tools::ElapsedTime maLastUpdate; // for the frame counter
+
+ D3DDEVICEDESC maDeviceDesc;
+
+ typedef std::vector<canvas::Vertex> vertexCache_t;
+ vertexCache_t maVertexCache;
+ std::size_t mnCount;
+
+ int mnBeginSceneCount;
+
+ const bool mbPageFlipping;
+ bool mbHasNoTearingBlt;
+ bool mbError;
+ PrimitiveType meType;
+
+ ::canvas::ISurfaceSharedPtr mpTexture;
+ ::basegfx::B2IVector maPageSize;
+ };
+
+ ::osl::Mutex DXRenderModule::maMutex;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::ImplRenderModuleGuard
+ //////////////////////////////////////////////////////////////////////////////////
+
+ inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard(
+ DXRenderModule& rRenderModule ) :
+ mrRenderModule( rRenderModule )
+ {
+ mrRenderModule.lock();
+ }
+
+ inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard()
+ {
+ mrRenderModule.unlock();
+ }
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ static sal_uInt32 gNumSurfaces = 0;
+#endif
+
+ void fillRect( sal_uInt32 *pDest,
+ sal_uInt32 dwWidth,
+ sal_uInt32 dwHeight,
+ sal_uInt32 dwPitch,
+ sal_uInt32 dwColor )
+ {
+ for(sal_uInt32 i=0; i<dwWidth; ++i)
+ {
+ pDest[i]=dwColor;
+ pDest[((dwHeight-1)*dwPitch)+i]=dwColor;
+ }
+
+ for(sal_uInt32 j=0; j<dwHeight; ++j)
+ {
+ pDest[0]=dwColor;
+ pDest[dwWidth-1]=dwColor;
+ pDest += dwPitch;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize ) :
+ mrRenderModule(rRenderModule),
+ mpTexture(NULL),
+ mpSurface(NULL),
+ maSize()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ ++gNumSurfaces;
+ if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES)
+ return;
+#endif
+
+#ifdef FAKE_MAX_TEXTURE_SIZE
+ if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+ if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+#endif
+
+ ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0,
+ "DXSurface::DXSurface(): request for zero-sized surface");
+
+ const D3DDEVICEDESC &deviceDesc = rRenderModule.getDeviceDesc();
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+ aSurfaceDesc.dwWidth = ::std::min(deviceDesc.dwMaxTextureWidth,::canvas::tools::nextPow2(rSize.getX()));
+ aSurfaceDesc.dwHeight = ::std::min(deviceDesc.dwMaxTextureHeight,::canvas::tools::nextPow2(rSize.getY()));
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
+ DDSCAPS_VIDEOMEMORY |
+ DDSCAPS_LOCALVIDMEM;
+ rtl_copyMemory(&aSurfaceDesc.ddpfPixelFormat,&rRenderModule.getTextureFormat(),sizeof(DDPIXELFORMAT));
+
+ IDirectDrawSurface *pSurface;
+ COMReference<IDirectDraw2> pDirectDraw(rRenderModule.getDirectDraw());
+ HRESULT hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ if(FAILED(hr))
+ {
+ // if the call failed due to 'out of videomemory',
+ // retry with request for AGP memory.
+ if(DDERR_OUTOFVIDEOMEMORY == hr)
+ {
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
+ DDSCAPS_VIDEOMEMORY |
+ DDSCAPS_NONLOCALVIDMEM;
+ hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ }
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ IDirect3DTexture2* pTexture;
+ if( FAILED(pSurface->QueryInterface(IID_IDirect3DTexture2, (LPVOID *)&pTexture)) )
+ {
+ pSurface->Release();
+ return;
+ }
+
+ maSize.setX(aSurfaceDesc.dwWidth);
+ maSize.setY(aSurfaceDesc.dwHeight);
+
+ mpSurface=COMReference<IDirectDrawSurface>(pSurface);
+ mpTexture=COMReference<IDirect3DTexture2>(pTexture);
+
+ // #122683# Clear texture, to avoid ugly artifacts at the
+ // border to invisible sprite areas (note that the textures
+ // are usually only partly utilized).
+ clearSurface( mpSurface );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::~DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::~DXSurface()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ gNumSurfaces--;
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::selectTexture
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::selectTexture()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ mrRenderModule.flushVertexCache();
+
+ D3DTEXTUREHANDLE aTextureHandle;
+ if(FAILED(mpTexture->GetHandle(
+ mrRenderModule.getDevice().get(),
+ &aTextureHandle)))
+ {
+ return false;
+ }
+
+ // select texture for next primitive
+ if(FAILED(mrRenderModule.getDevice()->SetRenderState(
+ D3DRENDERSTATE_TEXTUREHANDLE,aTextureHandle)))
+ {
+ return false;
+ }
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ if( mpSurface.is() )
+ {
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( SUCCEEDED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ {
+ imdebug( "rgba w=%d h=%d %p",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight,
+ aSurfaceDesc.lpSurface );
+
+ mpSurface->Unlock(NULL);
+ }
+ }
+# endif
+#endif
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::isValid
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::isValid()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ if(!(mpSurface.is()))
+ return false;
+
+ if(mpSurface->IsLost() == DDERR_SURFACELOST)
+ {
+ mpSurface->Restore();
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::update
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource )
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ // can't update if surface is not valid, that means
+ // either not existent nor restored...
+ if(!(isValid()))
+ return false;
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ // TODO(P2): only lock the region we want to update
+ if( FAILED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY,
+ NULL)) )
+ return false;
+
+ if(sal_uInt8* pImage = rSource.lock())
+ {
+ switch( rSource.getFormat() )
+ {
+ case ::canvas::IColorBuffer::FMT_A8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt32 nNumBytesToCopy(
+ static_cast<sal_uInt32>(
+ rSourceRect.getWidth())*
+ nSourceBytesPerPixel);
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ rtl_copyMemory(pDst,pImage,nNumBytesToCopy);
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(3);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt64 nNumColumns(rSourceRect.getWidth());
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst);
+ sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage);
+ for(sal_uInt32 x=0; x<nNumColumns; ++x)
+ {
+ sal_uInt32 color(0xFF000000);
+ color |= pSrcScanline[2]<<16;
+ color |= pSrcScanline[1]<<8;
+ color |= pSrcScanline[0];
+ pSrcScanline += 3;
+ *pDstScanline++ = color;
+ }
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_X8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage);
+ sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst);
+ for(sal_uInt32 j=0; j<rSourceRect.getWidth(); ++j)
+ pDst32[j] = 0xFF000000 | pSrc32[j];
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ default:
+ ENSURE_OR_RETURN_FALSE(false,
+ "DXSurface::update(): Unknown/unimplemented buffer format" );
+ break;
+ }
+
+ rSource.unlock();
+ }
+
+ return SUCCEEDED(mpSurface->Unlock(NULL));
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurface::getSize()
+ {
+ return maSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::DXRenderModule( const ::Window& rWindow ) :
+ mhWnd(0),
+ mpWindow(),
+ maSize(),
+ maSelectedFullscreenMode(),
+ maTextureFormat(),
+ maMonitorInfo(),
+ mpDirectDraw(),
+ mpPrimarySurface(),
+ mpBackBufferSurface(),
+ mpDirect3D(),
+ mpDirect3DDevice(),
+ maLastUpdate(),
+ maDeviceDesc(),
+ maVertexCache(),
+ mnCount(0),
+ mnBeginSceneCount(0),
+ mbPageFlipping( false ),
+ mbHasNoTearingBlt( false ),
+ mbError( false ),
+ meType( PRIMITIVE_TYPE_UNKNOWN ),
+ mpTexture(),
+ maPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(!(create(rWindow)))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+
+ // allocate a single texture surface which can be used later.
+ // we also use this to calibrate the page size.
+ ::basegfx::B2IVector aPageSize(
+ ::std::min(
+ static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureWidth),
+ static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)),
+ ::std::min(
+ static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureHeight),
+ static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)));
+ while(true)
+ {
+ mpTexture = ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,aPageSize));
+ if(mpTexture->isValid())
+ break;
+
+ aPageSize.setX(aPageSize.getX()>>1);
+ aPageSize.setY(aPageSize.getY()>>1);
+ if((aPageSize.getX() < MIN_TEXTURE_SIZE) ||
+ (aPageSize.getY() < MIN_TEXTURE_SIZE))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+ }
+ maPageSize=aPageSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::create
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::create( const ::Window& rWindow )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maVertexCache.reserve(1024);
+
+ mpWindow.reset(
+ new SystemChildWindow(
+ const_cast<Window *>(&rWindow), 0) );
+
+ // system child window must not receive mouse events
+ mpWindow->SetMouseTransparent( TRUE );
+
+ // parent should receive paint messages as well
+ // [PARENTCLIPMODE_NOCLIP], the argument is here
+ // passed as plain numeric value since the stupid
+ // define utilizes a USHORT cast.
+ mpWindow->SetParentClipMode(0x0002);
+
+ // the system child window must not clear its background
+ mpWindow->EnableEraseBackground( FALSE );
+
+ mpWindow->SetControlForeground();
+ mpWindow->SetControlBackground();
+ mpWindow->EnablePaint(FALSE);
+
+ const SystemEnvData *pData = mpWindow->GetSystemData();
+ const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd));
+ mhWnd = const_cast<HWND>(hwnd);
+
+ ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ),
+ "DXRenderModuleDXRenderModuleWin32() No valid HWND given." );
+
+ // retrieve position and size of the parent window
+ const ::Size &rSizePixel(rWindow.GetSizePixel());
+
+ // remember the size of the parent window, since we
+ // need to use this for our child window.
+ maSize.setX(static_cast<sal_Int32>(rSizePixel.Width()));
+ maSize.setY(static_cast<sal_Int32>(rSizePixel.Height()));
+
+ // let the child window cover the same size as the parent window.
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ MonitorList aMonitorList;
+ fillMonitorList( aMonitorList );
+
+ mpDirectDraw = COMReference<IDirectDraw2>(
+ createDirectDraw(aMonitorList, maMonitorInfo, mhWnd));
+
+ if(!mpDirectDraw.is())
+ return false;
+
+ if( !queryCaps() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): GetCaps failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ if( !validateCaps() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Insufficient DirectX capabilities, failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ if( FAILED( mpDirectDraw->SetCooperativeLevel( mhWnd,
+ DDSCL_NORMAL|DDSCL_MULTITHREADED|DDSCL_FPUPRESERVE ) ) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): SetCooperativeLevel failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // setup query struct
+ rtl_fillMemory( &maSelectedFullscreenMode.selectedDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ maSelectedFullscreenMode.selectedDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ // read current display mode, e.g. for screen dimension
+ if( FAILED( mpDirectDraw->GetDisplayMode( &maSelectedFullscreenMode.selectedDesc )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): GetDisplayMode failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // check for supported primary surface formats...
+ unsigned int nDisplayFormat = getDisplayFormat() & 0x00000FFF;
+ if(nDisplayFormat != 0x888 && nDisplayFormat != 0x565)
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Unsupported DisplayFormat" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // create primary surface reference
+ DDSURFACEDESC aSurfaceDesc;
+ IDirectDrawSurface* pPrimarySurface;
+
+ rtl_fillMemory( &aSurfaceDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(aSurfaceDesc);
+ aSurfaceDesc.dwFlags = DDSD_CAPS;
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
+
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pPrimarySurface, NULL)) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ mpPrimarySurface = COMReference< IDirectDrawSurface >(pPrimarySurface);
+
+ // create a Clipper and associate it with the primary surface
+ // and the render window
+ LPDIRECTDRAWCLIPPER pClipper;
+ if( FAILED(mpDirectDraw->CreateClipper( 0, &pClipper, NULL )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateClipper failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ if( FAILED(pClipper->SetHWnd(0, mhWnd)) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Clipper->SetHWnd failed" );
+ pClipper->Release();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ if( FAILED(mpPrimarySurface->SetClipper( pClipper )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): SetClipper failed" );
+ pClipper->Release();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // clipper is now owned by mpPrimarySurface, release our reference
+ pClipper->Release();
+
+ // TODO(F3): Check whether palette needs any setup here
+
+ // get us a backbuffer for simulated flipping
+ IDirectDrawSurface* pSurface;
+
+ // Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with
+ // the current window size, but this will make it
+ // necessary to temporarily have two buffers while copying
+ // from the old to the new one. What's more, at the time
+ // we need a larger buffer, DX might not have sufficient
+ // resources available, and we're then left with too small
+ // a back buffer, and no way of falling back to a
+ // different canvas implementation.
+ const ::basegfx::B2ISize aSize( getFramebufferSize() );
+
+ rtl_fillMemory( &aSurfaceDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ aSurfaceDesc.dwHeight= aSize.getY();
+ aSurfaceDesc.dwWidth = aSize.getX();
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+
+ if( FAILED( nRes ) )
+ {
+ if( nRes == DDERR_OUTOFVIDEOMEMORY )
+ {
+ // local vid mem failed. Maybe AGP mem works?
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
+ {
+ // no chance, go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
+ }
+ else
+ {
+ // no chance, go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ }
+
+ VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight );
+
+ mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
+ clearSurface(mpBackBufferSurface);
+
+ if( !setup3DDevice() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): setup3DDevice failed" );
+ mpBackBufferSurface.reset();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ mpWindow->Show();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2ISize DXRenderModule::getFramebufferSize() const
+ {
+ return mpDirectDraw.is() ?
+ ::basegfx::B2ISize( maSelectedFullscreenMode.selectedDesc.dwWidth,
+ maSelectedFullscreenMode.selectedDesc.dwHeight ) :
+ ::basegfx::B2ISize();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::setup3DDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::setup3DDevice()
+ {
+ // create and setup 3D device
+ // ==========================
+ LPDIRECT3D2 pDirect3D;
+ if( FAILED( mpDirectDraw->QueryInterface( IID_IDirect3D2, (LPVOID*)&pDirect3D ) ) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): QueryInterface() for Direct3D failed" );
+ return false;
+ }
+
+ mpDirect3D = COMReference< IDirect3D2 >(pDirect3D);
+
+ LPDIRECT3DDEVICE2 pDirect3DDevice;
+ // try HW-accelerated device first
+ if( FAILED(mpDirect3D->CreateDevice( IID_IDirect3DHALDevice,
+ mpBackBufferSurface.get(),
+ &pDirect3DDevice )) )
+ {
+ // no HW 3D support - go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): CreateDevice() for HW Direct3D rendering failed" );
+ mpDirect3D.reset();
+ return false;
+ }
+
+ D3DDEVICEDESC aHELDeviceDesc;
+ rtl_fillMemory(&maDeviceDesc,sizeof(maDeviceDesc),0);
+ rtl_fillMemory(&aHELDeviceDesc,sizeof(aHELDeviceDesc),0);
+ maDeviceDesc.dwSize = sizeof(maDeviceDesc);
+ aHELDeviceDesc.dwSize = sizeof(aHELDeviceDesc);
+ if(FAILED(pDirect3DDevice->GetCaps(&maDeviceDesc,&aHELDeviceDesc)))
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): GetCaps() for Direct3DDevice failed" );
+ mpDirect3D.reset();
+ return false;
+ }
+
+ mpDirect3DDevice = COMReference< IDirect3DDevice2 >(pDirect3DDevice);
+
+ // select appropriate texture format (_need_ alpha channel here)
+ rtl_fillMemory( &maTextureFormat,
+ sizeof(DDPIXELFORMAT), 0 );
+ maTextureFormat.dwSize = sizeof(DDPIXELFORMAT);
+ if( SUCCEEDED(mpDirect3DDevice->EnumTextureFormats( EnumTextureFormatsCallback, &maTextureFormat )) )
+ {
+ bool bSupportedFormat = true;
+ if((maTextureFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) != (DDPF_ALPHAPIXELS | DDPF_RGB))
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwRGBAlphaBitMask != 0xFF000000)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwRBitMask != 0x00FF0000)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwGBitMask != 0x0000FF00)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwBBitMask != 0x000000FF)
+ bSupportedFormat = false;
+
+ if(bSupportedFormat)
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): chose texture format dwRGBBitCount %d, dwRBitMask %x, "
+ "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The texture uses %s alpha.",
+ maTextureFormat.dwRGBBitCount,
+ maTextureFormat.dwRBitMask,
+ maTextureFormat.dwGBitMask,
+ maTextureFormat.dwBBitMask,
+ maTextureFormat.dwRGBAlphaBitMask,
+ maTextureFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
+
+ // setup the device (with as much as we can possibly do here)
+ // ==========================================================
+
+ LPDIRECT3DVIEWPORT2 pViewport;
+
+ if( SUCCEEDED(mpDirect3D->CreateViewport( &pViewport, NULL )) )
+ {
+ if( SUCCEEDED(mpDirect3DDevice->AddViewport( pViewport )) )
+ {
+ // setup viewport (to whole backbuffer)
+ D3DVIEWPORT2 aViewport;
+
+ aViewport.dwSize = sizeof(D3DVIEWPORT2);
+ aViewport.dwX = 0;
+ aViewport.dwY = 0;
+ aViewport.dwWidth = maSelectedFullscreenMode.selectedDesc.dwWidth;
+ aViewport.dwHeight = maSelectedFullscreenMode.selectedDesc.dwHeight;
+ aViewport.dvClipX = -1.0;
+ aViewport.dvClipY = -1.0;
+ aViewport.dvClipWidth = 2.0;
+ aViewport.dvClipHeight = 2.0;
+ aViewport.dvMinZ = 0.0;
+ aViewport.dvMaxZ = 1.0;
+
+ if( SUCCEEDED(pViewport->SetViewport2( &aViewport )) )
+ {
+ if( SUCCEEDED(mpDirect3DDevice->SetCurrentViewport( pViewport )) )
+ {
+ // Viewport was handed over to 3DDevice, thus we can release now
+ pViewport->Release();
+
+ // currently, no need for any
+ // matrix or light source
+ // setup, since we only render
+ // transformed&lighted
+ // vertices
+
+ // done; successfully
+ return true;
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): SetCurrentViewport failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): SetViewport2 failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): AddViewport failed" );
+ }
+
+ pViewport->Release();
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): CreateViewport failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): No supported pixelformat" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): EnumTextureFormats failed" );
+ }
+
+ // go defunct, and exit
+ mpDirect3DDevice.reset();
+ mpDirect3D.reset();
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::queryCaps
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::queryCaps()
+ {
+ DDCAPS aHWCaps;
+ DDCAPS aHELCaps;
+
+ rtl_fillMemory( &aHWCaps,
+ sizeof(aHWCaps), 0 );
+ rtl_fillMemory( &aHELCaps,
+ sizeof(aHELCaps), 0 );
+ aHWCaps.dwSize = sizeof( aHWCaps );
+ aHELCaps.dwSize = sizeof( aHELCaps );
+
+ if( FAILED( mpDirectDraw->GetCaps( &aHWCaps,
+ &aHELCaps ) ) )
+ {
+ return false;
+ }
+
+ mbHasNoTearingBlt = aHWCaps.dwFXCaps & DDBLTFX_NOTEARING;
+
+ VERBOSE_TRACE( "dxcanvas initialization: %d bytes VRAM free for surfaces (%d with AGP mem), "
+ "%d bytes VRAM free for textures (%d with AGP mem)",
+ getAvailableSurfaceMem( false ),
+ getAvailableSurfaceMem( true ),
+ getAvailableTextureMem( false ),
+ getAvailableTextureMem( true ) );
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::validateCaps
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::validateCaps()
+ {
+ // TODO(E3): Validate HW capabilities. Depending on primary
+ // surface size, reject HW e.g. on the grounds of insufficient
+ // VRAM.
+
+ // setup query struct
+ DDSURFACEDESC desc;
+ rtl_fillMemory(&desc,sizeof(DDSURFACEDESC),0);
+ desc.dwSize = sizeof(DDSURFACEDESC);
+
+ // read current display mode, e.g. for screen dimension
+ if(FAILED( mpDirectDraw->GetDisplayMode(&desc)))
+ return false;
+
+ // simple heuristic: we need at least 3 times the desktop
+ // resolution based on ARGB color values...
+ std::size_t nMinimumVRAMSize = ((desc.dwWidth*desc.dwHeight)<<2)*3;
+ if(getAvailableSurfaceMem() < nMinimumVRAMSize)
+ return false;
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getDisplayFormat
+ //////////////////////////////////////////////////////////////////////////////////
+
+ unsigned int DXRenderModule::getDisplayFormat() const
+ {
+ unsigned int nFormat;
+ nFormat = ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRBitMask)<<8;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwGBitMask)<<4;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwBBitMask);
+ return nFormat;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAvailableSurfaceMem
+ //////////////////////////////////////////////////////////////////////////////////
+
+ std::size_t DXRenderModule::getAvailableSurfaceMem( bool bWithAGPMem ) const
+ {
+ if( !mpDirectDraw.is() )
+ return 0;
+
+ std::size_t nRes( 0 );
+
+ DDSCAPS aSurfaceCaps;
+ DWORD nTotal, nFree;
+
+ // real VRAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+
+ if( bWithAGPMem )
+ {
+ // AGP RAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+ }
+
+ return nRes;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAvailableTextureMem
+ //////////////////////////////////////////////////////////////////////////////////
+
+ std::size_t DXRenderModule::getAvailableTextureMem( bool bWithAGPMem ) const
+ {
+ if( !mpDirectDraw.is() )
+ return 0;
+
+ std::size_t nRes( 0 );
+
+ DDSCAPS aSurfaceCaps;
+ DWORD nTotal, nFree;
+
+ // TODO(F1): Check if flags are applicable
+
+ // real VRAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+
+ if( bWithAGPMem )
+ {
+ // AGP RAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+ }
+
+ // TODO(F1): Add pool mem
+
+ return nRes;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::convert2Screen
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
+ ::basegfx::B2IRange& io_rDestArea )
+ {
+ POINT aPoint = { 0, 0 };
+ ClientToScreen( mhWnd, &aPoint );
+
+ // i52230 make sure given screen coordinate is relative to
+ // this monitor's area (the device rendering is always
+ // contained to a single monitor)
+ aPoint.x -= maMonitorInfo.rcMonitor.left;
+ aPoint.y -= maMonitorInfo.rcMonitor.top;
+
+ io_rDestPos.setX( io_rDestPos.getX() + aPoint.x );
+ io_rDestPos.setY( io_rDestPos.getY() + aPoint.y );
+
+ const ::basegfx::B2ISize& rSize( getFramebufferSize() );
+
+ // calc output bounds (clip against framebuffer bounds)
+ io_rDestArea = ::basegfx::B2IRange(
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getX()),
+ sal_Int32(io_rDestArea.getMinX() + aPoint.x) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getY()),
+ sal_Int32(io_rDestArea.getMinY() + aPoint.y) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getX()),
+ sal_Int32(io_rDestArea.getMaxX() + aPoint.x) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getY()),
+ sal_Int32(io_rDestArea.getMaxY() + aPoint.y) ) ) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSystemMemorySurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ COMReference<IDirectDrawSurface> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize )
+ {
+ DDSURFACEDESC aSurfaceDesc;
+ IDirectDrawSurface* pSurface;
+
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;;
+ aSurfaceDesc.dwWidth = rSize.getX();
+ aSurfaceDesc.dwHeight= rSize.getY();
+
+ rtl_copyMemory( &aSurfaceDesc.ddpfPixelFormat, &maTextureFormat, sizeof(DDPIXELFORMAT) );
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ if(FAILED(nRes))
+ return COMReference<IDirectDrawSurface>(NULL);
+
+ return COMReference<IDirectDrawSurface>(pSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flip
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ // see if the main surfaces got lost. if so, try to
+ // restore them. bail out if this operation fails.
+ if(!(validateMainSurfaces()))
+ return false;
+
+ flushVertexCache();
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "Device::flip(): within 3D scene" );
+
+ // TODO(E3): handle DX errors more thoroughly. For fullscreen
+ // exclusive mode, actually even our primary surface can get
+ // lost and needs restore!
+
+ if( mpDirectDraw.is() &&
+ mpPrimarySurface.is() &&
+ mpBackBufferSurface.is() )
+ {
+ // ignore area and offset for page flipping device
+ if( mbPageFlipping )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ renderFPSCounter();
+ renderMemAvailable();
+#endif
+ VERBOSE_TRACE( "Device::flip(): Using true page flipping" );
+
+ // use true page flipping. Hopefully, the 3D hardware
+ // is flushed on this flip call (rumours have it that
+ // way), otherwise, perform the Lock hack as for the
+ // Blt below.
+ if( SUCCEEDED(mpPrimarySurface->Flip( NULL, DDFLIP_WAIT )) )
+ return true;
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::flip(): Using blt for page flipping" );
+
+ // determine actual window position
+ ::basegfx::B2IPoint aDestPoint( rUpdateArea.getMinimum() );
+ ::basegfx::B2IRange aSourceArea( rUpdateArea );
+ ::basegfx::B2IRange aDestArea( 0,0,
+ static_cast<sal_Int32>(rCurrWindowArea.getWidth()),
+ static_cast<sal_Int32>(rCurrWindowArea.getHeight()) );
+ convert2Screen( aDestPoint, aDestArea );
+
+ // perform clipping
+ if( !::canvas::tools::clipBlit( aSourceArea,
+ aDestPoint,
+ rUpdateArea,
+ aDestArea ) )
+ return true; // fully clipped, but still, in a way,
+ // successful.
+
+ // TODO(P1): Rumours have it that the 3D hardware
+ // _might_ still be rendering with flaky drivers,
+ // which don't flush properly on Blt(). It was said,
+ // that 'usually', it works to lock the 3D render
+ // target (the backbuffer in this case). OTOH, I've
+ // found that this tends to degrade performance
+ // significantly on complying cards...
+
+ // TODO(P1): Up until rev. 1.3, this method contained
+ // code to make sure the blit will start _immediately_
+ // after the Blt call. If this is not warranted, wait
+ // for the next vsync. As this case was found to be
+ // extremely seldom, kicked out (what's more, there's
+ // simply no guarantee that the blitter will be
+ // available at any point in the code - Windows still
+ // is a preemptive multi-processing environment. And
+ // _if_ we're competing with someone over the blitter,
+ // we will do so the next VBLANK interval, and the
+ // following...)
+
+ // screen update seems to be smoother when waiting
+ // for vblank in every case - even when blitter
+ // supports the DDBLTFX_NOTEARING flag.
+ if( FAILED(mpDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,
+ NULL)) )
+ return false;
+
+ DDBLTFX aBltFx;
+ DDBLTFX* pBltFX = NULL;
+ if( mbHasNoTearingBlt )
+ {
+ // Blt can internally schedule for no-tearing
+ // ===========================================
+
+ rtl_fillMemory( &aBltFx,
+ sizeof(aBltFx), 0 );
+ aBltFx.dwSize = sizeof(aBltFx);
+ aBltFx.dwDDFX = DDBLTFX_NOTEARING;
+
+ pBltFX = &aBltFx;
+ }
+
+ if( doBlit( aDestPoint,
+ *mpPrimarySurface,
+ aSourceArea,
+ *mpBackBufferSurface,
+ pBltFX,false ) )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ renderFPSCounter();
+ renderMemAvailable();
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::disposing
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::disposing()
+ {
+ if(!(mhWnd))
+ return;
+
+ mpTexture.reset();
+ mpWindow.reset();
+ mhWnd=NULL;
+
+ // refrain from releasing the DX5 objects - deleting the
+ // DX5 device seems to kill the whole engine, including
+ // all objects we might still hold references to
+ // (surfaces, e.g.)
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::screenshot
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::screenShot()
+ {
+ if(!(mpBackBufferSurface.get()))
+ return;
+ char filename[256];
+ static sal_uInt32 counter = 0;
+ sprintf(filename,"c:\\shot%d.bmp",counter++);
+ dumpSurface(mpBackBufferSurface,filename);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::validateMainSurfaces
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::validateMainSurfaces()
+ {
+ if(mpPrimarySurface.get()) {
+ if(mpPrimarySurface->IsLost() == DDERR_SURFACELOST) {
+ if(FAILED(mpPrimarySurface->Restore()))
+ return false;
+ }
+ }
+
+ if(mpBackBufferSurface.get()) {
+ if(mpBackBufferSurface->IsLost() == DDERR_SURFACELOST)
+ {
+ // TODO(F1): simply restoring the backbuffer does not
+ // work as expected, we need to re-create everything
+ // from scratch. find out why...
+ //if(SUCCEEDED(mpBackBufferSurface->Restore()))
+ // return setup3DDevice();
+
+ mpBackBufferSurface.reset();
+
+ // get us a backbuffer for simulated flipping
+ IDirectDrawSurface* pSurface;
+
+ // TODO(P2): Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with the current
+ // window size, but this will make it necessary to temporarily have two
+ // buffers while copying from the old to the new one. YMMV.
+ const ::basegfx::B2ISize aSize( getFramebufferSize() );
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc, sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ aSurfaceDesc.dwHeight= aSize.getY();
+ aSurfaceDesc.dwWidth = aSize.getX();
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+
+ if( FAILED( nRes ) )
+ {
+ if( nRes == DDERR_OUTOFVIDEOMEMORY )
+ {
+ // local vid mem failed. Maybe AGP mem works?
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
+ {
+ // no chance
+ return false;
+ }
+
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
+ }
+ else
+ {
+ // no chance
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ return false;
+ }
+ }
+
+ VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight );
+
+ mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
+
+ return setup3DDevice();
+ }
+ }
+
+ return true;
+ }
+
+ void DXRenderModule::renderInfoText( const ::rtl::OUString& rStr,
+ const Gdiplus::PointF& rPos ) const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "Device::renderInfoText(): within 3D scene" );
+
+ // render text directly to primary surface
+ GraphicsSharedPtr pGraphics;
+
+ if( mbPageFlipping )
+ {
+ // render on top of backbuffer. We have
+ // page flipping, anyway, thus this will
+ // cost us nothing.
+ pGraphics = createSurfaceGraphics( mpBackBufferSurface );
+ }
+ else
+ {
+ // render FPS directly to front buffer.
+ // That saves us another explicit blit,
+ // and for me, the FPS counter can blink,
+ // if it likes to...
+ pGraphics = createSurfaceGraphics( mpPrimarySurface );
+ }
+
+ if( !mbPageFlipping )
+ {
+ // clear background. We might be doing optimized redraws,
+ // and the background under the FPS count will then not be
+ // cleared.
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color( 255, 255, 255 ) );
+
+ pGraphics->FillRectangle( &aBrush,
+ rPos.X, rPos.Y, 80.0, 20.0 );
+ }
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color( 255, 0, 255 ) );
+ Gdiplus::Font aFont( NULL,
+ 16,
+ Gdiplus::FontStyleRegular,
+ Gdiplus::UnitWorld,
+ NULL );
+ pGraphics->DrawString( reinterpret_cast<LPCWSTR>(rStr.getStr()),
+ rStr.getLength(),
+ &aFont,
+ rPos,
+ &aBrush );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::renderMemAvailable
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::renderMemAvailable() const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::renderMemAvailable(): within 3D scene" );
+
+ const double nSurfaceMem( getAvailableSurfaceMem()/1024 );
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( nSurfaceMem,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("S: ")) + text;
+
+ renderInfoText( text,
+ Gdiplus::PointF( 0.0, 20) );
+
+
+ const double nTexMem( getAvailableTextureMem()/1024 );
+
+ text = ::rtl::math::doubleToUString( nTexMem,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ');
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("T: ")) + text;
+
+ renderInfoText( text,
+ Gdiplus::PointF( 0.0, 40) );
+
+ VERBOSE_TRACE( "dxcanvas: %f free surface mem, %f free texture mem",
+ nSurfaceMem, nTexMem );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::renderFPSCounter
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::renderFPSCounter() const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::ren derFPSCounter(): within 3D scene" );
+
+ const double denominator( maLastUpdate.getElapsedTime() );
+ maLastUpdate.reset();
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" fps"));
+
+ renderInfoText( text,
+ Gdiplus::PointF() );
+
+ VERBOSE_TRACE( "dxcanvas: %f FPS",
+ denominator == 0.0 ? 100.0 : 1.0/denominator );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::resize( const ::basegfx::B2IRange& rect )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if( mhWnd==0 )
+ return;
+
+ // don't do anything if the size didn't change.
+ if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) &&
+ maSize.getY() == static_cast<sal_Int32>(rect.getHeight()))
+ return;
+
+ // TODO(Q2): use numeric cast to prevent overflow
+ maSize.setX(static_cast<sal_Int32>(rect.getWidth()));
+ maSize.setY(static_cast<sal_Int32>(rect.getHeight()));
+
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getPageSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXRenderModule::getPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+ return maPageSize;
+ }
+
+ ::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ const ::basegfx::B2IVector& rPageSize( getPageSize() );
+ ::basegfx::B2ISize aSize(surfaceSize);
+ if(!(aSize.getX()))
+ aSize.setX(rPageSize.getX());
+ if(!(aSize.getY()))
+ aSize.setY(rPageSize.getY());
+
+ if(mpTexture.use_count() == 1)
+ return mpTexture;
+
+ return ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,
+ aSize) );
+ }
+
+ void DXRenderModule::beginPrimitive( PrimitiveType eType )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::beginPrimitive(): nested call" );
+
+ ++mnBeginSceneCount;
+ meType=eType;
+ mnCount=0;
+ }
+
+ void DXRenderModule::endPrimitive()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ --mnBeginSceneCount;
+ meType=PRIMITIVE_TYPE_UNKNOWN;
+ mnCount=0;
+ }
+
+ void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ switch(meType)
+ {
+ case PRIMITIVE_TYPE_TRIANGLE:
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ mnCount &= 3;
+ break;
+ }
+
+ case PRIMITIVE_TYPE_QUAD:
+ {
+ if(mnCount == 3)
+ {
+ const std::size_t size(maVertexCache.size());
+ ::canvas::Vertex v0(maVertexCache[size-1]);
+ ::canvas::Vertex v2(maVertexCache[size-3]);
+ maVertexCache.push_back(v0);
+ maVertexCache.push_back(vertex);
+ maVertexCache.push_back(v2);
+ mnCount=0;
+ }
+ else
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE( false,
+ "DXRenderModule::pushVertex(): unexpected primitive types" );
+ break;
+ }
+ }
+
+ bool DXRenderModule::isError()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ return mbError;
+ }
+
+ void DXRenderModule::flushVertexCache()
+ {
+ if(!(maVertexCache.size()))
+ return;
+
+ mbError=true;
+
+ if( FAILED(mpDirect3DDevice->BeginScene()) )
+ return;
+
+ // enable texture alpha blending
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE)))
+ return;
+
+ // enable texture alpha modulation, for honoring fAlpha
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND,
+ D3DTBLEND_MODULATEALPHA)) )
+ return;
+
+ // enable texture magnification filtering (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAG,
+ D3DFILTER_LINEAR);
+
+ // enable texture minification filtering (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMIN,
+ D3DFILTER_LINEAR);
+
+ // enable subpixel texture output (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SUBPIXEL,
+ TRUE);
+
+ // normal combination of object...
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,
+ D3DBLEND_SRCALPHA)) )
+ return;
+
+ // ..and background color
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,
+ D3DBLEND_INVSRCALPHA)) )
+ return;
+
+ // disable backface culling; this enables us to mirror sprites
+ // by simply reverting the triangles, which, with enabled
+ // culling, would be invisible otherwise
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE,
+ D3DCULL_NONE)) )
+ return;
+
+ mbError=false;
+
+ const float nHalfPixelSizeX(0.5f/maPageSize.getX());
+ const float nHalfPixelSizeY(0.5f/maPageSize.getY());
+ sal_uInt32 nIndex(0);
+ const std::size_t size(maVertexCache.size());
+ D3DTLVERTEX *vertices = static_cast<D3DTLVERTEX *>(_alloca(sizeof(D3DTLVERTEX)*size));
+ vertexCache_t::const_iterator it(maVertexCache.begin());
+ while(it != maVertexCache.end())
+ {
+ vertices[nIndex++] = D3DTLVERTEX(
+ D3DVECTOR(static_cast<D3DVALUE>(it->x),
+ static_cast<D3DVALUE>(it->y),
+ static_cast<D3DVALUE>(it->z)),
+ 1,
+ D3DRGBA(1,1,1,it->a),
+ D3DRGBA(0,0,0,0),
+ static_cast<float>(it->u + nHalfPixelSizeX),
+ static_cast<float>(it->v + nHalfPixelSizeY));
+ ++it;
+ }
+
+ maVertexCache.clear();
+
+ mbError |= FAILED(mpDirect3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DVT_TLVERTEX,
+ (LPVOID)vertices,
+ size,
+ 0));
+
+ mbError |= FAILED(mpDirect3DDevice->EndScene());
+ }
+ }
+
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent )
+ {
+ return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) );
+ }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_9rm.cxx b/canvas/source/directx/dx_9rm.cxx
new file mode 100644
index 000000000000..50c0a3d9bcdf
--- /dev/null
+++ b/canvas/source/directx/dx_9rm.cxx
@@ -0,0 +1,1366 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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"
+
+#if DIRECTX_VERSION == 0x0900
+
+#define MAX_TEXTURE_SIZE (2048)
+#define MIN_TEXTURE_SIZE (32)
+//#define FAKE_MAX_NUMBER_TEXTURES (2)
+//#define FAKE_MAX_TEXTURE_SIZE (4096)
+
+#define VERTEX_BUFFER_SIZE (341*3) // 1023, the size of the internal
+ // vertex buffer (must be divisable
+ // by 3, as each triangle primitive
+ // has 3 vertices)
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// includes
+//////////////////////////////////////////////////////////////////////////////////
+#include <vcl/syschild.hxx>
+#include <vcl/window.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <canvas/elapsedtime.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/isurface.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_config.hxx"
+
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#include "dx_impltools.hxx"
+#include <vcl/sysdata.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////////
+// 'dxcanvas' namespace
+//////////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ namespace
+ {
+ //////////////////////////////////////////////////////////////////////////////////
+ // monitorSupport
+ //////////////////////////////////////////////////////////////////////////////////
+
+ class monitorSupport
+ {
+ public:
+
+ monitorSupport() :
+ mhLibrary(LoadLibrary("user32.dll")),
+ mpMonitorFromWindow(NULL)
+ {
+ if(mhLibrary)
+ mpMonitorFromWindow = reinterpret_cast<fMonitorFromWindow>(
+ GetProcAddress(
+ mhLibrary,"MonitorFromWindow"));
+ }
+
+ ~monitorSupport()
+ {
+ if(mhLibrary)
+ FreeLibrary(mhLibrary);
+ mhLibrary=0;
+ }
+
+ HMONITOR MonitorFromWindow( HWND hwnd )
+ {
+ // return adapter_default in case something went wrong...
+ if(!(mpMonitorFromWindow))
+ return HMONITOR(0);
+ // MONITOR_DEFAULTTONEAREST
+ const DWORD dwFlags(0x00000002);
+ return mpMonitorFromWindow(hwnd,dwFlags);
+ }
+ private:
+
+ HINSTANCE mhLibrary;
+ typedef HMONITOR (WINAPI *fMonitorFromWindow )( HWND hwnd, DWORD dwFlags );
+ fMonitorFromWindow mpMonitorFromWindow;
+ };
+
+ monitorSupport aMonitorSupport;
+
+
+ class DXRenderModule;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** ISurface implemenation.
+
+ @attention holds the DXRenderModule via non-refcounted
+ reference! This is safe with current state of affairs, since
+ the canvas::PageManager holds surface and render module via
+ shared_ptr (and makes sure all surfaces are deleted before its
+ render module member goes out of scope).
+ */
+ class DXSurface : public canvas::ISurface
+ {
+ public:
+ DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize );
+ ~DXSurface();
+
+ virtual bool selectTexture();
+ virtual bool isValid();
+ virtual bool update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource );
+ virtual ::basegfx::B2IVector getSize();
+ COMReference<IDirect3DTexture9> getTexture() const;
+
+ private:
+ /// Guard local methods against concurrent acces to RenderModule
+ class ImplRenderModuleGuard : private ::boost::noncopyable
+ {
+ public:
+ explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule );
+ inline ~ImplRenderModuleGuard();
+
+ private:
+ DXRenderModule& mrRenderModule;
+ };
+
+ DXRenderModule& mrRenderModule;
+ COMReference<IDirect3DTexture9> mpTexture;
+
+ ::basegfx::B2IVector maSize;
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /// Default implementation of IDXRenderModule
+ class DXRenderModule : public IDXRenderModule
+ {
+ public:
+ explicit DXRenderModule( const ::Window& rWindow );
+ ~DXRenderModule();
+
+ virtual void lock() const { maMutex.acquire(); }
+ virtual void unlock() const { maMutex.release(); }
+
+ virtual COMReference<IDirect3DSurface9>
+ createSystemMemorySurface( const ::basegfx::B2IVector& rSize );
+ virtual void disposing();
+ virtual HWND getHWND() const { return mhWnd; }
+ virtual void screenShot();
+
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea );
+
+ virtual void resize( const ::basegfx::B2IRange& rect );
+ virtual ::basegfx::B2IVector getPageSize();
+ virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize );
+ virtual void beginPrimitive( PrimitiveType eType );
+ virtual void endPrimitive();
+ virtual void pushVertex( const ::canvas::Vertex& vertex );
+ virtual bool isError();
+
+ COMReference<IDirect3DDevice9> getDevice() { return mpDevice; }
+
+ void flushVertexCache();
+ void commitVertexCache();
+
+ private:
+
+ bool create( const ::Window& rWindow );
+ bool createDevice();
+ bool verifyDevice( const UINT nAdapter );
+ UINT getAdapterFromWindow();
+
+ /** This object represents the DirectX state machine. In order
+ to serialize access to DirectX's global state, a global
+ mutex is required.
+ */
+ static ::osl::Mutex maMutex;
+
+ HWND mhWnd;
+ COMReference<IDirect3DDevice9> mpDevice;
+ COMReference<IDirect3D9> mpDirect3D9;
+ COMReference<IDirect3DSwapChain9> mpSwapChain;
+ COMReference<IDirect3DVertexBuffer9> mpVertexBuffer;
+ ::canvas::ISurfaceSharedPtr mpTexture;
+ ::boost::scoped_ptr<SystemChildWindow> mpWindow;
+ ::basegfx::B2IVector maSize;
+ typedef std::vector<canvas::Vertex> vertexCache_t;
+ vertexCache_t maVertexCache;
+ std::size_t mnCount;
+ int mnBeginSceneCount;
+ bool mbCanUseDynamicTextures;
+ bool mbError;
+ PrimitiveType meType;
+ ::basegfx::B2IVector maPageSize;
+ D3DPRESENT_PARAMETERS mad3dpp;
+
+ inline bool isDisposed() const { return (mhWnd==NULL); }
+
+ struct dxvertex
+ {
+ float x,y,z,rhw;
+ DWORD diffuse;
+ float u,v;
+ };
+
+ std::size_t maNumVertices;
+ std::size_t maWriteIndex;
+ std::size_t maReadIndex;
+ };
+
+ ::osl::Mutex DXRenderModule::maMutex;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::ImplRenderModuleGuard
+ //////////////////////////////////////////////////////////////////////////////////
+
+ inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard(
+ DXRenderModule& rRenderModule ) :
+ mrRenderModule( rRenderModule )
+ {
+ mrRenderModule.lock();
+ }
+
+ inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard()
+ {
+ mrRenderModule.unlock();
+ }
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ static sal_uInt32 gNumSurfaces = 0;
+#endif
+
+ void fillRect( sal_uInt32 *pDest,
+ sal_uInt32 dwWidth,
+ sal_uInt32 dwHeight,
+ sal_uInt32 dwPitch,
+ sal_uInt32 dwColor )
+ {
+ for(sal_uInt32 i=0; i<dwWidth; ++i)
+ {
+ pDest[i]=dwColor;
+ pDest[((dwHeight-1)*dwPitch)+i]=dwColor;
+ }
+
+ for(sal_uInt32 j=0; j<dwHeight; ++j)
+ {
+ pDest[0]=dwColor;
+ pDest[dwWidth-1]=dwColor;
+ pDest += dwPitch;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize ) :
+ mrRenderModule(rRenderModule),
+ mpTexture(NULL),
+ maSize()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ ++gNumSurfaces;
+ if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES)
+ return;
+#endif
+
+#ifdef FAKE_MAX_TEXTURE_SIZE
+ if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+ if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+#endif
+
+ ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0,
+ "DXSurface::DXSurface(): request for zero-sized surface");
+
+ COMReference<IDirect3DDevice9> pDevice(rRenderModule.getDevice());
+
+ IDirect3DTexture9 *pTexture(NULL);
+ if(FAILED(pDevice->CreateTexture(
+ rSize.getX(),
+ rSize.getY(),
+ 1,0,D3DFMT_A8R8G8B8,
+ D3DPOOL_MANAGED,
+ &pTexture,NULL)))
+ return;
+
+ mpTexture=COMReference<IDirect3DTexture9>(pTexture);
+ maSize = rSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::~DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::~DXSurface()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ gNumSurfaces--;
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::selectTexture
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::selectTexture()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+ mrRenderModule.flushVertexCache();
+ COMReference<IDirect3DDevice9> pDevice(mrRenderModule.getDevice());
+
+ if( FAILED(pDevice->SetTexture(0,mpTexture.get())) )
+ return false;
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::isValid
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::isValid()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ if(!(mpTexture.is()))
+ return false;
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::update
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource )
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ // can't update if surface is not valid, that means
+ // either not existent nor restored...
+ if(!(isValid()))
+ return false;
+
+ D3DLOCKED_RECT aLockedRect;
+ RECT rect;
+ rect.left = std::max(sal_Int32(0),rDestPos.getX());
+ rect.top = std::max(sal_Int32(0),rDestPos.getY());
+ // to avoid interpolation artifacts from other textures,
+ // the surface manager allocates one pixel gap between
+ // them. Clear that to transparent.
+ rect.right = std::min(maSize.getX(),
+ rect.left + sal_Int32(rSourceRect.getWidth()+1));
+ rect.bottom = std::min(maSize.getY(),
+ rect.top + sal_Int32(rSourceRect.getHeight()+1));
+ const bool bClearRightColumn( rect.right < maSize.getX() );
+ const bool bClearBottomRow( rect.bottom < maSize.getY() );
+
+ if(SUCCEEDED(mpTexture->LockRect(0,&aLockedRect,&rect,D3DLOCK_NOSYSLOCK)))
+ {
+ if(sal_uInt8* pImage = rSource.lock())
+ {
+ switch( rSource.getFormat() )
+ {
+ case ::canvas::IColorBuffer::FMT_A8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_uInt32 nNumBytesToCopy(
+ static_cast<sal_uInt32>(
+ rSourceRect.getWidth())*
+ nSourceBytesPerPixel);
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ rtl_copyMemory(pDst,pImage,nNumBytesToCopy);
+
+ if( bClearRightColumn )
+ {
+ // to avoid interpolation artifacts
+ // from other textures, the surface
+ // manager allocates one pixel gap
+ // between them. Clear that to
+ // transparent.
+ pDst[nNumBytesToCopy] =
+ pDst[nNumBytesToCopy+1] =
+ pDst[nNumBytesToCopy+2] =
+ pDst[nNumBytesToCopy+3] = 0x00;
+ }
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,nNumBytesToCopy+4);
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(3);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_Int32 nNumColumns(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getWidth()));
+ const sal_Int32 nNumLines(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getHeight()));
+ for(sal_Int32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst);
+ sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage);
+
+ for(sal_Int32 x=0; x<nNumColumns; ++x)
+ {
+ sal_uInt32 color(0xFF000000);
+ color |= pSrcScanline[2]<<16;
+ color |= pSrcScanline[1]<<8;
+ color |= pSrcScanline[0];
+ pSrcScanline += 3;
+ *pDstScanline++ = color;
+ }
+ if( bClearRightColumn )
+ *pDstScanline++ = 0xFF000000;
+
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,4*(nNumColumns+1));
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_X8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_Int32 nNumLines(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getHeight()));
+ const sal_Int32 nNumColumns(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getWidth()));
+ for(sal_Int32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage);
+ sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst);
+ for(sal_Int32 j=0; j<nNumColumns; ++j)
+ pDst32[j] = 0xFF000000 | pSrc32[j];
+
+ if( bClearRightColumn )
+ pDst32[nNumColumns] = 0xFF000000;
+
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,4*(nNumColumns+1));
+ }
+ break;
+
+ default:
+ ENSURE_OR_RETURN_FALSE(false,
+ "DXSurface::update(): Unknown/unimplemented buffer format" );
+ break;
+ }
+
+ rSource.unlock();
+ }
+
+ return SUCCEEDED(mpTexture->UnlockRect(0));
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurface::getSize()
+ {
+ return maSize;
+ }
+
+ COMReference<IDirect3DTexture9> DXSurface::getTexture() const
+ {
+ return mpTexture;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::DXRenderModule( const ::Window& rWindow ) :
+ mhWnd(0),
+ mpDevice(),
+ mpDirect3D9(),
+ mpSwapChain(),
+ mpVertexBuffer(),
+ mpTexture(),
+ maSize(),
+ maVertexCache(),
+ mnCount(0),
+ mnBeginSceneCount(0),
+ mbCanUseDynamicTextures(false),
+ mbError( false ),
+ meType( PRIMITIVE_TYPE_UNKNOWN ),
+ maPageSize(),
+ mad3dpp(),
+ maNumVertices( VERTEX_BUFFER_SIZE ),
+ maWriteIndex(0),
+ maReadIndex(0)
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(!(create(rWindow)))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+
+ // allocate a single texture surface which can be used later.
+ // we also use this to calibrate the page size.
+ ::basegfx::B2IVector aPageSize(maPageSize);
+ while(true)
+ {
+ mpTexture = ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,aPageSize));
+ if(mpTexture->isValid())
+ break;
+
+ aPageSize.setX(aPageSize.getX()>>1);
+ aPageSize.setY(aPageSize.getY()>>1);
+ if((aPageSize.getX() < MIN_TEXTURE_SIZE) ||
+ (aPageSize.getY() < MIN_TEXTURE_SIZE))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - "
+ "insufficient texture space!") ),NULL);
+ }
+ }
+ maPageSize=aPageSize;
+
+ IDirect3DVertexBuffer9 *pVB(NULL);
+ DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
+ if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices,
+ D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
+ aFVF,
+ D3DPOOL_DEFAULT,
+ &pVB,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - out of memory!")),NULL);
+ }
+
+ mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::~DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::~DXRenderModule()
+ {
+ disposing();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::disposing
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::disposing()
+ {
+ if(!(mhWnd))
+ return;
+
+ mpTexture.reset();
+ mpWindow.reset();
+ mhWnd=NULL;
+
+ // refrain from releasing the DX9 objects. We're the only
+ // ones holding references to them, and it might be
+ // dangerous to destroy the DX9 device, before all other
+ // objects are dead.
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::create
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::create( const ::Window& rWindow )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maVertexCache.reserve(1024);
+
+ mpWindow.reset(
+ new SystemChildWindow(
+ const_cast<Window *>(&rWindow), 0) );
+
+ // system child window must not receive mouse events
+ mpWindow->SetMouseTransparent( TRUE );
+
+ // parent should receive paint messages as well
+ // [PARENTCLIPMODE_NOCLIP], the argument is here
+ // passed as plain numeric value since the stupid
+ // define utilizes a USHORT cast.
+ mpWindow->SetParentClipMode(0x0002);
+
+ // the system child window must not clear its background
+ mpWindow->EnableEraseBackground( FALSE );
+
+ mpWindow->SetControlForeground();
+ mpWindow->SetControlBackground();
+ mpWindow->EnablePaint(FALSE);
+
+ const SystemEnvData *pData = mpWindow->GetSystemData();
+ const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd));
+ mhWnd = const_cast<HWND>(hwnd);
+
+ ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ),
+ "DXRenderModule::create() No valid HWND given." );
+
+ // retrieve position and size of the parent window
+ const ::Size &rSizePixel(rWindow.GetSizePixel());
+
+ // remember the size of the parent window, since we
+ // need to use this for our child window.
+ maSize.setX(static_cast<sal_Int32>(rSizePixel.Width()));
+ maSize.setY(static_cast<sal_Int32>(rSizePixel.Height()));
+
+ // let the child window cover the same size as the parent window.
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ // TODO(F2): since we would like to share precious hardware
+ // resources, the direct3d9 object should be global. each new
+ // request for a canvas should only create a new swapchain.
+ mpDirect3D9 = COMReference<IDirect3D9>(
+ Direct3DCreate9(D3D_SDK_VERSION));
+ if(!mpDirect3D9.is())
+ return false;
+
+ // create a device from the direct3d9 object.
+ if(!(createDevice()))
+ return false;
+
+ mpWindow->Show();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::verifyDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::verifyDevice( const UINT nAdapter )
+ {
+ ENSURE_OR_THROW( mpDirect3D9.is(),
+ "DXRenderModule::verifyDevice() No valid device." );
+
+ // ask direct3d9 about the capabilities of hardware devices on a specific adapter.
+ // here we decide if the underlying hardware of the machine 'is good enough'.
+ // since we only need a tiny little fraction of what could be used, this
+ // is basically a no-op.
+ D3DCAPS9 aCaps;
+ if(FAILED(mpDirect3D9->GetDeviceCaps(nAdapter,D3DDEVTYPE_HAL,&aCaps)))
+ return false;
+ if(!(aCaps.MaxTextureWidth))
+ return false;
+ if(!(aCaps.MaxTextureHeight))
+ return false;
+ maPageSize = ::basegfx::B2IVector(aCaps.MaxTextureWidth,aCaps.MaxTextureHeight);
+
+ // check device against white & blacklist entries
+ D3DADAPTER_IDENTIFIER9 aIdent;
+ if(FAILED(mpDirect3D9->GetAdapterIdentifier(nAdapter,0,&aIdent)))
+ return false;
+
+ DXCanvasItem aConfigItem;
+ DXCanvasItem::DeviceInfo aInfo;
+ aInfo.nVendorId = aIdent.VendorId;
+ aInfo.nDeviceId = aIdent.DeviceId;
+ aInfo.nDeviceSubSysId = aIdent.SubSysId;
+ aInfo.nDeviceRevision = aIdent.Revision;
+
+ aInfo.nDriverId = HIWORD(aIdent.DriverVersion.HighPart);
+ aInfo.nDriverVersion = LOWORD(aIdent.DriverVersion.HighPart);
+ aInfo.nDriverSubVersion = HIWORD(aIdent.DriverVersion.LowPart);
+ aInfo.nDriverBuildId = LOWORD(aIdent.DriverVersion.LowPart);
+
+ if( !aConfigItem.isDeviceUsable(aInfo) )
+ return false;
+
+ if( aConfigItem.isBlacklistCurrentDevice() )
+ {
+ aConfigItem.blacklistDevice(aInfo);
+ return false;
+ }
+
+ aConfigItem.adaptMaxTextureSize(maPageSize);
+
+ mbCanUseDynamicTextures = (aCaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0;
+
+ return true;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::createDevice()
+ {
+ // we expect that the caller provides us with a valid HWND
+ ENSURE_OR_THROW( IsWindow(mhWnd),
+ "DXRenderModule::createDevice() No valid HWND given." );
+
+ // we expect that the caller already created the direct3d9 object.
+ ENSURE_OR_THROW( mpDirect3D9.is(),
+ "DXRenderModule::createDevice() no direct3d?." );
+
+ // find the adapter identifier from the window.
+ const UINT aAdapter(getAdapterFromWindow());
+ if(aAdapter == static_cast<UINT>(-1))
+ return false;
+
+ // verify that device possibly works
+ if( !verifyDevice(aAdapter) )
+ return false;
+
+ // query the display mode from the selected adapter.
+ // we'll later request the backbuffer format to be same
+ // same as the display format.
+ D3DDISPLAYMODE d3ddm;
+ mpDirect3D9->GetAdapterDisplayMode(aAdapter,&d3ddm);
+
+ // we need to use D3DSWAPEFFECT_COPY here since the canvas-api has
+ // basically nothing to do with efficient resource handling. it tries
+ // to avoid drawing whenevery possible, which is simply not the most
+ // efficient way we could leverage the hardware in this case. it would
+ // be far better to redraw the backbuffer each time we would like to
+ // display the content of the backbuffer, but we need to face reality
+ // here and follow how the canvas was designed.
+
+ // Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with
+ // the current window size, but this will make it
+ // necessary to temporarily have two buffers while copying
+ // from the old to the new one. What's more, at the time
+ // we need a larger buffer, DX might not have sufficient
+ // resources available, and we're then left with too small
+ // a back buffer, and no way of falling back to a
+ // different canvas implementation.
+ ZeroMemory( &mad3dpp, sizeof(mad3dpp) );
+ mad3dpp.BackBufferWidth = std::max(sal_Int32(maSize.getX()),
+ sal_Int32(d3ddm.Width));
+ mad3dpp.BackBufferHeight = std::max(sal_Int32(maSize.getY()),
+ sal_Int32(d3ddm.Height));
+ mad3dpp.BackBufferCount = 1;
+ mad3dpp.Windowed = TRUE;
+ mad3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
+ mad3dpp.BackBufferFormat = d3ddm.Format;
+ mad3dpp.EnableAutoDepthStencil = FALSE;
+ mad3dpp.hDeviceWindow = mhWnd;
+ mad3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+
+ // now create the device, first try hardware vertex processing,
+ // then software vertex processing. if both queries fail, we give up
+ // and indicate failure.
+ IDirect3DDevice9 *pDevice(NULL);
+ if(FAILED(mpDirect3D9->CreateDevice(aAdapter,
+ D3DDEVTYPE_HAL,
+ mhWnd,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING|
+ D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE,
+ &mad3dpp,
+ &pDevice)))
+ if(FAILED(mpDirect3D9->CreateDevice(aAdapter,
+ D3DDEVTYPE_HAL,
+ mhWnd,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING|
+ D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE,
+ &mad3dpp,
+ &pDevice)))
+ return false;
+
+ // got it, store it in a safe place...
+ mpDevice=COMReference<IDirect3DDevice9>(pDevice);
+
+ // After CreateDevice, the first swap chain already exists, so just get it...
+ IDirect3DSwapChain9 *pSwapChain(NULL);
+ pDevice->GetSwapChain(0,&pSwapChain);
+ mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain);
+ if( !mpSwapChain.is() )
+ return false;
+
+ // clear the render target [which is the backbuffer in this case].
+ // we are forced to do this once, and furthermore right now.
+ // please note that this is only possible since we created the
+ // backbuffer with copy semantics [the content is preserved after
+ // calls to Present()], which is an unnecessarily expensive operation.
+ LPDIRECT3DSURFACE9 pBackBuffer = NULL;
+ mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
+ mpDevice->SetRenderTarget( 0, pBackBuffer );
+ mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L);
+ pBackBuffer->Release();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSystemMemorySurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ COMReference<IDirect3DSurface9> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize )
+ {
+ if(isDisposed())
+ return COMReference<IDirect3DSurface9>(NULL);
+
+ // please note that D3DFMT_X8R8G8B8 is the only format we're
+ // able to choose here, since GetDC() doesn't support any
+ // other 32bit-format.
+ IDirect3DSurface9 *pSurface(NULL);
+ if( FAILED(mpDevice->CreateOffscreenPlainSurface(
+ rSize.getX(),
+ rSize.getY(),
+ D3DFMT_X8R8G8B8,
+ D3DPOOL_SYSTEMMEM,
+ &pSurface,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create offscreen surface - out of mem!") ),NULL);
+ }
+
+ return COMReference<IDirect3DSurface9>(pSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flip
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& /*rCurrWindowArea*/ )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed() || !mpSwapChain.is())
+ return false;
+
+ flushVertexCache();
+
+ // TODO(P2): Might be faster to actually pass update area here
+ RECT aRect =
+ {
+ rUpdateArea.getMinX(),
+ rUpdateArea.getMinY(),
+ rUpdateArea.getMaxX(),
+ rUpdateArea.getMaxY()
+ };
+ HRESULT hr(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0));
+ if(FAILED(hr))
+ {
+ if(hr != D3DERR_DEVICELOST)
+ return false;
+
+ // interestingly enough, sometimes the Reset() below
+ // *still* causes DeviceLost errors. So, cycle until
+ // DX was kind enough to really reset the device...
+ do
+ {
+ mpVertexBuffer.reset();
+ hr = mpDevice->Reset(&mad3dpp);
+ if(SUCCEEDED(hr))
+ {
+ IDirect3DVertexBuffer9 *pVB(NULL);
+ DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
+ if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices,
+ D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
+ aFVF,
+ D3DPOOL_DEFAULT,
+ &pVB,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - out of memory!")),NULL);
+ }
+ mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB);
+
+ // retry after the restore
+ if(SUCCEEDED(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0)))
+ return true;
+ }
+
+ TimeValue aTimeout;
+ aTimeout.Seconds=1;
+ aTimeout.Nanosec=0;
+ osl_waitThread(&aTimeout);
+ }
+ while(hr == D3DERR_DEVICELOST);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::screenShot
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::screenShot()
+ {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::resize( const ::basegfx::B2IRange& rect )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ // don't do anything if the size didn't change.
+ if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) &&
+ maSize.getY() == static_cast<sal_Int32>(rect.getHeight()))
+ return;
+
+ // TODO(Q2): use numeric cast to prevent overflow
+ maSize.setX(static_cast<sal_Int32>(rect.getWidth()));
+ maSize.setY(static_cast<sal_Int32>(rect.getHeight()));
+
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ // resize back buffer, if necessary
+ // -------------------------------------------------------------
+
+ // don't attempt to create anything if the
+ // requested size is NULL.
+ if(!(maSize.getX()))
+ return;
+ if(!(maSize.getY()))
+ return;
+
+ // backbuffer too small (might happen, if window is
+ // maximized across multiple monitors)
+ if( sal_Int32(mad3dpp.BackBufferWidth) < maSize.getX() ||
+ sal_Int32(mad3dpp.BackBufferHeight) < maSize.getY() )
+ {
+ mad3dpp.BackBufferWidth = maSize.getX();
+ mad3dpp.BackBufferHeight = maSize.getY();
+
+ // clear before, save resources
+ mpSwapChain.reset();
+
+ IDirect3DSwapChain9 *pSwapChain(NULL);
+ if(FAILED(mpDevice->CreateAdditionalSwapChain(&mad3dpp,&pSwapChain)))
+ return;
+ mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain);
+
+ // clear the render target [which is the backbuffer in this case].
+ // we are forced to do this once, and furthermore right now.
+ // please note that this is only possible since we created the
+ // backbuffer with copy semantics [the content is preserved after
+ // calls to Present()], which is an unnecessarily expensive operation.
+ LPDIRECT3DSURFACE9 pBackBuffer = NULL;
+ mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
+ mpDevice->SetRenderTarget( 0, pBackBuffer );
+ mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L);
+ pBackBuffer->Release();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getPageSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXRenderModule::getPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+ return maPageSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return ::canvas::ISurfaceSharedPtr();
+
+ const ::basegfx::B2IVector& rPageSize( getPageSize() );
+ ::basegfx::B2ISize aSize(surfaceSize);
+ if(!(aSize.getX()))
+ aSize.setX(rPageSize.getX());
+ if(!(aSize.getY()))
+ aSize.setY(rPageSize.getY());
+
+ if(mpTexture.use_count() == 1)
+ return mpTexture;
+
+ return ::canvas::ISurfaceSharedPtr( new DXSurface(*this,aSize) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::beginPrimitive
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::beginPrimitive( PrimitiveType eType )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::beginPrimitive(): nested call" );
+
+ ++mnBeginSceneCount;
+ meType=eType;
+ mnCount=0;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::endPrimitive
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::endPrimitive()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ --mnBeginSceneCount;
+ meType=PRIMITIVE_TYPE_UNKNOWN;
+ mnCount=0;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::pushVertex
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ switch(meType)
+ {
+ case PRIMITIVE_TYPE_TRIANGLE:
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ mnCount &= 3;
+ break;
+ }
+
+ case PRIMITIVE_TYPE_QUAD:
+ {
+ if(mnCount == 3)
+ {
+ const std::size_t size(maVertexCache.size());
+ ::canvas::Vertex v0(maVertexCache[size-1]);
+ ::canvas::Vertex v2(maVertexCache[size-3]);
+ maVertexCache.push_back(v0);
+ maVertexCache.push_back(vertex);
+ maVertexCache.push_back(v2);
+ mnCount=0;
+ }
+ else
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE(false,
+ "DXRenderModule::pushVertex(): unexpected primitive type");
+ break;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::isError
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::isError()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ return mbError;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAdapterFromWindow
+ //////////////////////////////////////////////////////////////////////////////////
+
+ UINT DXRenderModule::getAdapterFromWindow()
+ {
+ HMONITOR hMonitor(aMonitorSupport.MonitorFromWindow(mhWnd));
+ UINT aAdapterCount(mpDirect3D9->GetAdapterCount());
+ for(UINT i=0; i<aAdapterCount; ++i)
+ if(hMonitor == mpDirect3D9->GetAdapterMonitor(i))
+ return i;
+ return static_cast<UINT>(-1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::commitVertexCache
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::commitVertexCache()
+ {
+ if(maReadIndex != maWriteIndex)
+ {
+ const std::size_t nVertexStride = sizeof(dxvertex);
+ const unsigned int nNumVertices = maWriteIndex-maReadIndex;
+ const unsigned int nNumPrimitives = nNumVertices / 3;
+
+ if(FAILED(mpDevice->SetStreamSource(0,mpVertexBuffer.get(),0,nVertexStride)))
+ return;
+
+ if(FAILED(mpDevice->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)))
+ return;
+
+ if(FAILED(mpDevice->BeginScene()))
+ return;
+
+ mbError |= FAILED(mpDevice->DrawPrimitive(D3DPT_TRIANGLELIST,maReadIndex,nNumPrimitives));
+ mbError |= FAILED(mpDevice->EndScene());
+
+ maReadIndex += nNumVertices;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flushVertexCache
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::flushVertexCache()
+ {
+ if(!(maVertexCache.size()))
+ return;
+
+ mbError=true;
+
+ if( FAILED(mpDevice->SetRenderState(D3DRS_LIGHTING,FALSE)))
+ return;
+
+ // enable texture alpha blending
+ if( FAILED(mpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE)))
+ return;
+
+ mpDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
+ mpDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
+ mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSU ,D3DTADDRESS_CLAMP );
+ mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSV ,D3DTADDRESS_CLAMP );
+
+ // configure the fixed-function pipeline.
+ // the only 'feature' we need here is to modulate the alpha-channels
+ // from the texture and the interpolated diffuse color. the result
+ // will then be blended with the backbuffer.
+ // fragment color = texture color * diffuse.alpha.
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
+
+ // normal combination of object...
+ if( FAILED(mpDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA)) )
+ return;
+
+ // ..and background color
+ if( FAILED(mpDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA)) )
+ return;
+
+ // disable backface culling; this enables us to mirror sprites
+ // by simply reverting the triangles, which, with enabled
+ // culling, would be invisible otherwise
+ if( FAILED(mpDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE)) )
+ return;
+
+ mbError=false;
+
+ std::size_t nSize(maVertexCache.size());
+ const std::size_t nVertexStride = sizeof(dxvertex);
+
+ const ::basegfx::B2IVector aPageSize(getPageSize());
+ const float nHalfPixelSizeX(0.5f/aPageSize.getX());
+ const float nHalfPixelSizeY(0.5f/aPageSize.getY());
+ vertexCache_t::const_iterator it(maVertexCache.begin());
+
+ while( nSize )
+ {
+ DWORD dwLockFlags(D3DLOCK_NOOVERWRITE);
+
+ // Check to see if there's space for the current set of
+ // vertices in the buffer.
+ if( maNumVertices - maWriteIndex < nSize )
+ {
+ commitVertexCache();
+ dwLockFlags = D3DLOCK_DISCARD;
+ maWriteIndex = 0;
+ maReadIndex = 0;
+ }
+
+ dxvertex *vertices(NULL);
+ const std::size_t nNumVertices(
+ std::min(maNumVertices - maWriteIndex,
+ nSize));
+ if(FAILED(mpVertexBuffer->Lock(maWriteIndex*nVertexStride,
+ nNumVertices*nVertexStride,
+ (void **)&vertices,
+ dwLockFlags)))
+ return;
+
+ std::size_t nIndex(0);
+ while( nIndex < nNumVertices )
+ {
+ dxvertex &dest = vertices[nIndex++];
+ dest.x=it->x;
+ dest.y=it->y;
+ dest.z=it->z;
+ dest.rhw=1;
+ const sal_uInt32 alpha(static_cast<sal_uInt32>(it->a*255.0f));
+ dest.diffuse=D3DCOLOR_ARGB(alpha,255,255,255);
+ dest.u=static_cast<float>(it->u + nHalfPixelSizeX);
+ dest.v=static_cast<float>(it->v + nHalfPixelSizeY);
+ ++it;
+ }
+
+ mpVertexBuffer->Unlock();
+
+ // Advance to the next position in the vertex buffer.
+ maWriteIndex += nNumVertices;
+ nSize -= nNumVertices;
+
+ commitVertexCache();
+ }
+
+ maVertexCache.clear();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // createRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent )
+ {
+ return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) );
+ }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_bitmap.cxx b/canvas/source/directx/dx_bitmap.cxx
new file mode 100644
index 000000000000..88ded9f61e32
--- /dev/null
+++ b/canvas/source/directx/dx_bitmap.cxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "dx_bitmap.hxx"
+#include "dx_graphicsprovider.hxx"
+#include "dx_impltools.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irange.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXBitmap::DXBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXBitmap::DXBitmap( const BitmapSharedPtr& rBitmap,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rBitmap->GetWidth(),rBitmap->GetHeight()),
+ mpBitmap(rBitmap),
+ mpGraphics(tools::createGraphicsFromBitmap(mpBitmap)),
+ mbAlpha(bWithAlpha)
+ {
+ }
+
+ DXBitmap::DXBitmap( const ::basegfx::B2IVector& rSize,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rSize),
+ mpBitmap(),
+ mpGraphics(),
+ mbAlpha(bWithAlpha)
+ {
+ // create container for pixel data
+ if(mbAlpha)
+ {
+ mpBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat32bppARGB));
+ }
+ else
+ {
+ mpBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat24bppRGB));
+ }
+
+ mpGraphics.reset( tools::createGraphicsFromBitmap(mpBitmap) );
+ }
+
+ BitmapSharedPtr DXBitmap::getBitmap() const
+ {
+ return mpBitmap;
+ }
+
+ GraphicsSharedPtr DXBitmap::getGraphics()
+ {
+ return mpGraphics;
+ }
+
+ ::basegfx::B2IVector DXBitmap::getSize() const
+ {
+ return maSize;
+ }
+
+ bool DXBitmap::hasAlpha() const
+ {
+ return mbAlpha;
+ }
+
+ uno::Sequence< sal_Int8 > DXBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
+
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = aRes.getArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ // read data from bitmap
+ if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO(F1): Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ mpBitmap->UnlockBits( &aBmpData );
+
+ return aRes;
+ }
+
+ void DXBitmap::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = (void*)data.getConstArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO: Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ // commit data to bitmap
+ mpBitmap->UnlockBits( &aBmpData );
+ }
+
+ void DXBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ if( Gdiplus::Ok != mpBitmap->SetPixel( pos.X, pos.Y,
+ Gdiplus::Color( tools::sequenceToArgb( color ))))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+
+ uno::Sequence< sal_Int8 > DXBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+ Gdiplus::Color aColor;
+
+ if( Gdiplus::Ok != mpBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
+ return uno::Sequence< sal_Int8 >();
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_bitmap.hxx b/canvas/source/directx/dx_bitmap.hxx
new file mode 100644
index 000000000000..338bcbb15d32
--- /dev/null
+++ b/canvas/source/directx/dx_bitmap.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_DXBITMAP_HXX
+#define _DXCANVAS_DXBITMAP_HXX
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "dx_winstuff.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_graphicsprovider.hxx"
+#include "dx_gdiplususer.hxx"
+
+namespace dxcanvas
+{
+ class DXBitmap : public IBitmap
+ {
+ public:
+ DXBitmap( const BitmapSharedPtr& rBitmap,
+ bool bWithAlpha );
+ DXBitmap( const ::basegfx::B2IVector& rSize,
+ bool bWithAlpha );
+
+ virtual GraphicsSharedPtr getGraphics();
+
+ virtual BitmapSharedPtr getBitmap() const;
+ virtual ::basegfx::B2IVector getSize() const;
+ virtual bool hasAlpha() const;
+
+ ::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 );
+
+ private:
+ // Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ // size of this image in pixels [integral unit]
+ ::basegfx::B2IVector maSize;
+
+ BitmapSharedPtr mpBitmap;
+ GraphicsSharedPtr mpGraphics;
+
+ // true if the bitmap contains an alpha channel
+ bool mbAlpha;
+ };
+
+ typedef ::boost::shared_ptr< DXBitmap > DXBitmapSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_bitmapcanvashelper.cxx b/canvas/source/directx/dx_bitmapcanvashelper.cxx
new file mode 100644
index 000000000000..c20c0ec06956
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapcanvashelper.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <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 <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ BitmapCanvasHelper::BitmapCanvasHelper() :
+ mpTarget()
+ {}
+
+ void BitmapCanvasHelper::disposing()
+ {
+ mpTarget.reset();
+ CanvasHelper::disposing();
+ }
+
+ void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "BitmapCanvasHelper::setTarget(): Invalid target" );
+ ENSURE_OR_THROW( !mpTarget.get(),
+ "BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpTarget = rTarget;
+ CanvasHelper::setTarget(rTarget);
+ }
+
+ void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "BitmapCanvasHelper::setTarget(): invalid target" );
+ ENSURE_OR_THROW( !mpTarget.get(),
+ "BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpTarget = rTarget;
+ CanvasHelper::setTarget(rTarget,rOutputOffset);
+ }
+
+ void BitmapCanvasHelper::clear()
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpTarget->getGraphics() );
+
+ Gdiplus::Color aClearColor = hasAlpha() ?
+ Gdiplus::Color( 0,255,255,255 ) : Gdiplus::Color((Gdiplus::ARGB)Gdiplus::Color::White);
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->SetCompositingMode(
+ Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
+ "BitmapCanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->Clear( aClearColor ),
+ "BitmapCanvasHelper::clear(): GDI+ Clear call failed" );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > BitmapCanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xLayoutetText.is(),
+ "BitmapCanvasHelper::drawTextLayout: layout is NULL");
+
+ if( needOutput() )
+ {
+ TextLayout* pTextLayout =
+ dynamic_cast< TextLayout* >( xLayoutetText.get() );
+
+ ENSURE_OR_THROW( pTextLayout,
+ "BitmapCanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+
+ pTextLayout->draw( mpTarget->getGraphics(),
+ viewState,
+ renderState,
+ maOutputOffset,
+ mpDevice,
+ mpTarget->hasAlpha() );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ void BitmapCanvasHelper::copyRect( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmapCanvas >& /*sourceCanvas*/,
+ const geometry::RealRectangle2D& /*sourceRect*/,
+ const rendering::ViewState& /*sourceViewState*/,
+ const rendering::RenderState& /*sourceRenderState*/,
+ const geometry::RealRectangle2D& /*destRect*/,
+ const rendering::ViewState& /*destViewState*/,
+ const rendering::RenderState& /*destRenderState*/ )
+ {
+ // TODO(F2): copyRect NYI
+ }
+
+ geometry::IntegerSize2D BitmapCanvasHelper::getSize()
+ {
+ if( !mpTarget )
+ return geometry::IntegerSize2D(1, 1);
+
+ return basegfx::unotools::integerSize2DFromB2ISize(mpTarget->getSize());
+ }
+
+ uno::Reference< rendering::XBitmap > BitmapCanvasHelper::getScaledBitmap( const geometry::RealSize2D& /*newSize*/,
+ sal_Bool /*beFast*/ )
+ {
+ // TODO(F1):
+ return uno::Reference< rendering::XBitmap >();
+ }
+
+ uno::Sequence< sal_Int8 > BitmapCanvasHelper::getData( rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::getData()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::getData(): disposed" );
+
+ if( !mpTarget )
+ return uno::Sequence< sal_Int8 >();
+
+ bitmapLayout = getMemoryLayout();
+ return mpTarget->getData(bitmapLayout,rect);
+ }
+
+ void BitmapCanvasHelper::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::setData()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::setData(): disposed" );
+
+ if( !mpTarget )
+ return;
+
+ mpTarget->setData(data,bitmapLayout,rect);
+ }
+
+ void BitmapCanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::setPixel()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::setPixel(): disposed" );
+
+ if( !mpTarget )
+ return;
+
+ mpTarget->setPixel(color,bitmapLayout,pos);
+ }
+
+ uno::Sequence< sal_Int8 > BitmapCanvasHelper::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::getPixel()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::getPixel(): disposed" );
+
+ if( !mpTarget )
+ return uno::Sequence< sal_Int8 >();
+
+ bitmapLayout = getMemoryLayout();
+ return mpTarget->getPixel(bitmapLayout,pos);
+ }
+
+ uno::Reference< rendering::XBitmapPalette > BitmapCanvasHelper::getPalette()
+ {
+ // TODO(F1): Palette bitmaps NYI
+ return uno::Reference< rendering::XBitmapPalette >();
+ }
+
+ rendering::IntegerBitmapLayout BitmapCanvasHelper::getMemoryLayout()
+ {
+ if( !mpTarget )
+ return rendering::IntegerBitmapLayout(); // we're disposed
+
+ return ::canvas::tools::getStdMemoryLayout(getSize());
+ }
+ bool BitmapCanvasHelper::hasAlpha() const
+ {
+ return mpTarget ? mpTarget->hasAlpha() : false;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_bitmapcanvashelper.hxx b/canvas/source/directx/dx_bitmapcanvashelper.hxx
new file mode 100644
index 000000000000..9cbbbbb54588
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapcanvashelper.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_BITMAPCANVASHELPER_HXX_
+#define _DXCANVAS_BITMAPCANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+#include "dx_canvashelper.hxx"
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ HDC to render into.
+ */
+ class BitmapCanvasHelper : public CanvasHelper
+ {
+ public:
+ BitmapCanvasHelper();
+
+ /// Release all references
+ void disposing();
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+ */
+ void setTarget( const IBitmapSharedPtr& rTarget );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+
+ @param rOutputOffset
+ Output offset in pixel
+ */
+ void setTarget( const IBitmapSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+
+ // CanvasHelper functionality is implementation-inherited. yuck.
+ // =============================================================
+ void clear();
+
+ ::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 );
+
+ // 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();
+
+ bool hasAlpha() const;
+
+ protected:
+ /// Render target
+ IBitmapSharedPtr mpTarget;
+ };
+}
+
+#endif /* _DXCANVAS_BITMAPCANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_bitmapprovider.hxx b/canvas/source/directx/dx_bitmapprovider.hxx
new file mode 100644
index 000000000000..2ba2aeb88a3f
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapprovider.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_BITMAPPROVIDER_HXX_
+#define _DXCANVAS_BITMAPPROVIDER_HXX_
+
+#include "dx_ibitmap.hxx"
+#include <boost/shared_ptr.hpp>
+
+namespace dxcanvas
+{
+ struct BitmapProvider
+ {
+ virtual ~BitmapProvider() {}
+ virtual IBitmapSharedPtr getBitmap() const = 0;
+ };
+
+ typedef boost::shared_ptr<BitmapProvider> BitmapProviderSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvas.cxx b/canvas/source/directx/dx_canvas.cxx
new file mode 100644
index 000000000000..f9505642be2c
--- /dev/null
+++ b/canvas/source/directx/dx_canvas.cxx
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#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/awt/XWindow.hpp>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#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 <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_winstuff.hxx"
+#include "dx_canvas.hxx"
+
+#include <vcl/sysdata.hxx>
+
+#define CANVAS_TECH "GDI+"
+#define CANVAS_SERVICE_NAME "com.sun.star.rendering.Canvas." CANVAS_TECH
+#define CANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.Canvas." CANVAS_TECH
+#define BITMAPCANVAS_SERVICE_NAME "com.sun.star.rendering.BitmapCanvas." CANVAS_TECH
+#define BITMAPCANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.BitmapCanvas." CANVAS_TECH
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ /// Actual canonical implementation of the GraphicsProvider interface
+ class GraphicsProviderImpl : public GraphicsProvider
+ {
+ GraphicsSharedPtr mpGraphics;
+ public:
+ explicit GraphicsProviderImpl( Gdiplus::Graphics* pGraphics ) : mpGraphics( pGraphics ) {}
+ virtual GraphicsSharedPtr getGraphics() { return mpGraphics; }
+ };
+
+ 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;
+
+ VERBOSE_TRACE( "Canvas::initialize called" );
+
+ // At index 1, we expect a HWND handle here, containing a
+ // pointer to a valid window, on which to output
+ // At index 2, we expect the current window bound rect
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
+ "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Sequence<sal_Int8> aSeq;
+ maArguments[5] >>= aSeq;
+
+ const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
+ if( !pSysData || !pSysData->hDC )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed SystemGraphicsData or HDC invalid!")),
+ NULL);
+
+ // setup helper
+ maDeviceHelper.init( pSysData->hDC,
+ *this );
+ maCanvasHelper.setDevice( *this );
+ maCanvasHelper.setTarget(
+ GraphicsProviderSharedPtr(
+ new GraphicsProviderImpl(
+ Gdiplus::Graphics::FromHDC(pSysData->hDC))));
+
+ maArguments.realloc(0);
+ }
+
+ 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 ) );
+ }
+
+ BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext ),
+ mpTarget()
+ {
+ }
+
+ void BitmapCanvas::initialize()
+ {
+ // #i64742# Only perform initialization when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "BitmapCanvas::initialize called" );
+
+ // At index 1, we expect a HWND handle here, containing a
+ // pointer to a valid window, on which to output
+ // At index 2, we expect the current window bound rect
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
+ "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Sequence<sal_Int8> aSeq;
+ maArguments[5] >>= aSeq;
+
+ const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
+ if( !pSysData || !pSysData->hDC )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed SystemGraphicsData or HDC invalid!")),
+ NULL);
+
+ // setup helper
+ maDeviceHelper.init( pSysData->hDC,
+ *this );
+ maCanvasHelper.setDevice( *this );
+
+ // check whether we can actually provide a BitmapCanvas
+ // here. for this, check whether the HDC has a bitmap
+ // selected.
+ HBITMAP hBmp;
+ hBmp=(HBITMAP)GetCurrentObject(pSysData->hDC, OBJ_BITMAP);
+ if( !hBmp || GetObjectType(pSysData->hDC) != OBJ_MEMDC )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed HDC is no mem DC/has no bitmap selected!")),
+ NULL);
+ }
+
+ mpTarget.reset( new DXBitmap(
+ BitmapSharedPtr(
+ Gdiplus::Bitmap::FromHBITMAP(
+ hBmp, 0) ),
+ false ));
+
+ maCanvasHelper.setTarget( mpTarget );
+
+ maArguments.realloc(0);
+ }
+
+ void SAL_CALL BitmapCanvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpTarget.reset();
+ mxComponentContext.clear();
+
+ // forward to parent
+ BitmapCanvasBaseT::disposing();
+ }
+
+ ::rtl::OUString SAL_CALL BitmapCanvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( BITMAPCANVAS_SERVICE_NAME ) );
+ }
+
+ IBitmapSharedPtr BitmapCanvas::getBitmap() const
+ {
+ return mpTarget;
+ }
+
+ 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 dxCanvasDecl(
+ serviceImpl1,
+ CANVAS_IMPLEMENTATION_NAME,
+ CANVAS_SERVICE_NAME );
+
+ static uno::Reference<uno::XInterface> initBitmapCanvas( BitmapCanvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_<BitmapCanvas, sdecl::with_args<true> > serviceImpl2(&initBitmapCanvas);
+ const sdecl::ServiceDecl dxBitmapCanvasDecl(
+ serviceImpl2,
+ BITMAPCANVAS_IMPLEMENTATION_NAME,
+ BITMAPCANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS2(dxcanvas::dxCanvasDecl,
+ dxcanvas::dxBitmapCanvasDecl);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvas.hxx b/canvas/source/directx/dx_canvas.hxx
new file mode 100644
index 000000000000..4f71939ab695
--- /dev/null
+++ b/canvas/source/directx/dx_canvas.hxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_CANVAS_HXX_
+#define _DXCANVAS_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/XServiceName.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.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 <cppuhelper/compbase6.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/graphicdevicebase.hxx>
+
+#include "dx_bitmapprovider.hxx"
+#include "dx_canvashelper.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_devicehelper.hxx"
+
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper6< ::com::sun::star::rendering::XCanvas,
+ ::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 > GraphicDeviceBase1_Base;
+ typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase1_Base >,
+ DeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBase1_Base;
+ typedef ::canvas::CanvasBase< CanvasBase1_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:
+ 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();
+
+ /// 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, GraphicDeviceBase1_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ 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;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ 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 > GraphicDeviceBase2_Base;
+ typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase2_Base >,
+ DeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBase2_Base;
+ typedef ::canvas::IntegerBitmapBase< CanvasBase2_Base,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > BitmapCanvasBaseT;
+
+ /** 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 BitmapCanvas : public BitmapCanvasBaseT, public BitmapProvider
+ {
+ public:
+ BitmapCanvas( 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();
+
+ /// 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( BitmapCanvas, GraphicDeviceBase2_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const;
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ IBitmapSharedPtr mpTarget;
+ };
+
+ typedef ::rtl::Reference< BitmapCanvas > BitmapCanvasRef;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvasbitmap.cxx b/canvas/source/directx/dx_canvasbitmap.cxx
new file mode 100644
index 000000000000..263fe9dad53d
--- /dev/null
+++ b/canvas/source/directx/dx_canvasbitmap.cxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/bitmapex.hxx>
+
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/scoped_array.hpp>
+
+#include "dx_canvasbitmap.hxx"
+#include "dx_impltools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
+ const DeviceRef& rDevice ) :
+ mpDevice( rDevice ),
+ mpBitmap( rBitmap )
+ {
+ ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
+ "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
+
+ maCanvasHelper.setDevice( *mpDevice.get() );
+ maCanvasHelper.setTarget( mpBitmap );
+ }
+
+ void SAL_CALL CanvasBitmap::disposing()
+ {
+ mpBitmap.reset();
+ mpDevice.clear();
+
+ // forward to parent
+ CanvasBitmap_Base::disposing();
+ }
+
+ struct AlphaDIB
+ {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[256];
+ };
+
+ uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
+ {
+ uno::Any aRes;
+ // 0 ... get BitmapEx
+ // 1 ... get Pixbuf with bitmap RGB content
+ // 2 ... get Pixbuf with bitmap alpha mask
+ switch( nHandle )
+ {
+ // sorry, no BitmapEx here...
+ case 0:
+ aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
+ break;
+
+ case 1:
+ {
+ if(!mpBitmap->hasAlpha())
+ {
+ HBITMAP aHBmp;
+ mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(aHBmp) );
+
+ aRes <<= args;
+ }
+ else
+ {
+ // need to copy&convert the bitmap, since dx
+ // canvas uses inline alpha channel
+ HDC hScreenDC=GetDC(NULL);
+ const basegfx::B2IVector aSize(mpBitmap->getSize());
+ HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
+ aSize.getX(),
+ aSize.getY() );
+ if( !hBmpBitmap )
+ return aRes;
+
+ BITMAPINFOHEADER aBIH;
+
+ aBIH.biSize = sizeof( BITMAPINFOHEADER );
+ aBIH.biWidth = aSize.getX();
+ aBIH.biHeight = -aSize.getY();
+ aBIH.biPlanes = 1;
+ aBIH.biBitCount = 32;
+ aBIH.biCompression = BI_RGB; // expects pixel in
+ // bbggrrxx format
+ // (little endian)
+ aBIH.biSizeImage = 0;
+ aBIH.biXPelsPerMeter = 0;
+ aBIH.biYPelsPerMeter = 0;
+ aBIH.biClrUsed = 0;
+ aBIH.biClrImportant = 0;
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = aSize.getX();
+ aBmpData.Height = aSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
+ BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
+ if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB, // outputs ARGB (big endian)
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return aRes;
+ }
+
+ // now aBmpData.Scan0 contains our bits - push
+ // them into HBITMAP, ignoring alpha
+ SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS );
+
+ pGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(hBmpBitmap) );
+
+ aRes <<= args;
+ }
+ }
+ break;
+
+ case 2:
+ {
+ if(!mpBitmap->hasAlpha())
+ {
+ return aRes;
+ }
+ else
+ {
+ static AlphaDIB aDIB=
+ {
+ {0,0,0,1,8,BI_RGB,0,0,0,0,0},
+ {
+ // this here fills palette with grey
+ // level colors, starting from 0,0,0
+ // up to 255,255,255
+#define BOOST_PP_LOCAL_MACRO(n_) \
+ BOOST_PP_COMMA_IF(n_) \
+ {n_,n_,n_,n_}
+#define BOOST_PP_LOCAL_LIMITS (0, 255)
+#include BOOST_PP_LOCAL_ITERATE()
+ }
+ };
+
+ // need to copy&convert the bitmap, since dx
+ // canvas uses inline alpha channel
+ HDC hScreenDC=GetDC(NULL);
+ const basegfx::B2IVector aSize(mpBitmap->getSize());
+ HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() );
+ if( !hBmpBitmap )
+ return aRes;
+
+ aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+ aDIB.bmiHeader.biWidth = aSize.getX();
+ aDIB.bmiHeader.biHeight = -aSize.getY();
+ aDIB.bmiHeader.biPlanes = 1;
+ aDIB.bmiHeader.biBitCount = 8;
+ aDIB.bmiHeader.biCompression = BI_RGB;
+ aDIB.bmiHeader.biSizeImage = 0;
+ aDIB.bmiHeader.biXPelsPerMeter = 0;
+ aDIB.bmiHeader.biYPelsPerMeter = 0;
+ aDIB.bmiHeader.biClrUsed = 0;
+ aDIB.bmiHeader.biClrImportant = 0;
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = aSize.getX();
+ aBmpData.Height = aSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
+ BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
+ if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB, // outputs ARGB (big endian)
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return aRes;
+ }
+
+ // copy only alpha channel to pAlphaBits
+ const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3);
+ boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] );
+ const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0;
+ pInBits+=3;
+ sal_uInt8* pOutBits;
+ for( sal_Int32 y=0; y<aSize.getY(); ++y )
+ {
+ pOutBits=pAlphaBits.get()+y*nScanWidth;
+ for( sal_Int32 x=0; x<aSize.getX(); ++x )
+ {
+ *pOutBits++ = 255-*pInBits;
+ pInBits += 4;
+ }
+ }
+
+ pGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ // set bits to newly create HBITMAP
+ SetDIBits( hScreenDC, hBmpBitmap, 0,
+ aSize.getY(), pAlphaBits.get(),
+ (PBITMAPINFO)&aDIB, DIB_RGB_COLORS );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(hBmpBitmap) );
+
+ aRes <<= args;
+ }
+ }
+ break;
+ }
+
+ return aRes;
+ }
+
+#define IMPLEMENTATION_NAME "DXCanvas.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;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvasbitmap.hxx b/canvas/source/directx/dx_canvasbitmap.hxx
new file mode 100644
index 000000000000..68cc4da062ff
--- /dev/null
+++ b/canvas/source/directx/dx_canvasbitmap.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_CANVASBITMAP_HXX
+#define _DXCANVAS_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 <basegfx/vector/b2isize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <cppuhelper/compbase3.hxx>
+#include <comphelper/uno3.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/integerbitmapbase.hxx>
+
+#include "dx_bitmapprovider.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_devicehelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_ibitmap.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace dxcanvas
+{
+ 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;
+ typedef ::canvas::IntegerBitmapBase< ::canvas::BaseMutexHelper< CanvasBitmapBase_Base >,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBitmap_Base;
+
+ class CanvasBitmap : public CanvasBitmap_Base, public BitmapProvider
+ {
+ public:
+ /** Create a canvas bitmap for the given surface
+
+ @param rSurface
+ Surface to create API object for.
+
+ @param rDevice
+ Reference device, with which bitmap should be compatible
+ */
+ CanvasBitmap( const IBitmapSharedPtr& rSurface,
+ const DeviceRef& rDevice );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // 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);
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const { return mpBitmap; }
+
+ 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:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ DeviceRef mpDevice;
+ IBitmapSharedPtr mpBitmap;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvascustomsprite.cxx b/canvas/source/directx/dx_canvascustomsprite.cxx
new file mode 100644
index 000000000000..df36fb3ac1c9
--- /dev/null
+++ b/canvas/source/directx/dx_canvascustomsprite.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#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 "dx_canvascustomsprite.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ bool bShowSpriteBounds ) :
+ mpSpriteCanvas( rRefDevice ),
+ mpSurface()
+ {
+ ENSURE_OR_THROW( rRefDevice.get(),
+ "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+ mpSurface.reset(
+ new DXSurfaceBitmap(
+ ::basegfx::B2IVector(
+ ::canvas::tools::roundUp( rSpriteSize.Width ),
+ ::canvas::tools::roundUp( rSpriteSize.Height )),
+ rSurfaceProxy,
+ rRenderModule,
+ true));
+
+ maCanvasHelper.setDevice( *rRefDevice.get() );
+ maCanvasHelper.setTarget( mpSurface );
+
+ maSpriteHelper.init( rSpriteSize,
+ rRefDevice,
+ rRenderModule,
+ mpSurface,
+ bShowSpriteBounds );
+
+ // clear sprite to 100% transparent
+ maCanvasHelper.clear();
+ }
+
+ void SAL_CALL CanvasCustomSprite::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpSurface.reset();
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteBaseT::disposing();
+ }
+
+#define IMPLEMENTATION_NAME "DXCanvas.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;
+ }
+
+ void CanvasCustomSprite::redraw() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maSpriteHelper.redraw( mbSurfaceDirty );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvascustomsprite.hxx b/canvas/source/directx/dx_canvascustomsprite.hxx
new file mode 100644
index 000000000000..016882ae2c7c
--- /dev/null
+++ b/canvas/source/directx/dx_canvascustomsprite.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_CANVASCUSTOMSPRITE_HXX
+#define _DXCANVAS_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 "dx_sprite.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_spritehelper.hxx"
+#include "dx_spritecanvas.hxx"
+
+
+namespace dxcanvas
+{
+ 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
+ {
+ };
+
+ typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
+ SpriteHelper,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasCustomSpriteBaseT;
+
+ /* Definition of CanvasCustomSprite class */
+
+ class CanvasCustomSprite : public CanvasCustomSpriteBaseT
+ {
+ public:
+ /** Create a custom sprite
+
+ @param rSpriteSize
+ Size of the sprite in pixel
+
+ @param rRefDevice
+ Associated output device
+
+ @param rSpriteCanvas
+ Target canvas
+
+ @param rDevice
+ Target DX device
+ */
+ CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ bool bShowSpriteBounds );
+
+ 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;
+
+ private:
+ /** MUST hold here, too, since BitmapCanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ SpriteCanvasRef mpSpriteCanvas;
+ DXSurfaceBitmapSharedPtr mpSurface;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASCUSTOMSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvasfont.cxx b/canvas/source/directx/dx_canvasfont.cxx
new file mode 100644
index 000000000000..e9c8b62629c7
--- /dev/null
+++ b/canvas/source/directx/dx_canvasfont.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include "dx_winstuff.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/PanoseWeight.hpp>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ INT calcFontStyle( const rendering::FontRequest& rFontRequest )
+ {
+ INT nFontStyle( Gdiplus::FontStyleRegular );
+
+ if( rFontRequest.FontDescription.FontDescription.Weight > rendering::PanoseWeight::BOOK )
+ nFontStyle = Gdiplus::FontStyleBold;
+
+ return nFontStyle;
+ }
+ }
+
+ CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
+ const uno::Sequence< beans::PropertyValue >& /*extraFontProperties*/,
+ const geometry::Matrix2D& fontMatrix ) :
+ CanvasFont_Base( m_aMutex ),
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ // TODO(F1): extraFontProperties, fontMatrix
+ mpFontFamily(),
+ mpFont(),
+ maFontRequest( rFontRequest ),
+ maFontMatrix( fontMatrix )
+ {
+ const sal_Int32 nLen(rFontRequest.FontDescription.FamilyName.getLength());
+ const sal_Unicode* pStr(rFontRequest.FontDescription.FamilyName.getStr());
+ std::vector< sal_Unicode > pStrBuf(nLen+1,0);
+ std::copy(pStr,pStr+nLen,&pStrBuf[0]);
+
+ mpFontFamily.reset( new Gdiplus::FontFamily(reinterpret_cast<LPCWSTR>(&pStrBuf[0]),NULL) );
+ if( !mpFontFamily->IsAvailable() )
+ mpFontFamily.reset( new Gdiplus::FontFamily(L"Arial",NULL) );
+
+ mpFont.reset( new Gdiplus::Font( mpFontFamily.get(),
+ static_cast<Gdiplus::REAL>(rFontRequest.CellSize),
+ calcFontStyle( rFontRequest ),
+ Gdiplus::UnitWorld ));
+ }
+
+ void SAL_CALL CanvasFont::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpFont.reset();
+ mpFontFamily.reset();
+ mpGdiPlusUser.reset();
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) );
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+ rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::FontMetrics();
+ }
+
+#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"
+#define IMPLEMENTATION_NAME "DXCanvas::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;
+ }
+
+ double CanvasFont::getCellAscent() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFontFamily->GetCellAscent(0); // TODO(F1): rFontRequest.styleName
+ }
+
+ double CanvasFont::getEmHeight() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFontFamily->GetEmHeight(0); // TODO(F1): rFontRequest.styleName
+ }
+
+ FontSharedPtr CanvasFont::getFont() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFont;
+ }
+
+ const ::com::sun::star::geometry::Matrix2D& CanvasFont::getFontMatrix() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maFontMatrix;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvasfont.hxx b/canvas/source/directx/dx_canvasfont.hxx
new file mode 100644
index 000000000000..3224d7893269
--- /dev/null
+++ b/canvas/source/directx/dx_canvasfont.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_CANVASFONT_HXX
+#define _DXCANVAS_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/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <rtl/ref.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+/* Definition of CanvasFont class */
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+
+ typedef ::boost::shared_ptr< Gdiplus::Font > FontSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::FontFamily > FontFamilySharedPtr;
+
+ 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 > ImplRef;
+
+ CanvasFont( const ::com::sun::star::rendering::FontRequest& fontRequest,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& extraFontProperties,
+ const ::com::sun::star::geometry::Matrix2D& fontMatrix );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XCanvasFont
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > SAL_CALL createTextLayout( const ::com::sun::star::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontRequest SAL_CALL getFontRequest( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontMetrics SAL_CALL getFontMetrics( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getAvailableSizes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // 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 );
+
+ double getCellAscent() const;
+ double getEmHeight() const;
+ FontSharedPtr getFont() const;
+ const ::com::sun::star::geometry::Matrix2D& getFontMatrix() const;
+
+ private:
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+ FontFamilySharedPtr mpFontFamily;
+ FontSharedPtr mpFont;
+ ::com::sun::star::rendering::FontRequest maFontRequest;
+ ::com::sun::star::geometry::Matrix2D maFontMatrix;
+ };
+
+}
+
+#endif /* _DXCANVAS_CANVASFONT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvashelper.cxx b/canvas/source/directx/dx_canvashelper.cxx
new file mode 100644
index 000000000000..1abf16ca4621
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper.cxx
@@ -0,0 +1,817 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <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 <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+#include "dx_vcltools.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_canvashelper.hxx"
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ Gdiplus::LineCap gdiCapFromCap( sal_Int8 nCapType )
+ {
+ switch( nCapType )
+ {
+ case rendering::PathCapType::BUTT:
+ return Gdiplus::LineCapFlat;
+
+ case rendering::PathCapType::ROUND:
+ return Gdiplus::LineCapRound;
+
+ case rendering::PathCapType::SQUARE:
+ return Gdiplus::LineCapSquare;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "gdiCapFromCap(): Unexpected cap type" );
+ }
+
+ return Gdiplus::LineCapFlat;
+ }
+
+ Gdiplus::LineJoin gdiJoinFromJoin( sal_Int8 nJoinType )
+ {
+ switch( nJoinType )
+ {
+ case rendering::PathJoinType::NONE:
+ OSL_ENSURE( false,
+ "gdiJoinFromJoin(): Join NONE not possible, mapping to MITER" );
+ // FALLTHROUGH intended
+ case rendering::PathJoinType::MITER:
+ return Gdiplus::LineJoinMiter;
+
+ case rendering::PathJoinType::ROUND:
+ return Gdiplus::LineJoinRound;
+
+ case rendering::PathJoinType::BEVEL:
+ return Gdiplus::LineJoinBevel;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "gdiJoinFromJoin(): Unexpected join type" );
+ }
+
+ return Gdiplus::LineJoinMiter;
+ }
+ }
+
+ CanvasHelper::CanvasHelper() :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ mpDevice( NULL ),
+ mpGraphicsProvider(),
+ maOutputOffset()
+ {
+ }
+
+ void CanvasHelper::disposing()
+ {
+ mpGraphicsProvider.reset();
+ mpDevice = NULL;
+ mpGdiPlusUser.reset();
+ }
+
+ void CanvasHelper::setDevice( rendering::XGraphicDevice& rDevice )
+ {
+ mpDevice = &rDevice;
+ }
+
+ void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "CanvasHelper::setTarget(): Invalid target" );
+ ENSURE_OR_THROW( !mpGraphicsProvider.get(),
+ "CanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpGraphicsProvider = rTarget;
+ }
+
+ void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "CanvasHelper::setTarget(): invalid target" );
+ ENSURE_OR_THROW( !mpGraphicsProvider.get(),
+ "CanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpGraphicsProvider = rTarget;
+ maOutputOffset = rOutputOffset;
+ }
+
+ void CanvasHelper::clear()
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+ Gdiplus::Color aClearColor = Gdiplus::Color((Gdiplus::ARGB)Gdiplus::Color::White);
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->SetCompositingMode(
+ Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
+ "CanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->Clear( aClearColor ),
+ "CanvasHelper::clear(): GDI+ Clear call failed" );
+ }
+ }
+
+ void CanvasHelper::drawPoint( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& aPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)) );
+
+ // determine size of one-by-one device pixel ellipse
+ Gdiplus::Matrix aMatrix;
+ pGraphics->GetTransform(&aMatrix);
+ aMatrix.Invert();
+ Gdiplus::PointF vector(1, 1);
+ aMatrix.TransformVectors(&vector);
+
+ // paint a one-by-one circle, with the given point
+ // in the middle (rounded to float)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->FillEllipse( &aBrush,
+ // disambiguate call
+ Gdiplus::REAL(aPoint.X),
+ Gdiplus::REAL(aPoint.Y),
+ Gdiplus::REAL(vector.X),
+ Gdiplus::REAL(vector.Y) ),
+ "CanvasHelper::drawPoint(): GDI+ call failed" );
+ }
+ }
+
+ void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& aStartPoint,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ Gdiplus::Status hr = pGraphics->DrawLine( &aPen,
+ Gdiplus::REAL(aStartPoint.X), // disambiguate call
+ Gdiplus::REAL(aStartPoint.Y),
+ Gdiplus::REAL(aEndPoint.X),
+ Gdiplus::REAL(aEndPoint.Y) );
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawLine(): GDI+ call failed" );
+ }
+ }
+
+ void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealBezierSegment2D& aBezierSegment,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ Gdiplus::Status hr = pGraphics->DrawBezier( &aPen,
+ Gdiplus::REAL(aBezierSegment.Px), // disambiguate call
+ Gdiplus::REAL(aBezierSegment.Py),
+ Gdiplus::REAL(aBezierSegment.C1x),
+ Gdiplus::REAL(aBezierSegment.C1y),
+ Gdiplus::REAL(aEndPoint.X),
+ Gdiplus::REAL(aEndPoint.Y),
+ Gdiplus::REAL(aBezierSegment.C2x),
+ Gdiplus::REAL(aBezierSegment.C2y) );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawBezier(): GDI+ call failed" );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::drawPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+
+ // TODO(E1): Return value
+ Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawPolyPolygon(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::StrokeAttributes& strokeAttributes )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::drawPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+
+ // Setup stroke pen
+ // ----------------
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ static_cast< Gdiplus::REAL >(strokeAttributes.StrokeWidth) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ const bool bIsMiter(rendering::PathJoinType::MITER == strokeAttributes.JoinType);
+ const bool bIsNone(rendering::PathJoinType::NONE == strokeAttributes.JoinType);
+
+ if(bIsMiter)
+ aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) );
+
+ const ::std::vector< Gdiplus::REAL >& rDashArray(
+ ::comphelper::sequenceToContainer< ::std::vector< Gdiplus::REAL > >(
+ strokeAttributes.DashArray ) );
+ if( !rDashArray.empty() )
+ {
+ aPen.SetDashPattern( &rDashArray[0],
+ rDashArray.size() );
+ }
+ aPen.SetLineCap( gdiCapFromCap(strokeAttributes.StartCapType),
+ gdiCapFromCap(strokeAttributes.EndCapType),
+ Gdiplus::DashCapFlat );
+ if(!bIsNone)
+ aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon, bIsNone ) );
+
+ // TODO(E1): Return value
+ Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::strokePolyPolygon(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ tools::sequenceToArgb(renderState.DeviceColor));
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+
+ // TODO(F1): FillRule
+ ENSURE_OR_THROW( Gdiplus::Ok == pGraphics->FillPath( &aBrush, pPath.get() ),
+ "CanvasHelper::fillPolyPolygon(): GDI+ call failed " );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontRequest& fontRequest,
+ const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+ const geometry::Matrix2D& fontMatrix )
+ {
+ if( needOutput() )
+ {
+ return uno::Reference< rendering::XCanvasFont >(
+ new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
+ }
+
+ return uno::Reference< rendering::XCanvasFont >();
+ }
+
+ uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontInfo& /*aFilter*/,
+ const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
+ {
+ // TODO
+ return uno::Sequence< rendering::FontInfo >();
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::StringContext& text,
+ const uno::Reference< rendering::XCanvasFont >& xFont,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ sal_Int8 /*textDirection*/ )
+ {
+ ENSURE_OR_THROW( xFont.is(),
+ "CanvasHelper::drawText: font is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)));
+
+ CanvasFont::ImplRef pFont(
+ tools::canvasFontFromXFont(xFont) );
+
+ // Move glyphs up, such that output happens at the font
+ // baseline.
+ Gdiplus::PointF aPoint( 0.0,
+ static_cast<Gdiplus::REAL>(-(pFont->getFont()->GetSize()*
+ pFont->getCellAscent() /
+ pFont->getEmHeight())) );
+
+ // TODO(F1): According to
+ // http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q307208,
+ // we might have to revert to GDI and ExTextOut here,
+ // since GDI+ takes the scalability a little bit too
+ // far...
+
+ // TODO(F2): Proper layout (BiDi, CTL)! IMHO must use
+ // DrawDriverString here, and perform layouting myself...
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->DrawString( reinterpret_cast<LPCWSTR>(
+ text.Text.copy( text.StartPosition,
+ text.Length ).getStr()),
+ text.Length,
+ pFont->getFont().get(),
+ aPoint,
+ &aBrush ),
+ "CanvasHelper::drawText(): GDI+ call failed" );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xLayoutetText.is(),
+ "CanvasHelper::drawTextLayout: layout is NULL");
+
+ if( needOutput() )
+ {
+ TextLayout* pTextLayout =
+ dynamic_cast< TextLayout* >( xLayoutetText.get() );
+
+ ENSURE_OR_THROW( pTextLayout,
+ "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+
+ pTextLayout->draw( mpGraphicsProvider->getGraphics(),
+ viewState,
+ renderState,
+ maOutputOffset,
+ mpDevice,
+ false );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xBitmap.is(),
+ "CanvasHelper::drawBitmap: bitmap is NULL");
+
+ if( needOutput() )
+ {
+ // check whether one of our own objects - need to retrieve
+ // bitmap _before_ calling
+ // GraphicsProvider::getGraphics(), to avoid locking our
+ // own surface.
+ BitmapSharedPtr pGdiBitmap;
+ BitmapProvider* pBitmap = dynamic_cast< BitmapProvider* >(xBitmap.get());
+ if( pBitmap )
+ {
+ IBitmapSharedPtr pDXBitmap( pBitmap->getBitmap() );
+ if( pDXBitmap )
+ pGdiBitmap = pDXBitmap->getBitmap();
+ }
+
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ if( pGdiBitmap )
+ tools::drawGdiPlusBitmap(pGraphics,pGdiBitmap);
+ else
+ tools::drawVCLBitmapFromXBitmap(pGraphics,
+ xBitmap);
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xBitmap.is(),
+ "CanvasHelper::drawBitmap: bitmap is NULL");
+
+ // no color set -> this is equivalent to a plain drawBitmap(), then
+ if( renderState.DeviceColor.getLength() < 3 )
+ return drawBitmap( pCanvas, xBitmap, viewState, renderState );
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ BitmapSharedPtr pBitmap( tools::bitmapFromXBitmap( xBitmap ) );
+ Gdiplus::Rect aRect( 0, 0,
+ pBitmap->GetWidth(),
+ pBitmap->GetHeight() );
+
+ // Setup an ImageAttributes with an alpha-modulating
+ // color matrix.
+ const rendering::ARGBColor& rARGBColor(
+ mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0]);
+
+ Gdiplus::ImageAttributes aImgAttr;
+ tools::setModulateImageAttributes( aImgAttr,
+ rARGBColor.Red,
+ rARGBColor.Green,
+ rARGBColor.Blue,
+ rARGBColor.Alpha );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->DrawImage( pBitmap.get(),
+ aRect,
+ 0, 0,
+ pBitmap->GetWidth(),
+ pBitmap->GetHeight(),
+ Gdiplus::UnitPixel,
+ &aImgAttr,
+ NULL,
+ NULL ),
+ "CanvasHelper::drawBitmapModulated(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+ {
+ return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+ }
+
+ // private helper
+ // --------------------------------------------------
+
+ Gdiplus::CompositingMode CanvasHelper::calcCompositingMode( sal_Int8 nMode )
+ {
+ Gdiplus::CompositingMode aRet( Gdiplus::CompositingModeSourceOver );
+
+ switch( nMode )
+ {
+ case rendering::CompositeOperation::OVER:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::CLEAR:
+ aRet = Gdiplus::CompositingModeSourceOver;
+ break;
+
+ case rendering::CompositeOperation::SOURCE:
+ aRet = Gdiplus::CompositingModeSourceCopy;
+ break;
+
+ case rendering::CompositeOperation::DESTINATION:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::UNDER:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::INSIDE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::INSIDE_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::OUTSIDE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::OUTSIDE_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ATOP:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ATOP_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::XOR:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ADD:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::SATURATE:
+ // TODO(F2): Problem, because GDI+ only knows about two compositing modes
+ aRet = Gdiplus::CompositingModeSourceOver;
+ break;
+
+ default:
+ ENSURE_OR_THROW( false, "CanvasHelper::calcCompositingMode: unexpected mode" );
+ break;
+ }
+
+ return aRet;
+ }
+
+ void CanvasHelper::setupGraphicsState( GraphicsSharedPtr& rGraphics,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( needOutput(),
+ "CanvasHelper::setupGraphicsState: primary graphics invalid" );
+ ENSURE_OR_THROW( mpDevice,
+ "CanvasHelper::setupGraphicsState: reference device invalid" );
+
+ // setup view transform first. Clipping e.g. depends on it
+ ::basegfx::B2DHomMatrix aTransform;
+ ::canvas::tools::getViewStateTransform(aTransform, viewState);
+
+ // add output offset
+ if( !maOutputOffset.equalZero() )
+ {
+ const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix(
+ maOutputOffset.getX(), maOutputOffset.getY()));
+ aTransform = aOutputOffset * aTransform;
+ }
+
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
+ "CanvasHelper::setupGraphicsState(): Failed to set GDI+ transformation" );
+
+ // setup view and render state clipping
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->ResetClip(),
+ "CanvasHelper::setupGraphicsState(): Failed to reset GDI+ clip" );
+
+ if( viewState.Clip.is() )
+ {
+ GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( viewState.Clip ) );
+
+ // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
+ // Try SetClip( Rect ) or similar for simple clip paths (need some support in
+ // LinePolyPolygon, then)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
+ Gdiplus::CombineModeIntersect ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
+ }
+
+ // setup overall transform only now. View clip above was relative to
+ // view transform
+ ::canvas::tools::mergeViewAndRenderTransform(aTransform,
+ viewState,
+ renderState);
+
+ // add output offset
+ if( !maOutputOffset.equalZero() )
+ {
+ const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix(
+ maOutputOffset.getX(), maOutputOffset.getY()));
+ aTransform = aOutputOffset * aTransform;
+ }
+
+ tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ transformation" );
+
+ if( renderState.Clip.is() )
+ {
+ GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( renderState.Clip ) );
+
+ // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
+ // Try SetClip( Rect ) or similar for simple clip paths (need some support in
+ // LinePolyPolygon, then)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
+ Gdiplus::CombineModeIntersect ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
+ }
+
+ // setup compositing
+ const Gdiplus::CompositingMode eCompositing( calcCompositingMode( renderState.CompositeOperation ) );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" );
+ }
+
+ void CanvasHelper::flush() const
+ {
+ if( needOutput() )
+ mpGraphicsProvider->getGraphics()->Flush( Gdiplus::FlushIntentionSync );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvashelper.hxx b/canvas/source/directx/dx_canvashelper.hxx
new file mode 100644
index 000000000000..ae590ef67fa6
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper.hxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_CANVASHELPER_HXX_
+#define _DXCANVAS_CANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ HDC to render into.
+ */
+ 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 output objects. Note that
+ the CanvasHelper does <em>not</em> take ownership of the
+ passed rDevice reference, nor does it perform any
+ reference counting. Thus, to prevent the reference counted
+ SpriteCanvas object from deletion, the user of this class
+ is responsible for holding ref-counted references itself!
+
+ @param rDevice
+ Reference device this canvas is associated with
+
+ */
+ void setDevice( com::sun::star::rendering::XGraphicDevice& rDevice );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+ */
+ void setTarget( const GraphicsProviderSharedPtr& rTarget );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+
+ @param rOutputOffset
+ Output offset in pixel
+ */
+ void setTarget( const GraphicsProviderSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+
+ // 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();
+
+ // Flush drawing queue to screen
+ void flush() const;
+
+ /** Called from XCanvas base classes, to notify that content
+ is _about_ to change
+ */
+ void modifying() {}
+
+ protected:
+ /// Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for spritecanvas.
+ */
+ com::sun::star::rendering::XGraphicDevice* mpDevice;
+
+ /// Provides the Gdiplus::Graphics to render into
+ GraphicsProviderSharedPtr mpGraphicsProvider;
+
+ bool needOutput() const { return mpGraphicsProvider.get() != NULL; };
+
+ // returns transparency of color
+ void setupGraphicsState( GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ Gdiplus::CompositingMode calcCompositingMode( sal_Int8 nMode );
+
+ /// Current (transformation-independent) output buffer offset
+ ::basegfx::B2ISize maOutputOffset;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx
new file mode 100644
index 000000000000..2b7ad6fd6d22
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx
@@ -0,0 +1,630 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/math.hxx>
+
+#include <com/sun/star/rendering/TexturingMode.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/tools/lerp.hxx>
+#include <basegfx/tools/keystoplerp.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <canvas/parametricpolypolygon.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_canvashelper.hxx"
+#include "dx_impltools.hxx"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ typedef ::boost::shared_ptr< Gdiplus::PathGradientBrush > PathGradientBrushSharedPtr;
+
+ bool fillLinearGradient( GraphicsSharedPtr& rGraphics,
+ const ::canvas::ParametricPolyPolygon::Values& /*rValues*/,
+ const std::vector< Gdiplus::Color >& rColors,
+ const std::vector< Gdiplus::REAL >& rStops,
+ const GraphicsPathSharedPtr& rFillPath,
+ const rendering::Texture& texture )
+ {
+ // setup a linear gradient with given colors
+ // -----------------------------------------
+
+ Gdiplus::LinearGradientBrush aBrush(
+ Gdiplus::PointF(0.0f,
+ 0.5f),
+ Gdiplus::PointF(1.0f,
+ 0.5f),
+ rColors[0],
+ rColors[1] );
+
+ aBrush.SetInterpolationColors(&rColors[0],
+ &rStops[0],
+ rColors.size());
+
+ // render background color, as LinearGradientBrush does not
+ // properly support the WrapModeClamp repeat mode
+ Gdiplus::SolidBrush aBackgroundBrush( rColors[0] );
+ rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() );
+
+ // TODO(F2): This does not yet support other repeat modes
+ // except clamp, and probably also no multi-texturing
+
+ // calculate parallelogram of gradient in object space, extend
+ // top and bottom of it such that they cover the whole fill
+ // path bound area
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+ texture.AffineTransform );
+
+ ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
+ ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
+ ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
+ ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
+
+ aLeftTop *= aTextureTransform;
+ aLeftBottom *= aTextureTransform;
+ aRightTop *= aTextureTransform;
+ aRightBottom*= aTextureTransform;
+
+ Gdiplus::RectF aBounds;
+ rFillPath->GetBounds( &aBounds, NULL, NULL );
+
+ // now, we potentially have to enlarge our gradient area
+ // atop and below the transformed [0,1]x[0,1] unit rect,
+ // for the gradient to fill the complete bound rect.
+ ::basegfx::tools::infiniteLineFromParallelogram( aLeftTop,
+ aLeftBottom,
+ aRightTop,
+ aRightBottom,
+ tools::b2dRangeFromGdiPlusRectF( aBounds ) );
+
+ // calc length of bound rect diagonal
+ const double nDiagonalLength(
+ hypot( aBounds.Width,
+ aBounds.Height ) );
+
+ // generate a path which covers the 'right' side of the
+ // gradient, extending two times the bound rect diagonal to
+ // the right (and thus covering the whole half plane 'right'
+ // of the gradient). Take the middle of the gradient as the
+ // 'left' side of the polygon, to not fall victim to rounding
+ // errors at the edge.
+ ::basegfx::B2DVector aDirection( aLeftTop - aLeftBottom );
+ aDirection = ::basegfx::getNormalizedPerpendicular( aDirection );
+ aDirection *= nDiagonalLength;
+
+ const ::basegfx::B2DPoint aHalfPlaneLeftTop( (aLeftTop + aRightTop) * 0.5 );
+ const ::basegfx::B2DPoint aHalfPlaneLeftBottom( (aLeftBottom + aRightBottom) * 0.5 );
+ const ::basegfx::B2DPoint aHalfPlaneRightTop( aRightTop + aDirection );
+ const ::basegfx::B2DPoint aHalfPlaneRightBottom( aRightBottom + aDirection );
+
+ Gdiplus::GraphicsPath aSolidFillPath;
+ aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getY()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getY()) );
+ aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getY()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getY()) );
+ aSolidFillPath.CloseFigure();
+
+ // limit output to fill path, we've just generated a path that
+ // might be substantially larger
+ if( Gdiplus::Ok != rGraphics->SetClip( rFillPath.get(),
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ Gdiplus::SolidBrush aBackgroundBrush2( rColors.back() );
+ rGraphics->FillPath( &aBackgroundBrush2, &aSolidFillPath );
+
+ // generate clip polygon from the extended parallelogram
+ // (exploit the feature that distinct lines in a figure are
+ // automatically closed by a straight line)
+ Gdiplus::GraphicsPath aClipPath;
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aLeftTop.getX()),
+ static_cast<Gdiplus::REAL>(aLeftTop.getY()),
+ static_cast<Gdiplus::REAL>(aRightTop.getX()),
+ static_cast<Gdiplus::REAL>(aRightTop.getY()) );
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aRightBottom.getX()),
+ static_cast<Gdiplus::REAL>(aRightBottom.getY()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getX()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getY()) );
+ aClipPath.CloseFigure();
+
+ // limit output to a _single_ strip of the gradient (have to
+ // clip here, since GDI+ wrapmode clamp does not work here)
+ if( Gdiplus::Ok != rGraphics->SetClip( &aClipPath,
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ // now, finally, output the gradient
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
+ texture.AffineTransform );
+ aBrush.SetTransform( &aMatrix );
+
+ rGraphics->FillRectangle( &aBrush, aBounds );
+
+ return true;
+ }
+
+ int numColorSteps( const Gdiplus::Color& rColor1, const Gdiplus::Color& rColor2 )
+ {
+ return ::std::max(
+ labs( rColor1.GetRed() - rColor2.GetRed() ),
+ ::std::max(
+ labs( rColor1.GetGreen() - rColor2.GetGreen() ),
+ labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) );
+ }
+
+ bool fillPolygonalGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< Gdiplus::Color >& rColors,
+ const std::vector< Gdiplus::REAL >& rStops,
+ GraphicsSharedPtr& rGraphics,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::Texture& texture )
+ {
+ // copy original fill path object, might have to change it
+ // below
+ GraphicsPathSharedPtr pFillPath( rPath );
+ const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
+
+ PathGradientBrushSharedPtr pGradientBrush;
+
+ // fill background uniformly with end color
+ Gdiplus::SolidBrush aBackgroundBrush( rColors[0] );
+ rGraphics->FillPath( &aBackgroundBrush, pFillPath.get() );
+
+ // scale focus according to aspect ratio: for wider-than-tall
+ // bounds (nAspectRatio > 1.0), the focus must have non-zero
+ // width. Specifically, a bound rect twice as wide as tall has
+ // a focus of half it's width.
+ if( !::rtl::math::approxEqual(rValues.mnAspectRatio,
+ 1.0) )
+ {
+ // KLUDGE 1:
+ //
+ // And here comes the greatest shortcoming of the GDI+
+ // gradients ever: SetFocusScales completely ignores
+ // transformations, both when set at the PathGradientBrush
+ // and for the world coordinate system. Thus, to correctly
+ // display anisotrophic path gradients, we have to render
+ // them by hand. WTF.
+
+ // TODO(F2): This does not yet support other repeat modes
+ // except clamp, and probably also no multi-texturing
+
+ // limit output to to-be-filled polygon
+ if( Gdiplus::Ok != rGraphics->SetClip( pFillPath.get(),
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ // disable anti-aliasing, if any
+ const Gdiplus::SmoothingMode eOldAAMode( rGraphics->GetSmoothingMode() );
+ rGraphics->SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed );
+
+
+ // determine number of steps to use
+ // --------------------------------
+
+ // TODO(Q2): Unify step calculations with VCL canvas
+ int nColorSteps = 0;
+ for( size_t i=0; i<rColors.size()-1; ++i )
+ nColorSteps += numColorSteps(rColors[i],rColors[i+1]);
+ ::basegfx::B2DHomMatrix aTotalTransform;
+ const int nStepCount=
+ ::canvas::tools::calcGradientStepCount(aTotalTransform,
+ viewState,
+ renderState,
+ texture,
+ nColorSteps);
+
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+ texture.AffineTransform );
+ // determine overall transformation for inner polygon (might
+ // have to be prefixed by anisotrophic scaling)
+ ::basegfx::B2DHomMatrix aInnerPolygonTransformMatrix;
+
+ // For performance reasons, we create a temporary VCL polygon
+ // here, keep it all the way and only change the vertex values
+ // in the loop below (as ::Polygon is a pimpl class, creating
+ // one every loop turn would really stress the mem allocator)
+ ::basegfx::B2DPolygon aOuterPoly( rGradientPoly );
+ ::basegfx::B2DPolygon aInnerPoly;
+
+ // subdivide polygon _before_ rendering, would otherwise have
+ // to be performed on every loop turn.
+ if( aOuterPoly.areControlPointsUsed() )
+ aOuterPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aOuterPoly);
+
+ aInnerPoly = aOuterPoly;
+ aOuterPoly.transform(aTextureTransform);
+
+
+ // apply scaling (possibly anisotrophic) to inner polygon
+ // ------------------------------------------------------
+
+ // scale inner polygon according to aspect ratio: for
+ // wider-than-tall bounds (nAspectRatio > 1.0), the inner
+ // polygon, representing the gradient focus, must have
+ // non-zero width. Specifically, a bound rect twice as wide as
+ // tall has a focus polygon of half it's width.
+ const double nAspectRatio( rValues.mnAspectRatio );
+ if( nAspectRatio > 1.0 )
+ {
+ // width > height case
+ aInnerPolygonTransformMatrix.scale( 1.0 - 1.0/nAspectRatio,
+ 0.0 );
+ }
+ else if( nAspectRatio < 1.0 )
+ {
+ // width < height case
+ aInnerPolygonTransformMatrix.scale( 0.0,
+ 1.0 - nAspectRatio );
+ }
+ else
+ {
+ // isotrophic case
+ aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
+ }
+
+ // and finally, add texture transform to it.
+ aInnerPolygonTransformMatrix *= aTextureTransform;
+
+ // apply final matrix to polygon
+ aInnerPoly.transform( aInnerPolygonTransformMatrix );
+
+ Gdiplus::GraphicsPath aCurrPath;
+ Gdiplus::SolidBrush aFillBrush( rColors[0] );
+ const sal_uInt32 nNumPoints( aOuterPoly.count() );
+ basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
+ for( int i=1; i<nStepCount; ++i )
+ {
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ const double fT( i/double(nStepCount) );
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
+ const Gdiplus::Color aFillColor(
+ static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha) ),
+ static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha) ),
+ static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha) ) );
+
+ aFillBrush.SetColor( aFillColor );
+ aCurrPath.Reset(); aCurrPath.StartFigure();
+ for( unsigned int p=1; p<nNumPoints; ++p )
+ {
+ const ::basegfx::B2DPoint& rOuterPoint1( aOuterPoly.getB2DPoint(p-1) );
+ const ::basegfx::B2DPoint& rInnerPoint1( aInnerPoly.getB2DPoint(p-1) );
+ const ::basegfx::B2DPoint& rOuterPoint2( aOuterPoly.getB2DPoint(p) );
+ const ::basegfx::B2DPoint& rInnerPoint2( aInnerPoly.getB2DPoint(p) );
+
+ aCurrPath.AddLine(
+ Gdiplus::REAL(fT*rInnerPoint1.getX() + (1-fT)*rOuterPoint1.getX()),
+ Gdiplus::REAL(fT*rInnerPoint1.getY() + (1-fT)*rOuterPoint1.getY()),
+ Gdiplus::REAL(fT*rInnerPoint2.getX() + (1-fT)*rOuterPoint2.getX()),
+ Gdiplus::REAL(fT*rInnerPoint2.getY() + (1-fT)*rOuterPoint2.getY()));
+ }
+ aCurrPath.CloseFigure();
+
+ rGraphics->FillPath( &aFillBrush, &aCurrPath );
+ }
+
+ // reset to old anti-alias mode
+ rGraphics->SetSmoothingMode( eOldAAMode );
+ }
+ else
+ {
+ // KLUDGE 2:
+ //
+ // We're generating a PathGradientBrush from scratch here,
+ // and put in a transformed GraphicsPath (transformed with
+ // the texture transform). This is because the
+ // straight-forward approach to store a Brush pointer at
+ // this class and set a texture transform via
+ // PathGradientBrush::SetTransform() is spoiled by MS: it
+ // seems that _either_ the texture transform, _or_ the
+ // transform at the Graphics can be set, but not both. If
+ // one sets both, only the translational components of the
+ // texture is respected.
+
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
+ texture.AffineTransform );
+ GraphicsPathSharedPtr pGradientPath(
+ tools::graphicsPathFromB2DPolygon( rValues.maGradientPoly ));
+ pGradientPath->Transform( &aMatrix );
+
+ pGradientBrush.reset(
+ new Gdiplus::PathGradientBrush( pGradientPath.get() ) );
+ pGradientBrush->SetInterpolationColors( &rColors[0],
+ &rStops[0],
+ rStops.size() );
+
+ // explicitely setup center point. Since the center of GDI+
+ // gradients are by default the _centroid_ of the path
+ // (i.e. the weighted sum of edge points), it will not
+ // necessarily coincide with our notion of center.
+ Gdiplus::PointF aCenterPoint(0, 0);
+ aMatrix.TransformPoints( &aCenterPoint );
+ pGradientBrush->SetCenterPoint( aCenterPoint );
+
+ const bool bTileX( texture.RepeatModeX != rendering::TexturingMode::CLAMP );
+ const bool bTileY( texture.RepeatModeY != rendering::TexturingMode::CLAMP );
+
+ if( bTileX && bTileY )
+ pGradientBrush->SetWrapMode( Gdiplus::WrapModeTile );
+ else
+ {
+ OSL_ENSURE( bTileY == bTileX,
+ "ParametricPolyPolygon::fillPolygonalGradient(): Cannot have repeat x and repeat y differ!" );
+
+ pGradientBrush->SetWrapMode( Gdiplus::WrapModeClamp );
+ }
+
+ // render actual gradient
+ rGraphics->FillPath( pGradientBrush.get(), pFillPath.get() );
+ }
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ rGraphics->MultiplyTransform( &aMatrix );
+
+ Gdiplus::Pen aPen( Gdiplus::Color( 255, 255, 0, 0 ),
+ 0.0001f );
+
+ rGraphics->DrawRectangle( &aPen,
+ Gdiplus::RectF( 0.0f, 0.0f,
+ 1.0f, 1.0f ) );
+#endif
+
+ return true;
+ }
+
+ bool fillGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< Gdiplus::Color >& rColors,
+ const std::vector< Gdiplus::REAL >& rStops,
+ GraphicsSharedPtr& rGraphics,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::Texture& texture )
+ {
+ switch( rValues.meType )
+ {
+ case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
+ fillLinearGradient( rGraphics,
+ rValues,
+ rColors,
+ rStops,
+ rPath,
+ texture );
+ break;
+
+ case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
+ // FALLTHROUGH intended
+ case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
+ fillPolygonalGradient( rValues,
+ rColors,
+ rStops,
+ rGraphics,
+ rPath,
+ viewState,
+ renderState,
+ texture );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "CanvasHelper::fillGradient(): Unexpected case" );
+ }
+
+ return true;
+ }
+
+ void fillBitmap( const uno::Reference< rendering::XBitmap >& xBitmap,
+ GraphicsSharedPtr& rGraphics,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::Texture& rTexture )
+ {
+ OSL_ENSURE( rTexture.RepeatModeX ==
+ rTexture.RepeatModeY,
+ "CanvasHelper::fillBitmap(): GDI+ cannot handle differing X/Y repeat mode." );
+
+ const bool bClamp( rTexture.RepeatModeX == rendering::TexturingMode::NONE &&
+ rTexture.RepeatModeY == rendering::TexturingMode::NONE );
+
+ const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
+ ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 &&
+ aBmpSize.Height != 0,
+ "CanvasHelper::fillBitmap(): zero-sized texture bitmap" );
+
+ // TODO(P3): Detect case that path is rectangle and
+ // bitmap is just scaled into that. Then, we can
+ // render directly, without generating a temporary
+ // GDI+ bitmap (this is significant, because drawing
+ // layer presents background object bitmap in that
+ // way!)
+ BitmapSharedPtr pBitmap(
+ tools::bitmapFromXBitmap( xBitmap ) );
+
+ TextureBrushSharedPtr pBrush;
+ if( ::rtl::math::approxEqual( rTexture.Alpha,
+ 1.0 ) )
+ {
+ pBrush.reset(
+ new Gdiplus::TextureBrush(
+ pBitmap.get(),
+ bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile ) );
+ }
+ else
+ {
+ Gdiplus::ImageAttributes aImgAttr;
+
+ tools::setModulateImageAttributes( aImgAttr,
+ 1.0,
+ 1.0,
+ 1.0,
+ rTexture.Alpha );
+
+ Gdiplus::Rect aRect(0,0,
+ aBmpSize.Width,
+ aBmpSize.Height);
+ pBrush.reset(
+ new Gdiplus::TextureBrush(
+ pBitmap.get(),
+ aRect,
+ &aImgAttr ) );
+
+ pBrush->SetWrapMode(
+ bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile );
+ }
+
+ Gdiplus::Matrix aTextureTransform;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aTextureTransform,
+ rTexture.AffineTransform );
+
+ // scale down bitmap to [0,1]x[0,1] rect, as required
+ // from the XCanvas interface.
+ pBrush->MultiplyTransform( &aTextureTransform );
+ pBrush->ScaleTransform( static_cast< Gdiplus::REAL >(1.0/aBmpSize.Width),
+ static_cast< Gdiplus::REAL >(1.0/aBmpSize.Height) );
+
+ // TODO(F1): FillRule
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->FillPath( pBrush.get(),
+ rPath.get() ),
+ "CanvasHelper::fillTexturedPolyPolygon(): GDI+ call failed" );
+ }
+ }
+
+ // -------------------------------------------------------------
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Sequence< rendering::Texture >& textures )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillTexturedPolyPolygon: polygon is NULL");
+ ENSURE_OR_THROW( textures.getLength(),
+ "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ // TODO(F1): Multi-texturing
+ if( textures[0].Gradient.is() )
+ {
+ // try to cast XParametricPolyPolygon2D reference to
+ // our implementation class.
+ ::canvas::ParametricPolyPolygon* pGradient =
+ dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
+
+ if( pGradient )
+ {
+ const ::canvas::ParametricPolyPolygon::Values& rValues(
+ pGradient->getValues() );
+
+ OSL_ASSERT(rValues.maColors.getLength() == rValues.maStops.getLength()
+ && rValues.maColors.getLength() > 1);
+
+ std::vector< Gdiplus::Color > aColors(rValues.maColors.getLength());
+ std::transform(&rValues.maColors[0],
+ &rValues.maColors[0]+rValues.maColors.getLength(),
+ aColors.begin(),
+ boost::bind(
+ (Gdiplus::ARGB (*)( const uno::Sequence< double >& ))(
+ &tools::sequenceToArgb),
+ _1));
+ std::vector< Gdiplus::REAL > aStops;
+ comphelper::sequenceToContainer(aStops,rValues.maStops);
+
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ fillGradient( rValues,
+ aColors,
+ aStops,
+ pGraphics,
+ tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
+ viewState,
+ renderState,
+ textures[0] );
+ }
+ }
+ else if( textures[0].Bitmap.is() )
+ {
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ fillBitmap( textures[0].Bitmap,
+ pGraphics,
+ tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
+ textures[0] );
+ }
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_config.cxx b/canvas/source/directx/dx_config.cxx
new file mode 100644
index 000000000000..154673f6b449
--- /dev/null
+++ b/canvas/source/directx/dx_config.cxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "dx_config.hxx"
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <comphelper/anytostring.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace com::sun::star;
+
+namespace dxcanvas
+{
+ DXCanvasItem::DXCanvasItem() :
+ ConfigItem(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "Office.Canvas/DXCanvas" )),
+ CONFIG_MODE_IMMEDIATE_UPDATE ),
+ maValues(),
+ maMaxTextureSize(),
+ mbBlacklistCurrentDevice(false),
+ mbValuesDirty(false)
+ {
+ try
+ {
+ uno::Sequence< ::rtl::OUString > aName(1);
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DeviceBlacklist" ));
+
+ uno::Sequence< uno::Any > aProps( GetProperties( aName ));
+ uno::Sequence< sal_Int32 > aValues;
+
+ if( aProps.getLength() > 0 &&
+ (aProps[0] >>= aValues) )
+ {
+ const sal_Int32* pValues = aValues.getConstArray();
+ const sal_Int32 nNumEntries( aValues.getLength()*sizeof(sal_Int32)/sizeof(DeviceInfo) );
+ for( sal_Int32 i=0; i<nNumEntries; ++i )
+ {
+ DeviceInfo aInfo;
+ aInfo.nVendorId = *pValues++;
+ aInfo.nDeviceId = *pValues++;
+ aInfo.nDeviceSubSysId = *pValues++;
+ aInfo.nDeviceRevision = *pValues++;
+ aInfo.nDriverId = *pValues++;
+ aInfo.nDriverVersion = *pValues++;
+ aInfo.nDriverSubVersion = *pValues++;
+ aInfo.nDriverBuildId = *pValues++;
+ maValues.insert(aInfo);
+ }
+ }
+
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlacklistCurrentDevice" ));
+ aProps = GetProperties( aName );
+ if( aProps.getLength() > 0 )
+ aProps[0] >>= mbBlacklistCurrentDevice;
+
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxTextureSize" ));
+ aProps = GetProperties( aName );
+ if( aProps.getLength() > 0 )
+ maMaxTextureSize.reset( aProps[0].get<sal_Int32>() );
+ else
+ maMaxTextureSize.reset();
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ DXCanvasItem::~DXCanvasItem()
+ {
+ if( !mbValuesDirty )
+ return;
+
+ try
+ {
+ uno::Sequence< ::rtl::OUString > aName(1);
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DeviceBlacklist" ));
+
+ uno::Sequence< sal_Int32 > aValues( sizeof(DeviceInfo)/sizeof(sal_Int32)*maValues.size() );
+
+ sal_Int32* pValues = aValues.getArray();
+ ValueSet::const_iterator aIter( maValues.begin() );
+ const ValueSet::const_iterator aEnd( maValues.end() );
+ while( aIter != aEnd )
+ {
+ const DeviceInfo& rInfo( *aIter );
+ *pValues++ = rInfo.nVendorId;
+ *pValues++ = rInfo.nDeviceId;
+ *pValues++ = rInfo.nDeviceSubSysId;
+ *pValues++ = rInfo.nDeviceRevision;
+ *pValues++ = rInfo.nDriverId;
+ *pValues++ = rInfo.nDriverVersion;
+ *pValues++ = rInfo.nDriverSubVersion;
+ *pValues++ = rInfo.nDriverBuildId;
+ ++aIter;
+ }
+
+ uno::Sequence< uno::Any > aValue(1);
+ aValue[0] <<= aValues;
+ PutProperties( aName, aValue );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ void DXCanvasItem::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& ) {}
+ void DXCanvasItem::Commit() {}
+
+ bool DXCanvasItem::isDeviceUsable( const DeviceInfo& rDeviceInfo ) const
+ {
+ return maValues.find(rDeviceInfo) == maValues.end();
+ }
+
+ bool DXCanvasItem::isBlacklistCurrentDevice() const
+ {
+ return mbBlacklistCurrentDevice;
+ }
+
+ void DXCanvasItem::blacklistDevice( const DeviceInfo& rDeviceInfo )
+ {
+ mbValuesDirty = true;
+ maValues.insert(rDeviceInfo);
+ }
+
+ void DXCanvasItem::adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const
+ {
+ if( maMaxTextureSize )
+ {
+ io_maxTextureSize.setX(
+ std::min( *maMaxTextureSize,
+ io_maxTextureSize.getX() ));
+ io_maxTextureSize.setY(
+ std::min( *maMaxTextureSize,
+ io_maxTextureSize.getY() ));
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_config.hxx b/canvas/source/directx/dx_config.hxx
new file mode 100644
index 000000000000..8fc13bdd0d9d
--- /dev/null
+++ b/canvas/source/directx/dx_config.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_DXCONFIG_HXX
+#define _DXCANVAS_DXCONFIG_HXX
+
+#include <unotools/configitem.hxx>
+#include <boost/optional.hpp>
+#include <set>
+
+namespace basegfx { class B2IVector; }
+
+namespace dxcanvas
+{
+ /** Provide DX canvas config data
+ */
+ class DXCanvasItem : public ::utl::ConfigItem
+ {
+ public:
+ DXCanvasItem();
+
+ struct DeviceInfo
+ {
+ sal_Int32 nVendorId;
+ sal_Int32 nDeviceId;
+ sal_Int32 nDeviceSubSysId;
+ sal_Int32 nDeviceRevision;
+
+ sal_Int32 nDriverId;
+ sal_Int32 nDriverVersion;
+ sal_Int32 nDriverSubVersion;
+ sal_Int32 nDriverBuildId;
+
+ bool operator<( const DeviceInfo& rRHS ) const
+ {
+ return nVendorId != rRHS.nVendorId ? nVendorId < rRHS.nVendorId :
+ (nDeviceId != rRHS.nDeviceId ? nDeviceId < rRHS.nDeviceId :
+ (nDeviceSubSysId != rRHS.nDeviceSubSysId ? nDeviceSubSysId < rRHS.nDeviceSubSysId :
+ (nDeviceRevision != rRHS.nDeviceRevision ? nDeviceRevision < rRHS.nDeviceRevision :
+ (nDriverId != rRHS.nDriverId ? nDriverId < rRHS.nDriverId :
+ (nDriverVersion != rRHS.nDriverVersion ? nDriverVersion < rRHS.nDriverVersion :
+ (nDriverSubVersion != rRHS.nDriverSubVersion ? nDriverSubVersion < rRHS.nDriverSubVersion :
+ (nDriverBuildId != rRHS.nDriverBuildId ? nDriverBuildId < rRHS.nDriverBuildId : false)))))));
+ }
+ };
+
+ ~DXCanvasItem();
+
+ bool isDeviceUsable( const DeviceInfo& rDeviceInfo ) const;
+ bool isBlacklistCurrentDevice() const;
+ void blacklistDevice( const DeviceInfo& rDeviceInfo );
+ void adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const;
+ virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
+ virtual void Commit();
+
+ private:
+ typedef std::set< DeviceInfo > ValueSet;
+ ValueSet maValues;
+ boost::optional<sal_Int32> maMaxTextureSize;
+ bool mbBlacklistCurrentDevice;
+ bool mbValuesDirty;
+ };
+}
+
+#endif /* #ifndef _DXCANVAS_DXCONFIG_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_devicehelper.cxx b/canvas/source/directx/dx_devicehelper.cxx
new file mode 100644
index 000000000000..a5eb371a7e64
--- /dev/null
+++ b/canvas/source/directx/dx_devicehelper.cxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include <vcl/window.hxx>
+#include <vcl/canvastools.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#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 "dx_linepolypolygon.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_devicehelper.hxx"
+
+
+#undef WB_LEFT
+#undef WB_RIGHT
+#include "dx_winstuff.hxx"
+
+
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ DeviceHelper::DeviceHelper() :
+ mpDevice( NULL ),
+ mnHDC(0)
+ {
+ }
+
+ void DeviceHelper::init( HDC hdc,
+ rendering::XGraphicDevice& rDevice )
+ {
+ mnHDC = hdc;
+ mpDevice = &rDevice;
+ }
+
+ void DeviceHelper::disposing()
+ {
+ // release all references
+ mnHDC = 0;
+ mpDevice = NULL;
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalResolution()
+ {
+ if( !mpDevice )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ HDC hDC = getHDC();
+ ENSURE_OR_THROW( hDC,
+ "DeviceHelper::getPhysicalResolution(): cannot retrieve HDC from window" );
+
+ const int nHorzRes( GetDeviceCaps( hDC,
+ LOGPIXELSX ) );
+ const int nVertRes( GetDeviceCaps( hDC,
+ LOGPIXELSY ) );
+
+ return geometry::RealSize2D( nHorzRes*25.4,
+ nVertRes*25.4 );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalSize()
+ {
+ if( !mpDevice )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ HDC hDC=getHDC();
+ ENSURE_OR_THROW( hDC,
+ "DeviceHelper::getPhysicalSize(): cannot retrieve HDC from window" );
+
+ const int nHorzSize( GetDeviceCaps( hDC,
+ HORZSIZE ) );
+ const int nVertSize( GetDeviceCaps( hDC,
+ VERTSIZE ) );
+
+ return geometry::RealSize2D( nHorzSize,
+ nVertSize );
+ }
+
+ uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XLinePolyPolygon2D >(
+ new LinePolyPolygon(
+ ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(
+ new LinePolyPolygon(
+ ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXBitmapSharedPtr pBitmap(
+ new DXBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ false));
+
+ // create a 24bit RGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ 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 )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXBitmapSharedPtr pBitmap(
+ new DXBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ true));
+
+ // create a 32bit ARGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool DeviceHelper::hasFullScreenMode()
+ {
+ return false;
+ }
+
+ sal_Bool DeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
+ {
+ return false;
+ }
+
+ uno::Any DeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(false);
+ }
+
+ uno::Any DeviceHelper::getDeviceHandle() const
+ {
+ HDC hdc( getHDC() );
+ if( hdc )
+ return uno::makeAny( reinterpret_cast< sal_Int64 >(hdc) );
+ else
+ return uno::Any();
+ }
+
+ uno::Any DeviceHelper::getSurfaceHandle() const
+ {
+ // TODO(F1): expose DirectDraw object
+ //return mpBackBuffer->getBitmap().get();
+ 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();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_devicehelper.hxx b/canvas/source/directx/dx_devicehelper.hxx
new file mode 100644
index 000000000000..8ce02db4148d
--- /dev/null
+++ b/canvas/source/directx/dx_devicehelper.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_DEVICEHELPER_HXX
+#define _DXCANVAS_DEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_bitmap.hxx"
+
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include <boost/utility.hpp>
+
+
+/* Definition of DeviceHelper class */
+
+namespace dxcanvas
+{
+ class DeviceHelper : private ::boost::noncopyable
+ {
+ public:
+ DeviceHelper();
+
+ /** Init the device helper
+
+ @param hdc
+ private or class dc of the output device. is only stored,
+ not release
+
+ @param rDevice
+ Ref back to owning UNO device
+ */
+ void init( HDC hdc,
+ com::sun::star::rendering::XGraphicDevice& rDevice );
+
+ /// 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 {}
+
+ protected:
+ HDC getHDC() const { return mnHDC; }
+ com::sun::star::rendering::XGraphicDevice* getDevice() const { return mpDevice; }
+
+ private:
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for canvas. Needed to
+ create bitmaps
+ */
+ com::sun::star::rendering::XGraphicDevice* mpDevice;
+ HDC mnHDC;
+ };
+
+ typedef ::rtl::Reference< com::sun::star::rendering::XGraphicDevice > DeviceRef;
+}
+
+#endif /* _DXCANVAS_DEVICEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_gdiplususer.cxx b/canvas/source/directx/dx_gdiplususer.cxx
new file mode 100644
index 000000000000..b88e32083e0f
--- /dev/null
+++ b/canvas/source/directx/dx_gdiplususer.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <osl/mutex.hxx>
+
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+namespace dxcanvas
+{
+ namespace
+ {
+ ::osl::Mutex* p_gdiPlusUsageCountMutex( osl::Mutex::getGlobalMutex() );
+ int n_gdiPlusUsageCount( 0 );
+
+ ULONG_PTR a_GdiPlusToken; // GDI+ handle. Owned by this object
+ }
+
+ GDIPlusUserSharedPtr GDIPlusUser::createInstance()
+ {
+ return GDIPlusUserSharedPtr( new GDIPlusUser() );
+ }
+
+ GDIPlusUser::~GDIPlusUser()
+ {
+ ::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
+
+ --n_gdiPlusUsageCount;
+
+ if( n_gdiPlusUsageCount == 0 )
+ Gdiplus::GdiplusShutdown( a_GdiPlusToken );
+ }
+
+ GDIPlusUser::GDIPlusUser()
+ {
+ ::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
+
+ if( n_gdiPlusUsageCount == 0 )
+ {
+ // Setup GDI+
+
+ // No extras here, simply taking GdiplusStartupInput's
+ // default constructor
+ Gdiplus::GdiplusStartupInput gdiPlusStartupInput;
+
+ Gdiplus::GdiplusStartup( &a_GdiPlusToken,
+ &gdiPlusStartupInput,
+ NULL );
+ }
+
+ ++n_gdiPlusUsageCount;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_gdiplususer.hxx b/canvas/source/directx/dx_gdiplususer.hxx
new file mode 100644
index 000000000000..463f8a31b613
--- /dev/null
+++ b/canvas/source/directx/dx_gdiplususer.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_GDIPLUSUSER_HXX
+#define _DXCANVAS_GDIPLUSUSER_HXX
+
+#include <sal/config.h>
+
+#include <boost/shared_ptr.hpp>
+
+/* Definition of GDIPlusUser class */
+
+namespace dxcanvas
+{
+ class GDIPlusUser
+ {
+ public:
+ typedef ::boost::shared_ptr< GDIPlusUser > GDIPlusUserSharedPtr;
+
+ static GDIPlusUserSharedPtr createInstance();
+ ~GDIPlusUser();
+
+ private:
+ GDIPlusUser(); // create us via factory method
+ };
+
+ typedef GDIPlusUser::GDIPlusUserSharedPtr GDIPlusUserSharedPtr;
+
+}
+
+#endif /* _DXCANVAS_GDIPLUSUSER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_graphicsprovider.hxx b/canvas/source/directx/dx_graphicsprovider.hxx
new file mode 100644
index 000000000000..8ab9fefc4247
--- /dev/null
+++ b/canvas/source/directx/dx_graphicsprovider.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_GRAPHICSPROVIDER_HXX
+#define _DXCANVAS_GRAPHICSPROVIDER_HXX
+
+#include "dx_winstuff.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+namespace Gdiplus{ class Graphics; }
+
+namespace dxcanvas
+{
+ /** Provider of a Gdiplus::Graphics. Interface
+ */
+ class GraphicsProvider : private ::boost::noncopyable
+ {
+ public:
+ virtual ~GraphicsProvider() {}
+
+ virtual GraphicsSharedPtr getGraphics() = 0;
+ };
+
+ typedef ::boost::shared_ptr< GraphicsProvider > GraphicsProviderSharedPtr;
+}
+
+#endif /* _DXCANVAS_GRAPHICSPROVIDER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_ibitmap.hxx b/canvas/source/directx/dx_ibitmap.hxx
new file mode 100644
index 000000000000..ea165e96032f
--- /dev/null
+++ b/canvas/source/directx/dx_ibitmap.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_DXIBITMAP_HXX
+#define _DXCANVAS_DXIBITMAP_HXX
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "dx_graphicsprovider.hxx"
+
+namespace dxcanvas
+{
+ /// Interface for internal canvas bitmap objects
+ struct IBitmap : public GraphicsProvider
+ {
+ virtual BitmapSharedPtr getBitmap() const = 0;
+ virtual ::basegfx::B2IVector getSize() const = 0;
+ virtual bool hasAlpha() const = 0;
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getData(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) = 0;
+
+ virtual 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 ) = 0;
+
+ virtual 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 ) = 0;
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getPixel(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) = 0;
+ };
+
+ typedef boost::shared_ptr<IBitmap> IBitmapSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_impltools.cxx b/canvas/source/directx/dx_impltools.cxx
new file mode 100644
index 000000000000..fb4bd9e19460
--- /dev/null
+++ b/canvas/source/directx/dx_impltools.cxx
@@ -0,0 +1,671 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <canvas/verifyinput.hxx>
+
+#include "dx_impltools.hxx"
+#include "dx_vcltools.hxx"
+#include "dx_linepolypolygon.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_canvas.hxx"
+#include "dx_spritecanvas.hxx"
+
+#include <boost/scoped_array.hpp>
+
+#include <vector>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
+ {
+ LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
+
+ if( pPolyImpl )
+ {
+ return pPolyImpl->getPolyPolygon();
+ }
+ else
+ {
+ const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );
+
+ // not a known implementation object - try data source
+ // interfaces
+ uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
+ xPoly,
+ uno::UNO_QUERY );
+
+ if( xBezierPoly.is() )
+ {
+ return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
+ xBezierPoly->getBezierSegments( 0,
+ nPolys,
+ 0,
+ -1 ) );
+ }
+ else
+ {
+ uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
+ xPoly,
+ uno::UNO_QUERY );
+
+ // no implementation class and no data provider
+ // found - contract violation.
+ ENSURE_ARG_OR_THROW( xLinePoly.is(),
+ "VCLCanvas::polyPolygonFromXPolyPolygon2D(): Invalid input "
+ "poly-polygon, cannot retrieve vertex data" );
+
+ return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
+ xLinePoly->getPoints( 0,
+ nPolys,
+ 0,
+ -1 ) );
+ }
+ }
+ }
+
+ void setupGraphics( Gdiplus::Graphics& rGraphics )
+ {
+ // setup graphics with (somewhat arbitrary) defaults
+ //rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighQuality );
+ rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
+ //rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear ); // with prefiltering for shrinks
+ rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf ); // Pixel center at (0.5, 0.5) etc.
+ //rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed ); // no line/curve antialiasing
+ //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
+ rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
+ //rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
+ rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintSystemDefault );
+ rGraphics.SetPageUnit(Gdiplus::UnitPixel);
+ }
+
+ Gdiplus::Graphics* createGraphicsFromHDC(HDC aHDC)
+ {
+ Gdiplus::Graphics* pRet = new Gdiplus::Graphics(aHDC);
+ if( pRet )
+ setupGraphics( *pRet );
+ return pRet;
+ }
+
+ Gdiplus::Graphics* createGraphicsFromBitmap(const BitmapSharedPtr& rBitmap)
+ {
+ Gdiplus::Graphics* pRet = Gdiplus::Graphics::FromImage(rBitmap.get());
+ if( pRet )
+ setupGraphics( *pRet );
+ return pRet;
+ }
+
+ void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix, const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.get(0,0)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,0)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(0,1)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,1)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(0,2)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,2)) );
+ }
+
+ void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
+ const geometry::AffineMatrix2D& rMatrix )
+ {
+ rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.m00),
+ static_cast<Gdiplus::REAL>(rMatrix.m10),
+ static_cast<Gdiplus::REAL>(rMatrix.m01),
+ static_cast<Gdiplus::REAL>(rMatrix.m11),
+ static_cast<Gdiplus::REAL>(rMatrix.m02),
+ static_cast<Gdiplus::REAL>(rMatrix.m12) );
+ }
+
+ namespace
+ {
+ // TODO(P2): Check whether this gets inlined. If not, make functor
+ // out of it
+ inline Gdiplus::PointF implGdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
+ {
+ return Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.X),
+ static_cast<Gdiplus::REAL>(rPoint.Y) );
+ }
+
+ void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr& rOutput,
+ ::std::vector< Gdiplus::PointF >& rPoints,
+ const ::basegfx::B2DPolygon& rPoly,
+ bool bNoLineJoin)
+ {
+ const sal_uInt32 nPoints( rPoly.count() );
+
+ if( nPoints < 2 )
+ return;
+
+ rOutput->StartFigure();
+
+ const bool bClosedPolygon( rPoly.isClosed() );
+
+ if( rPoly.areControlPointsUsed() )
+ {
+ // control points used -> for now, add all
+ // segments as curves to GraphicsPath
+
+ // If the polygon is closed, we need to add the
+ // first point, thus, one more (can't simply
+ // GraphicsPath::CloseFigure() it, since the last
+ // point cannot have any control points for GDI+)
+ rPoints.resize( 3*nPoints + bClosedPolygon );
+
+ sal_uInt32 nCurrOutput=0;
+ for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
+ {
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+
+ const ::basegfx::B2DPoint& rControlPointA( rPoly.getNextControlPoint( nCurrPoint ) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointA.getX()),
+ static_cast<Gdiplus::REAL>(rControlPointA.getY()) );
+
+ const ::basegfx::B2DPoint& rControlPointB( rPoly.getPrevControlPoint( (nCurrPoint + 1) % nPoints) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointB.getX()),
+ static_cast<Gdiplus::REAL>(rControlPointB.getY()) );
+ }
+
+ if( bClosedPolygon )
+ {
+ // add first point again (to be able to pass
+ // control points for the last point, see
+ // above)
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint(0) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+
+ if(bNoLineJoin && nCurrOutput > 7)
+ {
+ for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
+ {
+ rOutput->StartFigure();
+ rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
+ }
+ }
+ else
+ {
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput );
+ }
+ }
+ else
+ {
+ // GraphicsPath expects 3(n-1)+1 points (i.e. the
+ // last point must not have any trailing control
+ // points after it).
+ // Therefore, simply don't pass the last two
+ // points here.
+ if( nCurrOutput > 3 )
+ {
+ if(bNoLineJoin && nCurrOutput > 7)
+ {
+ for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
+ {
+ rOutput->StartFigure();
+ rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
+ }
+ }
+ else
+ {
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput-2 );
+ }
+ }
+ }
+ }
+ else
+ {
+ // no control points -> no curves, simply add
+ // straigt lines to GraphicsPath
+ rPoints.resize( nPoints );
+
+ for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
+ {
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
+ rPoints[nCurrPoint] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+ }
+
+ if(bNoLineJoin && nPoints > 2)
+ {
+ for(sal_uInt32 a(1); a < nPoints; a++)
+ {
+ rOutput->StartFigure();
+ rOutput->AddLine(rPoints[a - 1], rPoints[a]);
+ }
+
+ if(bClosedPolygon)
+ {
+ rOutput->StartFigure();
+ rOutput->AddLine(rPoints[nPoints - 1], rPoints[0]);
+ }
+ }
+ else
+ {
+ rOutput->AddLines( &rPoints[0], nPoints );
+ }
+ }
+
+ if( bClosedPolygon && !bNoLineJoin )
+ rOutput->CloseFigure();
+ }
+ }
+
+ Gdiplus::PointF gdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
+ {
+ return implGdiPlusPointFromRealPoint2D( rPoint );
+ }
+
+ Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRect )
+ {
+ return Gdiplus::Rect( rRect.X1,
+ rRect.Y1,
+ rRect.X2 - rRect.X1,
+ rRect.Y2 - rRect.Y1 );
+ }
+
+ Gdiplus::RectF gdiPlusRectFFromRectangle2D( const geometry::RealRectangle2D& rRect )
+ {
+ return Gdiplus::RectF( static_cast<Gdiplus::REAL>(rRect.X1),
+ static_cast<Gdiplus::REAL>(rRect.Y1),
+ static_cast<Gdiplus::REAL>(rRect.X2 - rRect.X1),
+ static_cast<Gdiplus::REAL>(rRect.Y2 - rRect.Y1) );
+ }
+
+ RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& rRect )
+ {
+ RECT aRect = {rRect.getMinX(),
+ rRect.getMinY(),
+ rRect.getMaxX(),
+ rRect.getMaxY()};
+
+ return aRect;
+ }
+
+ geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
+ {
+ return geometry::RealPoint2D( rPoint.X, rPoint.Y );
+ }
+
+ geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& rRect )
+ {
+ return geometry::RealRectangle2D( rRect.X, rRect.Y,
+ rRect.X + rRect.Width,
+ rRect.Y + rRect.Height );
+ }
+
+ ::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
+ {
+ return ::basegfx::B2DPoint( rPoint.X, rPoint.Y );
+ }
+
+ ::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& rRect )
+ {
+ return ::basegfx::B2DRange( rRect.X, rRect.Y,
+ rRect.X + rRect.Width,
+ rRect.Y + rRect.Height );
+ }
+
+ uno::Sequence< double > argbToDoubleSequence( const Gdiplus::ARGB& rColor )
+ {
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ uno::Sequence< double > aRet(4);
+
+ aRet[0] = ((rColor >> 16) & 0xFF) / 255.0; // red
+ aRet[1] = ((rColor >> 8) & 0xFF) / 255.0; // green
+ aRet[2] = (rColor & 0xFF) / 255.0; // blue
+ aRet[3] = ((rColor >> 24) & 0xFF) / 255.0; // alpha
+
+ return aRet;
+ }
+
+ uno::Sequence< sal_Int8 > argbToIntSequence( const Gdiplus::ARGB& rColor )
+ {
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ uno::Sequence< sal_Int8 > aRet(4);
+
+ aRet[0] = static_cast<sal_Int8>((rColor >> 16) & 0xFF); // red
+ aRet[1] = static_cast<sal_Int8>((rColor >> 8) & 0xFF); // green
+ aRet[2] = static_cast<sal_Int8>(rColor & 0xFF); // blue
+ aRet[3] = static_cast<sal_Int8>((rColor >> 24) & 0xFF); // alpha
+
+ return aRet;
+ }
+
+ Gdiplus::ARGB sequenceToArgb( const uno::Sequence< sal_Int8 >& rColor )
+ {
+ ENSURE_OR_THROW( rColor.getLength() > 2,
+ "sequenceToArgb: need at least three channels" );
+
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ Gdiplus::ARGB aColor;
+
+ aColor = (static_cast<sal_uInt8>(rColor[0]) << 16) | (static_cast<sal_uInt8>(rColor[1]) << 8) | static_cast<sal_uInt8>(rColor[2]);
+
+ if( rColor.getLength() > 3 )
+ aColor |= static_cast<sal_uInt8>(rColor[3]) << 24;
+
+ return aColor;
+ }
+
+ Gdiplus::ARGB sequenceToArgb( const uno::Sequence< double >& rColor )
+ {
+ ENSURE_OR_THROW( rColor.getLength() > 2,
+ "sequenceToColor: need at least three channels" );
+
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ Gdiplus::ARGB aColor;
+
+ ::canvas::tools::verifyRange(rColor[0],0.0,1.0);
+ ::canvas::tools::verifyRange(rColor[1],0.0,1.0);
+ ::canvas::tools::verifyRange(rColor[2],0.0,1.0);
+
+ aColor =
+ (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[0] ) ) << 16) |
+ (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[1] ) ) << 8) |
+ static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[2] ) );
+
+ if( rColor.getLength() > 3 )
+ {
+ ::canvas::tools::verifyRange(rColor[3],0.0,1.0);
+ aColor |= static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[3] ) ) << 24;
+ }
+
+ return aColor;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ sal_Int32 nCurrPoly;
+ for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
+ {
+ const sal_Int32 nCurrSize( points[nCurrPoly].getLength() );
+ if( nCurrSize )
+ {
+ aPoints.resize( nCurrSize );
+
+ // TODO(F1): Closed/open polygons
+
+ // convert from RealPoint2D array to Gdiplus::PointF array
+ ::std::transform( const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray(),
+ const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray()+nCurrSize,
+ aPoints.begin(),
+ implGdiPlusPointFromRealPoint2D );
+
+ pRes->AddLines( &aPoints[0], nCurrSize );
+ }
+ }
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly, bool bNoLineJoin )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ graphicsPathFromB2DPolygon( pRes, aPoints, rPoly, bNoLineJoin );
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, bool bNoLineJoin )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ const sal_uInt32 nPolies( rPoly.count() );
+ for( sal_uInt32 nCurrPoly=0; nCurrPoly<nPolies; ++nCurrPoly )
+ {
+ graphicsPathFromB2DPolygon( pRes,
+ aPoints,
+ rPoly.getB2DPolygon( nCurrPoly ),
+ bNoLineJoin);
+ }
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly, bool bNoLineJoin )
+ {
+ LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
+
+ if( pPolyImpl )
+ {
+ return pPolyImpl->getGraphicsPath( bNoLineJoin );
+ }
+ else
+ {
+ return tools::graphicsPathFromB2DPolyPolygon(
+ polyPolygonFromXPolyPolygon2D( xPoly ), bNoLineJoin );
+ }
+ }
+
+ bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
+ const BitmapSharedPtr& rBitmap )
+ {
+ Gdiplus::PointF aPoint;
+ return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
+ aPoint ) );
+ }
+
+ bool drawDIBits( const GraphicsSharedPtr& rGraphics,
+ const BITMAPINFO& rBI,
+ const void* pBits )
+ {
+ BitmapSharedPtr pBitmap(
+ Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
+ (void*)pBits ) );
+
+ return drawGdiPlusBitmap( rGraphics,
+ pBitmap );
+ }
+
+ bool drawRGBABits( const GraphicsSharedPtr& rGraphics,
+ const RawRGBABitmap& rRawRGBAData )
+ {
+ BitmapSharedPtr pBitmap( new Gdiplus::Bitmap( rRawRGBAData.mnWidth,
+ rRawRGBAData.mnHeight,
+ PixelFormat32bppARGB ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rRawRGBAData.mnWidth;
+ aBmpData.Height = rRawRGBAData.mnHeight;
+ aBmpData.Stride = 4*aBmpData.Width; // bottom-up format
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = rRawRGBAData.mpBitmapData.get();
+
+ const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
+ if( Gdiplus::Ok != pBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB,
+ &aBmpData ) )
+ {
+ return false;
+ }
+
+ // commit data to bitmap
+ pBitmap->UnlockBits( &aBmpData );
+
+ return drawGdiPlusBitmap( rGraphics,
+ pBitmap );
+ }
+
+ BitmapSharedPtr bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ BitmapProvider* pBitmapProvider = dynamic_cast< BitmapProvider* >(xBitmap.get());
+
+ if( pBitmapProvider )
+ {
+ IBitmapSharedPtr pBitmap( pBitmapProvider->getBitmap() );
+ return pBitmap->getBitmap();
+ }
+ else
+ {
+ // not a native CanvasBitmap, extract VCL bitmap and
+ // render into GDI+ bitmap of similar size
+ // =================================================
+
+ const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
+ BitmapSharedPtr pBitmap;
+
+ if( xBitmap->hasAlpha() )
+ {
+ // TODO(P2): At least for the alpha bitmap case, it
+ // would be possible to generate the corresponding
+ // bitmap directly
+ pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
+ aBmpSize.Height,
+ PixelFormat32bppARGB ) );
+ }
+ else
+ {
+ // TODO(F2): Might be wise to create bitmap compatible
+ // to the VCL bitmap. Also, check whether the VCL
+ // bitmap's system handles can be used to create the
+ // GDI+ bitmap (currently, it does not seem so).
+ pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
+ aBmpSize.Height,
+ PixelFormat24bppRGB ) );
+ }
+
+ GraphicsSharedPtr pGraphics(createGraphicsFromBitmap(pBitmap));
+ tools::setupGraphics(*pGraphics);
+ if( !drawVCLBitmapFromXBitmap(
+ pGraphics,
+ xBitmap) )
+ {
+ pBitmap.reset();
+ }
+
+ return pBitmap;
+ }
+ }
+
+ CanvasFont::ImplRef canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >& xFont )
+ {
+ CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get());
+
+ ENSURE_ARG_OR_THROW( pCanvasFont,
+ "canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" );
+
+ return CanvasFont::ImplRef( pCanvasFont );
+ }
+
+ void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
+ double nRedModulation,
+ double nGreenModulation,
+ double nBlueModulation,
+ double nAlphaModulation )
+ {
+ // This gets rather verbose, but we have to setup a color
+ // transformation matrix, in order to incorporate the global
+ // alpha value mfAlpha into the bitmap rendering.
+ Gdiplus::ColorMatrix aColorMatrix;
+
+ aColorMatrix.m[0][0] = static_cast<Gdiplus::REAL>(nRedModulation);
+ aColorMatrix.m[0][1] = 0.0;
+ aColorMatrix.m[0][2] = 0.0;
+ aColorMatrix.m[0][3] = 0.0;
+ aColorMatrix.m[0][4] = 0.0;
+
+ aColorMatrix.m[1][0] = 0.0;
+ aColorMatrix.m[1][1] = static_cast<Gdiplus::REAL>(nGreenModulation);
+ aColorMatrix.m[1][2] = 0.0;
+ aColorMatrix.m[1][3] = 0.0;
+ aColorMatrix.m[1][4] = 0.0;
+
+ aColorMatrix.m[2][0] = 0.0;
+ aColorMatrix.m[2][1] = 0.0;
+ aColorMatrix.m[2][2] = static_cast<Gdiplus::REAL>(nBlueModulation);
+ aColorMatrix.m[2][3] = 0.0;
+ aColorMatrix.m[2][4] = 0.0;
+
+ aColorMatrix.m[3][0] = 0.0;
+ aColorMatrix.m[3][1] = 0.0;
+ aColorMatrix.m[3][2] = 0.0;
+ aColorMatrix.m[3][3] = static_cast<Gdiplus::REAL>(nAlphaModulation);
+ aColorMatrix.m[3][4] = 0.0;
+
+ aColorMatrix.m[4][0] = 0.0;
+ aColorMatrix.m[4][1] = 0.0;
+ aColorMatrix.m[4][2] = 0.0;
+ aColorMatrix.m[4][3] = 0.0;
+ aColorMatrix.m[4][4] = 1.0;
+
+ o_rAttr.SetColorMatrix( &aColorMatrix,
+ Gdiplus::ColorMatrixFlagsDefault,
+ Gdiplus::ColorAdjustTypeDefault );
+ }
+
+ } // namespace tools
+} // namespace dxcanvas
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_impltools.hxx b/canvas/source/directx/dx_impltools.hxx
new file mode 100644
index 000000000000..449912c92075
--- /dev/null
+++ b/canvas/source/directx/dx_impltools.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_IMPLTOOLS_HXX
+#define _DXCANVAS_IMPLTOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/util/TriState.hpp>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include "dx_canvasfont.hxx"
+
+namespace basegfx
+{
+ class B2DPoint;
+ class B2DRange;
+ class B2DHomMatrix;
+ class B2IPoint;
+ class B2IRange;
+ class B2DPolyPolygon;
+};
+
+namespace com { namespace sun { namespace star { namespace geometry
+{
+ struct IntegerRectangle2D;
+ struct RealPoint2D;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvas;
+ class XGraphicDevice;
+ class XBitmap;
+ class XPolyPolygon2D;
+ class XCanvasFont;
+} } } }
+
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ struct RawRGBABitmap;
+
+ ::basegfx::B2DPolyPolygon
+ polyPolygonFromXPolyPolygon2D( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& );
+
+ Gdiplus::Graphics* createGraphicsFromHDC(HDC);
+ Gdiplus::Graphics* createGraphicsFromBitmap(const BitmapSharedPtr&);
+
+ void setupGraphics( Gdiplus::Graphics& rGraphics );
+
+ void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix,
+ const ::basegfx::B2DHomMatrix& rMatrix );
+ void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
+ const ::com::sun::star::geometry::AffineMatrix2D& rMatrix );
+
+ Gdiplus::PointF gdiPlusPointFFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& );
+ Gdiplus::RectF gdiPlusRectFFromRectangle2D( const ::com::sun::star::geometry::RealRectangle2D& );
+ Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const ::com::sun::star::geometry::IntegerRectangle2D& );
+ RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& );
+
+ ::com::sun::star::geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& );
+ ::com::sun::star::geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& );
+
+ ::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& );
+ ::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& );
+
+ ::com::sun::star::uno::Sequence< double > argbToDoubleSequence( const Gdiplus::ARGB& rColor );
+ ::com::sun::star::uno::Sequence< sal_Int8 > argbToIntSequence( const Gdiplus::ARGB& rColor );
+ Gdiplus::ARGB sequenceToArgb( const ::com::sun::star::uno::Sequence< sal_Int8 >& rColor );
+ Gdiplus::ARGB sequenceToArgb( const ::com::sun::star::uno::Sequence< double >& rColor );
+
+ GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& );
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon(
+ const ::basegfx::B2DPolygon& rPoly,
+ bool bNoLineJoin = false);
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon(
+ const ::basegfx::B2DPolyPolygon& rPoly,
+ bool bNoLineJoin = false);
+
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >&,
+ bool bNoLineJoin = false );
+
+ bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
+ const BitmapSharedPtr& rBitmap );
+ bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const BITMAPINFO& rBI,
+ const void* pBits );
+
+ bool drawRGBABits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const RawRGBABitmap& rRawRGBAData );
+
+ BitmapSharedPtr bitmapFromXBitmap( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap );
+
+ CanvasFont::ImplRef canvasFontFromXFont( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& xFont );
+
+ void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
+ double nRedModulation,
+ double nGreenModulation,
+ double nBlueModulation,
+ double nAlphaModulation );
+ }
+}
+
+#endif /* _DXCANVAS_IMPLTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_linepolypolygon.cxx b/canvas/source/directx/dx_linepolypolygon.cxx
new file mode 100644
index 000000000000..da0ea8d54f85
--- /dev/null
+++ b/canvas/source/directx/dx_linepolypolygon.cxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <basegfx/tools/canvastools.hxx>
+#include "dx_linepolypolygon.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ LinePolyPolygon::LinePolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ) :
+ ::basegfx::unotools::UnoPolyPolygon( rPolyPoly ),
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ mpPath()
+ {
+ }
+
+ GraphicsPathSharedPtr LinePolyPolygon::getGraphicsPath( bool bNoLineJoin ) const
+ {
+ // generate GraphicsPath only on demand (gets deleted as soon
+ // as any of the modifying methods above touches the
+ // B2DPolyPolygon).
+ if( !mpPath )
+ {
+ mpPath = tools::graphicsPathFromB2DPolyPolygon( getPolyPolygonUnsafe(), bNoLineJoin );
+ mpPath->SetFillMode( const_cast<LinePolyPolygon*>(this)->getFillRule() == rendering::FillRule_EVEN_ODD ?
+ Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding );
+ }
+
+ return mpPath;
+ }
+
+ void LinePolyPolygon::modifying() const
+ {
+ mpPath.reset();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_linepolypolygon.hxx b/canvas/source/directx/dx_linepolypolygon.hxx
new file mode 100644
index 000000000000..1abfe734c21b
--- /dev/null
+++ b/canvas/source/directx/dx_linepolypolygon.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_LINEPOLYPOLYGON_HXX_
+#define _DXCANVAS_LINEPOLYPOLYGON_HXX_
+
+#include <canvas/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+
+
+namespace dxcanvas
+{
+ class LinePolyPolygon : public ::basegfx::unotools::UnoPolyPolygon
+ {
+ public:
+ explicit LinePolyPolygon( const ::basegfx::B2DPolyPolygon& );
+
+ GraphicsPathSharedPtr getGraphicsPath( bool bNoLineJoin = false) const;
+
+ private:
+ // overridden, to clear mpPath
+ virtual void modifying() const;
+
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+ mutable GraphicsPathSharedPtr mpPath;
+ };
+}
+
+#endif /* _DXCANVAS_LINEPOLYPOLYGON_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_rendermodule.hxx b/canvas/source/directx/dx_rendermodule.hxx
new file mode 100644
index 000000000000..be7b43a14fdc
--- /dev/null
+++ b/canvas/source/directx/dx_rendermodule.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_RENDERMODULE_HXX
+#define _DXCANVAS_RENDERMODULE_HXX
+
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <boost/shared_ptr.hpp>
+#include "dx_winstuff.hxx"
+
+class Window;
+namespace basegfx
+{
+ class B2IRange;
+ class B2DVector;
+}
+
+namespace dxcanvas
+{
+ /// Specialization of IRenderModule for DirectX
+ struct IDXRenderModule : public canvas::IRenderModule
+ {
+ /** Flip front- and backbuffer, update only given area
+
+ Note: Both update area and offset are ignored for
+ fullscreen canvas, that uses page flipping (cannot, by
+ definition, do anything else there except displaying the
+ full backbuffer instead of the front buffer)
+
+ @param rUpdateArea
+ Area to copy from backbuffer to front
+
+ @param rCurrWindowArea
+ Current area of VCL window (coordinates relative to VCL
+ HWND)
+ */
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea ) = 0;
+
+ /** Resize backbuffer area for this render module
+ */
+ virtual void resize( const ::basegfx::B2IRange& rect ) = 0;
+
+ /// Write a snapshot of the screen to disk
+ virtual void screenShot() = 0;
+
+ virtual COMReference<surface_type>
+ createSystemMemorySurface(
+ const ::basegfx::B2IVector& rSize ) = 0;
+
+ virtual void disposing() = 0;
+ virtual HWND getHWND() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< IDXRenderModule > IDXRenderModuleSharedPtr;
+
+
+ /** Factory method, to create an IRenderModule instance for the
+ given VCL window instance
+ */
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_sprite.hxx b/canvas/source/directx/dx_sprite.hxx
new file mode 100644
index 000000000000..5889e8d3f9a8
--- /dev/null
+++ b/canvas/source/directx/dx_sprite.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_DXCANVAS_SPRITE_HXX
+#define INCLUDED_DXCANVAS_SPRITE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+namespace dxcanvas
+{
+ /** Specialization of ::canvas::Sprite interface, to also provide
+ redraw methods.
+ */
+ class Sprite : public ::canvas::Sprite
+ {
+ public:
+
+ /** Redraw sprite using the hardware
+
+ This method will silently fail, if the previous
+ restoreTextures() call failed.
+ */
+ virtual void redraw() const = 0;
+ };
+}
+
+#endif /* INCLUDED_DXCANVAS_SPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritecanvas.cxx b/canvas/source/directx/dx_spritecanvas.cxx
new file mode 100644
index 000000000000..3dd2e69e975e
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvas.cxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <canvas/canvastools.hxx>
+
+#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 <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "dx_winstuff.hxx"
+#include "dx_spritecanvas.hxx"
+
+#if DIRECTX_VERSION < 0x0900
+# define CANVAS_TECH "DX5"
+#else
+# define CANVAS_TECH "DX9"
+#endif
+
+#define SPRITECANVAS_SERVICE_NAME "com.sun.star.rendering.SpriteCanvas." CANVAS_TECH
+#define SPRITECANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.SpriteCanvas." CANVAS_TECH
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void SpriteCanvas::initialize()
+ {
+ // #i64742# Only call initialize when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "SpriteCanvas::initialize called" );
+
+ /* aArguments:
+ 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() >= 5 &&
+ maArguments[4].getValueTypeClass() == uno::TypeClass_INTERFACE,
+ "VCLSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ 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);
+
+ awt::Rectangle aRect;
+ maArguments[2] >>= aRect;
+
+ sal_Bool bIsFullscreen( sal_False );
+ maArguments[3] >>= bIsFullscreen;
+
+ // setup helper
+ maDeviceHelper.init( *pParentWindow,
+ *this,
+ aRect,
+ bIsFullscreen );
+ maCanvasHelper.init( *this,
+ maRedrawManager,
+ maDeviceHelper.getRenderModule(),
+ maDeviceHelper.getSurfaceProxy(),
+ maDeviceHelper.getBackBuffer(),
+ ::basegfx::B2ISize() );
+ 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)
+ {
+ ::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 : SpriteCanvasBaseT::showBuffer( bUpdateAll );
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::switchBuffer( ::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 : SpriteCanvasBaseT::switchBuffer( 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 ) );
+ }
+
+ const IDXRenderModuleSharedPtr& SpriteCanvas::getRenderModule() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maDeviceHelper.getRenderModule();
+ }
+
+ const DXSurfaceBitmapSharedPtr& SpriteCanvas::getBackBuffer() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maDeviceHelper.getBackBuffer();
+ }
+
+ IBitmapSharedPtr SpriteCanvas::getBitmap() const
+ {
+ return maDeviceHelper.getBackBuffer();
+ }
+
+ static uno::Reference<uno::XInterface> initCanvas( 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> > serviceImpl(&initCanvas);
+ const sdecl::ServiceDecl dxSpriteCanvasDecl(
+ serviceImpl,
+ SPRITECANVAS_IMPLEMENTATION_NAME,
+ SPRITECANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(dxcanvas::dxSpriteCanvasDecl);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritecanvas.hxx b/canvas/source/directx/dx_spritecanvas.hxx
new file mode 100644
index 000000000000..d64892e74712
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvas.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_SPRITECANVAS_HXX_
+#define _DXCANVAS_SPRITECANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.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 "dx_bitmapprovider.hxx"
+#include "dx_spritecanvashelper.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_impltools.hxx"
+#include "dx_spritedevicehelper.hxx"
+
+
+namespace dxcanvas
+{
+ 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
+ {
+ };
+
+ 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 BitmapProvider
+ {
+ 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();
+
+ /// 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);
+
+ /// Retrieve rendermodule object for this Canvas
+ const IDXRenderModuleSharedPtr& getRenderModule() const;
+
+ /// Get backbuffer for this canvas
+ const DXSurfaceBitmapSharedPtr& getBackBuffer() const;
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const;
+
+ 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritecanvashelper.cxx b/canvas/source/directx/dx_spritecanvashelper.cxx
new file mode 100644
index 000000000000..708f98e2933c
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvashelper.cxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <comphelper/scopeguard.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/cast.hpp>
+
+#include "dx_spritecanvashelper.hxx"
+#include "dx_canvascustomsprite.hxx"
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ void repaintBackground( const ::basegfx::B2DRange& rUpdateArea,
+ const ::basegfx::B2IRange& rOutputArea,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer )
+ {
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(rOutputArea.getWidth()),
+ static_cast<sal_Int32>(rOutputArea.getHeight()) );
+ aActualArea.intersect( fround( rUpdateArea ) );
+
+ // repaint the given area of the screen with background content
+ rBackBuffer->draw(aActualArea);
+ }
+
+ void spriteRedraw( const ::canvas::Sprite::Reference& rSprite )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw();
+ }
+
+ void spriteRedrawStub( const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw();
+ }
+ }
+
+ void spriteRedrawStub2( const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
+ {
+ if( rComponent.second.getSprite().is() )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rComponent.second.getSprite().get() )->redraw();
+ }
+ }
+ }
+
+ SpriteCanvasHelper::SpriteCanvasHelper() :
+ mpSpriteSurface( NULL ),
+ mpRedrawManager( NULL ),
+ mpRenderModule(),
+ mpSurfaceProxy(),
+ mpBackBuffer(),
+ maUpdateRect(),
+ maScrapRect(),
+ mbShowSpriteBounds( false )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ // inverse default for verbose debug mode
+ mbShowSpriteBounds = true;
+#endif
+ }
+
+ void SpriteCanvasHelper::init( SpriteCanvas& rParent,
+ ::canvas::SpriteRedrawManager& rManager,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ // init base
+ setDevice( rParent );
+ setTarget( rBackBuffer, rOutputOffset );
+
+ mpSpriteSurface = &rParent;
+ mpRedrawManager = &rManager;
+ mpRenderModule = rRenderModule;
+ mpSurfaceProxy = rSurfaceProxy;
+ mpBackBuffer = rBackBuffer;
+ }
+
+ void SpriteCanvasHelper::disposing()
+ {
+ if(mpRenderModule)
+ mpRenderModule->disposing();
+
+ mpBackBuffer.reset();
+ mpRenderModule.reset();
+ mpRedrawManager = NULL;
+ mpSpriteSurface = NULL;
+
+ // forward to base
+ CanvasHelper::disposing();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
+ const uno::Reference< rendering::XAnimation >& /*animation*/ )
+ {
+ 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,
+ mpSpriteSurface,
+ mpRenderModule,
+ mpSurfaceProxy,
+ mbShowSpriteBounds ) );
+ }
+
+ uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
+ {
+ return uno::Reference< rendering::XSprite >();
+ }
+
+ sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
+ sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty )
+ {
+ if( !mpRedrawManager ||
+ !mpRenderModule ||
+ !mpBackBuffer )
+ {
+ return sal_False; // disposed, or otherwise dysfunctional
+ }
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ mpBackBuffer->imageDebugger();
+# endif
+#endif
+
+ // store current output area (need to tunnel that to the
+ // background, scroll, opaque and general sprite repaint
+ // routines)
+ maScrapRect = rCurrArea;
+
+ // clear area that needs to be blitted to screen beforehand
+ maUpdateRect.reset();
+
+ // TODO(P1): Might be worthwile to track areas of background
+ // changes, too.
+
+ // TODO(P2): Might be worthwhile to use page-flipping only if
+ // a certain percentage of screen area has changed - and
+ // compose directly to the front buffer otherwise.
+ 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 );
+
+ // flip primary surface to screen
+ // ==============================
+
+ // perform buffer flipping
+ mpRenderModule->flip( maUpdateRect,
+ rCurrArea );
+ }
+ else
+ {
+ // limit update to parent window area (ignored for fullscreen)
+ // TODO(E1): Use numeric_cast to catch overflow here
+ const ::basegfx::B2IRectangle aUpdateArea( 0,0,
+ static_cast<sal_Int32>(rCurrArea.getWidth()),
+ static_cast<sal_Int32>(rCurrArea.getHeight()) );
+
+ // background has changed, or called requested full
+ // update, or we're performing double buffering via page
+ // flipping, so we currently have no choice but repaint
+ // everything
+
+ // repaint the whole screen with background content
+ mpBackBuffer->draw(aUpdateArea);
+
+ // redraw sprites
+ mpRedrawManager->forEachSprite(::std::ptr_fun( &spriteRedraw ) );
+
+ // flip primary surface to screen
+ // ==============================
+
+ // perform buffer flipping
+ mpRenderModule->flip( aUpdateArea,
+ rCurrArea );
+ }
+
+ // change record vector must be cleared, for the next turn of
+ // rendering and sprite changing
+ mpRedrawManager->clearChangeRecords();
+
+ io_bSurfaceDirty = false;
+
+ return sal_True;
+ }
+
+ void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
+
+ repaintBackground( rUpdateRect,
+ maScrapRect,
+ mpBackBuffer );
+ }
+
+ void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
+
+ // 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.
+ const ::basegfx::B2IRange& rDestRect(
+ ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
+
+ // not much sense in really implementing scrollUpdate here,
+ // since outputting a sprite only partially would result in
+ // expensive clipping. Furthermore, we cannot currently render
+ // 3D directly to the front buffer, thus, would have to blit
+ // the full sprite area, anyway. But at least optimized in the
+ // sense that unnecessary background paints behind the sprites
+ // are avoided.
+ ::std::for_each( rUpdateArea.maComponentList.begin(),
+ rUpdateArea.maComponentList.end(),
+ ::std::ptr_fun( &spriteRedrawStub2 ) );
+
+ // 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,
+ _1,
+ ::boost::cref(maScrapRect),
+ ::boost::cref(mpBackBuffer) ) );
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+
+ void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
+
+ // TODO(P2): optimize this by truly rendering to the front
+ // buffer. Currently, we've the 3D device only for the back
+ // buffer.
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::std::ptr_fun( &spriteRedrawStub ) );
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rTotalArea ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+
+ void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
+
+ // paint background
+ // ================
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rTotalArea ) );
+
+ // repaint the given area of the screen with background content
+ mpBackBuffer->draw(aActualArea);
+
+ // paint sprite
+ // ============
+
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::std::ptr_fun( &spriteRedrawStub ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritecanvashelper.hxx b/canvas/source/directx/dx_spritecanvashelper.hxx
new file mode 100644
index 000000000000..09c5c0e2aa02
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvashelper.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_SPRITECANVASHELPER_HXX_
+#define _DXCANVAS_SPRITECANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <canvas/spriteredrawmanager.hxx>
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_rendermodule.hxx"
+#include "dx_surfacebitmap.hxx"
+
+#include <basegfx/range/b2irectangle.hxx>
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+
+ class SpriteCanvasHelper : public BitmapCanvasHelper
+ {
+ public:
+ SpriteCanvasHelper();
+
+ void init( SpriteCanvas& rParent,
+ ::canvas::SpriteRedrawManager& rManager,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+ /// 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::B2IRectangle& 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:
+ /// For generating sprites
+ SpriteCanvas* mpSpriteSurface;
+
+ /// Set from the SpriteCanvas: instance coordinating sprite redraw
+ ::canvas::SpriteRedrawManager* mpRedrawManager;
+
+ /// DX device, handling all low-level rendering
+ IDXRenderModuleSharedPtr mpRenderModule;
+
+ ::canvas::ISurfaceProxyManagerSharedPtr mpSurfaceProxy;
+
+ /// Backbuffer, contains the static canvas render output
+ DXSurfaceBitmapSharedPtr mpBackBuffer;
+
+ /// Completely temporary rect storage (used by sprite repaint)
+ mutable ::basegfx::B2IRange maUpdateRect;
+
+ /// Completely temporary rect storage (used by sprite repaint)
+ mutable ::basegfx::B2IRange maScrapRect;
+
+ /// When true, show small bound rects around each sprite
+ bool mbShowSpriteBounds;
+ };
+}
+
+#endif /* _DXCANVAS_SPRITECANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritedevicehelper.cxx b/canvas/source/directx/dx_spritedevicehelper.cxx
new file mode 100644
index 000000000000..e65c13a99c87
--- /dev/null
+++ b/canvas/source/directx/dx_spritedevicehelper.cxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <vcl/window.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#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 "dx_linepolypolygon.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_spritedevicehelper.hxx"
+
+
+#undef WB_LEFT
+#undef WB_RIGHT
+#include "dx_winstuff.hxx"
+
+
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteDeviceHelper::SpriteDeviceHelper() :
+ DeviceHelper(),
+ mpSpriteCanvas( NULL ),
+ mpSurfaceProxyManager(),
+ mpRenderModule(),
+ mpBackBuffer()
+ {
+ }
+
+ void SpriteDeviceHelper::init( Window& rWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const awt::Rectangle& rRect,
+ bool /*bFullscreen*/ )
+ {
+ // #i60490# ensure backbuffer has sensible minimal size
+ const sal_Int32 w( ::std::max(sal_Int32(1),sal_Int32(rRect.Width)));
+ const sal_Int32 h( ::std::max(sal_Int32(1),sal_Int32(rRect.Height)));
+
+ rSpriteCanvas.setWindow(
+ uno::Reference<awt::XWindow2>(
+ VCLUnoHelper::GetInterface(&rWindow),
+ uno::UNO_QUERY_THROW) );
+
+ const SystemEnvData *pData = rWindow.GetSystemData();
+ const HWND hWnd = reinterpret_cast<HWND>(pData->hWnd);
+ if( !IsWindow( hWnd ) )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed window has invalid system window, or canvas out-of-process!")),
+ NULL);
+
+ mpSpriteCanvas = &rSpriteCanvas;
+
+ try
+ {
+ // setup directx rendermodule
+ mpRenderModule = createRenderModule( rWindow );
+ }
+ catch (...) {
+
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),
+ static_cast< ::cppu::OWeakObject* >(&rSpriteCanvas) );
+ }
+
+ // create the surfaceproxy manager
+ mpSurfaceProxyManager = ::canvas::createSurfaceProxyManager( mpRenderModule );
+
+ // #i60490# ensure backbuffer has sensible minimal size
+ mpBackBuffer.reset(new DXSurfaceBitmap(
+ ::basegfx::B2ISize(w,h),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ false));
+
+ // Assumes: SystemChildWindow() has CS_OWNDC
+ DeviceHelper::init(GetDC(mpRenderModule->getHWND()),
+ rSpriteCanvas);
+ }
+
+ void SpriteDeviceHelper::disposing()
+ {
+ // release all references
+ mpBackBuffer.reset();
+ mpSurfaceProxyManager.reset();
+ mpRenderModule.reset();
+ mpSpriteCanvas = NULL;
+
+ DeviceHelper::disposing();
+ }
+
+ uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !getDevice() )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXSurfaceBitmapSharedPtr pBitmap(
+ new DXSurfaceBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ false));
+
+ // create a 24bit RGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !getDevice() )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXSurfaceBitmapSharedPtr pBitmap(
+ new DXSurfaceBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ true));
+
+ // create a 32bit ARGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool SpriteDeviceHelper::hasFullScreenMode()
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ sal_Bool SpriteDeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ ::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);
+ }
+
+ void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
+ {
+ // #i60490# ensure backbuffer has sensible minimal size
+ const sal_Int32 x(rBounds.X);
+ const sal_Int32 y(rBounds.Y);
+ const sal_Int32 w(::std::max(sal_Int32(1),sal_Int32(rBounds.Width)));
+ const sal_Int32 h(::std::max(sal_Int32(1),sal_Int32(rBounds.Height)));
+
+ if( mpRenderModule )
+ mpRenderModule->resize(::basegfx::B2IRange(x,y,x+w,y+h));
+
+ resizeBackBuffer(::basegfx::B2ISize(w,h));
+ }
+
+ void SpriteDeviceHelper::resizeBackBuffer( const ::basegfx::B2ISize& rNewSize )
+ {
+ // disposed?
+ if(!(mpBackBuffer))
+ return;
+
+ mpBackBuffer->resize(rNewSize);
+ mpBackBuffer->clear();
+ }
+
+ HWND SpriteDeviceHelper::getHwnd() const
+ {
+ if( mpRenderModule )
+ return mpRenderModule->getHWND();
+ else
+ return 0;
+ }
+
+ void SpriteDeviceHelper::dumpScreenContent() const
+ {
+ if( mpRenderModule )
+ mpRenderModule->screenShot();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritedevicehelper.hxx b/canvas/source/directx/dx_spritedevicehelper.hxx
new file mode 100644
index 000000000000..0569606dbada
--- /dev/null
+++ b/canvas/source/directx/dx_spritedevicehelper.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_SPRITEDEVICEHELPER_HXX
+#define _DXCANVAS_SPRITEDEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_devicehelper.hxx"
+
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+ class SpriteCanvasHelper;
+
+ class SpriteDeviceHelper : public DeviceHelper
+ {
+ public:
+ SpriteDeviceHelper();
+
+ void init( Window& rWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const ::com::sun::star::awt::Rectangle& rRect,
+ bool bFullscreen );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // partial override XWindowGraphicDevice
+ ::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 );
+
+ ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
+ void destroyBuffers( );
+ ::sal_Bool showBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+ ::sal_Bool switchBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+
+ const IDXRenderModuleSharedPtr& getRenderModule() const { return mpRenderModule; }
+ const DXSurfaceBitmapSharedPtr& getBackBuffer() const { return mpBackBuffer; }
+ const ::canvas::ISurfaceProxyManagerSharedPtr &getSurfaceProxy() const { return mpSurfaceProxyManager; }
+
+ ::com::sun::star::uno::Any isAccelerated() const;
+
+ void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const;
+
+ private:
+ void resizeBackBuffer( const ::basegfx::B2ISize& rNewSize );
+ HWND getHwnd() const;
+
+ /// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
+ SpriteCanvas* mpSpriteCanvas;
+
+ DXSurfaceBitmapSharedPtr mpBackBuffer;
+
+ /// Instance passing out HW textures
+ ::canvas::ISurfaceProxyManagerSharedPtr mpSurfaceProxyManager;
+
+ /// Our encapsulation interface to DirectX
+ IDXRenderModuleSharedPtr mpRenderModule;
+ };
+}
+
+#endif /* _DXCANVAS_SPRITEDEVICEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritehelper.cxx b/canvas/source/directx/dx_spritehelper.cxx
new file mode 100644
index 000000000000..cb99abc31102
--- /dev/null
+++ b/canvas/source/directx/dx_spritehelper.cxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#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 "dx_canvascustomsprite.hxx"
+#include "dx_spritehelper.hxx"
+#include "dx_impltools.hxx"
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteHelper::SpriteHelper() :
+ mpSpriteCanvas(),
+ mpBitmap(),
+ mbTextureDirty( true ),
+ mbShowSpriteBounds( false )
+ {
+ }
+
+ void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rSpriteCanvas,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const DXSurfaceBitmapSharedPtr rBitmap,
+ bool bShowSpriteBounds )
+ {
+ ENSURE_OR_THROW( rSpriteCanvas.get() &&
+ rRenderModule &&
+ rBitmap,
+ "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
+
+ mpSpriteCanvas = rSpriteCanvas;
+ mpBitmap = rBitmap;
+ mbTextureDirty = true;
+ mbShowSpriteBounds = bShowSpriteBounds;
+
+ // also init base class
+ CanvasCustomSpriteHelper::init( rSpriteSize,
+ rSpriteCanvas.get() );
+ }
+
+ void SpriteHelper::disposing()
+ {
+ mpBitmap.reset();
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteHelper::disposing();
+ }
+
+ ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
+ {
+ return tools::polyPolygonFromXPolyPolygon2D( xPoly );
+ }
+
+ bool SpriteHelper::needRedraw() const
+ {
+ if( !mpBitmap ||
+ !mpSpriteCanvas.get() )
+ {
+ return false; // we're disposed, no redraw necessary
+ }
+
+ if( !isActive() ||
+ ::basegfx::fTools::equalZero( getAlpha() ) )
+ {
+ return false; // sprite is invisible
+ }
+
+ return true;
+ }
+
+ void SpriteHelper::redraw( bool& io_bSurfaceDirty ) const
+ {
+ if( !mpBitmap ||
+ !mpSpriteCanvas.get() )
+ {
+ return; // we're disposed
+ }
+
+ const ::basegfx::B2DPoint& rPos( getPosPixel() );
+ const double fAlpha( getAlpha() );
+
+ if( isActive() &&
+ !::basegfx::fTools::equalZero( fAlpha ) )
+ {
+
+ // TODO(Q2): For the time being, Device does not take a target
+ // surface, but always unconditionally renders to the
+ // background buffer.
+
+ // log output pos in device pixel
+ VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
+ rPos.getX(),
+ rPos.getY() );
+
+ const double fAlpha( getAlpha() );
+ const ::basegfx::B2DVector& rSize( getSizePixel() );
+ const ::basegfx::B2DHomMatrix& rTransform( getTransformation() );
+ const uno::Reference< rendering::XPolyPolygon2D >& xClip( getClip() );
+
+ mbTextureDirty = false;
+ io_bSurfaceDirty = false; // state taken, and processed.
+
+ ::basegfx::B2DPolyPolygon aClipPath; // empty for no clip
+ bool bIsClipRectangular( false ); // false, if no
+ // clip, or clip
+ // is complex
+
+ // setup and apply clip (if any)
+ // =================================
+
+ if( xClip.is() )
+ {
+ aClipPath = tools::polyPolygonFromXPolyPolygon2D( xClip );
+
+ const sal_Int32 nNumClipPolygons( aClipPath.count() );
+ if( nNumClipPolygons )
+ {
+ // TODO(P2): hold rectangle attribute directly
+ // at the XPolyPolygon2D
+
+ // check whether the clip is rectangular
+ if( nNumClipPolygons == 1 )
+ if( ::basegfx::tools::isRectangle( aClipPath.getB2DPolygon( 0 ) ) )
+ bIsClipRectangular = true;
+ }
+ }
+
+ const ::basegfx::B2DRectangle aSourceRect( 0.0,
+ 0.0,
+ rSize.getX(),
+ rSize.getY() );
+
+ // draw simple rectangular area if no clip is set.
+ if( !aClipPath.count() )
+ {
+ mpBitmap->draw(fAlpha,rPos,rTransform);
+ }
+ else if( bIsClipRectangular )
+ {
+ // apply a simple rect clip
+ // ========================
+
+ ::basegfx::B2DRectangle aClipBounds(
+ ::basegfx::tools::getRange( aClipPath ) );
+ aClipBounds.intersect( aSourceRect );
+
+ mpBitmap->draw(fAlpha,rPos,aClipBounds,rTransform);
+ }
+ else
+ {
+ // apply clip the hard way
+ // =======================
+
+ mpBitmap->draw(fAlpha,rPos,aClipPath,rTransform);
+ }
+
+ if( mbShowSpriteBounds )
+ {
+ if( aClipPath.count() )
+ {
+ // TODO(F2): Re-enable debug output
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_spritehelper.hxx b/canvas/source/directx/dx_spritehelper.hxx
new file mode 100644
index 000000000000..0eba43546706
--- /dev/null
+++ b/canvas/source/directx/dx_spritehelper.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_SPRITEHELPER_HXX
+#define _DXCANVAS_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 "dx_spritecanvas.hxx"
+#include "dx_surfacebitmap.hxx"
+
+namespace dxcanvas
+{
+ /* 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 rRenderModule
+ rendermodule 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,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const DXSurfaceBitmapSharedPtr rBitmap,
+ bool bShowSpriteBounds );
+
+ void disposing();
+
+ /** Repaint sprite content via hardware to associated sprite
+ canvas
+
+ @param io_bSurfaceDirty
+ Input/output parameter, whether the sprite content is
+ dirty or not. If texture was updated, set to false
+
+ */
+ void redraw( bool& io_bSurfaceDirty ) const;
+
+ private:
+ virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPoly ) const;
+
+ /// Returns true, if the sprite _really_ needs redraw
+ bool needRedraw() const;
+
+ SpriteCanvasRef mpSpriteCanvas;
+
+ DXSurfaceBitmapSharedPtr mpBitmap;
+ mutable bool mbTextureDirty; // when true, texture needs update
+ bool mbShowSpriteBounds; // when true, debug bound rect for sprites is shown
+ };
+}
+
+#endif /* _DXCANVAS_SPRITEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_surfacebitmap.cxx b/canvas/source/directx/dx_surfacebitmap.cxx
new file mode 100644
index 000000000000..4272e59d1aea
--- /dev/null
+++ b/canvas/source/directx/dx_surfacebitmap.cxx
@@ -0,0 +1,806 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "dx_surfacebitmap.hxx"
+#include "dx_impltools.hxx"
+#include "dx_surfacegraphics.hxx"
+#include "dx_graphicsprovider.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irange.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXColorBuffer
+ //////////////////////////////////////////////////////////////////////////////////
+
+ struct DXColorBuffer : public canvas::IColorBuffer
+ {
+ public:
+ DXColorBuffer( const COMReference<surface_type>& rSurface,
+ const ::basegfx::B2IVector& rSize ) :
+ mpSurface(rSurface),
+ maSize(rSize),
+ mbAlpha(false)
+ {
+ }
+
+ // implementation of the 'IColorBuffer' interface
+ public:
+
+ virtual sal_uInt8* lock() const;
+ virtual void unlock() const;
+ virtual sal_uInt32 getWidth() const;
+ virtual sal_uInt32 getHeight() const;
+ virtual sal_uInt32 getStride() const;
+ virtual Format getFormat() const;
+
+ private:
+
+ ::basegfx::B2IVector maSize;
+#if DIRECTX_VERSION < 0x0900
+ mutable DDSURFACEDESC aSurfaceDesc;
+#else
+ mutable D3DLOCKED_RECT maLockedRect;
+#endif
+ mutable COMReference<surface_type> mpSurface;
+ bool mbAlpha;
+ };
+
+ sal_uInt8* DXColorBuffer::lock() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ rtl_fillMemory((void *)&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+ if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ return static_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
+#else
+ if(SUCCEEDED(mpSurface->LockRect(&maLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ return static_cast<sal_uInt8 *>(maLockedRect.pBits);
+#endif
+ return NULL;
+ }
+
+ void DXColorBuffer::unlock() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ mpSurface->Unlock(NULL);
+#else
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ sal_uInt32 DXColorBuffer::getWidth() const
+ {
+ return maSize.getX();
+ }
+
+ sal_uInt32 DXColorBuffer::getHeight() const
+ {
+ return maSize.getY();
+ }
+
+ sal_uInt32 DXColorBuffer::getStride() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ return aSurfaceDesc.lPitch;
+#else
+ return maLockedRect.Pitch;
+#endif
+ }
+
+ canvas::IColorBuffer::Format DXColorBuffer::getFormat() const
+ {
+ return canvas::IColorBuffer::FMT_X8R8G8B8;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // GDIColorBuffer
+ //////////////////////////////////////////////////////////////////////////////////
+
+ struct GDIColorBuffer : public canvas::IColorBuffer
+ {
+ public:
+
+ GDIColorBuffer( const BitmapSharedPtr& rSurface,
+ const ::basegfx::B2IVector& rSize ) :
+ mpGDIPlusBitmap(rSurface),
+ maSize(rSize),
+ mbAlpha(true)
+ {
+ }
+
+ // implementation of the 'IColorBuffer' interface
+ public:
+
+ virtual sal_uInt8* lock() const;
+ virtual void unlock() const;
+ virtual sal_uInt32 getWidth() const;
+ virtual sal_uInt32 getHeight() const;
+ virtual sal_uInt32 getStride() const;
+ virtual Format getFormat() const;
+
+ private:
+
+ ::basegfx::B2IVector maSize;
+ mutable Gdiplus::BitmapData aBmpData;
+ BitmapSharedPtr mpGDIPlusBitmap;
+ bool mbAlpha;
+ };
+
+ sal_uInt8* GDIColorBuffer::lock() const
+ {
+ aBmpData.Width = maSize.getX();
+ aBmpData.Height = maSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB,
+ &aBmpData ) )
+ {
+ return NULL;
+ }
+
+ return static_cast<sal_uInt8*>(aBmpData.Scan0);
+ }
+
+ void GDIColorBuffer::unlock() const
+ {
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+ }
+
+ sal_uInt32 GDIColorBuffer::getWidth() const
+ {
+ return maSize.getX();
+ }
+
+ sal_uInt32 GDIColorBuffer::getHeight() const
+ {
+ return maSize.getY();
+ }
+
+ sal_uInt32 GDIColorBuffer::getStride() const
+ {
+ return aBmpData.Stride;
+ }
+
+ canvas::IColorBuffer::Format GDIColorBuffer::getFormat() const
+ {
+ return canvas::IColorBuffer::FMT_A8R8G8B8;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::DXSurfaceBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurfaceBitmap::DXSurfaceBitmap( const ::basegfx::B2IVector& rSize,
+ const canvas::ISurfaceProxyManagerSharedPtr& rMgr,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rSize),
+ mpRenderModule(rRenderModule),
+ mpSurfaceManager(rMgr),
+ mpSurfaceProxy(),
+ mpSurface(),
+ mpGDIPlusBitmap(),
+ mpGraphics(),
+ mpColorBuffer(),
+ mbIsSurfaceDirty(true),
+ mbAlpha(bWithAlpha)
+ {
+ init();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurfaceBitmap::getSize() const
+ {
+ return maSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::init
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::init()
+ {
+ // create container for pixel data
+ if(mbAlpha)
+ {
+ mpGDIPlusBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat32bppARGB
+ ));
+ mpGraphics.reset( tools::createGraphicsFromBitmap(mpGDIPlusBitmap) );
+
+ // create the colorbuffer object, which is basically a simple
+ // wrapper around the directx surface. the colorbuffer is the
+ // interface which is used by the surfaceproxy to support any
+ // kind of underlying structure for the pixel data container.
+ mpColorBuffer.reset(new GDIColorBuffer(mpGDIPlusBitmap,maSize));
+ }
+ else
+ {
+ mpSurface = mpRenderModule->createSystemMemorySurface(maSize);
+
+ // create the colorbuffer object, which is basically a simple
+ // wrapper around the directx surface. the colorbuffer is the
+ // interface which is used by the surfaceproxy to support any
+ // kind of underlying structure for the pixel data container.
+ mpColorBuffer.reset(new DXColorBuffer(mpSurface,maSize));
+ }
+
+ // create a (possibly hardware accelerated) mirror surface.
+ mpSurfaceProxy = mpSurfaceManager->createSurfaceProxy(mpColorBuffer);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::resize( const ::basegfx::B2IVector& rSize )
+ {
+ if(maSize != rSize)
+ {
+ maSize = rSize;
+ init();
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::clear
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::clear()
+ {
+ GraphicsSharedPtr pGraphics(getGraphics());
+ Gdiplus::Color transColor(255,0,0,0);
+ pGraphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy );
+ pGraphics->Clear( transColor );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::hasAlpha
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::hasAlpha() const
+ {
+ return mbAlpha;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getGraphics
+ //////////////////////////////////////////////////////////////////////////////////
+
+ GraphicsSharedPtr DXSurfaceBitmap::getGraphics()
+ {
+ // since clients will most probably draw directly
+ // to the GDI+ bitmap, we need to mark it as dirty
+ // to ensure that the corrosponding dxsurface will
+ // be updated.
+ mbIsSurfaceDirty = true;
+
+ if(hasAlpha())
+ return mpGraphics;
+ else
+ return createSurfaceGraphics(mpSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ BitmapSharedPtr DXSurfaceBitmap::getBitmap() const
+ {
+ if(hasAlpha())
+ return mpGDIPlusBitmap;
+
+ BitmapSharedPtr pResult;
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ {
+ // decide about the format we pass the gdi+, the directx surface is always
+ // 32bit, either with or without alpha component.
+ Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
+
+ // construct a gdi+ bitmap from the raw pixel data.
+ pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
+ aSurfaceDesc.lPitch,
+ nFormat,
+ (BYTE *)aSurfaceDesc.lpSurface ));
+
+ // unlock the directx surface
+ mpSurface->Unlock(NULL);
+ }
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if(SUCCEEDED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ {
+ // decide about the format we pass the gdi+, the directx surface is always
+ // 32bit, either with or without alpha component.
+ Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
+
+ // construct a gdi+ bitmap from the raw pixel data.
+ pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
+ aLockedRect.Pitch,
+ nFormat,
+ (BYTE *)aLockedRect.pBits ));
+
+ mpSurface->UnlockRect();
+ }
+#endif
+
+ return pResult;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rClipPoly, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rArea, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( const ::basegfx::B2IRange& rArea )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ const double fAlpha(1.0);
+ const ::basegfx::B2DHomMatrix aTransform;
+ const ::basegfx::B2DRange aIEEEArea( rArea );
+ return mpSurfaceProxy->draw(fAlpha,
+ ::basegfx::B2DPoint(),
+ aIEEEArea,
+ aTransform);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::imageDebugger
+ //////////////////////////////////////////////////////////////////////////////////
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ void DXSurfaceBitmap::imageDebugger()
+ {
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( FAILED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ return;
+
+ imdebug("bgra w=%d h=%d %p", aSurfaceDesc.dwWidth, aSurfaceDesc.dwHeight, aSurfaceDesc.lpSurface);
+
+ mpSurface->Unlock(NULL);
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if( FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)) )
+ return;
+
+ imdebug("bgra w=%d h=%d %p", maSize.getX(),
+ maSize.getY(), aLockedRect.pBits);
+ mpSurface->UnlockRect();
+#endif
+ }
+# endif
+#endif
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getData
+ //////////////////////////////////////////////////////////////////////////////////
+
+ uno::Sequence< sal_Int8 > DXSurfaceBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if(hasAlpha())
+ {
+ uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
+
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = aRes.getArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ // read data from bitmap
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO(F1): Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ return aRes;
+ }
+ else
+ {
+ sal_uInt32 nWidth = rect.X2-rect.X1;
+ sal_uInt32 nHeight = rect.Y2-rect.Y1;
+
+ uno::Sequence< sal_Int8 > aRes(nWidth*nHeight*4);
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ return uno::Sequence< sal_Int8 >();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
+ sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pDst += nSegmentSizeInBytes;
+ pSrc += aSurfaceDesc.lPitch;
+ }
+
+ mpSurface->Unlock(NULL);
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ return uno::Sequence< sal_Int8 >();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
+ sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pDst += nSegmentSizeInBytes;
+ pSrc += aLockedRect.Pitch;
+ }
+
+ mpSurface->UnlockRect();
+#endif
+ return aRes;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::setData
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if(hasAlpha())
+ {
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = (void*)data.getConstArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO: Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ // commit data to bitmap
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+ }
+ else
+ {
+ sal_uInt32 nWidth = rect.X2-rect.X1;
+ sal_uInt32 nHeight = rect.Y2-rect.Y1;
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
+ sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pSrc += nSegmentSizeInBytes;
+ pDst += aSurfaceDesc.lPitch;
+ }
+
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
+ sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pSrc += nSegmentSizeInBytes;
+ pDst += aLockedRect.Pitch;
+ }
+
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ mbIsSurfaceDirty = true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::setPixel
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if(hasAlpha())
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->SetPixel( pos.X, pos.Y,
+ Gdiplus::Color( tools::sequenceToArgb( color ))))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ Gdiplus::Color aColor(tools::sequenceToArgb(color));
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
+ *pDst = aColor.GetValue();
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
+ *pDst = aColor.GetValue();
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ mbIsSurfaceDirty = true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getPixel
+ //////////////////////////////////////////////////////////////////////////////////
+
+ uno::Sequence< sal_Int8 > DXSurfaceBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if(hasAlpha())
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+ Gdiplus::Color aColor;
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
+ return uno::Sequence< sal_Int8 >();
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
+ Gdiplus::Color aColor(*pDst);
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
+ Gdiplus::Color aColor(*pDst);
+ mpSurface->UnlockRect();
+#endif
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // End of file
+ //////////////////////////////////////////////////////////////////////////////////
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_surfacebitmap.hxx b/canvas/source/directx/dx_surfacebitmap.hxx
new file mode 100644
index 000000000000..b51735dda9f6
--- /dev/null
+++ b/canvas/source/directx/dx_surfacebitmap.hxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_DXSURFACEBITMAP_HXX
+#define _DXCANVAS_DXSURFACEBITMAP_HXX
+
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+#include "dx_ibitmap.hxx"
+#include "dx_canvasfont.hxx" //winstuff
+#include "dx_gdiplususer.hxx"
+#include "dx_rendermodule.hxx"
+
+namespace dxcanvas
+{
+ class DXSurfaceBitmap : public IBitmap
+ {
+ public:
+ DXSurfaceBitmap( const ::basegfx::B2IVector& rSize,
+ const canvas::ISurfaceProxyManagerSharedPtr& rMgr,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ bool bWithAlpha );
+
+ bool resize( const ::basegfx::B2IVector& rSize );
+ void clear();
+
+ virtual GraphicsSharedPtr getGraphics();
+
+ virtual BitmapSharedPtr getBitmap() const;
+ virtual ::basegfx::B2IVector getSize() const;
+ virtual bool hasAlpha() const;
+
+ COMReference<surface_type> getSurface() const { return mpSurface; }
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ bool draw( const ::basegfx::B2IRange& rArea );
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getData(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ virtual 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 );
+
+ virtual 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 );
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getPixel(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+#ifdef DX_DEBUG_IMAGES
+ void imageDebugger();
+#endif
+ private:
+ void init();
+
+ // Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ // size of this image in pixels [integral unit]
+ ::basegfx::B2IVector maSize;
+
+ // pointer to the rendermodule, needed to create surfaces
+ // which are used as container for the actual pixel data.
+ // generally we could use any kind of storage, but GDI+
+ // is not willing to render antialiased fonts unless we
+ // use this special kind of container, don't ask me why...
+ IDXRenderModuleSharedPtr mpRenderModule;
+
+ // pointer to the surface manager, needed in case clients
+ // want to resize the bitmap.
+ canvas::ISurfaceProxyManagerSharedPtr mpSurfaceManager;
+
+ // access point to the surface proxy which handles
+ // the hardware-dependent rendering stuff.
+ canvas::ISurfaceProxySharedPtr mpSurfaceProxy;
+
+ // container for pixel data, we need to use a directx
+ // surface since GDI+ sucks...
+ COMReference<surface_type> mpSurface;
+
+ // since GDI+ does not work correctly in case we
+ // run on a 16bit display [don't ask me why] we need
+ // to occasionally render to a native GDI+ bitmap.
+ BitmapSharedPtr mpGDIPlusBitmap;
+ // Graphics for the mpGDIPlusBitmap
+ GraphicsSharedPtr mpGraphics;
+
+ // internal implementation of the iColorBuffer interface
+ canvas::IColorBufferSharedPtr mpColorBuffer;
+
+ // indicates wether the associated surface needs
+ // to refresh its contents or not. in other words,
+ // this flag is set iff both representations are
+ // out of sync.
+ mutable bool mbIsSurfaceDirty;
+
+ // true if the bitmap contains an alpha channel
+ bool mbAlpha;
+ };
+
+ typedef ::boost::shared_ptr< DXSurfaceBitmap > DXSurfaceBitmapSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_surfacegraphics.cxx b/canvas/source/directx/dx_surfacegraphics.cxx
new file mode 100644
index 000000000000..e32a5c97dc8f
--- /dev/null
+++ b/canvas/source/directx/dx_surfacegraphics.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "dx_surfacegraphics.hxx"
+#include "dx_impltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ struct GraphicsDeleter
+ {
+ COMReference<surface_type> mpSurface;
+ HDC maHDC;
+
+ GraphicsDeleter(const COMReference<surface_type>& rSurface, HDC hdc) :
+ mpSurface(rSurface),
+ maHDC(hdc)
+ {}
+
+ void operator()( Gdiplus::Graphics* pGraphics )
+ {
+ if(!pGraphics)
+ return;
+
+ pGraphics->Flush(Gdiplus::FlushIntentionSync);
+ delete pGraphics;
+
+ if(mpSurface.is())
+ mpSurface->ReleaseDC( maHDC );
+ }
+ };
+ }
+
+ GraphicsSharedPtr createSurfaceGraphics(const COMReference<surface_type>& rSurface )
+ {
+ Gdiplus::Graphics* pGraphics;
+ GraphicsSharedPtr pRet;
+ HDC aHDC;
+ if( SUCCEEDED(rSurface->GetDC( &aHDC )) )
+ {
+ pGraphics = Gdiplus::Graphics::FromHDC( aHDC );
+ if(pGraphics)
+ {
+ tools::setupGraphics( *pGraphics );
+ pRet.reset(pGraphics,
+ GraphicsDeleter(rSurface, aHDC));
+ return pRet;
+ }
+ else
+ rSurface->ReleaseDC( aHDC );
+ }
+
+ throw uno::RuntimeException();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_surfacegraphics.hxx b/canvas/source/directx/dx_surfacegraphics.hxx
new file mode 100644
index 000000000000..12390c8cf7a2
--- /dev/null
+++ b/canvas/source/directx/dx_surfacegraphics.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_SURFACEGRAPHICS_HXX
+#define _DXCANVAS_SURFACEGRAPHICS_HXX
+
+#include "dx_graphicsprovider.hxx"
+
+namespace dxcanvas
+{
+ /** Container providing a Gdiplus::Graphics for a Surface
+
+ This wrapper class transparently handles allocation and
+ release of surface resources the RAII way (the
+ GraphicsSharedPtr returned has a deleter that does all the
+ necessary DX cleanup work).
+ */
+ GraphicsSharedPtr createSurfaceGraphics(const COMReference<surface_type>& rSurface );
+}
+
+#endif /* _DXCANVAS_SURFACEGRAPHICS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_textlayout.cxx b/canvas/source/directx/dx_textlayout.cxx
new file mode 100644
index 000000000000..1d5a27d271f5
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout.cxx
@@ -0,0 +1,283 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include "dx_bitmap.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_textlayout_drawhelper.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ TextLayout::TextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 /*nRandomSeed*/,
+ const CanvasFont::ImplRef& rFont ) :
+ TextLayout_Base( m_aMutex ),
+ maText( aText ),
+ maLogicalAdvancements(),
+ mpFont( rFont ),
+ mnTextDirection( nDirection )
+ {
+ }
+
+ TextLayout::~TextLayout()
+ {
+ }
+
+ void SAL_CALL TextLayout::disposing()
+ {
+ mpFont.reset();
+ }
+
+ // 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 );
+
+ uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
+ ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
+
+ // render text
+ const geometry::RealRectangle2D aBounds(
+ aDrawHelper.queryTextBounds(
+ maText,
+ maLogicalAdvancements,
+ mpFont.getRef(),
+ mpFont->getFontMatrix()));
+
+ return aBounds;
+ }
+
+ 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;
+ }
+
+ namespace
+ {
+ // TODO(P2): Check whether this gets inlined. If not, make functor
+ // out of it
+ inline Gdiplus::PointF gdiPlusPointFromDx( const double& dx )
+ {
+ return Gdiplus::PointF( static_cast<Gdiplus::REAL>(dx),
+ 0.0f );
+ }
+ }
+
+ bool TextLayout::draw( const GraphicsSharedPtr& rGraphics,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
+ bool bAlphaSurface ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
+
+ // render text
+ aDrawHelper.drawText(
+ rGraphics,
+ rViewState,
+ rRenderState,
+ rOutputOffset,
+ maText,
+ maLogicalAdvancements,
+ mpFont.getRef(),
+ mpFont->getFontMatrix(),
+ bAlphaSurface);
+
+ return true;
+ }
+
+
+#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
+#define IMPLEMENTATION_NAME "DXCanvas::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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_textlayout.hxx b/canvas/source/directx/dx_textlayout.hxx
new file mode 100644
index 000000000000..bae2e2b98787
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_TEXTLAYOUT_HXX
+#define _DXCANVAS_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 <boost/utility.hpp>
+
+#include "dx_canvasfont.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+/* Definition of TextLayout class */
+class DXBitmapSharedPtr;
+
+namespace dxcanvas
+{
+ 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::ImplRef& rFont );
+
+ /// 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( const GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice,
+ bool bAlphaSurface ) const;
+
+ protected:
+ ~TextLayout(); // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ private:
+ // NOTE: no need for GDIPlusUserSharedPtr, mpFont implicitely has one already
+
+ ::com::sun::star::rendering::StringContext maText;
+ ::com::sun::star::uno::Sequence< double > maLogicalAdvancements;
+ CanvasFont::ImplRef mpFont;
+ sal_Int8 mnTextDirection;
+ };
+
+}
+
+#endif /* _DXCANVAS_TEXTLAYOUT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_textlayout_drawhelper.cxx b/canvas/source/directx/dx_textlayout_drawhelper.cxx
new file mode 100644
index 000000000000..92cdcd7d8dc9
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout_drawhelper.cxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/poly.hxx>
+
+#include <vcl/metric.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <boost/scoped_array.hpp>
+#include <boost/bind.hpp>
+#include <com/sun/star/rendering/FontRequest.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <com/sun/star/rendering/PanoseProportion.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <tools/color.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/debug.hxx>
+#include "dx_impltools.hxx"
+#include <vcl/sysdata.hxx>
+#include <i18npool/mslangid.hxx>
+#include "dx_textlayout_drawhelper.hxx"
+#include "dx_bitmap.hxx"
+#include "dx_canvasfont.hxx"
+
+class ::com::sun::star::rendering::XCanvasFont;
+
+using namespace ::com::sun::star;
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ class DXBitmap;
+ TextLayoutDrawHelper::TextLayoutDrawHelper(
+ const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice ) :
+ mxGraphicDevice(xGraphicDevice)
+ {
+ }
+
+ TextLayoutDrawHelper::~TextLayoutDrawHelper()
+ {
+ }
+
+ void TextLayoutDrawHelper::drawText(
+ const GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
+ bool bAlphaSurface )
+ {
+ HDC hdc = rGraphics->GetHDC();
+
+ // issue an ReleaseHDC() when leaving the scope
+ const ::comphelper::ScopeGuard aGuard(
+ boost::bind( &Gdiplus::Graphics::ReleaseHDC,
+ rGraphics.get(),
+ hdc ));
+
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(hdc);
+ VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
+
+ // disable font antialiasing - GDI does not handle alpha
+ // surfaces properly.
+ if( bAlphaSurface )
+ aVirtualDevice.SetAntialiasing(ANTIALIASING_DISABLE_TEXT);
+
+ if(rText.Length)
+ {
+ sal_Bool test = mxGraphicDevice.is();
+ ENSURE_OR_THROW( test,
+ "TextLayoutDrawHelper::drawText(): Invalid GraphicDevice" );
+
+ // set text color. Make sure to remove transparence part first.
+ Color aColor( COL_WHITE );
+
+ if( rRenderState.DeviceColor.getLength() > 2 )
+ aColor = ::vcl::unotools::doubleSequenceToColor(
+ rRenderState.DeviceColor,
+ mxGraphicDevice->getDeviceColorSpace());
+ aColor.SetTransparency(0);
+ aVirtualDevice.SetTextColor(aColor);
+
+ // create the font
+ const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
+ Font aFont(
+ rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
+
+ aFont.SetAlign( ALIGN_BASELINE );
+ aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
+ aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+ aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+ aFont.SetPitch(
+ rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
+ ? PITCH_FIXED : PITCH_VARIABLE);
+
+ aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
+
+ // setup font color
+ aFont.SetColor( aColor );
+ aFont.SetFillColor( aColor );
+
+ // adjust to stretched font
+ if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
+ {
+ const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
+ const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+ double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+ if( !::basegfx::fTools::equalZero( fDividend) )
+ fStretch /= fDividend;
+
+ const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+ aFont.SetWidth( nNewWidth );
+ }
+
+ // set font
+ aVirtualDevice.SetFont(aFont);
+
+ // create world transformation matrix
+ ::basegfx::B2DHomMatrix aWorldTransform;
+ ::canvas::tools::mergeViewAndRenderTransform(aWorldTransform, rViewState, rRenderState);
+
+ if(!rOutputOffset.equalZero())
+ {
+ aWorldTransform.translate(rOutputOffset.getX(), rOutputOffset.getY());
+ }
+
+ // set ViewState clipping
+ if(rViewState.Clip.is())
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rViewState.Clip));
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, rViewState.AffineTransform );
+
+ if(!rOutputOffset.equalZero())
+ {
+ aMatrix.translate(rOutputOffset.getX(), rOutputOffset.getY());
+ }
+
+ aClipPoly.transform(aMatrix);
+ const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
+ aVirtualDevice.IntersectClipRegion(rClipRegion);
+ }
+
+ if(rRenderState.Clip.is())
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rRenderState.Clip));
+ aClipPoly.transform(aWorldTransform);
+ const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
+ aVirtualDevice.IntersectClipRegion(rClipRegion);
+ }
+
+ // set world transform
+ XFORM aXForm;
+ aXForm.eM11 = (FLOAT)aWorldTransform.get(0, 0);
+ aXForm.eM12 = (FLOAT)aWorldTransform.get(1, 0);
+ aXForm.eM21 = (FLOAT)aWorldTransform.get(0, 1);
+ aXForm.eM22 = (FLOAT)aWorldTransform.get(1, 1);
+ aXForm.eDx = (FLOAT)aWorldTransform.get(0, 2);
+ aXForm.eDy = (FLOAT)aWorldTransform.get(1, 2);
+
+ // TODO(F3): This is NOT supported on 95/98/ME!
+ SetGraphicsMode(hdc, GM_ADVANCED);
+ SetTextAlign(hdc, TA_BASELINE);
+ SetWorldTransform(hdc, &aXForm);
+
+ // use a empty StartPosition for text rendering
+ const Point aEmptyPoint(0, 0);
+
+ // create the String
+ const String aText(rText.Text.getStr());
+
+ if( rLogicalAdvancements.getLength() )
+ {
+ // create the DXArray
+ const sal_Int32 nLen( rLogicalAdvancements.getLength() );
+ ::boost::scoped_array<sal_Int32> pDXArray( new sal_Int32[nLen] );
+ for( sal_Int32 i=0; i<nLen; ++i )
+ pDXArray[i] = basegfx::fround( rLogicalAdvancements[i] );
+
+ // draw the String
+ aVirtualDevice.DrawTextArray( aEmptyPoint,
+ aText,
+ pDXArray.get(),
+ (xub_StrLen)rText.StartPosition,
+ (xub_StrLen)rText.Length );
+ }
+ else
+ {
+ // draw the String
+ aVirtualDevice.DrawText( aEmptyPoint,
+ aText,
+ (xub_StrLen)rText.StartPosition,
+ (xub_StrLen)rText.Length );
+ }
+ }
+ }
+
+ geometry::RealRectangle2D TextLayoutDrawHelper::queryTextBounds( const rendering::StringContext& rText,
+ const uno::Sequence< double >& rLogicalAdvancements,
+ const uno::Reference< rendering::XCanvasFont >& rCanvasFont,
+ const geometry::Matrix2D& rFontMatrix )
+ {
+ if(!(rText.Length))
+ return geometry::RealRectangle2D();
+
+ // TODO(F1): Fetching default screen DC here, will yield wrong
+ // metrics when e.g. formatting for a printer!
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(GetDC( NULL ));
+ VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
+
+ // create the font
+ const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
+ Font aFont(
+ rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
+
+ aFont.SetAlign( ALIGN_BASELINE );
+ aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
+ aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+ aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+ aFont.SetPitch(
+ rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
+ ? PITCH_FIXED : PITCH_VARIABLE);
+
+ // adjust to stretched font
+ if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
+ {
+ const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
+ const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+ double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+ if( !::basegfx::fTools::equalZero( fDividend) )
+ fStretch /= fDividend;
+
+ const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+ aFont.SetWidth( nNewWidth );
+ }
+
+ // set font
+ aVirtualDevice.SetFont(aFont);
+
+ // need metrics for Y offset, the XCanvas always renders
+ // relative to baseline
+ const ::FontMetric& aMetric( aVirtualDevice.GetFontMetric() );
+
+ const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
+ const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
+
+ if( rLogicalAdvancements.getLength() )
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ rLogicalAdvancements[ rLogicalAdvancements.getLength()-1 ],
+ nBelowBaseline );
+ }
+ else
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ aVirtualDevice.GetTextWidth(
+ rText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(rText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(rText.Length) ),
+ nBelowBaseline );
+ }
+ }
+}
+
+
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_textlayout_drawhelper.hxx b/canvas/source/directx/dx_textlayout_drawhelper.hxx
new file mode 100644
index 000000000000..837e715ec373
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout_drawhelper.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _TEXTLAYOUT_DRAWHELPER_HXX
+#define _TEXTLAYOUT_DRAWHELPER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+class ::com::sun::star::rendering::XCanvasFont;
+
+namespace Gdiplus { class Graphics; }
+
+namespace dxcanvas
+{
+ struct Bitmap;
+ class TextLayoutDrawHelper
+ {
+ public:
+ TextLayoutDrawHelper(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice);
+ ~TextLayoutDrawHelper();
+
+ // draw text
+ void drawText( const boost::shared_ptr<Gdiplus::Graphics>& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
+ bool bAlphaSurface );
+
+ ::com::sun::star::geometry::RealRectangle2D queryTextBounds(
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix );
+
+#ifdef DBG_UTIL
+ void test();
+#endif
+
+ protected:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice > mxGraphicDevice;
+ };
+}
+
+#endif /* _TEXTLAYOUT_DRAWHELPER_HXX */
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_vcltools.cxx b/canvas/source/directx/dx_vcltools.cxx
new file mode 100644
index 000000000000..23b2e00683de
--- /dev/null
+++ b/canvas/source/directx/dx_vcltools.cxx
@@ -0,0 +1,526 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <vcl/canvastools.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "dx_impltools.hxx"
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <boost/scoped_array.hpp>
+
+#include "dx_vcltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ namespace
+ {
+ /// Calc number of colors in given BitmapInfoHeader
+ sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
+ {
+ if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
+ {
+ if( rBIH.biBitCount <= 8 )
+ {
+ if( rBIH.biClrUsed )
+ return rBIH.biClrUsed;
+ else
+ return 1L << rBIH.biBitCount;
+ }
+ }
+ else
+ {
+ BITMAPCOREHEADER* pCoreHeader = (BITMAPCOREHEADER*)&rBIH;
+
+ if( pCoreHeader->bcBitCount <= 8 )
+ return 1L << pCoreHeader->bcBitCount;
+ }
+
+ return 0; // nothing known
+ }
+
+ /// Draw DI bits to given Graphics
+ bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const void* hDIB )
+ {
+ bool bRet( false );
+ BitmapSharedPtr pBitmap;
+
+ const BITMAPINFO* pBI = (BITMAPINFO*)GlobalLock( (HGLOBAL)hDIB );
+
+ if( pBI )
+ {
+ const BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)pBI;
+ const BYTE* pBits = (BYTE*) pBI + *(DWORD*)pBI +
+ calcDIBColorCount( *pBIH ) * sizeof( RGBQUAD );
+
+ // forward to outsourced GDI+ rendering method
+ // (header clashes)
+ bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
+
+ GlobalUnlock( (HGLOBAL)hDIB );
+ }
+
+ return bRet;
+ }
+
+ /** Draw VCL bitmap to given Graphics
+
+ @param rBmp
+ Reference to bitmap. Might get modified, in such a way
+ that it will hold a DIB after a successful function call.
+ */
+ bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ ::Bitmap& rBmp )
+ {
+ BitmapSystemData aBmpSysData;
+
+ if( !rBmp.GetSystemData( aBmpSysData ) ||
+ !aBmpSysData.pDIB )
+ {
+ // first of all, ensure that Bitmap contains a DIB, by
+ // aquiring a read access
+ BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
+
+ // TODO(P2): Acquiring a read access can actually
+ // force a read from VRAM, thus, avoiding this
+ // step somehow will increase performance
+ // here.
+ if( pReadAcc )
+ {
+ // try again: now, WinSalBitmap must have
+ // generated a DIB
+ if( rBmp.GetSystemData( aBmpSysData ) &&
+ aBmpSysData.pDIB )
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ rBmp.ReleaseAccess( pReadAcc );
+ }
+ }
+ else
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ // failed to generate DIBits from vcl bitmap
+ return false;
+ }
+
+ /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BbitmapEX
+ */
+ RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
+ {
+ // TODO(P2): Avoid temporary bitmap generation, maybe
+ // even ensure that created DIBs are copied back to
+ // BmpEx (currently, every AcquireReadAccess() will
+ // make the local bitmap copy unique, effectively
+ // duplicating the memory used)
+
+ ENSURE_OR_THROW( rBmpEx.IsTransparent(),
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "BmpEx not transparent" );
+
+ // convert transparent bitmap to 32bit RGBA
+ // ========================================
+
+ const ::Size aBmpSize( rBmpEx.GetSizePixel() );
+
+ RawRGBABitmap aBmpData;
+ aBmpData.mnWidth = aBmpSize.Width();
+ aBmpData.mnHeight = aBmpSize.Height();
+ aBmpData.mpBitmapData.reset( new sal_uInt8[ 4*aBmpData.mnWidth*aBmpData.mnHeight ] );
+
+ Bitmap aBitmap( rBmpEx.GetBitmap() );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to bitmap" );
+
+ if( rBmpEx.IsAlpha() )
+ {
+ Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
+
+ ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.AcquireReadAccess(),
+ aAlpha );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pAlphaReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to alpha" );
+
+ ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
+ pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported alpha scanline format" );
+
+ BitmapColor aCol;
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+ else
+ {
+ Bitmap aMask( rBmpEx.GetMask() );
+
+ ScopedBitmapReadAccess pMaskReadAccess( aMask.AcquireReadAccess(),
+ aMask );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pMaskReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to mask" );
+
+ ENSURE_OR_THROW( pMaskReadAccess->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported mask scanline format" );
+
+ BitmapColor aCol;
+ int nCurrBit;
+ const int nMask( 1L );
+ const int nInitialBit(7);
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ // mapping table, to get from mask index color to
+ // alpha value (which depends on the mask's palette)
+ sal_uInt8 aColorMap[2];
+
+ const BitmapColor& rCol0( pMaskReadAccess->GetPaletteColor( 0 ) );
+ const BitmapColor& rCol1( pMaskReadAccess->GetPaletteColor( 1 ) );
+
+ // shortcut for true luminance calculation
+ // (assumes that palette is grey-level). Note the
+ // swapped the indices here, to account for the
+ // fact that VCL's notion of alpha is inverted to
+ // the rest of the world's.
+ aColorMap[0] = rCol1.GetRed();
+ aColorMap[1] = rCol0.GetRed();
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ // store as RGBA
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+
+ return aBmpData;
+ }
+
+ bool drawVCLBitmapEx( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const ::BitmapEx& rBmpEx )
+ {
+ if( !rBmpEx.IsTransparent() )
+ {
+ Bitmap aBmp( rBmpEx.GetBitmap() );
+ return drawVCLBitmap( rGraphics, aBmp );
+ }
+ else
+ {
+ return drawRGBABits( rGraphics,
+ bitmapFromVCLBitmapEx( rBmpEx ) );
+ }
+ }
+ }
+
+ bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ // TODO(F2): add support for floating point bitmap formats
+ uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
+ xBitmap, uno::UNO_QUERY );
+
+ if( !xIntBmp.is() )
+ return false;
+
+ ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
+ if( !aBmpEx )
+ return false;
+
+ return drawVCLBitmapEx( rGraphics, aBmpEx );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_vcltools.hxx b/canvas/source/directx/dx_vcltools.hxx
new file mode 100644
index 000000000000..c51ba9e8d9cb
--- /dev/null
+++ b/canvas/source/directx/dx_vcltools.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_VCLTOOLS_HXX
+#define _DXCANVAS_VCLTOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/util/TriState.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace com { namespace sun { namespace star { namespace lang
+{
+ class XUnoTunnel;
+} } } }
+
+namespace Gdiplus { class Graphics; }
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ /** Raw RGBA bitmap data,
+ contiguous in memory
+ */
+ struct RawRGBABitmap
+ {
+ sal_Int32 mnWidth;
+ sal_Int32 mnHeight;
+ ::boost::shared_ptr< sal_uInt8 > mpBitmapData;
+ };
+
+ bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap );
+ }
+}
+
+#endif /* _DXCANVAS_VCLTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/dx_winstuff.hxx b/canvas/source/directx/dx_winstuff.hxx
new file mode 100644
index 000000000000..e92b17c62599
--- /dev/null
+++ b/canvas/source/directx/dx_winstuff.hxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _DXCANVAS_WINSTUFF_HXX
+#define _DXCANVAS_WINSTUFF_HXX
+
+#include <algorithm>
+
+#include <boost/shared_ptr.hpp>
+
+#include <basegfx/numeric/ftools.hxx>
+
+#ifdef _WINDOWS_
+#error someone else included <windows.h>
+#endif
+
+// Enabling Direct3D Debug Information Further more, with registry key
+// \\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Direct3D\D3D9Debugging\\EnableCreationStack
+// set to 1, sets a backtrace each time an object is created to the
+// following global variable: LPCWSTR CreationCallStack
+#if OSL_DEBUG_LEVEL > 0
+# define D3D_DEBUG_INFO
+#endif
+
+#ifndef DIRECTX_VERSION
+#error please define for which directx version we should compile
+#endif
+
+#if defined _MSC_VER
+#pragma warning(push,1)
+#endif
+
+
+#define BOOL win32BOOL
+#define INT32 win32INT32
+#define UINT32 win32UINT32
+#define GradientStyle_RECT win32GradientStyle_RECT
+#define Polygon win32Polygon
+#define PolyPolygon win32PolyPolygon
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h> // TODO(Q1): extract minimal set of required headers for gdiplus
+
+#if DIRECTX_VERSION < 0x0900
+
+ #include <multimon.h>
+
+ // Be compatible with directdraw 3.0. Lets see how far this takes us
+ #define DIRECTDRAW_VERSION 0x0300
+ #include <ddraw.h>
+
+ // Be compatible with direct3d 5.0. Lets see how far this takes us
+ #define DIRECT3D_VERSION 0x0500
+ #define D3D_OVERLOADS
+ #include <d3d.h>
+
+ typedef IDirectDrawSurface surface_type;
+
+#else
+
+ #include <dxsdkver.h>
+ #include <d3d9.h>
+ #include <d3dx9.h>
+ #if _DXSDK_BUILD_MAJOR < 1734 /* Earlier than the August 2009 DXSDK */
+ #include <dxerr9.h>
+ #else
+ #include <dxerr.h>
+ #endif
+
+ typedef IDirect3DSurface9 surface_type;
+
+#endif
+
+#undef DrawText
+
+#ifdef __MINGW32__
+using ::std::max;
+using ::std::min;
+#endif
+
+#include <gdiplus.h>
+
+#ifdef min
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
+namespace dxcanvas
+{
+ // some shared pointer typedefs to Gdiplus objects
+ typedef ::boost::shared_ptr< Gdiplus::Graphics > GraphicsSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::GraphicsPath > GraphicsPathSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Bitmap > BitmapSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::CachedBitmap > CachedBitmapSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Font > FontSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Brush > BrushSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::TextureBrush > TextureBrushSharedPtr;
+
+ /** COM object RAII wrapper
+
+ This template wraps a Windows COM object, transparently
+ handling lifetime issues the C++ way (i.e. releasing the
+ reference when the object is destroyed)
+ */
+ template< typename T > class COMReference
+ {
+ public:
+ typedef T Wrappee;
+
+ COMReference() :
+ mp( NULL )
+ {
+ }
+
+ /** Create from raw pointer
+
+ @attention This constructor assumes the interface is
+ already acquired (unless p is NULL), no additional AddRef
+ is called here.
+
+ This caters e.g. for all DirectX factory methods, which
+ return the created interfaces pre-acquired, into a raw
+ pointer. Simply pass the pointer to this class, but don't
+ call Release manually on it!
+
+ @example IDirectDrawSurface* pSurface;
+ pDD->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ mpSurface = COMReference< IDirectDrawSurface >(pSurface);
+
+ */
+ explicit COMReference( T* p ) :
+ mp( p )
+ {
+ }
+
+ COMReference( const COMReference& rNew ) :
+ mp( NULL )
+ {
+ if( rNew.mp == NULL )
+ return;
+
+ rNew.mp->AddRef(); // do that _before_ assigning the
+ // pointer. Just in case...
+ mp = rNew.mp;
+ }
+
+ COMReference& operator=( const COMReference& rRHS )
+ {
+ COMReference aTmp(rRHS);
+ ::std::swap( mp, aTmp.mp );
+
+ return *this;
+ }
+
+ ~COMReference()
+ {
+ reset();
+ }
+
+ int reset()
+ {
+ int refcount = 0;
+ if( mp )
+ refcount = mp->Release();
+
+ mp = NULL;
+ return refcount;
+ }
+
+ bool is() const { return mp != NULL; }
+ T* get() const { return mp; }
+ T* operator->() const { return mp; }
+ T& operator*() const { return *mp; }
+
+ private:
+ T* mp;
+ };
+
+ // get_pointer() enables boost::mem_fn to recognize COMReference
+ template<class T> inline T * get_pointer(COMReference<T> const& p)
+ {
+ return p.get();
+ }
+}
+
+#if defined _MSC_VER
+#pragma warning(pop)
+#endif
+
+#undef DELETE
+#undef BOOL
+#undef INT32
+#undef UINT32
+#undef PolyPolygon
+
+#endif /* _DXCANVAS_WINSTUFF_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/directx/exports.dxp b/canvas/source/directx/exports.dxp
new file mode 100644
index 000000000000..9630d7e06768
--- /dev/null
+++ b/canvas/source/directx/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory
diff --git a/canvas/source/directx/makefile.mk b/canvas/source/directx/makefile.mk
new file mode 100644
index 000000000000..4ccd5a8448b2
--- /dev/null
+++ b/canvas/source/directx/makefile.mk
@@ -0,0 +1,219 @@
+#*************************************************************************
+#
+# 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=directx9canvas
+TARGET2=directx5canvas
+TARGET3=gdipluscanvas
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Nothing to do if we're compiling with --disable-directx -----------
+.IF "$(ENABLE_DIRECTX)" == ""
+@all:
+ @echo "Building without DirectX support..."
+.ENDIF
+
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+CDEFS+= -DDX_DEBUG_IMAGES
+.ENDIF
+
+# --- This is Windows only! { ----------------------------------------------------------------
+
+.IF "$(GUI)" == "WNT"
+
+SHARED_SLOFILES = \
+ $(SLO)$/dx_bitmap.obj \
+ $(SLO)$/dx_bitmapcanvashelper.obj \
+ $(SLO)$/dx_canvasbitmap.obj \
+ $(SLO)$/dx_canvasfont.obj \
+ $(SLO)$/dx_canvashelper.obj \
+ $(SLO)$/dx_canvashelper_texturefill.obj \
+ $(SLO)$/dx_devicehelper.obj \
+ $(SLO)$/dx_gdiplususer.obj \
+ $(SLO)$/dx_impltools.obj \
+ $(SLO)$/dx_linepolypolygon.obj \
+ $(SLO)$/dx_textlayout.obj \
+ $(SLO)$/dx_textlayout_drawhelper.obj \
+ $(SLO)$/dx_vcltools.obj
+
+DX_SLOFILES = \
+ $(SLO)$/dx_5rm.obj \
+ $(SLO)$/dx_9rm.obj \
+ $(SLO)$/dx_canvascustomsprite.obj \
+ $(SLO)$/dx_config.obj \
+ $(SLO)$/dx_spritecanvas.obj \
+ $(SLO)$/dx_spritecanvashelper.obj \
+ $(SLO)$/dx_spritedevicehelper.obj \
+ $(SLO)$/dx_spritehelper.obj \
+ $(SLO)$/dx_surfacebitmap.obj \
+ $(SLO)$/dx_surfacegraphics.obj
+DX_SLOFILES += $(SHARED_SLOFILES)
+
+GDIPLUS_SLOFILES = \
+ $(SLO)$/dx_canvas.obj
+GDIPLUS_SLOFILES += $(SHARED_SLOFILES)
+
+STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+
+
+########################################################
+# DX9
+########################################################
+
+# Indicates the source obj files for the dx5 lib
+LIB1TARGET= $(SLB)$/$(TARGET).lib
+LIB1OBJFILES = $(DX_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL1TARGET=$(TARGET).uno
+
+# Links import libraries.
+SHL1STDLIBS= $(STDLIBS)
+
+# Specifies an import library to create. For Win32 only.
+SHL1IMPLIB=i$(TARGET)
+
+# Specifies libraries from the same module to put into the shared library.
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+CDEFS+=-DDIRECTX_VERSION=0x0900
+
+SHL1STDLIBS += $(GDI32LIB)
+.IF "$(COM)" == "GCC"
+SHL1STDLIBS += $(DIRECTXSDK_LIB)/d3d9.lib
+.ELSE
+SHL1STDLIBS += d3d9.lib
+.ENDIF
+SHL1STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL1STDLIBS += imdebug.lib
+.ENDIF
+
+
+########################################################
+# DX5
+########################################################
+
+.IF "$(USE_DIRECTX5)" != ""
+SECOND_BUILD=DX5
+DX5_SLOFILES=$(DX_SLOFILES)
+DX5CDEFS += -DDIRECTX_VERSION=0x0500
+
+LIB2TARGET= $(SLB)$/$(TARGET2).lib
+LIB2OBJFILES = $(REAL_DX5_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL2TARGET=$(TARGET2).uno
+
+# Links import libraries.
+SHL2STDLIBS= $(STDLIBS)
+
+# Specifies an import library to create. For Win32 only.
+SHL2IMPLIB=i$(TARGET2).lib
+
+# Specifies libraries from the same module to put into the shared library.
+SHL2LIBS=$(SLB)$/$(TARGET2).lib
+SHL2DEF=$(MISC)$/$(SHL2TARGET).def
+
+DEF2NAME=$(SHL2TARGET)
+DEF2EXPORTFILE=exports.dxp
+
+SHL2STDLIBS += $(GDI32LIB)
+SHL2STDLIBS += $(DDRAWLIB)
+SHL2STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(COM)" == "GCC"
+SHL2STDLIBS += $(DIRECTXSDK_LIB)/d3dx.lib
+.ELSE
+SHL2STDLIBS += d3dx.lib
+.ENDIF
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL2STDLIBS += imdebug.lib
+.ENDIF
+.ENDIF # IF "$(USE_DIRECTX5)" != ""
+
+
+########################################################
+# GDI+
+########################################################
+
+LIB3TARGET= $(SLB)$/$(TARGET3).lib
+LIB3OBJFILES = $(GDIPLUS_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL3TARGET=$(TARGET3).uno
+
+# Links import libraries.
+SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+
+# Specifies an import library to create. For Win32 only.
+SHL3IMPLIB=i$(TARGET3).lib
+
+# Specifies libraries from the same module to put into the shared library.
+SHL3LIBS=$(SLB)$/$(TARGET3).lib
+SHL3DEF=$(MISC)$/$(SHL3TARGET).def
+
+DEF3NAME=$(SHL3TARGET)
+DEF3EXPORTFILE=exports.dxp
+
+SHL3STDLIBS += $(GDI32LIB)
+SHL3STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL3STDLIBS += imdebug.lib
+.ENDIF
+
+.ENDIF # IF "$(GUI)" == "WNT"
+
+# --- This is Windows only! } ----------------------------------------------------------------
+
+# ==========================================================================
+
+.INCLUDE : target.mk
+
diff --git a/canvas/source/factory/cf_service.cxx b/canvas/source/factory/cf_service.cxx
new file mode 100644
index 000000000000..792c3b272470
--- /dev/null
+++ b/canvas/source/factory/cf_service.cxx
@@ -0,0 +1,555 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <osl/mutex.hxx>
+#include <osl/process.h>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <vcl/configsettings.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <boost/bind.hpp>
+#include <vector>
+#include <utility>
+#include <functional>
+#include <algorithm>
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+#define ARLEN(x) (sizeof (x) / sizeof *(x))
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+namespace
+{
+
+OUString SAL_CALL getImplName()
+{
+ return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
+}
+
+Sequence<OUString> SAL_CALL getSuppServices()
+{
+ OUString name = OUSTR("com.sun.star.rendering.CanvasFactory");
+ return Sequence<OUString>(&name, 1);
+}
+
+//==============================================================================
+class CanvasFactory
+ : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
+ lang::XMultiComponentFactory,
+ lang::XMultiServiceFactory >
+{
+ typedef std::pair<OUString,Sequence<OUString> > AvailPair;
+ typedef std::pair<OUString,OUString> CachePair;
+ typedef std::vector< AvailPair > AvailVector;
+ typedef std::vector< CachePair > CacheVector;
+
+
+ mutable ::osl::Mutex m_mutex;
+ Reference<XComponentContext> m_xContext;
+ Reference<container::XNameAccess> m_xCanvasConfigNameAccess;
+ AvailVector m_aAvailableImplementations;
+ AvailVector m_aAcceleratedImplementations;
+ AvailVector m_aAAImplementations;
+ mutable CacheVector m_aCachedImplementations;
+ mutable bool m_bCacheHasForcedLastImpl;
+ mutable bool m_bCacheHasUseAcceleratedEntry;
+ mutable bool m_bCacheHasUseAAEntry;
+
+ void checkConfigFlag( bool& r_bFlag,
+ bool& r_CacheFlag,
+ const OUString& nodeName ) const;
+ Reference<XInterface> use(
+ OUString const & serviceName,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const;
+ Reference<XInterface> lookupAndUse(
+ OUString const & serviceName, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const;
+
+public:
+ virtual ~CanvasFactory();
+ CanvasFactory( Reference<XComponentContext> const & xContext );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
+ throw (RuntimeException);
+ virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+
+ // XMultiComponentFactory
+ virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
+ throw (RuntimeException);
+ virtual Reference<XInterface> SAL_CALL createInstanceWithContext(
+ OUString const & name,
+ Reference<XComponentContext> const & xContext ) throw (Exception);
+ virtual Reference<XInterface> SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ OUString const & name,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) throw (Exception);
+
+ // XMultiServiceFactory
+ virtual Reference<XInterface> SAL_CALL createInstance(
+ OUString const & name )
+ throw (Exception);
+ virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
+ OUString const & name, Sequence<Any> const & args )
+ throw (Exception);
+};
+
+CanvasFactory::CanvasFactory( Reference<XComponentContext> const & xContext ) :
+ m_mutex(),
+ m_xContext(xContext),
+ m_xCanvasConfigNameAccess(),
+ m_aAvailableImplementations(),
+ m_aAcceleratedImplementations(),
+ m_aAAImplementations(),
+ m_aCachedImplementations(),
+ m_bCacheHasForcedLastImpl(),
+ m_bCacheHasUseAcceleratedEntry(),
+ m_bCacheHasUseAAEntry()
+{
+ try
+ {
+ // read out configuration for preferred services:
+ Reference<lang::XMultiServiceFactory> xConfigProvider(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ OUSTR("com.sun.star.configuration.ConfigurationProvider"),
+ m_xContext ), UNO_QUERY_THROW );
+
+ Any propValue(
+ makeAny( beans::PropertyValue(
+ OUSTR("nodepath"), -1,
+ makeAny( OUSTR("/org.openoffice.Office.Canvas") ),
+ beans::PropertyState_DIRECT_VALUE ) ) );
+
+ m_xCanvasConfigNameAccess.set(
+ xConfigProvider->createInstanceWithArguments(
+ OUSTR("com.sun.star.configuration.ConfigurationAccess"),
+ Sequence<Any>( &propValue, 1 ) ),
+ UNO_QUERY_THROW );
+
+ propValue = makeAny(
+ beans::PropertyValue(
+ OUSTR("nodepath"), -1,
+ makeAny( OUSTR("/org.openoffice.Office.Canvas/CanvasServiceList") ),
+ beans::PropertyState_DIRECT_VALUE ) );
+
+ Reference<container::XNameAccess> xNameAccess(
+ xConfigProvider->createInstanceWithArguments(
+ OUSTR("com.sun.star.configuration.ConfigurationAccess"),
+ Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW );
+ Reference<container::XHierarchicalNameAccess> xHierarchicalNameAccess(
+ xNameAccess, UNO_QUERY_THROW);
+
+ Sequence<OUString> serviceNames = xNameAccess->getElementNames();
+ const OUString* pCurr = serviceNames.getConstArray();
+ const OUString* const pEnd = pCurr + serviceNames.getLength();
+ while( pCurr != pEnd )
+ {
+ Reference<container::XNameAccess> xEntryNameAccess(
+ xHierarchicalNameAccess->getByHierarchicalName(*pCurr),
+ UNO_QUERY );
+
+ if( xEntryNameAccess.is() )
+ {
+ Sequence<OUString> implementationList;
+ if( (xEntryNameAccess->getByName( OUSTR("PreferredImplementations") ) >>= implementationList) )
+ m_aAvailableImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ if( (xEntryNameAccess->getByName( OUSTR("AcceleratedImplementations") ) >>= implementationList) )
+ m_aAcceleratedImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ if( (xEntryNameAccess->getByName( OUSTR("AntialiasingImplementations") ) >>= implementationList) )
+ m_aAAImplementations.push_back( std::make_pair(*pCurr,implementationList) );
+ }
+
+ ++pCurr;
+ }
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception&)
+ {
+ }
+
+ if( m_aAvailableImplementations.empty() )
+ {
+ // Ugh. Looks like configuration is borked. Fake minimal
+ // setup.
+ Sequence<OUString> aServices(1);
+ aServices[0] = OUSTR("com.sun.star.comp.rendering.Canvas.VCL");
+ m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.Canvas"),
+ aServices) );
+
+ aServices[0] = OUSTR("com.sun.star.comp.rendering.SpriteCanvas.VCL");
+ m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.SpriteCanvas"),
+ aServices) );
+ }
+}
+
+CanvasFactory::~CanvasFactory()
+{
+}
+
+//------------------------------------------------------------------------------
+Reference<XInterface> create( Reference<XComponentContext> const & xContext )
+{
+ return static_cast< ::cppu::OWeakObject * >(
+ new CanvasFactory( xContext ) );
+}
+
+// XServiceInfo
+//______________________________________________________________________________
+OUString CanvasFactory::getImplementationName() throw (RuntimeException)
+{
+ return getImplName();
+}
+
+//______________________________________________________________________________
+sal_Bool CanvasFactory::supportsService( OUString const & serviceName )
+ throw (RuntimeException)
+{
+ return serviceName.equals(getSuppServices()[0]);
+}
+
+//______________________________________________________________________________
+Sequence<OUString> CanvasFactory::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return getSuppServices();
+}
+
+// XMultiComponentFactory
+//______________________________________________________________________________
+Sequence<OUString> CanvasFactory::getAvailableServiceNames()
+ throw (RuntimeException)
+{
+ Sequence<OUString> aServiceNames(m_aAvailableImplementations.size());
+ std::transform(m_aAvailableImplementations.begin(),
+ m_aAvailableImplementations.end(),
+ aServiceNames.getArray(),
+ std::select1st<AvailPair>());
+ return aServiceNames;
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithContext(
+ OUString const & name, Reference<XComponentContext> const & xContext )
+ throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, Sequence<Any>(), xContext );
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::use(
+ OUString const & serviceName,
+ Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const
+{
+ try {
+ return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ serviceName, args, xContext);
+ }
+ catch (RuntimeException &)
+ {
+ throw;
+ }
+ catch (Exception &)
+ {
+ return Reference<XInterface>();
+ }
+}
+
+//______________________________________________________________________________
+void CanvasFactory::checkConfigFlag( bool& r_bFlag,
+ bool& r_CacheFlag,
+ const OUString& nodeName ) const
+{
+ if( m_xCanvasConfigNameAccess.is() )
+ {
+ m_xCanvasConfigNameAccess->getByName( nodeName ) >>= r_bFlag;
+
+ if( r_CacheFlag != r_bFlag )
+ {
+ // cache is invalid, because of different order of
+ // elements
+ r_CacheFlag = r_bFlag;
+ m_aCachedImplementations.clear();
+ }
+ }
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::lookupAndUse(
+ OUString const & serviceName, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) const
+{
+ ::osl::MutexGuard guard(m_mutex);
+
+ // forcing last entry from impl list, if config flag set
+ bool bForceLastEntry(false);
+ checkConfigFlag( bForceLastEntry,
+ m_bCacheHasForcedLastImpl,
+ OUSTR("ForceSafeServiceImpl") );
+
+ // use anti-aliasing canvas, if config flag set (or not existing)
+ bool bUseAAEntry(true);
+ checkConfigFlag( bUseAAEntry,
+ m_bCacheHasUseAAEntry,
+ OUSTR("UseAntialiasingCanvas") );
+
+ // use accelerated canvas, if config flag set (or not existing)
+ bool bUseAcceleratedEntry(true);
+ checkConfigFlag( bUseAcceleratedEntry,
+ m_bCacheHasUseAcceleratedEntry,
+ OUSTR("UseAcceleratedCanvas") );
+
+ // try to reuse last working implementation for given service name
+ const CacheVector::iterator aEnd(m_aCachedImplementations.end());
+ CacheVector::iterator aMatch;
+ if( (aMatch=std::find_if(m_aCachedImplementations.begin(),
+ aEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<CachePair>(),
+ _1)))) != aEnd )
+ {
+ Reference<XInterface> xCanvas( use( aMatch->second, args, xContext ) );
+ if(xCanvas.is())
+ return xCanvas;
+ }
+
+ // lookup in available service list
+ const AvailVector::const_iterator aAvailEnd(m_aAvailableImplementations.end());
+ AvailVector::const_iterator aAvailImplsMatch;
+ if( (aAvailImplsMatch=std::find_if(m_aAvailableImplementations.begin(),
+ aAvailEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAvailEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const AvailVector::const_iterator aAAEnd(m_aAAImplementations.end());
+ AvailVector::const_iterator aAAImplsMatch;
+ if( (aAAImplsMatch=std::find_if(m_aAAImplementations.begin(),
+ aAAEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAAEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const AvailVector::const_iterator aAccelEnd(m_aAcceleratedImplementations.end());
+ AvailVector::const_iterator aAccelImplsMatch;
+ if( (aAccelImplsMatch=std::find_if(m_aAcceleratedImplementations.begin(),
+ aAccelEnd,
+ boost::bind(&OUString::equals,
+ boost::cref(serviceName),
+ boost::bind(
+ std::select1st<AvailPair>(),
+ _1)))) == aAccelEnd )
+ {
+ return Reference<XInterface>();
+ }
+
+ const Sequence<OUString> aPreferredImpls( aAvailImplsMatch->second );
+ const OUString* pCurrImpl = aPreferredImpls.getConstArray();
+ const OUString* const pEndImpl = pCurrImpl + aPreferredImpls.getLength();
+
+ const Sequence<OUString> aAAImpls( aAAImplsMatch->second );
+ const OUString* const pFirstAAImpl = aAAImpls.getConstArray();
+ const OUString* const pEndAAImpl = pFirstAAImpl + aAAImpls.getLength();
+
+ const Sequence<OUString> aAccelImpls( aAccelImplsMatch->second );
+ const OUString* const pFirstAccelImpl = aAccelImpls.getConstArray();
+ const OUString* const pEndAccelImpl = pFirstAccelImpl + aAccelImpls.getLength();
+
+ // force last entry from impl list, if config flag set
+ if( bForceLastEntry )
+ pCurrImpl = pEndImpl-1;
+
+ while( pCurrImpl != pEndImpl )
+ {
+ const OUString aCurrName(pCurrImpl->trim());
+
+ // check whether given canvas service is listed in the
+ // sequence of "accelerated canvas implementations"
+ const bool bIsAcceleratedImpl(
+ std::find_if(pFirstAccelImpl,
+ pEndAccelImpl,
+ boost::bind(&OUString::equals,
+ boost::cref(aCurrName),
+ boost::bind(
+ &OUString::trim,
+ _1))) != pEndAccelImpl );
+
+ // check whether given canvas service is listed in the
+ // sequence of "antialiasing canvas implementations"
+ const bool bIsAAImpl(
+ std::find_if(pFirstAAImpl,
+ pEndAAImpl,
+ boost::bind(&OUString::equals,
+ boost::cref(aCurrName),
+ boost::bind(
+ &OUString::trim,
+ _1))) != pEndAAImpl );
+
+ // try to instantiate canvas *only* if either accel and AA
+ // property match preference, *or*, if there's a mismatch, only
+ // go for a less capable canvas (that effectively let those
+ // pour canvas impls still work as fallbacks, should an
+ // accelerated/AA one fail). Property implies configuration:
+ // http://en.wikipedia.org/wiki/Truth_table#Logical_implication
+ if( (!bIsAAImpl || bUseAAEntry) && (!bIsAcceleratedImpl || bUseAcceleratedEntry) )
+ {
+ Reference<XInterface> xCanvas(
+ use( pCurrImpl->trim(), args, xContext ) );
+
+ if(xCanvas.is())
+ {
+ if( aMatch != aEnd )
+ {
+ // cache entry exists, replace dysfunctional
+ // implementation name
+ aMatch->second = pCurrImpl->trim();
+ }
+ else
+ {
+ // new service name, add new cache entry
+ m_aCachedImplementations.push_back(std::make_pair(serviceName,
+ pCurrImpl->trim()));
+ }
+
+ return xCanvas;
+ }
+ }
+
+ ++pCurrImpl;
+ }
+
+ return Reference<XInterface>();
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithArgumentsAndContext(
+ OUString const & preferredOne, Sequence<Any> const & args,
+ Reference<XComponentContext> const & xContext ) throw (Exception)
+{
+ Reference<XInterface> xCanvas(
+ lookupAndUse( preferredOne, args, xContext ) );
+ if(xCanvas.is())
+ return xCanvas;
+
+ // last resort: try service name directly
+ return use( preferredOne, args, xContext );
+}
+
+// XMultiServiceFactory
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
+ throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, Sequence<Any>(), m_xContext );
+}
+
+//______________________________________________________________________________
+Reference<XInterface> CanvasFactory::createInstanceWithArguments(
+ OUString const & name, Sequence<Any> const & args ) throw (Exception)
+{
+ return createInstanceWithArgumentsAndContext(
+ name, args, m_xContext );
+}
+
+const ::cppu::ImplementationEntry s_entries [] = {
+ {
+ create,
+ getImplName,
+ getSuppServices,
+ ::cppu::createSingleComponentFactory,
+ 0, 0
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+} // anon namespace
+
+extern "C" {
+
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+sal_Bool SAL_CALL component_writeInfo(
+ lang::XMultiServiceFactory * pServiceManager,
+ registry::XRegistryKey * pRegistryKey )
+{
+ return ::cppu::component_writeInfoHelper(
+ pServiceManager, pRegistryKey, s_entries );
+}
+
+void * SAL_CALL component_getFactory(
+ sal_Char const * pImplName,
+ lang::XMultiServiceFactory * pServiceManager,
+ registry::XRegistryKey * pRegistryKey )
+{
+ return ::cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey, s_entries );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/factory/makefile.mk b/canvas/source/factory/makefile.mk
new file mode 100644
index 000000000000..fc6d423192d6
--- /dev/null
+++ b/canvas/source/factory/makefile.mk
@@ -0,0 +1,56 @@
+#*************************************************************************
+#
+# 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 = canvasfactory.uno
+ENABLE_EXCEPTIONS = TRUE
+
+.INCLUDE : settings.mk
+DLLPRE =
+.IF "$(L10N_framework)"==""
+SLOFILES = \
+ $(SLO)$/cf_service.obj
+
+SHL1TARGET = $(TARGET)
+
+SHL1STDLIBS = \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB) \
+ $(SALLIB)
+SHL1VERSIONMAP = $(SOLARENV)/src/component.map
+
+SHL1DEPN =
+SHL1IMPLIB = i$(TARGET)
+SHL1LIBS = $(SLB)$/$(TARGET).lib
+SHL1DEF = $(MISC)$/$(SHL1TARGET).def
+
+DEF1NAME = $(SHL1TARGET)
+.ENDIF
+.INCLUDE : target.mk
+
diff --git a/canvas/source/null/exports.dxp b/canvas/source/null/exports.dxp
new file mode 100644
index 000000000000..9630d7e06768
--- /dev/null
+++ b/canvas/source/null/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory
diff --git a/canvas/source/null/makefile.mk b/canvas/source/null/makefile.mk
new file mode 100644
index 000000000000..07971ef8153e
--- /dev/null
+++ b/canvas/source/null/makefile.mk
@@ -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.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=canvas
+TARGET=nullcanvas
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+.IF "$(L10N_framework)"==""
+SLOFILES = $(SLO)$/null_canvasbitmap.obj \
+ $(SLO)$/null_canvascustomsprite.obj \
+ $(SLO)$/null_canvasfont.obj \
+ $(SLO)$/null_canvashelper.obj \
+ $(SLO)$/null_devicehelper.obj \
+ $(SLO)$/null_spritecanvas.obj \
+ $(SLO)$/null_spritecanvashelper.obj \
+ $(SLO)$/null_spritehelper.obj \
+ $(SLO)$/null_textlayout.obj
+
+SHL1TARGET=$(TARGET).uno
+
+SHL1STDLIBS= $(CPPULIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB)
+
+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
diff --git a/canvas/source/null/null_canvasbitmap.cxx b/canvas/source/null/null_canvasbitmap.cxx
new file mode 100644
index 000000000000..f157890c05b8
--- /dev/null
+++ b/canvas/source/null/null_canvasbitmap.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/canvastools.hxx>
+
+#include "null_canvasbitmap.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize,
+ const DeviceRef& rDevice,
+ bool bHasAlpha ) :
+ mpDevice( rDevice )
+ {
+ ENSURE_OR_THROW( mpDevice.is(),
+ "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
+
+ maCanvasHelper.init( rSize,
+ *mpDevice.get(),
+ bHasAlpha );
+ }
+
+ void SAL_CALL CanvasBitmap::disposing()
+ {
+ mpDevice.clear();
+
+ // forward to parent
+ CanvasBitmap_Base::disposing();
+ }
+
+#define IMPLEMENTATION_NAME "NullCanvas.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;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvasbitmap.hxx b/canvas/source/null/null_canvasbitmap.hxx
new file mode 100644
index 000000000000..cd8f4aa71ef9
--- /dev/null
+++ b/canvas/source/null/null_canvasbitmap.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_CANVASBITMAP_HXX
+#define _NULLCANVAS_CANVASBITMAP_HXX
+
+#include <cppuhelper/compbase3.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <canvas/base/integerbitmapbase.hxx>
+
+#include "null_canvashelper.hxx"
+#include "null_spritecanvas.hxx"
+#include "null_usagecounter.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace nullcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper3< ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::lang::XServiceInfo > CanvasBitmapBase_Base;
+ typedef ::canvas::IntegerBitmapBase< ::canvas::BaseMutexHelper< CanvasBitmapBase_Base >,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBitmap_Base;
+
+ class CanvasBitmap : public CanvasBitmap_Base,
+ private UsageCounter< CanvasBitmap >
+ {
+ 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 DeviceRef& rDevice,
+ bool bHasAlpha );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // 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);
+
+ private:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ DeviceRef mpDevice;
+ };
+}
+
+#endif /* _NULLCANVAS_CANVASBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvascustomsprite.cxx b/canvas/source/null/null_canvascustomsprite.cxx
new file mode 100644
index 000000000000..b9e194a26a6f
--- /dev/null
+++ b/canvas/source/null/null_canvascustomsprite.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+#include "null_canvascustomsprite.hxx"
+#include "null_spritecanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice ) :
+ mpSpriteCanvas( rRefDevice )
+ {
+ ENSURE_OR_THROW( rRefDevice.get(),
+ "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+ maCanvasHelper.init( ::basegfx::B2ISize(
+ ::canvas::tools::roundUp( rSpriteSize.Width ),
+ ::canvas::tools::roundUp( rSpriteSize.Height ) ),
+ *rRefDevice.get(),
+ true );
+
+ maSpriteHelper.init( rSpriteSize,
+ rRefDevice );
+ }
+
+ void SAL_CALL CanvasCustomSprite::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteBaseT::disposing();
+ }
+
+ void CanvasCustomSprite::redraw() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maSpriteHelper.redraw( mbSurfaceDirty );
+ }
+
+#define IMPLEMENTATION_NAME "NullCanvas.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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvascustomsprite.hxx b/canvas/source/null/null_canvascustomsprite.hxx
new file mode 100644
index 000000000000..5435ed0ed39a
--- /dev/null
+++ b/canvas/source/null/null_canvascustomsprite.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_CANVASCUSTOMSPRITE_HXX
+#define _NULLCANVAS_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 "sprite.hxx"
+#include "null_canvashelper.hxx"
+#include "null_spritehelper.hxx"
+#include "null_spritecanvas.hxx"
+#include "null_usagecounter.hxx"
+
+
+namespace nullcanvas
+{
+ 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
+ {
+ };
+
+ typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
+ SpriteHelper,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasCustomSpriteBaseT;
+
+ /* Definition of CanvasCustomSprite class */
+
+ class CanvasCustomSprite : public CanvasCustomSpriteBaseT,
+ private UsageCounter< CanvasCustomSprite >
+ {
+ 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;
+
+ private:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ SpriteCanvasRef mpSpriteCanvas;
+ };
+}
+
+#endif /* _NULLCANVAS_CANVASCUSTOMSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvasfont.cxx b/canvas/source/null/null_canvasfont.cxx
new file mode 100644
index 000000000000..b9ea625ce758
--- /dev/null
+++ b/canvas/source/null/null_canvasfont.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "null_canvasfont.hxx"
+#include "null_textlayout.hxx"
+#include "null_spritecanvas.hxx"
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/PanoseWeight.hpp>
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
+ const uno::Sequence< beans::PropertyValue >& /*extraFontProperties*/,
+ const geometry::Matrix2D& fontMatrix ) :
+ CanvasFont_Base( m_aMutex ),
+ maFontRequest( rFontRequest ),
+ maFontMatrix( fontMatrix )
+ {
+ }
+
+ void SAL_CALL CanvasFont::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) );
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+ rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::FontMetrics();
+ }
+
+#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"
+#define IMPLEMENTATION_NAME "NullCanvas::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;
+ }
+
+ const ::com::sun::star::geometry::Matrix2D& CanvasFont::getFontMatrix() const
+ {
+ return maFontMatrix;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvasfont.hxx b/canvas/source/null/null_canvasfont.hxx
new file mode 100644
index 000000000000..c4975b20f2db
--- /dev/null
+++ b/canvas/source/null/null_canvasfont.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_CANVASFONT_HXX
+#define _NULLCANVAS_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/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <rtl/ref.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "null_usagecounter.hxx"
+
+
+/* Definition of CanvasFont class */
+
+namespace nullcanvas
+{
+ class SpriteCanvas;
+
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XCanvasFont,
+ ::com::sun::star::lang::XServiceInfo > CanvasFont_Base;
+
+ class CanvasFont : public ::comphelper::OBaseMutex,
+ public CanvasFont_Base,
+ private UsageCounter< CanvasFont >,
+ private ::boost::noncopyable
+ {
+ public:
+ typedef ::comphelper::ImplementationReference<
+ CanvasFont,
+ ::com::sun::star::rendering::XCanvasFont > ImplRef;
+
+ CanvasFont( const ::com::sun::star::rendering::FontRequest& fontRequest,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& extraFontProperties,
+ const ::com::sun::star::geometry::Matrix2D& fontMatrix );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XCanvasFont
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > SAL_CALL createTextLayout( const ::com::sun::star::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontRequest SAL_CALL getFontRequest( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontMetrics SAL_CALL getFontMetrics( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getAvailableSizes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // 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 );
+
+ const ::com::sun::star::geometry::Matrix2D& getFontMatrix() const;
+
+ private:
+ ::com::sun::star::rendering::FontRequest maFontRequest;
+ ::com::sun::star::geometry::Matrix2D maFontMatrix;
+ };
+
+}
+
+#endif /* _NULLCANVAS_CANVASFONT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvashelper.cxx b/canvas/source/null/null_canvashelper.cxx
new file mode 100644
index 000000000000..e22f1dfdf0eb
--- /dev/null
+++ b/canvas/source/null/null_canvashelper.cxx
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <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 <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "null_spritecanvas.hxx"
+#include "null_canvasfont.hxx"
+#include "null_textlayout.hxx"
+#include "null_canvashelper.hxx"
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ CanvasHelper::CanvasHelper() :
+ mpDevice( NULL ),
+ maSize(),
+ mbHaveAlpha()
+ {
+ }
+
+ void CanvasHelper::disposing()
+ {
+ mpDevice = NULL;
+ }
+
+ void CanvasHelper::init( const ::basegfx::B2ISize& rSize,
+ SpriteCanvas& rDevice,
+ bool bHasAlpha )
+ {
+ mpDevice = &rDevice;
+ maSize = rSize;
+ mbHaveAlpha = bHasAlpha;
+ }
+
+ void CanvasHelper::clear()
+ {
+ }
+
+ void CanvasHelper::drawPoint( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& /*aPoint*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ }
+
+ void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& /*aPoint1*/,
+ const geometry::RealPoint2D& /*aPoint2*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ }
+
+ void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealBezierSegment2D& /*aBezierSegment*/,
+ const geometry::RealPoint2D& /*aEndPoint*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontRequest& fontRequest,
+ const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+ const geometry::Matrix2D& fontMatrix )
+ {
+ return uno::Reference< rendering::XCanvasFont >(
+ new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
+ }
+
+ uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontInfo& /*aFilter*/,
+ const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
+ {
+ // TODO
+ return uno::Sequence< rendering::FontInfo >();
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::StringContext& /*text*/,
+ const uno::Reference< rendering::XCanvasFont >& /*xFont*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ sal_Int8 /*textDirection*/ )
+ {
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xLayoutetText.is(),
+ "CanvasHelper::drawTextLayout: layout is NULL");
+
+ TextLayout* pTextLayout =
+ dynamic_cast< TextLayout* >( xLayoutetText.get() );
+
+ ENSURE_OR_THROW( pTextLayout,
+ "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+
+ pTextLayout->draw( viewState,
+ renderState,
+ mpDevice );
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmap >& /*xBitmap*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmap >& /*xBitmap*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/ )
+ {
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+ {
+ return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+ }
+
+ void CanvasHelper::copyRect( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmapCanvas >& /*sourceCanvas*/,
+ const geometry::RealRectangle2D& /*sourceRect*/,
+ const rendering::ViewState& /*sourceViewState*/,
+ const rendering::RenderState& /*sourceRenderState*/,
+ const geometry::RealRectangle2D& /*destRect*/,
+ const rendering::ViewState& /*destViewState*/,
+ const rendering::RenderState& /*destRenderState*/ )
+ {
+ // TODO(F2): copyRect NYI
+ }
+
+ geometry::IntegerSize2D CanvasHelper::getSize()
+ {
+ if( !mpDevice )
+ 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*/ )
+ {
+ // TODO(F1):
+ return uno::Reference< rendering::XBitmap >();
+ }
+
+ uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& /*rect*/ )
+ {
+ // TODO
+ 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 >();
+ }
+
+ rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout()
+ {
+ return ::canvas::tools::getStdMemoryLayout(getSize());
+ }
+
+ void CanvasHelper::flush() const
+ {
+ }
+
+ bool CanvasHelper::hasAlpha() const
+ {
+ return mbHaveAlpha;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_canvashelper.hxx b/canvas/source/null/null_canvashelper.hxx
new file mode 100644
index 000000000000..b94768fb36a0
--- /dev/null
+++ b/canvas/source/null/null_canvashelper.hxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_CANVASHELPER_HXX_
+#define _NULLCANVAS_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 <boost/utility.hpp>
+
+
+namespace nullcanvas
+{
+ class SpriteCanvas;
+
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ HDC to render into.
+ */
+ 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,
+ SpriteCanvas& rDevice,
+ 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;
+
+ protected:
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for spritecanvas.
+ */
+ SpriteCanvas* mpDevice;
+
+ private:
+ /// Current size of the output surface in pixel
+ ::basegfx::B2ISize maSize;
+
+ /// When true, content is able to represent alpha
+ bool mbHaveAlpha;
+ };
+}
+
+#endif /* _NULLCANVAS_CANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_devicehelper.cxx b/canvas/source/null/null_devicehelper.cxx
new file mode 100644
index 000000000000..e35c2023f310
--- /dev/null
+++ b/canvas/source/null/null_devicehelper.cxx
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <rtl/instance.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+#include <vcl/canvastools.hxx>
+
+#include "null_spritecanvas.hxx"
+#include "null_canvasbitmap.hxx"
+#include "null_devicehelper.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ DeviceHelper::DeviceHelper() :
+ mpSpriteCanvas( NULL ),
+ maSize(),
+ mbFullScreen(false)
+ {
+ }
+
+ void DeviceHelper::init( SpriteCanvas& rSpriteCanvas,
+ const ::basegfx::B2ISize& rSize,
+ bool bFullscreen )
+ {
+ mpSpriteCanvas = &rSpriteCanvas;
+ maSize = rSize;
+ mbFullScreen = bFullscreen;
+ }
+
+ void DeviceHelper::disposing()
+ {
+ // release all references
+ mpSpriteCanvas = NULL;
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalResolution()
+ {
+ return geometry::RealSize2D( 75, 75 );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalSize()
+ {
+ return geometry::RealSize2D( 210, 280 );
+ }
+
+ uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ // disposed?
+ if( !mpSpriteCanvas )
+ 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 >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
+ {
+ // disposed?
+ if( !mpSpriteCanvas )
+ 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( !mpSpriteCanvas )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
+ mpSpriteCanvas,
+ false ));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ 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( !mpSpriteCanvas )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
+ mpSpriteCanvas,
+ true ));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ 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;
+ }
+
+ ::sal_Int32 DeviceHelper::createBuffers( ::sal_Int32 /*nBuffers*/ )
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ return 1;
+ }
+
+ void DeviceHelper::destroyBuffers()
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ }
+
+ ::sal_Bool DeviceHelper::showBuffer( bool bIsVisible, ::sal_Bool bUpdateAll )
+ {
+ // forward to sprite canvas helper
+ if( !bIsVisible || !mpSpriteCanvas )
+ return false;
+
+ return mpSpriteCanvas->updateScreen( bUpdateAll );
+ }
+
+ ::sal_Bool DeviceHelper::switchBuffer( bool bIsVisible, ::sal_Bool bUpdateAll )
+ {
+ // no difference for VCL canvas
+ return showBuffer( bIsVisible, bUpdateAll );
+ }
+
+ uno::Any DeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(false);
+ }
+
+ uno::Any DeviceHelper::getDeviceHandle() const
+ {
+ return uno::Any();
+ }
+
+ 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::notifySizeUpdate( const awt::Rectangle& /*rBounds*/ )
+ {
+ // TODO
+ }
+
+ void DeviceHelper::dumpScreenContent() const
+ {
+ OSL_TRACE( "%s\n",
+ BOOST_CURRENT_FUNCTION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_devicehelper.hxx b/canvas/source/null/null_devicehelper.hxx
new file mode 100644
index 000000000000..33560778d52d
--- /dev/null
+++ b/canvas/source/null/null_devicehelper.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_DEVICEHELPER_HXX
+#define _NULLCANVAS_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>
+
+
+/* Definition of DeviceHelper class */
+
+namespace nullcanvas
+{
+ class SpriteCanvas;
+ class SpriteCanvasHelper;
+
+ class DeviceHelper : private ::boost::noncopyable
+ {
+ public:
+ DeviceHelper();
+
+ void init( SpriteCanvas& rSpriteCanvas,
+ const ::basegfx::B2ISize& rSize,
+ bool bFullscreen );
+
+ /// 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 );
+
+ ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
+ void destroyBuffers( );
+ ::sal_Bool showBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+ ::sal_Bool switchBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+
+ ::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;
+
+ void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const;
+
+ private:
+ /// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
+ SpriteCanvas* mpSpriteCanvas;
+ ::basegfx::B2ISize maSize;
+ bool mbFullScreen;
+ };
+}
+
+#endif /* _NULLCANVAS_WINDOWGRAPHICDEVICE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritecanvas.cxx b/canvas/source/null/null_spritecanvas.cxx
new file mode 100644
index 000000000000..3e98e51a746a
--- /dev/null
+++ b/canvas/source/null/null_spritecanvas.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#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 <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "null_spritecanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+#define SERVICE_NAME "com.sun.star.rendering.NullCanvas"
+
+namespace nullcanvas
+{
+ SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void SpriteCanvas::initialize()
+ {
+ // #i64742# Only call initialize when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "SpriteCanvas::initialize called" );
+
+ // At index 1, we expect a system window handle here,
+ // containing a pointer to a valid window, on which to output
+ // At index 2, we expect the current window bound rect
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 4 &&
+ maArguments[1].getValueTypeClass() == uno::TypeClass_LONG,
+ "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ awt::Rectangle aRect;
+ maArguments[2] >>= aRect;
+ const ::basegfx::B2ISize aSize(aRect.Width,
+ aRect.Height);
+
+ sal_Bool bIsFullscreen( sal_False );
+ maArguments[3] >>= bIsFullscreen;
+
+ // setup helper
+ maDeviceHelper.init( *this,
+ aSize,
+ bIsFullscreen );
+ maCanvasHelper.init( maRedrawManager,
+ *this,
+ aSize,
+ false );
+
+ 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)
+ {
+ ::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 : SpriteCanvasBaseT::showBuffer( bUpdateAll );
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::switchBuffer( ::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 : SpriteCanvasBaseT::switchBuffer( 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( SERVICE_NAME ) );
+ }
+
+ static uno::Reference<uno::XInterface> initCanvas( 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> > serviceImpl(&initCanvas);
+ const sdecl::ServiceDecl nullCanvasDecl(
+ serviceImpl,
+ "com.sun.star.comp.rendering.NullCanvas",
+ SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(nullcanvas::nullCanvasDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritecanvas.hxx b/canvas/source/null/null_spritecanvas.hxx
new file mode 100644
index 000000000000..c10b5d0a61e4
--- /dev/null
+++ b/canvas/source/null/null_spritecanvas.hxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_SPRITECANVAS_HXX_
+#define _NULLCANVAS_SPRITECANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/awt/XWindowListener.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 <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <cppuhelper/compbase8.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/spritecanvasbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/bufferedgraphicdevicebase.hxx>
+
+#include "null_spritecanvashelper.hxx"
+#include "null_devicehelper.hxx"
+#include "null_usagecounter.hxx"
+
+
+namespace nullcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper8< ::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::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > WindowGraphicDeviceBase_Base;
+ typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::BaseMutexHelper< WindowGraphicDeviceBase_Base >,
+ DeviceHelper,
+ ::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
+ {
+ };
+
+ 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,
+ private UsageCounter< SpriteCanvas >
+ {
+ 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);
+
+ 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;
+ typedef ::rtl::Reference< SpriteCanvas > DeviceRef;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritecanvashelper.cxx b/canvas/source/null/null_spritecanvashelper.cxx
new file mode 100644
index 000000000000..3f1b9ce6a4ca
--- /dev/null
+++ b/canvas/source/null/null_spritecanvashelper.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <comphelper/scopeguard.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/cast.hpp>
+
+#include "null_spritecanvashelper.hxx"
+#include "null_canvascustomsprite.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ SpriteCanvasHelper::SpriteCanvasHelper() :
+ mpRedrawManager( NULL )
+ {
+ }
+
+ void SpriteCanvasHelper::init( ::canvas::SpriteRedrawManager& rManager,
+ SpriteCanvas& rDevice,
+ const ::basegfx::B2ISize& rSize,
+ bool bHasAlpha )
+ {
+ mpRedrawManager = &rManager;
+
+ CanvasHelper::init( rSize, rDevice, bHasAlpha );
+ }
+
+ void SpriteCanvasHelper::disposing()
+ {
+ mpRedrawManager = NULL;
+
+ // forward to base
+ CanvasHelper::disposing();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
+ const uno::Reference< rendering::XAnimation >& /*animation*/ )
+ {
+ 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,
+ mpDevice ) );
+ }
+
+ uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
+ {
+ return uno::Reference< rendering::XSprite >();
+ }
+
+ sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRange& /*rCurrArea*/,
+ sal_Bool /*bUpdateAll*/,
+ bool& /*io_bSurfaceDirty*/ )
+ {
+ // TODO
+ return sal_True;
+ }
+
+ void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& /*rUpdateRect*/ )
+ {
+ // TODO
+ }
+
+ void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/,
+ const ::basegfx::B2DRange& /*rMoveEnd*/,
+ const ::canvas::SpriteRedrawManager::UpdateArea& /*rUpdateArea*/ )
+ {
+ // TODO
+ }
+
+ void SpriteCanvasHelper::opaqueUpdate( const ::canvas::SpriteRedrawManager::UpdateArea& /*rUpdateArea*/ )
+ {
+ // TODO
+ }
+
+ void SpriteCanvasHelper::genericUpdate( const ::canvas::SpriteRedrawManager::UpdateArea& /*rUpdateArea*/ )
+ {
+ // TODO
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritecanvashelper.hxx b/canvas/source/null/null_spritecanvashelper.hxx
new file mode 100644
index 000000000000..c3c6aa892053
--- /dev/null
+++ b/canvas/source/null/null_spritecanvashelper.hxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_SPRITECANVASHELPER_HXX_
+#define _NULLCANVAS_SPRITECANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <canvas/spriteredrawmanager.hxx>
+
+#include "null_canvashelper.hxx"
+
+namespace basegfx
+{
+ class B2IRange;
+}
+
+namespace nullcanvas
+{
+ class SpriteCanvas;
+
+ class SpriteCanvasHelper : public CanvasHelper
+ {
+ public:
+ SpriteCanvasHelper();
+
+ void init( ::canvas::SpriteRedrawManager& rManager,
+ SpriteCanvas& rDevice,
+ const ::basegfx::B2ISize& rSize,
+ bool bHasAlpha );
+
+ /// 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 ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
+
+ void genericUpdate( const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
+
+ private:
+ /// Set from the SpriteCanvas: instance coordinating sprite redraw
+ ::canvas::SpriteRedrawManager* mpRedrawManager;
+ };
+}
+
+#endif /* _NULLCANVAS_SPRITECANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritehelper.cxx b/canvas/source/null/null_spritehelper.cxx
new file mode 100644
index 000000000000..e0370396827e
--- /dev/null
+++ b/canvas/source/null/null_spritehelper.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+
+#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 "null_canvascustomsprite.hxx"
+#include "null_spritehelper.hxx"
+
+#include <memory>
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ SpriteHelper::SpriteHelper() :
+ mpSpriteCanvas(),
+ 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::disposing()
+ {
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteHelper::disposing();
+ }
+
+ void SpriteHelper::redraw( bool& /*io_bSurfaceDirty*/ ) const
+ {
+ // TODO
+ }
+
+ ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
+ {
+ return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_spritehelper.hxx b/canvas/source/null/null_spritehelper.hxx
new file mode 100644
index 000000000000..3c50bc7c9341
--- /dev/null
+++ b/canvas/source/null/null_spritehelper.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_SPRITEHELPER_HXX
+#define _NULLCANVAS_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 "null_spritecanvas.hxx"
+
+
+namespace nullcanvas
+{
+ /* 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();
+
+ // make CanvasCustomSpriteHelper::init visible for name lookup
+ using ::canvas::CanvasCustomSpriteHelper::init;
+
+ /** 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();
+
+ /** Repaint sprite content via hardware to associated sprite
+ canvas
+
+ @param io_bSurfaceDirty
+ Input/output parameter, whether the sprite content is
+ dirty or not. If texture was updated, set to false
+ */
+ void redraw( bool& io_bSurfaceDirty ) const;
+
+ private:
+ virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPoly ) const;
+
+
+ SpriteCanvasRef mpSpriteCanvas;
+ mutable bool mbTextureDirty; // when true, texture needs update
+ };
+}
+
+#endif /* _NULLCANVAS_SPRITEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_textlayout.cxx b/canvas/source/null/null_textlayout.cxx
new file mode 100644
index 000000000000..9b3ec566ad2a
--- /dev/null
+++ b/canvas/source/null/null_textlayout.cxx
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "null_textlayout.hxx"
+#include "null_spritecanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace nullcanvas
+{
+ TextLayout::TextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 /*nRandomSeed*/,
+ const CanvasFont::ImplRef& rFont ) :
+ TextLayout_Base( m_aMutex ),
+ maText( aText ),
+ maLogicalAdvancements(),
+ mpFont( rFont ),
+ mnTextDirection( nDirection )
+ {
+ }
+
+ TextLayout::~TextLayout()
+ {
+ }
+
+ void SAL_CALL TextLayout::disposing()
+ {
+ mpFont.reset();
+ }
+
+ // 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 );
+
+ ENSURE_OR_THROW( mpFont.get(),
+ "TextLayout::queryTextBounds(): invalid font" );
+
+ // fake text bounds by either taking the advancement values,
+ // or assuming square glyph boxes (width similar to height)
+ const rendering::FontRequest& rFontRequest( mpFont->getFontRequest() );
+ const double nFontSize( ::std::max( rFontRequest.CellSize,
+ rFontRequest.ReferenceAdvancement ) );
+ if( maLogicalAdvancements.getLength() )
+ {
+ return geometry::RealRectangle2D( 0, -nFontSize/2,
+ maLogicalAdvancements[ maLogicalAdvancements.getLength()-1 ],
+ nFontSize/2 );
+ }
+ else
+ {
+ return geometry::RealRectangle2D( 0, -nFontSize/2,
+ nFontSize * maText.Length,
+ nFontSize/2 );
+ }
+ }
+
+ 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;
+ }
+
+ bool TextLayout::draw( const rendering::ViewState& /*rViewState*/,
+ const rendering::RenderState& /*rRenderState*/,
+ const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/ ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+
+ return true;
+ }
+
+
+#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
+#define IMPLEMENTATION_NAME "NullCanvas::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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_textlayout.hxx b/canvas/source/null/null_textlayout.hxx
new file mode 100644
index 000000000000..521fab20820f
--- /dev/null
+++ b/canvas/source/null/null_textlayout.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_TEXTLAYOUT_HXX
+#define _NULLCANVAS_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 <boost/utility.hpp>
+
+#include "null_canvasfont.hxx"
+#include "null_usagecounter.hxx"
+
+
+/* Definition of TextLayout class */
+
+namespace nullcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XTextLayout,
+ ::com::sun::star::lang::XServiceInfo > TextLayout_Base;
+
+ class TextLayout : public ::comphelper::OBaseMutex,
+ public TextLayout_Base,
+ private UsageCounter< TextLayout >,
+ private ::boost::noncopyable
+ {
+ public:
+ TextLayout( const ::com::sun::star::rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed,
+ const CanvasFont::ImplRef& rFont );
+
+ /// 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( const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice ) 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::ImplRef mpFont;
+ sal_Int8 mnTextDirection;
+ };
+
+}
+
+#endif /* _NULLCANVAS_TEXTLAYOUT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/null_usagecounter.hxx b/canvas/source/null/null_usagecounter.hxx
new file mode 100644
index 000000000000..ab8085824f79
--- /dev/null
+++ b/canvas/source/null/null_usagecounter.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 _NULLCANVAS_USAGECOUNTER_HXX
+#define _NULLCANVAS_USAGECOUNTER_HXX
+
+#include <osl/interlck.h>
+#include <boost/current_function.hpp>
+
+namespace nullcanvas
+{
+ /** Little resource tracking counter.
+
+ When using this object, a global use counter, specific to the
+ given type is incremented on object construction, and
+ decremented on object destruction.
+ */
+ template< class Type > class UsageCounter
+ {
+ public:
+ UsageCounter()
+ {
+ OSL_TRACE( "%s, %d objects currently in use.\n",
+ BOOST_CURRENT_FUNCTION,
+ osl_incrementInterlockedCount( &s_nCount ) );
+ }
+
+ ~UsageCounter()
+ {
+ const sal_Int32 nCount( osl_decrementInterlockedCount( &s_nCount ) );
+
+ if( !nCount )
+ {
+ OSL_TRACE( "%s, last instance deleted.\n",
+ BOOST_CURRENT_FUNCTION );
+ }
+ else
+ {
+ OSL_TRACE( "%s, %d instances left.\n",
+ BOOST_CURRENT_FUNCTION,
+ nCount );
+ }
+ }
+
+ private:
+ static oslInterlockedCount s_nCount;
+ };
+
+ template< class Type > oslInterlockedCount UsageCounter<Type>::s_nCount = 0;
+}
+
+#endif /* _NULLCANVAS_USAGECOUNTER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/null/sprite.hxx b/canvas/source/null/sprite.hxx
new file mode 100644
index 000000000000..97eb1bfc621c
--- /dev/null
+++ b/canvas/source/null/sprite.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_NULLCANVAS_SPRITE_HXX
+#define INCLUDED_NULLCANVAS_SPRITE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+namespace nullcanvas
+{
+ /** Specialization of ::canvas::Sprite interface, to also provide
+ redraw methods.
+ */
+ class Sprite : public ::canvas::Sprite
+ {
+ public:
+ /** Redraw sprite
+ */
+ virtual void redraw() const = 0;
+ };
+}
+
+#endif /* INCLUDED_NULLCANVAS_SPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/simplecanvas/exports.dxp b/canvas/source/simplecanvas/exports.dxp
new file mode 100644
index 000000000000..0c2e3e7cddd7
--- /dev/null
+++ b/canvas/source/simplecanvas/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory \ No newline at end of file
diff --git a/canvas/source/simplecanvas/makefile.mk b/canvas/source/simplecanvas/makefile.mk
new file mode 100644
index 000000000000..4d5a7e7bb3a1
--- /dev/null
+++ b/canvas/source/simplecanvas/makefile.mk
@@ -0,0 +1,63 @@
+#*************************************************************************
+#
+# 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=simplecanvas
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+.IF "$(L10N_framework)"==""
+SLOFILES = $(SLO)$/simplecanvasimpl.obj
+
+SHL1TARGET=$(TARGET).uno
+
+SHL1STDLIBS= $(CPPULIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB)
+
+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
diff --git a/canvas/source/simplecanvas/simplecanvasimpl.cxx b/canvas/source/simplecanvas/simplecanvasimpl.cxx
new file mode 100644
index 000000000000..fef1ab8ea162
--- /dev/null
+++ b/canvas/source/simplecanvas/simplecanvasimpl.cxx
@@ -0,0 +1,403 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/rendering/XSimpleCanvas.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/PanoseLetterForm.hpp>
+#include <com/sun/star/rendering/PanoseWeight.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+
+#include <o3tl/lazy_update.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include "canvas/canvastools.hxx"
+
+#include <boost/bind.hpp>
+
+#define SERVICE_NAME "com.sun.star.rendering.SimpleCanvas"
+
+using namespace ::com::sun::star;
+using namespace canvas;
+
+namespace
+{
+ inline uno::Sequence< double > color2Sequence( sal_Int32 const& nColor )
+ {
+ // TODO(F3): Color management
+ uno::Sequence< double > aRes( 4 );
+
+ aRes[0] = static_cast<sal_uInt8>( (nColor&0xFF000000U) >> 24U ) / 255.0;
+ aRes[1] = static_cast<sal_uInt8>( (nColor&0x00FF0000U) >> 16U ) / 255.0;
+ aRes[2] = static_cast<sal_uInt8>( (nColor&0x0000FF00U) >> 8U ) / 255.0;
+ aRes[3] = static_cast<sal_uInt8>( (nColor&0x000000FFU) ) / 255.0;
+
+ return aRes;
+ }
+
+ inline uno::Reference< rendering::XPolyPolygon2D > rect2Poly( uno::Reference<rendering::XGraphicDevice> const& xDevice,
+ geometry::RealRectangle2D const& rRect )
+ {
+ uno::Sequence< geometry::RealPoint2D > rectSequence( 4 );
+ geometry::RealPoint2D* pOutput = rectSequence.getArray();
+ pOutput[0] = geometry::RealPoint2D( rRect.X1, rRect.Y1 );
+ pOutput[1] = geometry::RealPoint2D( rRect.X2, rRect.Y1 );
+ pOutput[2] = geometry::RealPoint2D( rRect.X2, rRect.Y2 );
+ pOutput[3] = geometry::RealPoint2D( rRect.X1, rRect.Y2 );
+
+ uno::Sequence< uno::Sequence< geometry::RealPoint2D > > sequenceSequence( 1 );
+ sequenceSequence[0] = rectSequence;
+
+ uno::Reference< rendering::XPolyPolygon2D > xRes(
+ xDevice->createCompatibleLinePolyPolygon( sequenceSequence ),
+ uno::UNO_QUERY );
+ if( xRes.is() )
+ xRes->setClosed( 0, sal_True );
+ return xRes;
+ }
+
+ struct SimpleRenderState
+ {
+ o3tl::LazyUpdate<sal_Int32,
+ uno::Sequence<double>,
+ o3tl::LAZYUPDATE_FUNCTION_TAG > m_aPenColor;
+ o3tl::LazyUpdate<sal_Int32,
+ uno::Sequence<double>,
+ o3tl::LAZYUPDATE_FUNCTION_TAG > m_aFillColor;
+ o3tl::LazyUpdate<geometry::RealRectangle2D,
+ uno::Reference< rendering::XPolyPolygon2D >,
+ o3tl::LAZYUPDATE_FUNCTOR_TAG > m_aRectClip;
+ geometry::AffineMatrix2D m_aTransformation;
+
+ explicit SimpleRenderState( uno::Reference<rendering::XGraphicDevice> const& xDevice ) :
+ m_aPenColor( &color2Sequence),
+ m_aFillColor( &color2Sequence ),
+ m_aRectClip( boost::bind( &rect2Poly,
+ xDevice,
+ _1 )),
+ m_aTransformation()
+ {
+ tools::setIdentityAffineMatrix2D( m_aTransformation );
+ }
+ };
+
+
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XSimpleCanvas,
+ ::com::sun::star::lang::XServiceName > SimpleCanvasBase;
+
+ class SimpleCanvasImpl : private cppu::BaseMutex,
+ public SimpleCanvasBase
+ {
+ private:
+ bool isStrokingEnabled() const
+ {
+ return maRenderState.m_aPenColor.getInValue() && sal_Int32(0xFF) != 0;
+ }
+
+ rendering::RenderState createStrokingRenderState() const
+ {
+ return rendering::RenderState(maRenderState.m_aTransformation,
+ *maRenderState.m_aRectClip,
+ *maRenderState.m_aPenColor,
+ rendering::CompositeOperation::OVER);
+ }
+
+ bool isFillingEnabled() const
+ {
+ return maRenderState.m_aFillColor.getInValue() && sal_Int32(0xFF) != 0;
+ }
+
+ rendering::RenderState createFillingRenderState() const
+ {
+ return rendering::RenderState(maRenderState.m_aTransformation,
+ *maRenderState.m_aRectClip,
+ *maRenderState.m_aFillColor,
+ rendering::CompositeOperation::OVER);
+ }
+
+ static uno::Reference<rendering::XCanvas> grabCanvas( uno::Sequence<uno::Any> const& rArgs )
+ {
+ uno::Reference<rendering::XCanvas> xRet;
+
+ // can't do much without an XCanvas, can't we?
+ if( rArgs.getLength() < 1 )
+ throw lang::IllegalArgumentException();
+
+ xRet.set( rArgs[0], uno::UNO_QUERY );
+
+ // can't do much without an XCanvas, can't we?
+ if( !xRet.is() )
+ throw lang::IllegalArgumentException();
+
+ return xRet;
+ }
+
+ public:
+ SimpleCanvasImpl( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& ) :
+ SimpleCanvasBase( m_aMutex ),
+ mxCanvas( grabCanvas(aArguments) ),
+ maFont(boost::bind( &rendering::XCanvas::createFont,
+ boost::cref(mxCanvas),
+ _1,
+ uno::Sequence< beans::PropertyValue >(),
+ geometry::Matrix2D() )),
+ maViewState(),
+ maRenderState( mxCanvas->getDevice() )
+ {
+ tools::initViewState(maViewState);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ private:
+ // Ifc XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
+ }
+
+ // Ifc XSimpleCanvas
+ virtual void SAL_CALL selectFont( const ::rtl::OUString& sFontName,
+ double size,
+ ::sal_Bool bold,
+ ::sal_Bool italic ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maFont->FontDescription.FamilyName = sFontName;
+ maFont->CellSize = size;
+ maFont->FontDescription.FontDescription.Weight =
+ bold ? rendering::PanoseWeight::BOLD : rendering::PanoseWeight::MEDIUM;
+ maFont->FontDescription.FontDescription.Letterform =
+ italic ? rendering::PanoseLetterForm::OBLIQUE_CONTACT : rendering::PanoseLetterForm::ANYTHING;
+ }
+
+ virtual void SAL_CALL setPenColor( ::sal_Int32 nsRgbaColor ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ *(maRenderState.m_aPenColor) = nsRgbaColor;
+ }
+
+ virtual void SAL_CALL setFillColor( ::sal_Int32 nsRgbaColor ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ *(maRenderState.m_aFillColor) = nsRgbaColor;
+ }
+
+ virtual void SAL_CALL setRectClip( const geometry::RealRectangle2D& aRect ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ *(maRenderState.m_aRectClip) = aRect;
+ }
+
+ virtual void SAL_CALL setTransformation( const geometry::AffineMatrix2D& aTransform ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ maRenderState.m_aTransformation = aTransform;
+ }
+
+ virtual void SAL_CALL drawPixel( const geometry::RealPoint2D& aPoint ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ mxCanvas->drawPoint(aPoint,
+ maViewState,
+ createFillingRenderState());
+ }
+
+ virtual void SAL_CALL drawLine( const geometry::RealPoint2D& aStartPoint,
+ const geometry::RealPoint2D& aEndPoint ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ mxCanvas->drawLine(aStartPoint,
+ aEndPoint,
+ maViewState,
+ createStrokingRenderState());
+ }
+
+ virtual void SAL_CALL drawRect( const geometry::RealRectangle2D& aRect ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ rect2Poly( mxCanvas->getDevice(),
+ aRect));
+
+ if( isFillingEnabled() )
+ mxCanvas->drawPolyPolygon(xPoly,
+ maViewState,
+ createFillingRenderState());
+ if( isStrokingEnabled() )
+ mxCanvas->drawPolyPolygon(xPoly,
+ maViewState,
+ createStrokingRenderState());
+ }
+
+ virtual void SAL_CALL drawPolyPolygon( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if( isFillingEnabled() )
+ mxCanvas->drawPolyPolygon(xPolyPolygon,
+ maViewState,
+ createFillingRenderState());
+ if( isStrokingEnabled() )
+ mxCanvas->drawPolyPolygon(xPolyPolygon,
+ maViewState,
+ createStrokingRenderState());
+ }
+
+ virtual void SAL_CALL drawText( const rendering::StringContext& aText,
+ const geometry::RealPoint2D& aOutPos,
+ ::sal_Int8 nTextDirection ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aOutPos.X,aOutPos.Y));
+ rendering::RenderState aRenderState( createStrokingRenderState() );
+ tools::appendToRenderState(aRenderState, offsetTransform);
+
+ mxCanvas->drawText(aText,
+ maFont.getOutValue(),
+ maViewState,
+ aRenderState,
+ nTextDirection);
+ }
+
+ virtual void SAL_CALL drawBitmap( const uno::Reference< rendering::XBitmap >& xBitmap,
+ const geometry::RealPoint2D& aLeftTop ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aLeftTop.X,aLeftTop.Y));
+ rendering::RenderState aRenderState( createStrokingRenderState() );
+ tools::appendToRenderState(aRenderState, offsetTransform);
+
+ mxCanvas->drawBitmap(xBitmap,maViewState,aRenderState);
+ }
+
+ virtual uno::Reference< rendering::XGraphicDevice > SAL_CALL getDevice( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return mxCanvas->getDevice();
+ }
+
+ virtual uno::Reference< rendering::XCanvas > SAL_CALL getCanvas( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return mxCanvas;
+ }
+
+ virtual rendering::FontMetrics SAL_CALL getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maFont.getOutValue()->getFontMetrics();
+ }
+
+ virtual uno::Reference< rendering::XCanvasFont > SAL_CALL getCurrentFont( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maFont.getOutValue();
+ }
+
+ virtual ::sal_Int32 SAL_CALL getCurrentPenColor( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maRenderState.m_aPenColor.getInValue();
+ }
+
+ virtual ::sal_Int32 SAL_CALL getCurrentFillColor( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maRenderState.m_aFillColor.getInValue();
+ }
+
+ virtual geometry::RealRectangle2D SAL_CALL getCurrentClipRect( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maRenderState.m_aRectClip.getInValue();
+ }
+
+ virtual geometry::AffineMatrix2D SAL_CALL getCurrentTransformation( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maRenderState.m_aTransformation;
+ }
+
+ virtual rendering::ViewState SAL_CALL getCurrentViewState( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return maViewState;
+ }
+
+ virtual rendering::RenderState SAL_CALL getCurrentRenderState( sal_Bool bUseFillColor ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if( bUseFillColor )
+ return createFillingRenderState();
+ else
+ return createStrokingRenderState();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ typedef o3tl::LazyUpdate<
+ rendering::FontRequest,
+ uno::Reference< rendering::XCanvasFont >,
+ o3tl::LAZYUPDATE_FUNCTOR_TAG > SimpleFont;
+
+ uno::Reference<rendering::XCanvas> mxCanvas;
+ SimpleFont maFont;
+ rendering::ViewState maViewState;
+ SimpleRenderState maRenderState;
+ };
+
+ namespace sdecl = comphelper::service_decl;
+#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+ sdecl::class_<SimpleCanvasImpl, sdecl::with_args<true> > serviceImpl;
+ const sdecl::ServiceDecl simpleCanvasDecl(
+ serviceImpl,
+#else
+ const sdecl::ServiceDecl simpleCanvasDecl(
+ sdecl::class_<SimpleCanvasImpl, sdecl::with_args<true> >(),
+#endif
+ "com.sun.star.comp.rendering.SimpleCanvas",
+ SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(simpleCanvasDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/cachedprimitivebase.cxx b/canvas/source/tools/cachedprimitivebase.cxx
new file mode 100644
index 000000000000..fcdcffbc924c
--- /dev/null
+++ b/canvas/source/tools/cachedprimitivebase.cxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/base/cachedprimitivebase.hxx>
+
+#include <com/sun/star/rendering/RepaintResult.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+
+using namespace ::com::sun::star;
+
+#define IMPLEMENTATION_NAME "canvas::CachedPrimitiveBase"
+#define SERVICE_NAME "com.sun.star.rendering.CachedBitmap"
+
+namespace canvas
+{
+ CachedPrimitiveBase::CachedPrimitiveBase( const rendering::ViewState& rUsedViewState,
+ const uno::Reference< rendering::XCanvas >& rTarget,
+ bool bFailForChangedViewTransform ) :
+ CachedPrimitiveBase_Base( m_aMutex ),
+ maUsedViewState( rUsedViewState ),
+ mxTarget( rTarget ),
+ mbFailForChangedViewTransform( bFailForChangedViewTransform )
+ {
+ }
+
+ CachedPrimitiveBase::~CachedPrimitiveBase()
+ {
+ }
+
+ void SAL_CALL CachedPrimitiveBase::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maUsedViewState.Clip.clear();
+ mxTarget.clear();
+ }
+
+ sal_Int8 SAL_CALL CachedPrimitiveBase::redraw( const rendering::ViewState& aState ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::basegfx::B2DHomMatrix aUsedTransformation;
+ ::basegfx::B2DHomMatrix aNewTransformation;
+
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aUsedTransformation,
+ maUsedViewState.AffineTransform );
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aNewTransformation,
+ aState.AffineTransform );
+
+ const bool bSameViewTransforms( aUsedTransformation == aNewTransformation );
+
+ if( mbFailForChangedViewTransform &&
+ !bSameViewTransforms )
+ {
+ // differing transformations, don't try to draft the
+ // output, just plain fail here.
+ return rendering::RepaintResult::FAILED;
+ }
+
+ return doRedraw( aState,
+ maUsedViewState,
+ mxTarget,
+ bSameViewTransforms );
+ }
+
+ ::rtl::OUString SAL_CALL CachedPrimitiveBase::getImplementationName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CachedPrimitiveBase::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CachedPrimitiveBase::getSupportedServiceNames( ) throw (uno::RuntimeException)
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/canvascustomspritehelper.cxx b/canvas/source/tools/canvascustomspritehelper.cxx
new file mode 100644
index 000000000000..0c7a3e55a2d7
--- /dev/null
+++ b/canvas/source/tools/canvascustomspritehelper.cxx
@@ -0,0 +1,499 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <rtl/math.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/base/canvascustomspritehelper.hxx>
+
+using namespace ::com::sun::star;
+
+
+namespace canvas
+{
+ bool CanvasCustomSpriteHelper::updateClipState( const Sprite::Reference& rSprite )
+ {
+ if( !mxClipPoly.is() )
+ {
+ // empty clip polygon -> everything is visible now
+ maCurrClipBounds.reset();
+ mbIsCurrClipRectangle = true;
+ }
+ else
+ {
+ const sal_Int32 nNumClipPolygons( mxClipPoly->getNumberOfPolygons() );
+
+ // clip is not empty - determine actual update area
+ ::basegfx::B2DPolyPolygon aClipPath(
+ polyPolygonFromXPolyPolygon2D( mxClipPoly ) );
+
+ // apply sprite transformation also to clip!
+ aClipPath.transform( maTransform );
+
+ // clip which is about to be set, expressed as a
+ // b2drectangle
+ const ::basegfx::B2DRectangle& rClipBounds(
+ ::basegfx::tools::getRange( aClipPath ) );
+
+ const ::basegfx::B2DRectangle aBounds( 0.0, 0.0,
+ maSize.getX(),
+ maSize.getY() );
+
+ // rectangular area which is actually covered by the sprite.
+ // coordinates are relative to the sprite origin.
+ ::basegfx::B2DRectangle aSpriteRectPixel;
+ ::canvas::tools::calcTransformedRectBounds( aSpriteRectPixel,
+ aBounds,
+ maTransform );
+
+ // aClipBoundsA = new clip bound rect, intersected
+ // with sprite area
+ ::basegfx::B2DRectangle aClipBoundsA(rClipBounds);
+ aClipBoundsA.intersect( aSpriteRectPixel );
+
+ if( nNumClipPolygons != 1 )
+ {
+ // clip cannot be a single rectangle -> cannot
+ // optimize update
+ mbIsCurrClipRectangle = false;
+ maCurrClipBounds = aClipBoundsA;
+ }
+ else
+ {
+ // new clip could be a single rectangle - check
+ // that now:
+ const bool bNewClipIsRect(
+ ::basegfx::tools::isRectangle( aClipPath.getB2DPolygon(0) ) );
+
+ // both new and old clip are truly rectangles
+ // - can now take the optimized path
+ const bool bUseOptimizedUpdate( bNewClipIsRect &&
+ mbIsCurrClipRectangle );
+
+ const ::basegfx::B2DRectangle aOldBounds( maCurrClipBounds );
+
+ // store new current clip type
+ maCurrClipBounds = aClipBoundsA;
+ mbIsCurrClipRectangle = bNewClipIsRect;
+
+ if( mbActive &&
+ bUseOptimizedUpdate )
+ {
+ // aClipBoundsB = maCurrClipBounds, i.e. last
+ // clip, intersected with sprite area
+ typedef ::std::vector< ::basegfx::B2DRectangle > VectorOfRects;
+ VectorOfRects aClipDifferences;
+
+ // get all rectangles covered by exactly one
+ // of the polygons (aka XOR)
+ ::basegfx::computeSetDifference(aClipDifferences,
+ aClipBoundsA,
+ aOldBounds);
+
+ // aClipDifferences now contains the final
+ // update areas, coordinates are still relative
+ // to the sprite origin. before submitting
+ // this area to 'updateSprite()' we need to
+ // translate this area to the final position,
+ // coordinates need to be relative to the
+ // spritecanvas.
+ VectorOfRects::const_iterator aCurr( aClipDifferences.begin() );
+ const VectorOfRects::const_iterator aEnd( aClipDifferences.end() );
+ while( aCurr != aEnd )
+ {
+ mpSpriteCanvas->updateSprite(
+ rSprite,
+ maPosition,
+ ::basegfx::B2DRectangle(
+ maPosition + aCurr->getMinimum(),
+ maPosition + aCurr->getMaximum() ) );
+ ++aCurr;
+ }
+
+ // update calls all done
+ return true;
+ }
+ }
+ }
+
+ // caller needs to perform update calls
+ return false;
+ }
+
+ CanvasCustomSpriteHelper::CanvasCustomSpriteHelper() :
+ mpSpriteCanvas(),
+ maCurrClipBounds(),
+ maPosition(),
+ maSize(),
+ maTransform(),
+ mxClipPoly(),
+ mfPriority(0.0),
+ mfAlpha(0.0),
+ mbActive(false),
+ mbIsCurrClipRectangle(true),
+ mbIsContentFullyOpaque( false ),
+ mbAlphaDirty( true ),
+ mbPositionDirty( true ),
+ mbTransformDirty( true ),
+ mbClipDirty( true ),
+ mbPrioDirty( true ),
+ mbVisibilityDirty( true )
+ {
+ }
+
+ void CanvasCustomSpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
+ const SpriteSurface::Reference& rOwningSpriteCanvas )
+ {
+ ENSURE_OR_THROW( rOwningSpriteCanvas.get(),
+ "CanvasCustomSpriteHelper::init(): Invalid owning sprite canvas" );
+
+ mpSpriteCanvas = rOwningSpriteCanvas;
+ maSize.setX( ::std::max( 1.0,
+ ceil( rSpriteSize.Width ) ) ); // round up to nearest int,
+ // enforce sprite to have at
+ // least (1,1) pixel size
+ maSize.setY( ::std::max( 1.0,
+ ceil( rSpriteSize.Height ) ) );
+ }
+
+ void CanvasCustomSpriteHelper::disposing()
+ {
+ mpSpriteCanvas.clear();
+ }
+
+ void CanvasCustomSpriteHelper::clearingContent( const Sprite::Reference& /*rSprite*/ )
+ {
+ // about to clear content to fully transparent
+ mbIsContentFullyOpaque = false;
+ }
+
+ void CanvasCustomSpriteHelper::checkDrawBitmap( const Sprite::Reference& rSprite,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ // check whether bitmap is non-alpha, and whether its
+ // transformed size covers the whole sprite.
+ if( !xBitmap->hasAlpha() )
+ {
+ const geometry::IntegerSize2D& rInputSize(
+ xBitmap->getSize() );
+ const ::basegfx::B2DSize& rOurSize(
+ rSprite->getSizePixel() );
+
+ ::basegfx::B2DHomMatrix aTransform;
+ if( tools::isInside(
+ ::basegfx::B2DRectangle( 0.0,0.0,
+ rOurSize.getX(),
+ rOurSize.getY() ),
+ ::basegfx::B2DRectangle( 0.0,0.0,
+ rInputSize.Width,
+ rInputSize.Height ),
+ ::canvas::tools::mergeViewAndRenderTransform(aTransform,
+ viewState,
+ renderState) ) )
+ {
+ // bitmap is opaque and will fully cover the sprite,
+ // set flag appropriately
+ mbIsContentFullyOpaque = true;
+ }
+ }
+ }
+
+ void CanvasCustomSpriteHelper::setAlpha( const Sprite::Reference& rSprite,
+ double alpha )
+ {
+ if( !mpSpriteCanvas.get() )
+ return; // we're disposed
+
+ if( alpha != mfAlpha )
+ {
+ mfAlpha = alpha;
+
+ if( mbActive )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbAlphaDirty = true;
+ }
+ }
+
+ void CanvasCustomSpriteHelper::move( const Sprite::Reference& rSprite,
+ const geometry::RealPoint2D& aNewPos,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( !mpSpriteCanvas.get() )
+ return; // we're disposed
+
+ ::basegfx::B2DHomMatrix aTransform;
+ ::canvas::tools::mergeViewAndRenderTransform(aTransform,
+ viewState,
+ renderState);
+
+ // convert position to device pixel
+ ::basegfx::B2DPoint aPoint(
+ ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos) );
+ aPoint *= aTransform;
+
+ if( aPoint != maPosition )
+ {
+ const ::basegfx::B2DRectangle& rBounds( getFullSpriteRect() );
+
+ if( mbActive )
+ {
+ mpSpriteCanvas->moveSprite( rSprite,
+ rBounds.getMinimum(),
+ rBounds.getMinimum() - maPosition + aPoint,
+ rBounds.getRange() );
+ }
+
+ maPosition = aPoint;
+ mbPositionDirty = true;
+ }
+ }
+
+ void CanvasCustomSpriteHelper::transform( const Sprite::Reference& rSprite,
+ const geometry::AffineMatrix2D& aTransformation )
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix,
+ aTransformation);
+
+ if( maTransform != aMatrix )
+ {
+ // retrieve bounds before and after transformation change.
+ const ::basegfx::B2DRectangle& rPrevBounds( getUpdateArea() );
+
+ maTransform = aMatrix;
+
+ if( !updateClipState( rSprite ) &&
+ mbActive )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ rPrevBounds );
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbTransformDirty = true;
+ }
+ }
+
+ void CanvasCustomSpriteHelper::clip( const Sprite::Reference& rSprite,
+ const uno::Reference< rendering::XPolyPolygon2D >& xClip )
+ {
+ // NULL xClip explicitely allowed here (to clear clipping)
+
+ // retrieve bounds before and after clip change.
+ const ::basegfx::B2DRectangle& rPrevBounds( getUpdateArea() );
+
+ mxClipPoly = xClip;
+
+ if( !updateClipState( rSprite ) &&
+ mbActive )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ rPrevBounds );
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbClipDirty = true;
+ }
+
+ void CanvasCustomSpriteHelper::setPriority( const Sprite::Reference& rSprite,
+ double nPriority )
+ {
+ if( !mpSpriteCanvas.get() )
+ return; // we're disposed
+
+ if( nPriority != mfPriority )
+ {
+ mfPriority = nPriority;
+
+ if( mbActive )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbPrioDirty = true;
+ }
+ }
+
+ void CanvasCustomSpriteHelper::show( const Sprite::Reference& rSprite )
+ {
+ if( !mpSpriteCanvas.get() )
+ return; // we're disposed
+
+ if( !mbActive )
+ {
+ mpSpriteCanvas->showSprite( rSprite );
+ mbActive = true;
+
+ // TODO(P1): if clip is the NULL clip (nothing visible),
+ // also save us the update call.
+
+ if( mfAlpha != 0.0 )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbVisibilityDirty = true;
+ }
+ }
+
+ void CanvasCustomSpriteHelper::hide( const Sprite::Reference& rSprite )
+ {
+ if( !mpSpriteCanvas.get() )
+ return; // we're disposed
+
+ if( mbActive )
+ {
+ mpSpriteCanvas->hideSprite( rSprite );
+ mbActive = false;
+
+ // TODO(P1): if clip is the NULL clip (nothing visible),
+ // also save us the update call.
+
+ if( mfAlpha != 0.0 )
+ {
+ mpSpriteCanvas->updateSprite( rSprite,
+ maPosition,
+ getUpdateArea() );
+ }
+
+ mbVisibilityDirty = true;
+ }
+ }
+
+ // Sprite interface
+ bool CanvasCustomSpriteHelper::isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const
+ {
+ if( !mbIsCurrClipRectangle ||
+ !mbIsContentFullyOpaque ||
+ !::rtl::math::approxEqual(mfAlpha, 1.0) )
+ {
+ // sprite either transparent, or clip rect does not
+ // represent exact bounds -> update might not be fully
+ // opaque
+ return false;
+ }
+ else
+ {
+ // make sure sprite rect fully covers update area -
+ // although the update area originates from the sprite,
+ // it's by no means guaranteed that it's limited to this
+ // sprite's update area - after all, other sprites might
+ // have been merged, or this sprite is moving.
+ return getUpdateArea().isInside( rUpdateArea );
+ }
+ }
+
+ ::basegfx::B2DPoint CanvasCustomSpriteHelper::getPosPixel() const
+ {
+ return maPosition;
+ }
+
+ ::basegfx::B2DVector CanvasCustomSpriteHelper::getSizePixel() const
+ {
+ return maSize;
+ }
+
+ ::basegfx::B2DRange CanvasCustomSpriteHelper::getUpdateArea( const ::basegfx::B2DRange& rBounds ) const
+ {
+ // Internal! Only call with locked object mutex!
+ ::basegfx::B2DHomMatrix aTransform( maTransform );
+ aTransform.translate( maPosition.getX(),
+ maPosition.getY() );
+
+ // transform bounds at origin, as the sprite transformation is
+ // formulated that way
+ ::basegfx::B2DRectangle aTransformedBounds;
+ return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
+ rBounds,
+ aTransform );
+ }
+
+ ::basegfx::B2DRange CanvasCustomSpriteHelper::getUpdateArea() const
+ {
+ // Internal! Only call with locked object mutex!
+
+ // return effective sprite rect, i.e. take active clip into
+ // account
+ if( maCurrClipBounds.isEmpty() )
+ return getUpdateArea( ::basegfx::B2DRectangle( 0.0, 0.0,
+ maSize.getX(),
+ maSize.getY() ) );
+ else
+ return ::basegfx::B2DRectangle(
+ maPosition + maCurrClipBounds.getMinimum(),
+ maPosition + maCurrClipBounds.getMaximum() );
+ }
+
+ double CanvasCustomSpriteHelper::getPriority() const
+ {
+ return mfPriority;
+ }
+
+ ::basegfx::B2DRange CanvasCustomSpriteHelper::getFullSpriteRect() const
+ {
+ // Internal! Only call with locked object mutex!
+ return getUpdateArea( ::basegfx::B2DRectangle( 0.0, 0.0,
+ maSize.getX(),
+ maSize.getY() ) );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/canvastools.cxx b/canvas/source/tools/canvastools.cxx
new file mode 100644
index 000000000000..c5571b41b82a
--- /dev/null
+++ b/canvas/source/tools/canvastools.cxx
@@ -0,0 +1,1047 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/geometry/AffineMatrix2D.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/util/Endianness.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 <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XColorSpace.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <cppuhelper/compbase1.hxx>
+#include <rtl/instance.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <limits>
+
+
+using namespace ::com::sun::star;
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ bool operator==( const RenderState& renderState1,
+ const RenderState& renderState2 )
+ {
+ if( renderState1.Clip != renderState2.Clip )
+ return false;
+
+ if( renderState1.DeviceColor != renderState2.DeviceColor )
+ return false;
+
+ if( renderState1.CompositeOperation != renderState2.CompositeOperation )
+ return false;
+
+ ::basegfx::B2DHomMatrix mat1, mat2;
+ ::canvas::tools::getRenderStateTransform( mat1, renderState1 );
+ ::canvas::tools::getRenderStateTransform( mat2, renderState2 );
+ if( mat1 != mat2 )
+ return false;
+
+ return true;
+ }
+
+ bool operator==( const ViewState& viewState1,
+ const ViewState& viewState2 )
+ {
+ if( viewState1.Clip != viewState2.Clip )
+ return false;
+
+ ::basegfx::B2DHomMatrix mat1, mat2;
+ ::canvas::tools::getViewStateTransform( mat1, viewState1 );
+ ::canvas::tools::getViewStateTransform( mat2, viewState2 );
+ if( mat1 != mat2 )
+ return false;
+
+ return true;
+ }
+}}}}
+
+namespace canvas
+{
+ namespace tools
+ {
+ geometry::RealSize2D createInfiniteSize2D()
+ {
+ return geometry::RealSize2D(
+ ::std::numeric_limits<double>::infinity(),
+ ::std::numeric_limits<double>::infinity() );
+ }
+
+ rendering::RenderState& initRenderState( rendering::RenderState& renderState )
+ {
+ // setup identity transform
+ setIdentityAffineMatrix2D( renderState.AffineTransform );
+ renderState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
+ renderState.DeviceColor = uno::Sequence< double >();
+ renderState.CompositeOperation = rendering::CompositeOperation::OVER;
+
+ return renderState;
+ }
+
+ rendering::ViewState& initViewState( rendering::ViewState& viewState )
+ {
+ // setup identity transform
+ setIdentityAffineMatrix2D( viewState.AffineTransform );
+ viewState.Clip = uno::Reference< rendering::XPolyPolygon2D >();
+
+ return viewState;
+ }
+
+ ::basegfx::B2DHomMatrix& getViewStateTransform( ::basegfx::B2DHomMatrix& transform,
+ const rendering::ViewState& viewState )
+ {
+ return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, viewState.AffineTransform );
+ }
+
+ rendering::ViewState& setViewStateTransform( rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& transform )
+ {
+ ::basegfx::unotools::affineMatrixFromHomMatrix( viewState.AffineTransform, transform );
+
+ return viewState;
+ }
+
+ ::basegfx::B2DHomMatrix& getRenderStateTransform( ::basegfx::B2DHomMatrix& transform,
+ const rendering::RenderState& renderState )
+ {
+ return ::basegfx::unotools::homMatrixFromAffineMatrix( transform, renderState.AffineTransform );
+ }
+
+ rendering::RenderState& setRenderStateTransform( rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& transform )
+ {
+ ::basegfx::unotools::affineMatrixFromHomMatrix( renderState.AffineTransform, transform );
+
+ return renderState;
+ }
+
+ rendering::RenderState& appendToRenderState( rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::basegfx::B2DHomMatrix transform;
+
+ getRenderStateTransform( transform, renderState );
+ return setRenderStateTransform( renderState, transform * rTransform );
+ }
+
+ rendering::ViewState& appendToViewState( rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::basegfx::B2DHomMatrix transform;
+
+ getViewStateTransform( transform, viewState );
+ return setViewStateTransform( viewState, transform * rTransform );
+ }
+
+ rendering::RenderState& prependToRenderState( rendering::RenderState& renderState,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::basegfx::B2DHomMatrix transform;
+
+ getRenderStateTransform( transform, renderState );
+ return setRenderStateTransform( renderState, rTransform * transform );
+ }
+
+ rendering::ViewState& prependToViewState( rendering::ViewState& viewState,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::basegfx::B2DHomMatrix transform;
+
+ getViewStateTransform( transform, viewState );
+ return setViewStateTransform( viewState, rTransform * transform );
+ }
+
+ ::basegfx::B2DHomMatrix& mergeViewAndRenderTransform( ::basegfx::B2DHomMatrix& combinedTransform,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ::basegfx::B2DHomMatrix viewTransform;
+
+ ::basegfx::unotools::homMatrixFromAffineMatrix( combinedTransform, renderState.AffineTransform );
+ ::basegfx::unotools::homMatrixFromAffineMatrix( viewTransform, viewState.AffineTransform );
+
+ // this statement performs combinedTransform = viewTransform * combinedTransform
+ combinedTransform *= viewTransform;
+
+ return combinedTransform;
+ }
+
+ rendering::ViewState& mergeViewAndRenderState( rendering::ViewState& resultViewState,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Reference< rendering::XCanvas >& /*xCanvas*/ )
+ {
+ ::basegfx::B2DHomMatrix aTmpMatrix;
+ geometry::AffineMatrix2D convertedMatrix;
+
+ resultViewState.Clip = NULL; // TODO(F2): intersect clippings
+
+ return setViewStateTransform(
+ resultViewState,
+ mergeViewAndRenderTransform( aTmpMatrix,
+ viewState,
+ renderState ) );
+ }
+
+ geometry::AffineMatrix2D& setIdentityAffineMatrix2D( geometry::AffineMatrix2D& matrix )
+ {
+ matrix.m00 = 1.0;
+ matrix.m01 = 0.0;
+ matrix.m02 = 0.0;
+ matrix.m10 = 0.0;
+ matrix.m11 = 1.0;
+ matrix.m12 = 0.0;
+
+ return matrix;
+ }
+
+ geometry::Matrix2D& setIdentityMatrix2D( geometry::Matrix2D& matrix )
+ {
+ matrix.m00 = 1.0;
+ matrix.m01 = 0.0;
+ matrix.m10 = 0.0;
+ matrix.m11 = 1.0;
+
+ return matrix;
+ }
+
+ namespace
+ {
+ class StandardColorSpace : 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 )
+ {
+ *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
+ 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 )
+ {
+ *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
+ 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[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
+ 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->Red;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Blue;
+ *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->Red;
+ *pColors++ = pIn->Green;
+ *pColors++ = pIn->Blue;
+ *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->Red/pIn->Alpha;
+ *pColors++ = pIn->Green/pIn->Alpha;
+ *pColors++ = pIn->Blue/pIn->Alpha;
+ *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<StandardColorSpace*>(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(255-*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<StandardColorSpace*>(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 )
+ {
+ *pOut++ = rendering::RGBColor(
+ vcl::unotools::toDoubleColor(pIn[0]),
+ vcl::unotools::toDoubleColor(pIn[1]),
+ vcl::unotools::toDoubleColor(pIn[2]));
+ 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 )
+ {
+ *pOut++ = rendering::ARGBColor(
+ vcl::unotools::toDoubleColor(255-pIn[3]),
+ vcl::unotools::toDoubleColor(pIn[0]),
+ vcl::unotools::toDoubleColor(pIn[1]),
+ vcl::unotools::toDoubleColor(pIn[2]));
+ 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 )
+ {
+ const sal_Int8 nAlpha( 255-pIn[3] );
+ *pOut++ = rendering::ARGBColor(
+ vcl::unotools::toDoubleColor(nAlpha),
+ vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
+ vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
+ vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
+ 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->Red);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Green);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
+ *pColors++ = 0;
+ ++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 )
+ {
+ *pColors++ = vcl::unotools::toByteColor(pIn->Red);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Green);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
+ *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
+ ++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->Red/pIn->Alpha);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
+ *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
+ *pColors++ = 255-vcl::unotools::toByteColor(pIn->Alpha);
+ ++pIn;
+ }
+ return aRes;
+ }
+
+ public:
+ StandardColorSpace() :
+ maComponentTags(4),
+ maBitCounts(4)
+ {
+ sal_Int8* pTags = maComponentTags.getArray();
+ sal_Int32* pBitCounts = maBitCounts.getArray();
+ pTags[0] = rendering::ColorComponentTag::RGB_RED;
+ pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
+ pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
+ pTags[3] = rendering::ColorComponentTag::ALPHA;
+
+ pBitCounts[0] =
+ pBitCounts[1] =
+ pBitCounts[2] =
+ pBitCounts[3] = 8;
+ }
+ };
+
+ struct StandardColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
+ StandardColorSpaceHolder>
+ {
+ uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
+ {
+ return new StandardColorSpace();
+ }
+ };
+ }
+
+ uno::Reference<rendering::XIntegerBitmapColorSpace> getStdColorSpace()
+ {
+ return StandardColorSpaceHolder::get();
+ }
+
+ rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize )
+ {
+ rendering::IntegerBitmapLayout aLayout;
+
+ aLayout.ScanLines = rBmpSize.Height;
+ aLayout.ScanLineBytes = rBmpSize.Width*4;
+ aLayout.ScanLineStride = aLayout.ScanLineBytes;
+ aLayout.PlaneStride = 0;
+ aLayout.ColorSpace = getStdColorSpace();
+ aLayout.Palette.clear();
+ aLayout.IsMsbFirst = sal_False;
+
+ return aLayout;
+ }
+
+ ::Color stdIntSequenceToColor( const uno::Sequence<sal_Int8>& rColor )
+ {
+#ifdef OSL_BIGENDIAN
+ const sal_Int8* pCols( rColor.getConstArray() );
+ return ::Color( pCols[3], pCols[0], pCols[1], pCols[2] );
+#else
+ return ::Color( *reinterpret_cast< const ::ColorData* >(rColor.getConstArray()) );
+#endif
+ }
+
+ uno::Sequence<sal_Int8> colorToStdIntSequence( const ::Color& rColor )
+ {
+ uno::Sequence<sal_Int8> aRet(4);
+ sal_Int8* pCols( aRet.getArray() );
+#ifdef OSL_BIGENDIAN
+ pCols[0] = rColor.GetRed();
+ pCols[1] = rColor.GetGreen();
+ pCols[2] = rColor.GetBlue();
+ pCols[3] = 255-rColor.GetTransparency();
+#else
+ *reinterpret_cast<sal_Int32*>(pCols) = rColor.GetColor();
+#endif
+ return aRet;
+ }
+
+ // Create a corrected view transformation out of the give one,
+ // which ensures that the rectangle given by (0,0) and
+ // rSpriteSize is mapped with its left,top corner to (0,0)
+ // again. This is required to properly render sprite
+ // animations to buffer bitmaps.
+ ::basegfx::B2DHomMatrix& calcRectToOriginTransform( ::basegfx::B2DHomMatrix& o_transform,
+ const ::basegfx::B2DRange& i_srcRect,
+ const ::basegfx::B2DHomMatrix& i_transformation )
+ {
+ if( i_srcRect.isEmpty() )
+ return o_transform=i_transformation;
+
+ // transform by given transformation
+ ::basegfx::B2DRectangle aTransformedRect;
+
+ calcTransformedRectBounds( aTransformedRect,
+ i_srcRect,
+ i_transformation );
+
+ // now move resulting left,top point of bounds to (0,0)
+ const basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
+
+ // prepend to original transformation
+ o_transform = aCorrectedTransform * i_transformation;
+
+ return o_transform;
+ }
+
+ ::basegfx::B2DRange& calcTransformedRectBounds( ::basegfx::B2DRange& outRect,
+ const ::basegfx::B2DRange& inRect,
+ const ::basegfx::B2DHomMatrix& transformation )
+ {
+ outRect.reset();
+
+ if( inRect.isEmpty() )
+ return outRect;
+
+ // transform all four extremal points of the rectangle,
+ // take bounding rect of those.
+
+ // transform left-top point
+ outRect.expand( transformation * inRect.getMinimum() );
+
+ // transform bottom-right point
+ outRect.expand( transformation * inRect.getMaximum() );
+
+ ::basegfx::B2DPoint aPoint;
+
+ // transform top-right point
+ aPoint.setX( inRect.getMaxX() );
+ aPoint.setY( inRect.getMinY() );
+
+ aPoint *= transformation;
+ outRect.expand( aPoint );
+
+ // transform bottom-left point
+ aPoint.setX( inRect.getMinX() );
+ aPoint.setY( inRect.getMaxY() );
+
+ aPoint *= transformation;
+ outRect.expand( aPoint );
+
+ // over and out.
+ return outRect;
+ }
+
+ ::basegfx::B2DHomMatrix& calcRectToRectTransform( ::basegfx::B2DHomMatrix& o_transform,
+ const ::basegfx::B2DRange& destRect,
+ const ::basegfx::B2DRange& srcRect,
+ const ::basegfx::B2DHomMatrix& transformation )
+ {
+ if( srcRect.isEmpty() ||
+ destRect.isEmpty() )
+ {
+ return o_transform=transformation;
+ }
+
+ // transform inputRect by transformation
+ ::basegfx::B2DRectangle aTransformedRect;
+ calcTransformedRectBounds( aTransformedRect,
+ srcRect,
+ transformation );
+
+ // now move resulting left,top point of bounds to (0,0)
+ basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
+
+ // scale to match outRect
+ const double xDenom( aTransformedRect.getWidth() );
+ const double yDenom( aTransformedRect.getHeight() );
+ if( xDenom != 0.0 && yDenom != 0.0 )
+ aCorrectedTransform.scale( destRect.getWidth() / xDenom,
+ destRect.getHeight() / yDenom );
+ // TODO(E2): error handling
+
+ // translate to final position
+ aCorrectedTransform.translate( destRect.getMinX(),
+ destRect.getMinY() );
+
+ ::basegfx::B2DHomMatrix transform( transformation );
+ o_transform = aCorrectedTransform * transform;
+
+ return o_transform;
+ }
+
+ bool isInside( const ::basegfx::B2DRange& rContainedRect,
+ const ::basegfx::B2DRange& rTransformRect,
+ const ::basegfx::B2DHomMatrix& rTransformation )
+ {
+ if( rContainedRect.isEmpty() || rTransformRect.isEmpty() )
+ return false;
+
+ ::basegfx::B2DPolygon aPoly(
+ ::basegfx::tools::createPolygonFromRect( rTransformRect ) );
+ aPoly.transform( rTransformation );
+
+ return ::basegfx::tools::isInside( aPoly,
+ ::basegfx::tools::createPolygonFromRect(
+ rContainedRect ),
+ true );
+ }
+
+ namespace
+ {
+ bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea,
+ ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ const ::basegfx::B2IRange& rSourceBounds,
+ const ::basegfx::B2IRange& rDestBounds )
+ {
+ const ::basegfx::B2IPoint aSourceTopLeft(
+ io_rSourceArea.getMinimum() );
+
+ ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
+
+ // clip source area (which must be inside rSourceBounds)
+ aLocalSourceArea.intersect( rSourceBounds );
+
+ if( aLocalSourceArea.isEmpty() )
+ return false;
+
+ // calc relative new source area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aUpperLeftOffset(
+ aLocalSourceArea.getMinimum()-aSourceTopLeft );
+ const ::basegfx::B2IVector aLowerRightOffset(
+ aLocalSourceArea.getMaximum()-aSourceTopLeft );
+
+ ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
+ io_rDestPoint + aLowerRightOffset );
+
+ // clip dest area (which must be inside rDestBounds)
+ aLocalDestArea.intersect( rDestBounds );
+
+ if( aLocalDestArea.isEmpty() )
+ return false;
+
+ // calc relative new dest area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aDestUpperLeftOffset(
+ aLocalDestArea.getMinimum()-io_rDestPoint );
+ const ::basegfx::B2IVector aDestLowerRightOffset(
+ aLocalDestArea.getMaximum()-io_rDestPoint );
+
+ io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
+ aSourceTopLeft + aDestLowerRightOffset );
+ io_rDestPoint = aLocalDestArea.getMinimum();
+
+ if( o_pDestArea )
+ *o_pDestArea = aLocalDestArea;
+
+ return true;
+ }
+ }
+
+ bool clipScrollArea( ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ ::std::vector< ::basegfx::B2IRange >& o_ClippedAreas,
+ const ::basegfx::B2IRange& rBounds )
+ {
+ ::basegfx::B2IRange aResultingDestArea;
+
+ // compute full destination area (to determine uninitialized
+ // areas below)
+ const ::basegfx::B2I64Tuple& rRange( io_rSourceArea.getRange() );
+ ::basegfx::B2IRange aInputDestArea( io_rDestPoint.getX(),
+ io_rDestPoint.getY(),
+ (io_rDestPoint.getX()
+ + static_cast<sal_Int32>(rRange.getX())),
+ (io_rDestPoint.getY()
+ + static_cast<sal_Int32>(rRange.getY())) );
+ // limit to output area (no point updating outside of it)
+ aInputDestArea.intersect( rBounds );
+
+ // clip to rBounds
+ if( !clipAreaImpl( &aResultingDestArea,
+ io_rSourceArea,
+ io_rDestPoint,
+ rBounds,
+ rBounds ) )
+ return false;
+
+ // finally, compute all areas clipped off the total
+ // destination area.
+ ::basegfx::computeSetDifference( o_ClippedAreas,
+ aInputDestArea,
+ aResultingDestArea );
+
+ return true;
+ }
+
+ bool clipBlit( ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ const ::basegfx::B2IRange& rSourceBounds,
+ const ::basegfx::B2IRange& rDestBounds )
+ {
+ return clipAreaImpl( NULL,
+ io_rSourceArea,
+ io_rDestPoint,
+ rSourceBounds,
+ rDestBounds );
+ }
+
+ ::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange )
+ {
+ if( rRange.isEmpty() )
+ return ::basegfx::B2IRange();
+
+ const ::basegfx::B2IPoint aTopLeft( ::basegfx::fround( rRange.getMinX() ),
+ ::basegfx::fround( rRange.getMinY() ) );
+ return ::basegfx::B2IRange( aTopLeft,
+ aTopLeft + ::basegfx::B2IPoint(
+ ::basegfx::fround( rRange.getWidth() ),
+ ::basegfx::fround( rRange.getHeight() ) ) );
+ }
+
+ uno::Sequence< uno::Any >& getDeviceInfo( const uno::Reference< rendering::XCanvas >& i_rxCanvas,
+ uno::Sequence< uno::Any >& o_rxParams )
+ {
+ o_rxParams.realloc( 0 );
+
+ if( i_rxCanvas.is() )
+ {
+ try
+ {
+ uno::Reference< rendering::XGraphicDevice > xDevice( i_rxCanvas->getDevice(),
+ uno::UNO_QUERY_THROW );
+
+ uno::Reference< lang::XServiceInfo > xServiceInfo( xDevice,
+ uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xPropSet( xDevice,
+ uno::UNO_QUERY_THROW );
+
+ o_rxParams.realloc( 2 );
+
+ o_rxParams[ 0 ] = uno::makeAny( xServiceInfo->getImplementationName() );
+ o_rxParams[ 1 ] = uno::makeAny( xPropSet->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DeviceHandle") ) ) );
+ }
+ catch( uno::Exception& )
+ {
+ // ignore, but return empty sequence
+ }
+ }
+
+ return o_rxParams;
+ }
+
+ awt::Rectangle getAbsoluteWindowRect( const awt::Rectangle& rRect,
+ const uno::Reference< awt::XWindow2 >& xWin )
+ {
+ awt::Rectangle aRetVal( rRect );
+
+ ::Window* pWindow = VCLUnoHelper::GetWindow(xWin);
+ if( pWindow )
+ {
+ ::Point aPoint( aRetVal.X,
+ aRetVal.Y );
+
+ aPoint = pWindow->OutputToScreenPixel( aPoint );
+
+ aRetVal.X = aPoint.X();
+ aRetVal.Y = aPoint.Y();
+ }
+
+ return aRetVal;
+ }
+
+ ::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon( const ::basegfx::B2DRange& rRange )
+ {
+ ::basegfx::B2DPolyPolygon aPolyPoly;
+ ::basegfx::B2DPolygon aPoly;
+
+ const double nX0( rRange.getMinX() );
+ const double nY0( rRange.getMinY() );
+ const double nX1( rRange.getMaxX() );
+ const double nY1( rRange.getMaxY() );
+
+ aPoly.append( ::basegfx::B2DPoint( nX0+4,
+ nY0 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX0,
+ nY0 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX0,
+ nY0+4 ) );
+ aPolyPoly.append( aPoly ); aPoly.clear();
+
+ aPoly.append( ::basegfx::B2DPoint( nX1-4,
+ nY0 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX1,
+ nY0 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX1,
+ nY0+4 ) );
+ aPolyPoly.append( aPoly ); aPoly.clear();
+
+ aPoly.append( ::basegfx::B2DPoint( nX0+4,
+ nY1 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX0,
+ nY1 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX0,
+ nY1-4 ) );
+ aPolyPoly.append( aPoly ); aPoly.clear();
+
+ aPoly.append( ::basegfx::B2DPoint( nX1-4,
+ nY1 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX1,
+ nY1 ) );
+ aPoly.append( ::basegfx::B2DPoint( nX1,
+ nY1-4 ) );
+ aPolyPoly.append( aPoly );
+
+ return aPolyPoly;
+ }
+
+ int calcGradientStepCount( ::basegfx::B2DHomMatrix& rTotalTransform,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::Texture& texture,
+ int nColorSteps )
+ {
+ // calculate overall texture transformation (directly from
+ // texture to device space).
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ rTotalTransform.identity();
+ ::basegfx::unotools::homMatrixFromAffineMatrix( rTotalTransform,
+ texture.AffineTransform );
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ viewState,
+ renderState);
+ rTotalTransform *= aMatrix; // prepend total view/render transformation
+
+ // determine size of gradient in device coordinate system
+ // (to e.g. determine sensible number of gradient steps)
+ ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
+ ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
+ ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
+ ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
+
+ aLeftTop *= rTotalTransform;
+ aLeftBottom *= rTotalTransform;
+ aRightTop *= rTotalTransform;
+ aRightBottom*= rTotalTransform;
+
+ // longest line in gradient bound rect
+ const int nGradientSize(
+ static_cast<int>(
+ ::std::max(
+ ::basegfx::B2DVector(aRightBottom-aLeftTop).getLength(),
+ ::basegfx::B2DVector(aRightTop-aLeftBottom).getLength() ) + 1.0 ) );
+
+ // typical number for pixel of the same color (strip size)
+ const int nStripSize( nGradientSize < 50 ? 2 : 4 );
+
+ // use at least three steps, and at utmost the number of color
+ // steps
+ return ::std::max( 3,
+ ::std::min(
+ nGradientSize / nStripSize,
+ nColorSteps ) );
+ }
+
+ } // namespace tools
+
+} // namespace canvas
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/canvastools.flt b/canvas/source/tools/canvastools.flt
new file mode 100644
index 000000000000..67e713474bf1
--- /dev/null
+++ b/canvas/source/tools/canvastools.flt
@@ -0,0 +1,3 @@
+__CT
+__real
+internal
diff --git a/canvas/source/tools/elapsedtime.cxx b/canvas/source/tools/elapsedtime.cxx
new file mode 100644
index 000000000000..f4f6e5db8a67
--- /dev/null
+++ b/canvas/source/tools/elapsedtime.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "osl/time.h"
+#include "osl/diagnose.h"
+#include "canvas/elapsedtime.hxx"
+
+#if defined(WIN) || defined(WNT)
+
+#if defined _MSC_VER
+#pragma warning(push,1)
+#endif
+
+// TEMP!!!
+// Awaiting corresponding functionality in OSL
+//
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winbase.h>
+#include <mmsystem.h>
+#endif
+
+#if defined _MSC_VER
+#pragma warning(pop)
+#endif
+
+#include <algorithm>
+#include <limits>
+
+namespace canvas {
+namespace tools {
+
+
+#if defined(WIN) || defined(WNT)
+// TODO(Q2): is 0 okay for the failure case here?
+double ElapsedTime::getSystemTime()
+{
+ // TEMP!!!
+ // Awaiting corresponding functionality in OSL
+ //
+
+ // is there a performance counter available?
+ static bool bTimeSetupDone( false );
+ static bool bPerfTimerAvailable( false );
+ static LONGLONG nPerfCountFreq;
+
+ // TODO(F1): This _might_ cause problems, as it prevents correct
+ // time handling for very long lifetimes of this class's
+ // surrounding component in memory. When the difference between
+ // current sys time and nInitialCount exceeds IEEE double's
+ // mantissa, time will start to run jerky.
+ static LONGLONG nInitialCount;
+
+ if( !bTimeSetupDone )
+ {
+ if( QueryPerformanceFrequency(
+ reinterpret_cast<LARGE_INTEGER *>(&nPerfCountFreq) ) )
+ {
+ // read initial time:
+ QueryPerformanceCounter(
+ reinterpret_cast<LARGE_INTEGER *>(&nInitialCount) );
+ bPerfTimerAvailable = true;
+ }
+ bTimeSetupDone = true;
+ }
+
+ if( bPerfTimerAvailable )
+ {
+ LONGLONG nCurrCount;
+ QueryPerformanceCounter(
+ reinterpret_cast<LARGE_INTEGER *>(&nCurrCount) );
+ nCurrCount -= nInitialCount;
+ return double(nCurrCount) / nPerfCountFreq;
+ }
+ else
+ {
+ LONGLONG nCurrTime = timeGetTime();
+ return double(nCurrTime) / 1000.0;
+ }
+}
+
+#else // ! WNT
+
+// TODO(Q2): is 0 okay for the failure case here?
+double ElapsedTime::getSystemTime()
+{
+ TimeValue aTimeVal;
+ if( osl_getSystemTime( &aTimeVal ) )
+ return ((aTimeVal.Nanosec * 10e-10) + aTimeVal.Seconds);
+ else
+ return 0.0;
+}
+
+#endif
+
+ElapsedTime::ElapsedTime()
+ : m_pTimeBase(),
+ m_fLastQueriedTime( 0.0 ),
+ m_fStartTime( getSystemTime() ),
+ m_fFrozenTime( 0.0 ),
+ m_bInPauseMode( false ),
+ m_bInHoldMode( false )
+{
+}
+
+ElapsedTime::ElapsedTime(
+ boost::shared_ptr<ElapsedTime> const & pTimeBase )
+ : m_pTimeBase( pTimeBase ),
+ m_fLastQueriedTime( 0.0 ),
+ m_fStartTime( getCurrentTime() ),
+ m_fFrozenTime( 0.0 ),
+ m_bInPauseMode( false ),
+ m_bInHoldMode( false )
+{
+}
+
+boost::shared_ptr<ElapsedTime> const & ElapsedTime::getTimeBase() const
+{
+ return m_pTimeBase;
+}
+
+void ElapsedTime::reset()
+{
+ m_fLastQueriedTime = 0.0;
+ m_fStartTime = getCurrentTime();
+ m_fFrozenTime = 0.0;
+ m_bInPauseMode = false;
+ m_bInHoldMode = false;
+}
+
+void ElapsedTime::adjustTimer( double fOffset, bool /*bLimitToLastQueriedTime*/ )
+{
+ // to make getElapsedTime() become _larger_, have to reduce
+ // m_fStartTime.
+ m_fStartTime -= fOffset;
+
+ // also adjust frozen time, this method must _always_ affect the
+ // value returned by getElapsedTime()!
+ if (m_bInHoldMode || m_bInPauseMode)
+ m_fFrozenTime += fOffset;
+}
+
+double ElapsedTime::getCurrentTime() const
+{
+ return m_pTimeBase.get() == 0
+ ? getSystemTime() : m_pTimeBase->getElapsedTimeImpl();
+}
+
+double ElapsedTime::getElapsedTime() const
+{
+ m_fLastQueriedTime = getElapsedTimeImpl();
+ return m_fLastQueriedTime;
+}
+
+double ElapsedTime::getElapsedTimeImpl() const
+{
+ if (m_bInHoldMode || m_bInPauseMode)
+ return m_fFrozenTime;
+
+ return getCurrentTime() - m_fStartTime;
+}
+
+void ElapsedTime::pauseTimer()
+{
+ m_fFrozenTime = getElapsedTimeImpl();
+ m_bInPauseMode = true;
+}
+
+void ElapsedTime::continueTimer()
+{
+ m_bInPauseMode = false;
+
+ // stop pausing, time runs again. Note that
+ // getElapsedTimeImpl() honors hold mode, i.e. a
+ // continueTimer() in hold mode will preserve the latter
+ const double fPauseDuration( getElapsedTimeImpl() - m_fFrozenTime );
+
+ // adjust start time, such that subsequent getElapsedTime() calls
+ // will virtually start from m_fFrozenTime.
+ m_fStartTime += fPauseDuration;
+}
+
+void ElapsedTime::holdTimer()
+{
+ // when called during hold mode (e.g. more than once per time
+ // object), the original hold time will be maintained.
+ m_fFrozenTime = getElapsedTimeImpl();
+ m_bInHoldMode = true;
+}
+
+void ElapsedTime::releaseTimer()
+{
+ m_bInHoldMode = false;
+}
+
+} // namespace tools
+} // namespace canvas
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/imagecachedprimitive.hxx b/canvas/source/tools/imagecachedprimitive.hxx
new file mode 100644
index 000000000000..23cab7ce83f8
--- /dev/null
+++ b/canvas/source/tools/imagecachedprimitive.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_IMAGECACHEDPRIMITIVE_HXX
+#define INCLUDED_CANVAS_IMAGECACHEDPRIMITIVE_HXX
+
+#include <canvas/rendering/icachedprimitive.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace canvas
+{
+ /** Objects with this interface are returned from every Image
+ render operation.
+
+ These objects can be used to implement the
+ rendering::XCachedPrimitive interface, which in turn caches
+ render state and objects to facilitate quick redraws.
+
+ Derived from ICachedPrimitive, to add the setImage() method
+ (which, strictly speaking, is a technicality, because Image
+ cannot create objects with a shared_ptr to itself).
+ */
+ struct ImageCachedPrimitive : public ICachedPrimitive
+ {
+ virtual void setImage( const ::boost::shared_ptr< class Image >& rTargetImage ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ImageCachedPrimitive > ImageCachedPrimitiveSharedPtr;
+}
+
+#endif /* INCLUDED_CANVAS_IMAGECACHEDPRIMITIVE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/makefile.mk b/canvas/source/tools/makefile.mk
new file mode 100644
index 000000000000..d51053d1d491
--- /dev/null
+++ b/canvas/source/tools/makefile.mk
@@ -0,0 +1,91 @@
+#*************************************************************************
+#
+# 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=canvastools
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+.IF "$(profiler)"!="" || "$(PROFILER)"!=""
+CDEFS+= -DPROFILER
+.ENDIF
+
+#CFLAGS +:= /Ox /Ot # THIS IS IMPORTANT
+
+
+.IF "$(L10N_framework)"==""
+SLOFILES = \
+ $(SLO)$/cachedprimitivebase.obj \
+ $(SLO)$/canvascustomspritehelper.obj \
+ $(SLO)$/canvastools.obj \
+ $(SLO)$/elapsedtime.obj \
+ $(SLO)$/parametricpolypolygon.obj \
+ $(SLO)$/prioritybooster.obj \
+ $(SLO)$/propertysethelper.obj \
+ $(SLO)$/spriteredrawmanager.obj \
+ $(SLO)$/surface.obj \
+ $(SLO)$/surfaceproxy.obj \
+ $(SLO)$/surfaceproxymanager.obj \
+ $(SLO)$/pagemanager.obj \
+ $(SLO)$/page.obj \
+ $(SLO)$/verifyinput.obj
+
+SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
+SHL1IMPLIB= i$(TARGET)
+SHL1STDLIBS= $(SALLIB) $(CPPULIB) $(BASEGFXLIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(VCLLIB) $(TKLIB) $(TOOLSLIB)
+
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME =$(SHL1TARGET)
+DEF1DEPN =$(MISC)$/$(SHL1TARGET).flt \
+ $(LIB1TARGET)
+
+DEF1DES =Canvastools
+DEFLIB1NAME =$(TARGET)
+
+.IF "$(GUI)" == "WNT"
+SHL1STDLIBS += $(WINMMLIB) $(KERNEL32LIB)
+.ENDIF
+.ENDIF
+
+# ==========================================================================
+
+.INCLUDE : target.mk
+
+$(MISC)$/$(SHL1TARGET).flt : makefile.mk $(TARGET).flt
+ @$(TYPE) $(TARGET).flt > $@
diff --git a/canvas/source/tools/page.cxx b/canvas/source/tools/page.cxx
new file mode 100644
index 000000000000..7d85e419782a
--- /dev/null
+++ b/canvas/source/tools/page.cxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <boost/bind.hpp>
+#include "page.hxx"
+
+namespace canvas
+{
+ Page::Page( const IRenderModuleSharedPtr &rRenderModule ) :
+ mpRenderModule(rRenderModule),
+ mpSurface(rRenderModule->createSurface(::basegfx::B2ISize()))
+ {
+ }
+
+ void Page::validate()
+ {
+ if(!(isValid()))
+ {
+ ::std::for_each( mpFragments.begin(),
+ mpFragments.end(),
+ ::boost::mem_fn(&PageFragment::refresh));
+ }
+ }
+
+ bool Page::isValid() const
+ {
+ return mpSurface && mpSurface->isValid();
+ }
+
+ FragmentSharedPtr Page::allocateSpace( const ::basegfx::B2ISize& rSize )
+ {
+ SurfaceRect rect(rSize);
+ if(insert(rect))
+ {
+ FragmentSharedPtr pFragment(new PageFragment(rect,this));
+ mpFragments.push_back(pFragment);
+ return pFragment;
+ }
+
+ return FragmentSharedPtr();
+ }
+
+ bool Page::nakedFragment( const FragmentSharedPtr& pFragment )
+ {
+ SurfaceRect rect(pFragment->getSize());
+ if(insert(rect))
+ {
+ pFragment->setPage(this);
+ mpFragments.push_back(pFragment);
+ return true;
+ }
+
+ return false;
+ }
+
+ void Page::free( const FragmentSharedPtr& pFragment )
+ {
+ // the fragment passes as argument is no longer
+ // dedicated to this page. either it is about to
+ // be relocated to some other page or it will
+ // currently be deleted. in either case, simply
+ // remove the reference from our internal storage.
+ FragmentContainer_t::iterator it(
+ std::remove(
+ mpFragments.begin(),mpFragments.end(),pFragment));
+ mpFragments.erase(it,mpFragments.end());
+ }
+
+ bool Page::insert( SurfaceRect& r )
+ {
+ const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
+ FragmentContainer_t::const_iterator it(mpFragments.begin());
+ while(it != aEnd)
+ {
+ const SurfaceRect &rect = (*it)->getRect();
+ const sal_Int32 x = rect.maPos.getX();
+ const sal_Int32 y = rect.maPos.getY();
+ // to avoid interpolation artifacts from other textures,
+ // one pixel gap between them
+ const sal_Int32 w = rect.maSize.getX()+1;
+ const sal_Int32 h = rect.maSize.getY()+1;
+
+ // probe location to the right
+ r.maPos.setX(x+w);
+ r.maPos.setY(y);
+ if(isValidLocation(r))
+ return true;
+
+ // probe location at bottom
+ r.maPos.setX(x);
+ r.maPos.setY(y+h);
+ if(isValidLocation(r))
+ return true;
+
+ ++it;
+ }
+
+ r.maPos.setX(0);
+ r.maPos.setY(0);
+
+ return isValidLocation(r);
+ }
+
+ bool Page::isValidLocation( const SurfaceRect& r ) const
+ {
+ // the rectangle passed as argument has a valid
+ // location if and only if there's no intersection
+ // with existing areas.
+ SurfaceRect aBoundary(mpRenderModule->getPageSize()-basegfx::B2IVector(1,1));
+ if( !r.inside(aBoundary) )
+ return false;
+
+ const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
+ FragmentContainer_t::const_iterator it(mpFragments.begin());
+ while(it != aEnd)
+ {
+ if(r.intersection((*it)->getRect()))
+ return false;
+
+ ++it;
+ }
+
+ return true;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/page.hxx b/canvas/source/tools/page.hxx
new file mode 100644
index 000000000000..bef9684da594
--- /dev/null
+++ b/canvas/source/tools/page.hxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_PAGE_HXX
+#define INCLUDED_CANVAS_PAGE_HXX
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <canvas/rendering/isurface.hxx>
+
+#include <list>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include "surfacerect.hxx"
+
+namespace canvas
+{
+ class PageFragment;
+
+ typedef ::boost::shared_ptr< PageFragment > FragmentSharedPtr;
+
+ /** One page of IRenderModule-provided texture space
+ */
+ class Page
+ {
+ public:
+ Page( const IRenderModuleSharedPtr& rRenderModule );
+
+ FragmentSharedPtr allocateSpace( const ::basegfx::B2ISize& rSize );
+ bool nakedFragment( const FragmentSharedPtr& pFragment );
+ void free( const FragmentSharedPtr& pFragment );
+ const ISurfaceSharedPtr& getSurface() const { return mpSurface; }
+ bool isValid() const;
+ void validate();
+
+ private:
+ typedef std::list<FragmentSharedPtr> FragmentContainer_t;
+
+ IRenderModuleSharedPtr mpRenderModule;
+ ISurfaceSharedPtr mpSurface;
+ FragmentContainer_t mpFragments;
+
+ bool insert( SurfaceRect& r );
+ bool isValidLocation( const SurfaceRect& r ) const;
+ };
+
+ typedef ::boost::shared_ptr< Page > PageSharedPtr;
+
+
+ /** A part of a page, which gets allocated to a surface
+ */
+ class PageFragment
+ {
+ public:
+ PageFragment( const SurfaceRect& r,
+ Page* pPage ) :
+ mpPage(pPage),
+ maRect(r),
+ mpBuffer(),
+ maSourceOffset()
+ {
+ }
+
+ /// Creates a 'naked' fragment.
+ PageFragment( const ::basegfx::B2ISize& rSize ) :
+ mpPage(NULL),
+ maRect(rSize),
+ mpBuffer(),
+ maSourceOffset()
+ {
+ }
+
+ bool isNaked() const { return (mpPage == NULL); }
+ const SurfaceRect& getRect() const { return maRect; }
+ const ::basegfx::B2IPoint& getPos() const { return maRect.maPos; }
+ const ::basegfx::B2ISize& getSize() const { return maRect.maSize; }
+ void setColorBuffer( const IColorBufferSharedPtr& pColorBuffer ) { mpBuffer=pColorBuffer; }
+ void setSourceOffset( const ::basegfx::B2IPoint& rOffset ) { maSourceOffset=rOffset; }
+ void setPage( Page* pPage ) { mpPage=pPage; }
+
+ void free( const FragmentSharedPtr& pFragment )
+ {
+ if(mpPage)
+ mpPage->free(pFragment);
+
+ mpPage=NULL;
+ }
+
+ bool select( bool bRefresh )
+ {
+ // request was made to select this fragment,
+ // but this fragment has not been located on any
+ // of the available pages, we need to hurry now.
+ if(!(mpPage))
+ return false;
+
+ ISurfaceSharedPtr pSurface(mpPage->getSurface());
+
+ // select this surface before wiping the contents
+ // since a specific implementation could trigger
+ // a rendering operation here...
+ if(!(pSurface->selectTexture()))
+ return false;
+
+ // call refresh() if requested, otherwise we're up to date...
+ return bRefresh ? refresh() : true;
+ }
+
+ bool refresh()
+ {
+ if(!(mpPage))
+ return false;
+
+ ISurfaceSharedPtr pSurface(mpPage->getSurface());
+
+ return pSurface->update( maRect.maPos,
+ ::basegfx::B2IRectangle(
+ maSourceOffset,
+ maSourceOffset + maRect.maSize ),
+ *mpBuffer );
+ }
+
+ private:
+ Page* mpPage;
+ SurfaceRect maRect;
+ IColorBufferSharedPtr mpBuffer;
+ ::basegfx::B2IPoint maSourceOffset;
+ };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/pagemanager.cxx b/canvas/source/tools/pagemanager.cxx
new file mode 100644
index 000000000000..b37c578e19ab
--- /dev/null
+++ b/canvas/source/tools/pagemanager.cxx
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <boost/bind.hpp>
+#include "pagemanager.hxx"
+
+namespace canvas
+{
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager
+ //////////////////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::allocateSpace
+ //////////////////////////////////////////////////////////////////////////////////
+
+ FragmentSharedPtr PageManager::allocateSpace( const ::basegfx::B2ISize& rSize )
+ {
+ // we are asked to find a location for the requested size.
+ // first we try to satisfy the request from the
+ // remaining space in the existing pages.
+ const PageContainer_t::iterator aEnd(maPages.end());
+ PageContainer_t::iterator it(maPages.begin());
+ while(it != aEnd)
+ {
+ FragmentSharedPtr pFragment((*it)->allocateSpace(rSize));
+ if(pFragment)
+ {
+ // the page created a new fragment, since we maybe want
+ // to consolidate sparse pages we keep a reference to
+ // the fragment.
+ maFragments.push_back(pFragment);
+ return pFragment;
+ }
+
+ ++it;
+ }
+
+ // otherwise try to create a new page and allocate space there...
+ PageSharedPtr pPage(new Page(mpRenderModule));
+ if(pPage->isValid())
+ {
+ maPages.push_back(pPage);
+ FragmentSharedPtr pFragment(pPage->allocateSpace(rSize));
+ if (pFragment)
+ maFragments.push_back(pFragment);
+ return pFragment;
+ }
+
+ // the rendermodule failed to create a new page [maybe out
+ // of videomemory], and all other pages could not take
+ // the new request. we decide to create a 'naked' fragment
+ // which will receive its location later.
+ FragmentSharedPtr pFragment(new PageFragment(rSize));
+ maFragments.push_back(pFragment);
+ return pFragment;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::free
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void PageManager::free( const FragmentSharedPtr& pFragment )
+ {
+ // erase the reference to the given fragment from our
+ // internal container.
+ FragmentContainer_t::iterator it(
+ std::remove(
+ maFragments.begin(),maFragments.end(),pFragment));
+ maFragments.erase(it,maFragments.end());
+
+ // let the fragment itself know about it...
+ // we need to pass 'this' as argument since the fragment
+ // needs to pass this to the page and can't create
+ // shared_ptr from itself...
+ pFragment->free(pFragment);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::nakedFragment
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void PageManager::nakedFragment( const FragmentSharedPtr& pFragment )
+ {
+ if(maPages.empty())
+ return;
+
+ // okay, one last chance is left, we try all available
+ // pages again. maybe some other fragment was deleted
+ // and we can exploit the space.
+ while(!(relocate(pFragment)))
+ {
+ // no way, we need to free up some space...
+ // TODO(F1): this is a heuristic, could
+ // be designed as a policy.
+ const FragmentContainer_t::const_iterator aEnd(maFragments.end());
+ FragmentContainer_t::const_iterator candidate(maFragments.begin());
+ while(candidate != aEnd)
+ {
+ if(*candidate && !((*candidate)->isNaked()))
+ break;
+ ++candidate;
+ }
+
+ if (candidate != aEnd)
+ {
+ const ::basegfx::B2ISize& rSize((*candidate)->getSize());
+ sal_uInt32 nMaxArea(rSize.getX()*rSize.getY());
+
+ FragmentContainer_t::const_iterator it(candidate);
+ while(it != aEnd)
+ {
+ if (*it && !((*it)->isNaked()))
+ {
+ const ::basegfx::B2ISize& rCandidateSize((*it)->getSize());
+ const sal_uInt32 nArea(rCandidateSize.getX()*rCandidateSize.getY());
+ if(nArea > nMaxArea)
+ {
+ candidate=it;
+ nMaxArea=nArea;
+ }
+ }
+
+ ++it;
+ }
+
+ // this does not erase the candidate,
+ // but makes it 'naked'...
+ (*candidate)->free(*candidate);
+ }
+ else
+ break;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::relocate
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool PageManager::relocate( const FragmentSharedPtr& pFragment )
+ {
+ // the fragment passed as argument is assumed to
+ // be naked, that is it is not located on any page.
+ // we try all available pages again, maybe some
+ // other fragment was deleted and we can exploit the space.
+ const PageContainer_t::iterator aEnd(maPages.end());
+ PageContainer_t::iterator it(maPages.begin());
+ while(it != aEnd)
+ {
+ // if the page at hand takes the fragment, we immediatelly
+ // call select() to pull the information from the associated
+ // image to the hardware surface.
+ if((*it)->nakedFragment(pFragment))
+ {
+ // dirty, since newly allocated.
+ pFragment->select(true);
+ return true;
+ }
+
+ ++it;
+ }
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::validatePages
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void PageManager::validatePages()
+ {
+ ::std::for_each( maPages.begin(),
+ maPages.end(),
+ ::boost::mem_fn(&Page::validate));
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::getPageSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2ISize PageManager::getPageSize() const
+ {
+ return mpRenderModule->getPageSize();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager::getRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ canvas::IRenderModuleSharedPtr PageManager::getRenderModule() const
+ {
+ return mpRenderModule;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/pagemanager.hxx b/canvas/source/tools/pagemanager.hxx
new file mode 100644
index 000000000000..f82a8e339a0c
--- /dev/null
+++ b/canvas/source/tools/pagemanager.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_PAGEMANAGER_HXX
+#define INCLUDED_CANVAS_PAGEMANAGER_HXX
+
+#include <basegfx/vector/b2isize.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <canvas/rendering/isurface.hxx>
+
+#include "page.hxx"
+
+namespace canvas
+{
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManager
+ //////////////////////////////////////////////////////////////////////////////////
+
+ class PageManager
+ {
+ public:
+ PageManager( const canvas::IRenderModuleSharedPtr pRenderModule ) :
+ mpRenderModule(pRenderModule)
+ {
+ }
+
+ // returns the maximum size of a hardware
+ // accelerated page, e.g. OpenGL texture.
+ ::basegfx::B2ISize getPageSize() const;
+
+ canvas::IRenderModuleSharedPtr getRenderModule() const;
+
+ FragmentSharedPtr allocateSpace( const ::basegfx::B2ISize& rSize );
+ void free( const FragmentSharedPtr& pFragment );
+
+ void nakedFragment( const FragmentSharedPtr& pFragment );
+
+ void validatePages();
+
+ private:
+ // the pagemanager needs access to the rendermodule
+ // since we query for system resources from it.
+ canvas::IRenderModuleSharedPtr mpRenderModule;
+
+ // here we collect all fragments that will be created
+ // since we need them for relocation purposes.
+ typedef std::list<FragmentSharedPtr> FragmentContainer_t;
+ FragmentContainer_t maFragments;
+
+ // this is the container holding all created pages,
+ // behind the scenes these are real hardware surfaces.
+ typedef std::list<PageSharedPtr> PageContainer_t;
+ PageContainer_t maPages;
+
+ bool relocate( const FragmentSharedPtr& pFragment );
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // PageManagerSharedPtr
+ //////////////////////////////////////////////////////////////////////////////////
+
+ typedef ::boost::shared_ptr< PageManager > PageManagerSharedPtr;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // End of file
+ //////////////////////////////////////////////////////////////////////////////////
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/parametricpolypolygon.cxx b/canvas/source/tools/parametricpolypolygon.cxx
new file mode 100644
index 000000000000..8775c1eb3cc2
--- /dev/null
+++ b/canvas/source/tools/parametricpolypolygon.cxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <rtl/math.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/tools.hxx>
+
+#include <limits>
+
+#include <canvas/parametricpolypolygon.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace canvas
+{
+ uno::Sequence<rtl::OUString> ParametricPolyPolygon::getAvailableServiceNames()
+ {
+ uno::Sequence<rtl::OUString> aRet(3);
+ aRet[0] = rtl::OUString::createFromAscii("LinearGradient");
+ aRet[1] = rtl::OUString::createFromAscii("EllipticalGradient");
+ aRet[2] = rtl::OUString::createFromAscii("RectangularGradient");
+
+ return aRet;
+ }
+
+ ParametricPolyPolygon* ParametricPolyPolygon::create(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const ::rtl::OUString& rServiceName,
+ const uno::Sequence< uno::Any >& rArgs )
+ {
+ uno::Sequence< uno::Sequence< double > > colorSequence(2);
+ uno::Sequence< double > colorStops(2);
+ double fAspectRatio=1.0;
+
+ // defaults
+ uno::Sequence< rendering::RGBColor > rgbColors(1);
+ rgbColors[0] = rendering::RGBColor(0,0,0);
+ colorSequence[0] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
+ rgbColors[0] = rendering::RGBColor(1,1,1);
+ colorSequence[1] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
+ colorStops[0] = 0;
+ colorStops[1] = 1;
+
+ // extract args
+ for( sal_Int32 i=0; i<rArgs.getLength(); ++i )
+ {
+ beans::PropertyValue aProp;
+ if( (rArgs[i] >>= aProp) )
+ {
+ if( aProp.Name.equalsAscii("Colors") )
+ {
+ aProp.Value >>= colorSequence;
+ }
+ else if( aProp.Name.equalsAscii("Stops") )
+ {
+ aProp.Value >>= colorStops;
+ }
+ else if( aProp.Name.equalsAscii("AspectRatio") )
+ {
+ aProp.Value >>= fAspectRatio;
+ }
+ }
+ }
+
+ if( rServiceName.equalsAscii("LinearGradient") )
+ {
+ return createLinearHorizontalGradient(rDevice, colorSequence, colorStops);
+ }
+ else if( rServiceName.equalsAscii("EllipticalGradient") )
+ {
+ return createEllipticalGradient(rDevice, colorSequence, colorStops, fAspectRatio);
+ }
+ else if( rServiceName.equalsAscii("RectangularGradient") )
+ {
+ return createRectangularGradient(rDevice, colorSequence, colorStops, fAspectRatio);
+ }
+ else if( rServiceName.equalsAscii("VerticalLineHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("OrthogonalLinesHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("ThreeCrossingLinesHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("FourCrossingLinesHatch") )
+ {
+ // TODO: NYI
+ }
+
+ return NULL;
+ }
+
+ ParametricPolyPolygon* ParametricPolyPolygon::createLinearHorizontalGradient(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const uno::Sequence< uno::Sequence< double > >& colors,
+ const uno::Sequence< double >& stops )
+ {
+ // TODO(P2): hold gradient brush statically, and only setup
+ // the colors
+ return new ParametricPolyPolygon( rDevice, GRADIENT_LINEAR, colors, stops );
+ }
+
+ ParametricPolyPolygon* ParametricPolyPolygon::createEllipticalGradient(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const uno::Sequence< uno::Sequence< double > >& colors,
+ const uno::Sequence< double >& stops,
+ double fAspectRatio )
+ {
+ // TODO(P2): hold gradient polygon statically, and only setup
+ // the colors
+ return new ParametricPolyPolygon(
+ rDevice,
+ ::basegfx::tools::createPolygonFromCircle(
+ ::basegfx::B2DPoint(0,0), 1 ),
+ GRADIENT_ELLIPTICAL,
+ colors, stops, fAspectRatio );
+ }
+
+ ParametricPolyPolygon* ParametricPolyPolygon::createRectangularGradient( const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const uno::Sequence< uno::Sequence< double > >& colors,
+ const uno::Sequence< double >& stops,
+ double fAspectRatio )
+ {
+ // TODO(P2): hold gradient polygon statically, and only setup
+ // the colors
+ return new ParametricPolyPolygon(
+ rDevice,
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( -1, -1, 1, 1 ) ),
+ GRADIENT_RECTANGULAR,
+ colors, stops, fAspectRatio );
+ }
+
+ void SAL_CALL ParametricPolyPolygon::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxDevice.clear();
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL ParametricPolyPolygon::getOutline( double /*t*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO(F1): outline NYI
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ uno::Sequence< double > SAL_CALL ParametricPolyPolygon::getColor( double /*t*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO(F1): color NYI
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< double > SAL_CALL ParametricPolyPolygon::getPointColor( const geometry::RealPoint2D& /*point*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO(F1): point color NYI
+ return uno::Sequence< double >();
+ }
+
+ uno::Reference< rendering::XColorSpace > SAL_CALL ParametricPolyPolygon::getColorSpace() throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mxDevice.is() ? mxDevice->getDeviceColorSpace() : uno::Reference< rendering::XColorSpace >();
+ }
+
+#define IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon"
+#define SERVICE_NAME "com.sun.star.rendering.ParametricPolyPolygon"
+
+ ::rtl::OUString SAL_CALL ParametricPolyPolygon::getImplementationName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL ParametricPolyPolygon::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL ParametricPolyPolygon::getSupportedServiceNames( ) throw (uno::RuntimeException)
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+ ParametricPolyPolygon::~ParametricPolyPolygon()
+ {
+ }
+
+ ParametricPolyPolygon::ParametricPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const ::basegfx::B2DPolygon& rGradientPoly,
+ GradientType eType,
+ const uno::Sequence< uno::Sequence< double > >& rColors,
+ const uno::Sequence< double >& rStops ) :
+ ParametricPolyPolygon_Base( m_aMutex ),
+ mxDevice( rDevice ),
+ maValues( rGradientPoly,
+ rColors,
+ rStops,
+ 1.0,
+ eType )
+ {
+ }
+
+ ParametricPolyPolygon::ParametricPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const ::basegfx::B2DPolygon& rGradientPoly,
+ GradientType eType,
+ const uno::Sequence< uno::Sequence< double > >& rColors,
+ const uno::Sequence< double >& rStops,
+ double nAspectRatio ) :
+ ParametricPolyPolygon_Base( m_aMutex ),
+ mxDevice( rDevice ),
+ maValues( rGradientPoly,
+ rColors,
+ rStops,
+ nAspectRatio,
+ eType )
+ {
+ }
+
+ ParametricPolyPolygon::ParametricPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ GradientType eType,
+ const uno::Sequence< uno::Sequence< double > >& rColors,
+ const uno::Sequence< double >& rStops ) :
+ ParametricPolyPolygon_Base( m_aMutex ),
+ mxDevice( rDevice ),
+ maValues( ::basegfx::B2DPolygon(),
+ rColors,
+ rStops,
+ 1.0,
+ eType )
+ {
+ }
+
+ ParametricPolyPolygon::Values ParametricPolyPolygon::getValues() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maValues;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/prioritybooster.cxx b/canvas/source/tools/prioritybooster.cxx
new file mode 100644
index 000000000000..4256965627f7
--- /dev/null
+++ b/canvas/source/tools/prioritybooster.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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
+# if defined _MSC_VER
+# pragma warning(push,1)
+# endif
+
+# include <windows.h>
+
+# if defined _MSC_VER
+# pragma warning(pop)
+# endif
+#endif
+
+#include "osl/diagnose.h"
+#include "canvas/prioritybooster.hxx"
+
+
+namespace canvas
+{
+ namespace tools
+ {
+ struct PriorityBooster_Impl
+ {
+ int mnOldPriority;
+ };
+
+ PriorityBooster::PriorityBooster( sal_Int32 nDelta ) :
+ mpImpl( new PriorityBooster_Impl )
+ {
+#ifdef WNT
+ HANDLE aCurrThread = GetCurrentThread();
+ mpImpl->mnOldPriority = GetThreadPriority( aCurrThread );
+
+ if ( 0 == SetThreadPriority( aCurrThread, mpImpl->mnOldPriority + nDelta ) )
+ {
+ OSL_ENSURE( false,
+ "PriorityBooster::PriorityBooster(): Was not able to modify thread priority" );
+ }
+#else
+ nDelta = 0; // #i55991# placate gcc warning
+#endif
+ }
+
+ PriorityBooster::~PriorityBooster()
+ {
+#ifdef WNT
+ SetThreadPriority( GetCurrentThread(),
+ mpImpl->mnOldPriority );
+#endif
+ }
+ } // namespace tools
+
+} // namespace canvas
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/propertysethelper.cxx b/canvas/source/tools/propertysethelper.cxx
new file mode 100644
index 000000000000..d48f1922d689
--- /dev/null
+++ b/canvas/source/tools/propertysethelper.cxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/propertysethelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace canvas
+{
+ namespace
+ {
+ void throwUnknown( const ::rtl::OUString& aPropertyName )
+ {
+ throw beans::UnknownPropertyException(
+ ::rtl::OUString::createFromAscii("PropertySetHelper: property ") +
+ aPropertyName +
+ ::rtl::OUString::createFromAscii(" not found."),
+ uno::Reference< uno::XInterface >()
+ );
+ }
+
+ void throwVeto( const ::rtl::OUString& aPropertyName )
+ {
+ throw beans::PropertyVetoException(
+ ::rtl::OUString::createFromAscii("PropertySetHelper: property ") +
+ aPropertyName +
+ ::rtl::OUString::createFromAscii(" access was vetoed."),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ struct EntryComparator
+ {
+ bool operator()( const PropertySetHelper::MapType::MapEntry& rLHS,
+ const PropertySetHelper::MapType::MapEntry& rRHS )
+ {
+ return strcmp( rLHS.maKey,
+ rRHS.maKey ) < 0;
+ }
+ };
+ }
+
+ PropertySetHelper::PropertySetHelper() :
+ mpMap(),
+ maMapEntries()
+ {
+ }
+
+ PropertySetHelper::PropertySetHelper( const InputMap& rMap ) :
+ mpMap(),
+ maMapEntries()
+ {
+ initProperties(rMap);
+ }
+
+ void PropertySetHelper::initProperties( const InputMap& rMap )
+ {
+ mpMap.reset();
+ maMapEntries = rMap;
+
+ std::sort( maMapEntries.begin(),
+ maMapEntries.end(),
+ EntryComparator() );
+
+ if( !maMapEntries.empty() )
+ mpMap.reset( new MapType(&maMapEntries[0],
+ maMapEntries.size(),
+ true) );
+ }
+
+ void PropertySetHelper::addProperties( const InputMap& rMap )
+ {
+ InputMap aMerged( getPropertyMap() );
+ aMerged.insert( aMerged.end(),
+ rMap.begin(),
+ rMap.end() );
+
+ initProperties( aMerged );
+ }
+
+ bool PropertySetHelper::isPropertyName( const ::rtl::OUString& aPropertyName ) const
+ {
+ if( !mpMap.get() )
+ return false;
+
+ Callbacks aDummy;
+ return mpMap->lookup( aPropertyName,
+ aDummy );
+ }
+
+ uno::Reference< beans::XPropertySetInfo > PropertySetHelper::getPropertySetInfo() const
+ {
+ // we're a stealth property set
+ return uno::Reference< beans::XPropertySetInfo >();
+ }
+
+ void PropertySetHelper::setPropertyValue( const ::rtl::OUString& aPropertyName,
+ const uno::Any& aValue )
+ {
+ Callbacks aCallbacks;
+ if( !mpMap.get() ||
+ !mpMap->lookup( aPropertyName,
+ aCallbacks ) )
+ {
+ throwUnknown( aPropertyName );
+ }
+
+ if( aCallbacks.setter.empty() )
+ throwVeto( aPropertyName );
+
+ aCallbacks.setter(aValue);
+ }
+
+ uno::Any PropertySetHelper::getPropertyValue( const ::rtl::OUString& aPropertyName ) const
+ {
+ Callbacks aCallbacks;
+ if( !mpMap.get() ||
+ !mpMap->lookup( aPropertyName,
+ aCallbacks ) )
+ {
+ throwUnknown( aPropertyName );
+ }
+
+ if( !aCallbacks.getter.empty() )
+ return aCallbacks.getter();
+
+ // TODO(Q1): subtlety, empty getter method silently returns
+ // the empty any
+ return uno::Any();
+ }
+
+ void PropertySetHelper::addPropertyChangeListener( const ::rtl::OUString& aPropertyName,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ {
+ // check validity of property, but otherwise ignore the
+ // request
+ if( !isPropertyName( aPropertyName ) )
+ throwUnknown( aPropertyName );
+ }
+
+ void PropertySetHelper::removePropertyChangeListener( const ::rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ {
+ // ignore request, no listener added in the first place
+ }
+
+ void PropertySetHelper::addVetoableChangeListener( const ::rtl::OUString& aPropertyName,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
+ {
+ // check validity of property, but otherwise ignore the
+ // request
+ if( !isPropertyName( aPropertyName ) )
+ throwUnknown( aPropertyName );
+ }
+
+ void PropertySetHelper::removeVetoableChangeListener( const ::rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
+ {
+ // ignore request, no listener added in the first place
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/spriteredrawmanager.cxx b/canvas/source/tools/spriteredrawmanager.cxx
new file mode 100644
index 000000000000..9fce1be93a5b
--- /dev/null
+++ b/canvas/source/tools/spriteredrawmanager.cxx
@@ -0,0 +1,523 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/spriteredrawmanager.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/rangeexpander.hxx>
+
+#include <algorithm>
+#include <functional>
+#include <boost/bind.hpp>
+
+
+namespace canvas
+{
+ namespace
+ {
+ /** Helper class to condense sprite updates into a single action
+
+ This class tracks the sprite changes over the recorded
+ change list, and generates a single update action from
+ that (note that per screen update, several moves,
+ visibility changes and content updates might happen)
+ */
+ class SpriteTracer
+ {
+ public:
+ SpriteTracer( const Sprite::Reference& rAffectedSprite ) :
+ mpAffectedSprite(rAffectedSprite),
+ maMoveStartArea(),
+ maMoveEndArea(),
+ mbIsMove( false ),
+ mbIsGenericUpdate( false )
+ {
+ }
+
+ void operator()( const SpriteRedrawManager::SpriteChangeRecord& rSpriteRecord )
+ {
+ // only deal with change events from the currently
+ // affected sprite
+ if( rSpriteRecord.mpAffectedSprite == mpAffectedSprite )
+ {
+ switch( rSpriteRecord.meChangeType )
+ {
+ case SpriteRedrawManager::SpriteChangeRecord::move:
+ if( !mbIsMove )
+ {
+ // no move yet - this must be the first one
+ maMoveStartArea = ::basegfx::B2DRectangle(
+ rSpriteRecord.maOldPos,
+ rSpriteRecord.maOldPos + rSpriteRecord.maUpdateArea.getRange() );
+ mbIsMove = true;
+ }
+
+ maMoveEndArea = rSpriteRecord.maUpdateArea;
+ break;
+
+ case SpriteRedrawManager::SpriteChangeRecord::update:
+ // update end update area of the
+ // sprite. Thus, every update() action
+ // _after_ the last move will correctly
+ // update the final repaint area. And this
+ // does not interfere with subsequent
+ // moves, because moves always perform a
+ // hard set of maMoveEndArea to their
+ // stored value
+ maMoveEndArea.expand( rSpriteRecord.maUpdateArea );
+ mbIsGenericUpdate = true;
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "Unexpected case in SpriteUpdater::operator()" );
+ break;
+ }
+ }
+ }
+
+ void commit( SpriteRedrawManager::SpriteConnectedRanges& rUpdateCollector ) const
+ {
+ if( mbIsMove )
+ {
+ if( !maMoveStartArea.isEmpty() ||
+ !maMoveEndArea.isEmpty() )
+ {
+ // if mbIsGenericUpdate is false, this is a
+ // pure move (i.e. no other update
+ // operations). Pass that information on to
+ // the SpriteInfo
+ const bool bIsPureMove( !mbIsGenericUpdate );
+
+ // ignore the case that start and end update
+ // area overlap - the b2dconnectedranges
+ // handle that, anyway. doing it this way
+ // ensures that we have both old and new area
+ // stored
+
+ // round all given range up to enclosing
+ // integer rectangle - since the whole thing
+ // here is about
+
+ // first, draw the new sprite position
+ rUpdateCollector.addRange(
+ ::basegfx::unotools::b2DSurroundingIntegerRangeFromB2DRange( maMoveEndArea ),
+ SpriteRedrawManager::SpriteInfo(
+ mpAffectedSprite,
+ maMoveEndArea,
+ true,
+ bIsPureMove ) );
+
+ // then, clear the old place (looks smoother
+ // this way)
+ rUpdateCollector.addRange(
+ ::basegfx::unotools::b2DSurroundingIntegerRangeFromB2DRange( maMoveStartArea ),
+ SpriteRedrawManager::SpriteInfo(
+ Sprite::Reference(),
+ maMoveStartArea,
+ true,
+ bIsPureMove ) );
+ }
+ }
+ else if( mbIsGenericUpdate &&
+ !maMoveEndArea.isEmpty() )
+ {
+ rUpdateCollector.addRange(
+ ::basegfx::unotools::b2DSurroundingIntegerRangeFromB2DRange( maMoveEndArea ),
+ SpriteRedrawManager::SpriteInfo(
+ mpAffectedSprite,
+ maMoveEndArea,
+ true ) );
+ }
+ }
+
+ private:
+ Sprite::Reference mpAffectedSprite;
+ ::basegfx::B2DRectangle maMoveStartArea;
+ ::basegfx::B2DRectangle maMoveEndArea;
+
+ /// True, if at least one move was encountered
+ bool mbIsMove;
+
+ /// True, if at least one generic update was encountered
+ bool mbIsGenericUpdate;
+ };
+
+
+ /** SpriteChecker functor, which for every sprite checks the
+ given update vector for necessary screen updates
+ */
+ class SpriteUpdater
+ {
+ public:
+ /** Generate update area list
+
+ @param rUpdater
+ Reference to an updater object, which will receive the
+ update areas.
+
+ @param rChangeContainer
+ Container with all sprite change requests
+
+ */
+ SpriteUpdater( SpriteRedrawManager::SpriteConnectedRanges& rUpdater,
+ const SpriteRedrawManager::VectorOfChangeRecords& rChangeContainer ) :
+ mrUpdater( rUpdater ),
+ mrChangeContainer( rChangeContainer )
+ {
+ }
+
+ /** Call this method for every sprite on your screen
+
+ This method scans the change container, collecting all
+ update info for the given sprite into one or two
+ update operations, which in turn are inserted into the
+ connected ranges processor.
+
+ @param rSprite
+ Current sprite to collect update info for.
+ */
+ void operator()( const Sprite::Reference& rSprite )
+ {
+ const SpriteTracer aSpriteTracer(
+ ::std::for_each( mrChangeContainer.begin(),
+ mrChangeContainer.end(),
+ SpriteTracer( rSprite ) ) );
+
+ aSpriteTracer.commit( mrUpdater );
+ }
+
+ private:
+ SpriteRedrawManager::SpriteConnectedRanges& mrUpdater;
+ const SpriteRedrawManager::VectorOfChangeRecords& mrChangeContainer;
+ };
+ }
+
+ void SpriteRedrawManager::setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const
+ {
+ // TODO(T3): This is NOT thread safe at all. This only works
+ // under the assumption that NOBODY changes ANYTHING
+ // concurrently, while this method is on the stack. We should
+ // really rework the canvas::Sprite interface, in such a way
+ // that it dumps ALL its state with a single, atomic
+ // call. Then, we store that state locally. This prolly goes
+ // in line with the problem of having sprite state available
+ // for the frame before the last frame; plus, it avoids
+ // frequent locks of the object mutices
+ SpriteComparator aSpriteComparator;
+
+ // put all sprites that have changed content into update areas
+ ListOfSprites::const_iterator aCurrSprite( maSprites.begin() );
+ const ListOfSprites::const_iterator aEndSprite ( maSprites.end() );
+ while( aCurrSprite != aEndSprite )
+ {
+ if( (*aCurrSprite)->isContentChanged() )
+ const_cast<SpriteRedrawManager*>(this)->updateSprite( *aCurrSprite,
+ (*aCurrSprite)->getPosPixel(),
+ (*aCurrSprite)->getUpdateArea() );
+ ++aCurrSprite;
+ }
+
+ // sort sprites after prio
+ VectorOfSprites aSortedSpriteVector;
+ ::std::copy( maSprites.begin(),
+ maSprites.end(),
+ ::std::back_insert_iterator< VectorOfSprites >(aSortedSpriteVector) );
+ ::std::sort( aSortedSpriteVector.begin(),
+ aSortedSpriteVector.end(),
+ aSpriteComparator );
+
+ // extract all referenced sprites from the maChangeRecords
+ // (copy sprites, make the list unique, regarding the
+ // sprite pointer). This assumes that, until this scope
+ // ends, nobody changes the maChangeRecords vector!
+ VectorOfSprites aUpdatableSprites;
+ VectorOfChangeRecords::const_iterator aCurrRecord( maChangeRecords.begin() );
+ const VectorOfChangeRecords::const_iterator aEndRecords( maChangeRecords.end() );
+ while( aCurrRecord != aEndRecords )
+ {
+ const Sprite::Reference& rSprite( aCurrRecord->getSprite() );
+ if( rSprite.is() )
+ aUpdatableSprites.push_back( rSprite );
+ ++aCurrRecord;
+ }
+
+ VectorOfSprites::iterator aBegin( aUpdatableSprites.begin() );
+ VectorOfSprites::iterator aEnd ( aUpdatableSprites.end() );
+ ::std::sort( aBegin,
+ aEnd,
+ aSpriteComparator );
+
+ aEnd = ::std::unique( aBegin, aEnd );
+
+ // for each unique sprite, check the change event vector,
+ // calculate the update operation from that, and add the
+ // result to the aUpdateArea.
+ ::std::for_each( aBegin,
+ aEnd,
+ SpriteUpdater( rUpdateAreas,
+ maChangeRecords) );
+
+ // TODO(P2): Implement your own output iterator adapter, to
+ // avoid that totally superfluous temp aUnchangedSprites
+ // vector.
+
+ // add all sprites to rUpdateAreas, that are _not_ already
+ // contained in the uniquified vector of changed ones
+ // (i.e. the difference between aSortedSpriteVector and
+ // aUpdatableSprites).
+ VectorOfSprites aUnchangedSprites;
+ ::std::set_difference( aSortedSpriteVector.begin(),
+ aSortedSpriteVector.end(),
+ aBegin, aEnd,
+ ::std::back_insert_iterator< VectorOfSprites >(aUnchangedSprites) );
+
+ // add each remaining unchanged sprite to connected ranges,
+ // marked as "don't need update"
+ VectorOfSprites::const_iterator aCurr( aUnchangedSprites.begin() );
+ const VectorOfSprites::const_iterator aEnd2( aUnchangedSprites.end() );
+ while( aCurr != aEnd2 )
+ {
+ const ::basegfx::B2DRange& rUpdateArea( (*aCurr)->getUpdateArea() );
+ rUpdateAreas.addRange(
+ ::basegfx::unotools::b2DSurroundingIntegerRangeFromB2DRange( rUpdateArea ),
+ SpriteInfo(*aCurr,
+ rUpdateArea,
+ false) );
+ ++aCurr;
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ bool impIsEqualB2DRange(const basegfx::B2DRange& rRangeA, const basegfx::B2DRange& rRangeB, double fSmallValue)
+ {
+ return fabs(rRangeB.getMinX() - rRangeA.getMinX()) <= fSmallValue
+ && fabs(rRangeB.getMinY() - rRangeA.getMinY()) <= fSmallValue
+ && fabs(rRangeB.getMaxX() - rRangeA.getMaxX()) <= fSmallValue
+ && fabs(rRangeB.getMaxY() - rRangeA.getMaxY()) <= fSmallValue;
+ }
+
+ bool impIsEqualB2DVector(const basegfx::B2DVector& rVecA, const basegfx::B2DVector& rVecB, double fSmallValue)
+ {
+ return fabs(rVecB.getX() - rVecA.getX()) <= fSmallValue
+ && fabs(rVecB.getY() - rVecA.getY()) <= fSmallValue;
+ }
+#endif
+
+ bool SpriteRedrawManager::isAreaUpdateScroll( ::basegfx::B2DRectangle& o_rMoveStart,
+ ::basegfx::B2DRectangle& o_rMoveEnd,
+ const UpdateArea& rUpdateArea,
+ ::std::size_t nNumSprites ) const
+ {
+ // check for a solitary move, which consists of exactly two
+ // pure-move entries, the first with valid, the second with
+ // invalid sprite (see SpriteTracer::commit()). Note that we
+ // cannot simply store some flag in SpriteTracer::commit()
+ // above and just check that here, since during the connected
+ // range calculations, other sprites might get merged into the
+ // same region (thus spoiling the scrolling move
+ // optimization).
+ if( nNumSprites != 2 )
+ return false;
+
+ const SpriteConnectedRanges::ComponentListType::const_iterator aFirst(
+ rUpdateArea.maComponentList.begin() );
+ SpriteConnectedRanges::ComponentListType::const_iterator aSecond(
+ aFirst ); ++aSecond;
+
+ if( !aFirst->second.isPureMove() ||
+ !aSecond->second.isPureMove() ||
+ !aFirst->second.getSprite().is() ||
+ // use _true_ update area, not the rounded version
+ !aFirst->second.getSprite()->isAreaUpdateOpaque( aFirst->second.getUpdateArea() ) ||
+ aSecond->second.getSprite().is() )
+ {
+ // either no move update, or incorrect sprite, or sprite
+ // content not fully opaque over update region.
+ return false;
+ }
+
+ o_rMoveStart = aSecond->second.getUpdateArea();
+ o_rMoveEnd = aFirst->second.getUpdateArea();
+
+#if OSL_DEBUG_LEVEL > 0
+ ::basegfx::B2DRectangle aTotalBounds( o_rMoveStart );
+ aTotalBounds.expand( o_rMoveEnd );
+
+ OSL_POSTCOND(impIsEqualB2DRange(rUpdateArea.maTotalBounds, basegfx::unotools::b2DSurroundingIntegerRangeFromB2DRange(aTotalBounds), 0.5),
+ "SpriteRedrawManager::isAreaUpdateScroll(): sprite area and total area mismatch");
+ OSL_POSTCOND(impIsEqualB2DVector(o_rMoveStart.getRange(), o_rMoveEnd.getRange(), 0.5),
+ "SpriteRedrawManager::isAreaUpdateScroll(): scroll start and end area have mismatching size");
+#endif
+
+ return true;
+ }
+
+ bool SpriteRedrawManager::isAreaUpdateNotOpaque( const ::basegfx::B2DRectangle& rUpdateRect,
+ const AreaComponent& rComponent ) const
+ {
+ const Sprite::Reference& pAffectedSprite( rComponent.second.getSprite() );
+
+ if( !pAffectedSprite.is() )
+ return true; // no sprite, no opaque update!
+
+ return !pAffectedSprite->isAreaUpdateOpaque( rUpdateRect );
+ }
+
+ bool SpriteRedrawManager::isAreaUpdateOpaque( const UpdateArea& rUpdateArea,
+ ::std::size_t nNumSprites ) const
+ {
+ // check whether the sprites in the update area's list will
+ // fully cover the given area _and_ do that in an opaque way
+ // (i.e. no alpha, no non-rectangular sprite content).
+
+ // TODO(P1): Come up with a smarter early-exit criterion here
+ // (though, I think, the case that _lots_ of sprites _fully_
+ // cover a rectangular area _without_ any holes is extremely
+ // improbable)
+
+ // avoid checking large number of sprites (and probably fail,
+ // anyway). Note: the case nNumSprites < 1 should normally not
+ // happen, as handleArea() calls backgroundPaint() then.
+ if( nNumSprites > 3 || nNumSprites < 1 )
+ return false;
+
+ const SpriteConnectedRanges::ComponentListType::const_iterator aBegin(
+ rUpdateArea.maComponentList.begin() );
+ const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
+ rUpdateArea.maComponentList.end() );
+
+ // now, calc the _true_ update area, by merging all sprite's
+ // true update areas into one rectangle
+ ::basegfx::B2DRange aTrueArea( aBegin->second.getUpdateArea() );
+ ::std::for_each( aBegin,
+ aEnd,
+ ::boost::bind( ::basegfx::B2DRangeExpander(aTrueArea),
+ ::boost::bind( &SpriteInfo::getUpdateArea,
+ ::boost::bind( ::std::select2nd<AreaComponent>(),
+ _1 ) ) ) );
+
+ // and check whether _any_ of the sprites tells that its area
+ // update will not be opaque.
+ return (::std::find_if( aBegin,
+ aEnd,
+ ::boost::bind( &SpriteRedrawManager::isAreaUpdateNotOpaque,
+ this,
+ ::boost::cref(aTrueArea),
+ _1 ) ) == aEnd );
+ }
+
+ bool SpriteRedrawManager::areSpritesChanged( const UpdateArea& rUpdateArea ) const
+ {
+ // check whether SpriteInfo::needsUpdate returns false for
+ // all elements of this area's contained sprites
+ //
+ // if not a single changed sprite found - just ignore this
+ // component (return false)
+ const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
+ rUpdateArea.maComponentList.end() );
+ return (::std::find_if( rUpdateArea.maComponentList.begin(),
+ aEnd,
+ ::boost::bind( &SpriteInfo::needsUpdate,
+ ::boost::bind(
+ ::std::select2nd<SpriteConnectedRanges::ComponentType>(),
+ _1 ) ) ) != aEnd );
+ }
+
+ SpriteRedrawManager::SpriteRedrawManager() :
+ maSprites(),
+ maChangeRecords()
+ {
+ }
+
+ void SpriteRedrawManager::disposing()
+ {
+ // drop all references
+ maChangeRecords.clear();
+
+ // dispose all sprites - the spritecanvas, and by delegation,
+ // this object, is the owner of the sprites. After all, a
+ // sprite without a canvas to render into makes not terribly
+ // much sense.
+
+ // TODO(Q3): Once boost 1.33 is in, change back to for_each
+ // with ::boost::mem_fn. For the time being, explicit loop due
+ // to cdecl declaration of all UNO methods.
+ ListOfSprites::reverse_iterator aCurr( maSprites.rbegin() );
+ ListOfSprites::reverse_iterator aEnd( maSprites.rend() );
+ while( aCurr != aEnd )
+ (*aCurr++)->dispose();
+
+ maSprites.clear();
+ }
+
+ void SpriteRedrawManager::clearChangeRecords()
+ {
+ maChangeRecords.clear();
+ }
+
+ void SpriteRedrawManager::showSprite( const Sprite::Reference& rSprite )
+ {
+ maSprites.push_back( rSprite );
+ }
+
+ void SpriteRedrawManager::hideSprite( const Sprite::Reference& rSprite )
+ {
+ maSprites.remove( rSprite );
+ }
+
+ void SpriteRedrawManager::moveSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rOldPos,
+ const ::basegfx::B2DPoint& rNewPos,
+ const ::basegfx::B2DVector& rSpriteSize )
+ {
+ maChangeRecords.push_back( SpriteChangeRecord( rSprite,
+ rOldPos,
+ rNewPos,
+ rSpriteSize ) );
+ }
+
+ void SpriteRedrawManager::updateSprite( const Sprite::Reference& rSprite,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rUpdateArea )
+ {
+ maChangeRecords.push_back( SpriteChangeRecord( rSprite,
+ rPos,
+ rUpdateArea ) );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surface.cxx b/canvas/source/tools/surface.cxx
new file mode 100644
index 000000000000..4d23c40f7b27
--- /dev/null
+++ b/canvas/source/tools/surface.cxx
@@ -0,0 +1,498 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "surface.hxx"
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <boost/bind.hpp>
+
+namespace canvas
+{
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::Surface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ Surface::Surface( const PageManagerSharedPtr& rPageManager,
+ const IColorBufferSharedPtr& rColorBuffer,
+ const ::basegfx::B2IPoint& rPos,
+ const ::basegfx::B2ISize& rSize ) :
+ mpColorBuffer(rColorBuffer),
+ mpPageManager(rPageManager),
+ mpFragment(),
+ maSourceOffset(rPos),
+ maSize(rSize),
+ mbIsDirty(true)
+ {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::~Surface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ Surface::~Surface()
+ {
+ if(mpFragment)
+ mpPageManager->free(mpFragment);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::getUVCoords
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void Surface::setColorBufferDirty()
+ {
+ mbIsDirty=true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::getUVCoords
+ //////////////////////////////////////////////////////////////////////////////////
+
+ basegfx::B2DRectangle Surface::getUVCoords() const
+ {
+ ::basegfx::B2ISize aPageSize(mpPageManager->getPageSize());
+ ::basegfx::B2IPoint aDestOffset;
+ if( mpFragment )
+ aDestOffset = mpFragment->getPos();
+
+ const double pw( aPageSize.getX() );
+ const double ph( aPageSize.getY() );
+ const double ox( aDestOffset.getX() );
+ const double oy( aDestOffset.getY() );
+ const double sx( maSize.getX() );
+ const double sy( maSize.getY() );
+
+ return ::basegfx::B2DRectangle( ox/pw,
+ oy/ph,
+ (ox+sx)/pw,
+ (oy+sy)/ph );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::getUVCoords
+ //////////////////////////////////////////////////////////////////////////////////
+
+ basegfx::B2DRectangle Surface::getUVCoords( const ::basegfx::B2IPoint& rPos,
+ const ::basegfx::B2ISize& rSize ) const
+ {
+ ::basegfx::B2ISize aPageSize(mpPageManager->getPageSize());
+
+ const double pw( aPageSize.getX() );
+ const double ph( aPageSize.getY() );
+ const double ox( rPos.getX() );
+ const double oy( rPos.getY() );
+ const double sx( rSize.getX() );
+ const double sy( rSize.getY() );
+
+ return ::basegfx::B2DRectangle( ox/pw,
+ oy/ph,
+ (ox+sx)/pw,
+ (oy+sy)/ph );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool Surface::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ IRenderModuleSharedPtr pRenderModule(mpPageManager->getRenderModule());
+
+ RenderModuleGuard aGuard( pRenderModule );
+
+ prepareRendering();
+
+ // convert size to normalized device coordinates
+ const ::basegfx::B2DRectangle& rUV( getUVCoords() );
+
+ const double u1(rUV.getMinX());
+ const double v1(rUV.getMinY());
+ const double u2(rUV.getMaxX());
+ const double v2(rUV.getMaxY());
+
+ // concat transforms
+ // 1) offset of surface subarea
+ // 2) surface transform
+ // 3) translation to output position [rPos]
+ // 4) scale to normalized device coordinates
+ // 5) flip y-axis
+ // 6) translate to account for viewport transform
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ maSourceOffset.getX(), maSourceOffset.getY()));
+ aTransform = aTransform * rTransform;
+ aTransform.translate(::basegfx::fround(rPos.getX()),
+ ::basegfx::fround(rPos.getY()));
+
+ /*
+ ######################################
+ ######################################
+ ######################################
+
+ Y
+ ^+1
+ |
+ 2 | 3
+ x------------x
+ | | |
+ | | |
+ ------|-----O------|------>X
+ -1 | | | +1
+ | | |
+ x------------x
+ 1 | 0
+ |
+ |-1
+
+ ######################################
+ ######################################
+ ######################################
+ */
+
+ const ::basegfx::B2DPoint& p0(aTransform * ::basegfx::B2DPoint(maSize.getX(),maSize.getY()));
+ const ::basegfx::B2DPoint& p1(aTransform * ::basegfx::B2DPoint(0.0,maSize.getY()));
+ const ::basegfx::B2DPoint& p2(aTransform * ::basegfx::B2DPoint(0.0,0.0));
+ const ::basegfx::B2DPoint& p3(aTransform * ::basegfx::B2DPoint(maSize.getX(),0.0));
+
+ canvas::Vertex vertex;
+ vertex.r = 1.0f;
+ vertex.g = 1.0f;
+ vertex.b = 1.0f;
+ vertex.a = static_cast<float>(fAlpha);
+ vertex.z = 0.0f;
+
+ {
+ pRenderModule->beginPrimitive( canvas::IRenderModule::PRIMITIVE_TYPE_QUAD );
+
+ // issue an endPrimitive() when leaving the scope
+ const ::comphelper::ScopeGuard aScopeGuard(
+ boost::bind( &::canvas::IRenderModule::endPrimitive,
+ ::boost::ref(pRenderModule) ) );
+
+ vertex.u=static_cast<float>(u2); vertex.v=static_cast<float>(v2);
+ vertex.x=static_cast<float>(p0.getX()); vertex.y=static_cast<float>(p0.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u1); vertex.v=static_cast<float>(v2);
+ vertex.x=static_cast<float>(p1.getX()); vertex.y=static_cast<float>(p1.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u1); vertex.v=static_cast<float>(v1);
+ vertex.x=static_cast<float>(p2.getX()); vertex.y=static_cast<float>(p2.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u2); vertex.v=static_cast<float>(v1);
+ vertex.x=static_cast<float>(p3.getX()); vertex.y=static_cast<float>(p3.getY());
+ pRenderModule->pushVertex(vertex);
+ }
+
+ return !(pRenderModule->isError());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::drawRectangularArea
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool Surface::drawRectangularArea(
+ double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRectangle& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( rArea.isEmpty() )
+ return true; // immediate exit for empty area
+
+ IRenderModuleSharedPtr pRenderModule(mpPageManager->getRenderModule());
+
+ RenderModuleGuard aGuard( pRenderModule );
+
+ prepareRendering();
+
+ // these positions are relative to the texture
+ ::basegfx::B2IPoint aPos1(
+ ::basegfx::fround(rArea.getMinimum().getX()),
+ ::basegfx::fround(rArea.getMinimum().getY()));
+ ::basegfx::B2IPoint aPos2(
+ ::basegfx::fround(rArea.getMaximum().getX()),
+ ::basegfx::fround(rArea.getMaximum().getY()) );
+
+ // clip the positions to the area this surface covers
+ aPos1.setX(::std::max(aPos1.getX(),maSourceOffset.getX()));
+ aPos1.setY(::std::max(aPos1.getY(),maSourceOffset.getY()));
+ aPos2.setX(::std::min(aPos2.getX(),maSourceOffset.getX()+maSize.getX()));
+ aPos2.setY(::std::min(aPos2.getY(),maSourceOffset.getY()+maSize.getY()));
+
+ // if the resulting area is empty, return immediately
+ ::basegfx::B2IVector aSize(aPos2 - aPos1);
+ if(aSize.getX() <= 0 || aSize.getY() <= 0)
+ return true;
+
+ ::basegfx::B2IPoint aDestOffset;
+ if( mpFragment )
+ aDestOffset = mpFragment->getPos();
+
+ // convert size to normalized device coordinates
+ const ::basegfx::B2DRectangle& rUV(
+ getUVCoords(aPos1 - maSourceOffset + aDestOffset,
+ aSize) );
+ const double u1(rUV.getMinX());
+ const double v1(rUV.getMinY());
+ const double u2(rUV.getMaxX());
+ const double v2(rUV.getMaxY());
+
+ // concatenate transforms
+ // 1) offset of surface subarea
+ // 2) surface transform
+ // 3) translation to output position [rPos]
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(aPos1.getX(), aPos1.getY()));
+ aTransform = aTransform * rTransform;
+ aTransform.translate(::basegfx::fround(rPos.getX()),
+ ::basegfx::fround(rPos.getY()));
+
+
+ /*
+ ######################################
+ ######################################
+ ######################################
+
+ Y
+ ^+1
+ |
+ 2 | 3
+ x------------x
+ | | |
+ | | |
+ ------|-----O------|------>X
+ -1 | | | +1
+ | | |
+ x------------x
+ 1 | 0
+ |
+ |-1
+
+ ######################################
+ ######################################
+ ######################################
+ */
+
+ const ::basegfx::B2DPoint& p0(aTransform * ::basegfx::B2DPoint(aSize.getX(),aSize.getY()));
+ const ::basegfx::B2DPoint& p1(aTransform * ::basegfx::B2DPoint(0.0, aSize.getY()));
+ const ::basegfx::B2DPoint& p2(aTransform * ::basegfx::B2DPoint(0.0, 0.0));
+ const ::basegfx::B2DPoint& p3(aTransform * ::basegfx::B2DPoint(aSize.getX(),0.0));
+
+ canvas::Vertex vertex;
+ vertex.r = 1.0f;
+ vertex.g = 1.0f;
+ vertex.b = 1.0f;
+ vertex.a = static_cast<float>(fAlpha);
+ vertex.z = 0.0f;
+
+ {
+ pRenderModule->beginPrimitive( canvas::IRenderModule::PRIMITIVE_TYPE_QUAD );
+
+ // issue an endPrimitive() when leaving the scope
+ const ::comphelper::ScopeGuard aScopeGuard(
+ boost::bind( &::canvas::IRenderModule::endPrimitive,
+ ::boost::ref(pRenderModule) ) );
+
+ vertex.u=static_cast<float>(u2); vertex.v=static_cast<float>(v2);
+ vertex.x=static_cast<float>(p0.getX()); vertex.y=static_cast<float>(p0.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u1); vertex.v=static_cast<float>(v2);
+ vertex.x=static_cast<float>(p1.getX()); vertex.y=static_cast<float>(p1.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u1); vertex.v=static_cast<float>(v1);
+ vertex.x=static_cast<float>(p2.getX()); vertex.y=static_cast<float>(p2.getY());
+ pRenderModule->pushVertex(vertex);
+
+ vertex.u=static_cast<float>(u2); vertex.v=static_cast<float>(v1);
+ vertex.x=static_cast<float>(p3.getX()); vertex.y=static_cast<float>(p3.getY());
+ pRenderModule->pushVertex(vertex);
+ }
+
+ return !(pRenderModule->isError());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::drawWithClip
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool Surface::drawWithClip( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ IRenderModuleSharedPtr pRenderModule(mpPageManager->getRenderModule());
+
+ RenderModuleGuard aGuard( pRenderModule );
+
+ prepareRendering();
+
+ // untransformed surface rectangle, relative to the whole
+ // image (note: this surface might actually only be a tile of
+ // the whole image, with non-zero maSourceOffset)
+ const double x1(maSourceOffset.getX());
+ const double y1(maSourceOffset.getY());
+ const double w(maSize.getX());
+ const double h(maSize.getY());
+ const double x2(x1+w);
+ const double y2(y1+h);
+ const ::basegfx::B2DRectangle aSurfaceClipRect(x1,y1,x2,y2);
+
+ // concatenate transforms
+ // we use 'fround' here to avoid rounding errors. the vertices will
+ // be transformed by the overall transform and uv coordinates will
+ // be calculated from the result, and this is why we need to use
+ // integer coordinates here...
+ basegfx::B2DHomMatrix aTransform;
+ aTransform = aTransform * rTransform;
+ aTransform.translate(::basegfx::fround(rPos.getX()),
+ ::basegfx::fround(rPos.getY()));
+
+ /*
+ ######################################
+ ######################################
+ ######################################
+
+ Y
+ ^+1
+ |
+ 2 | 3
+ x------------x
+ | | |
+ | | |
+ ------|-----O------|------>X
+ -1 | | | +1
+ | | |
+ x------------x
+ 1 | 0
+ |
+ |-1
+
+ ######################################
+ ######################################
+ ######################################
+ */
+
+ // uv coordinates that map the surface rectangle
+ // to the destination rectangle.
+ const ::basegfx::B2DRectangle& rUV( getUVCoords() );
+
+ basegfx::B2DPolygon rTriangleList(basegfx::tools::clipTriangleListOnRange(rClipPoly,
+ aSurfaceClipRect));
+
+ // Push vertices to backend renderer
+ if(const sal_uInt32 nVertexCount = rTriangleList.count())
+ {
+ canvas::Vertex vertex;
+ vertex.r = 1.0f;
+ vertex.g = 1.0f;
+ vertex.b = 1.0f;
+ vertex.a = static_cast<float>(fAlpha);
+ vertex.z = 0.0f;
+
+#if defined(TRIANGLE_LOG) && defined(DBG_UTIL)
+ OSL_TRACE( "Surface::draw(): numvertices %d numtriangles %d\n",
+ nVertexCount,
+ nVertexCount/3 );
+#endif
+
+ pRenderModule->beginPrimitive( canvas::IRenderModule::PRIMITIVE_TYPE_TRIANGLE );
+
+ // issue an endPrimitive() when leaving the scope
+ const ::comphelper::ScopeGuard aScopeGuard(
+ boost::bind( &::canvas::IRenderModule::endPrimitive,
+ ::boost::ref(pRenderModule) ) );
+
+ for(sal_uInt32 nIndex=0; nIndex<nVertexCount; ++nIndex)
+ {
+ const basegfx::B2DPoint &aPoint = rTriangleList.getB2DPoint(nIndex);
+ basegfx::B2DPoint aTransformedPoint(aTransform * aPoint);
+ const double tu(((aPoint.getX()-aSurfaceClipRect.getMinX())*rUV.getWidth()/w)+rUV.getMinX());
+ const double tv(((aPoint.getY()-aSurfaceClipRect.getMinY())*rUV.getHeight()/h)+rUV.getMinY());
+ vertex.u=static_cast<float>(tu);
+ vertex.v=static_cast<float>(tv);
+ vertex.x=static_cast<float>(aTransformedPoint.getX());
+ vertex.y=static_cast<float>(aTransformedPoint.getY());
+ pRenderModule->pushVertex(vertex);
+ }
+ }
+
+ return !(pRenderModule->isError());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface::prepareRendering
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void Surface::prepareRendering()
+ {
+ mpPageManager->validatePages();
+
+ // clients requested to draw from this surface, therefore one
+ // of the above implemented concrete rendering operations
+ // was triggered. we therefore need to ask the pagemanager
+ // to allocate some space for the fragment we're dedicated to.
+ if(!(mpFragment))
+ {
+ mpFragment = mpPageManager->allocateSpace(maSize);
+ if( mpFragment )
+ {
+ mpFragment->setColorBuffer(mpColorBuffer);
+ mpFragment->setSourceOffset(maSourceOffset);
+ }
+ }
+
+ if( mpFragment )
+ {
+ // now we need to 'select' the fragment, which will in turn
+ // pull informations from the image on demand.
+ // in case this fragment is still not located on any of the
+ // available pages ['naked'], we force the page manager to
+ // do it now, no way to defer this any longer...
+ if(!(mpFragment->select(mbIsDirty)))
+ mpPageManager->nakedFragment(mpFragment);
+
+ }
+ mbIsDirty=false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // End of file
+ //////////////////////////////////////////////////////////////////////////////////
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surface.hxx b/canvas/source/tools/surface.hxx
new file mode 100644
index 000000000000..1238a97943ce
--- /dev/null
+++ b/canvas/source/tools/surface.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SURFACE_HXX
+#define INCLUDED_CANVAS_SURFACE_HXX
+
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/isurface.hxx>
+
+#include "surfacerect.hxx"
+#include "pagemanager.hxx"
+
+namespace canvas
+{
+ //////////////////////////////////////////////////////////////////////////////////
+ // Surface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** surfaces denote occupied areas withing pages.
+
+ pages encapsulate the hardware buffers that
+ contain image data which can be used for texturing.
+ surfaces are areas within those pages.
+ */
+ class Surface
+ {
+ public:
+
+ Surface( const PageManagerSharedPtr& rPageManager,
+ const IColorBufferSharedPtr& rColorBuffer,
+ const ::basegfx::B2IPoint& rPos,
+ const ::basegfx::B2ISize& rSize );
+ ~Surface();
+
+ void setColorBufferDirty();
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rArea
+ Subset of the surface to render. Coordinate system are
+ surface area pixel, given area will be clipped to the
+ surface bounds.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool drawRectangularArea(
+ double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rClipPoly
+ Clip polygon for the surface. The clip polygon is also
+ subject to the output transformation.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ bool drawWithClip( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ // private attributes
+ private:
+ IColorBufferSharedPtr mpColorBuffer;
+
+ // invoking any of the above defined 'draw' methods
+ // will forward primitive commands to the rendermodule.
+ PageManagerSharedPtr mpPageManager;
+
+ FragmentSharedPtr mpFragment;
+
+ // the offset of this surface with regard to the source
+ // image. if the source image had to be tiled into multiple
+ // surfaces, this offset denotes the relative pixel distance
+ // from the source image's upper, left corner
+ ::basegfx::B2IPoint maSourceOffset;
+
+ // the size in pixels of this surface. please note that
+ // this size is likely to be smaller than the size of
+ // the colorbuffer we're associated with since we
+ // maybe represent only a part of it.
+ ::basegfx::B2ISize maSize;
+
+ bool mbIsDirty;
+
+ // private methods
+ private:
+ bool refresh( canvas::IColorBuffer& rBuffer ) const;
+ void prepareRendering();
+
+ basegfx::B2DRectangle getUVCoords() const;
+ basegfx::B2DRectangle getUVCoords( const ::basegfx::B2IPoint& rPos,
+ const ::basegfx::B2ISize& rSize ) const;
+ };
+
+ typedef ::boost::shared_ptr< Surface > SurfaceSharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surfaceproxy.cxx b/canvas/source/tools/surfaceproxy.cxx
new file mode 100644
index 000000000000..a73246cfe211
--- /dev/null
+++ b/canvas/source/tools/surfaceproxy.cxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <boost/bind.hpp>
+#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include "surfaceproxy.hxx"
+
+namespace canvas
+{
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy::SurfaceProxy
+ //////////////////////////////////////////////////////////////////////////////////
+
+ SurfaceProxy::SurfaceProxy( const canvas::IColorBufferSharedPtr& pBuffer,
+ const PageManagerSharedPtr& pPageManager ) :
+ mpPageManager( pPageManager ),
+ maSurfaceList(),
+ mpBuffer( pBuffer )
+ {
+ const ::basegfx::B2ISize aImageSize(mpBuffer->getWidth(),mpBuffer->getHeight());
+ const ::basegfx::B2ISize aPageSize(mpPageManager->getPageSize());
+ const sal_Int32 aPageSizeX(aPageSize.getX());
+ const sal_Int32 aPageSizeY(aPageSize.getY());
+ const sal_Int32 aImageSizeX(aImageSize.getX());
+ const sal_Int32 aImageSizeY(aImageSize.getY());
+
+ // see if the size of the colorbuffer is larger than the size
+ // of a single page. if this is the case we divide the
+ // colorbuffer into as many surfaces as we need to get the
+ // whole area distributed. otherwise (the colorbuffer is
+ // smaller than the size of a single page) we search for free
+ // pages or create a new one.
+ // the incoming image is too large to fit into a single
+ // page. strategy: we split the image into rectangular
+ // areas that are as large as the maximum page size
+ // dictates and follow the strategy for fitting images.
+ size_t dwNumSurfaces(0);
+ for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
+ for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
+ ++dwNumSurfaces;
+ maSurfaceList.reserve(dwNumSurfaces);
+
+ for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
+ {
+ for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
+ {
+ // the current surface is located at the position [x,y]
+ // and has the size [min(restx,pagesizex),min(resty,pagesizey)
+ ::basegfx::B2IPoint aOffset(x,y);
+ ::basegfx::B2ISize aSize( ::std::min( aImageSize.getX()-x,
+ aPageSize.getX() ),
+ ::std::min( aImageSize.getY()-y,
+ aPageSize.getY() ) );
+
+ maSurfaceList.push_back(
+ SurfaceSharedPtr(
+ new Surface(
+ mpPageManager,
+ mpBuffer,
+ aOffset,
+ aSize)));
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy::setColorBufferDirty
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void SurfaceProxy::setColorBufferDirty()
+ {
+ ::std::for_each( maSurfaceList.begin(),
+ maSurfaceList.end(),
+ ::boost::mem_fn(&Surface::setColorBufferDirty));
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool SurfaceProxy::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::std::for_each( maSurfaceList.begin(),
+ maSurfaceList.end(),
+ ::boost::bind( &Surface::draw,
+ _1,
+ fAlpha,
+ ::boost::cref(rPos),
+ ::boost::cref(rTransform)));
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool SurfaceProxy::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ ::std::for_each( maSurfaceList.begin(),
+ maSurfaceList.end(),
+ ::boost::bind(&Surface::drawRectangularArea,
+ _1,
+ fAlpha,
+ ::boost::cref(rPos),
+ ::boost::cref(rArea),
+ ::boost::cref(rTransform)));
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool SurfaceProxy::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ const ::basegfx::B2DPolygon& rTriangulatedPolygon(
+ ::basegfx::triangulator::triangulate(rClipPoly));
+
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ // dump polygons
+ OSL_TRACE( "Original clip polygon: %s\n"
+ "Triangulated polygon: %s\n",
+ rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD( rClipPoly ),
+ RTL_TEXTENCODING_ASCII_US).getStr(),
+ rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(
+ basegfx::B2DPolyPolygon(rTriangulatedPolygon) ),
+ RTL_TEXTENCODING_ASCII_US).getStr() );
+#endif
+
+ ::std::for_each( maSurfaceList.begin(),
+ maSurfaceList.end(),
+ ::boost::bind(&Surface::drawWithClip,
+ _1,
+ fAlpha,
+ ::boost::cref(rPos),
+ ::boost::cref(rTriangulatedPolygon),
+ ::boost::cref(rTransform)));
+
+ return true;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surfaceproxy.hxx b/canvas/source/tools/surfaceproxy.hxx
new file mode 100644
index 000000000000..a68a1ce46b1b
--- /dev/null
+++ b/canvas/source/tools/surfaceproxy.hxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SURFACEPROXY_HXX
+#define INCLUDED_CANVAS_SURFACEPROXY_HXX
+
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+
+#include "pagemanager.hxx"
+#include "surface.hxx"
+
+namespace canvas
+{
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxy
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** Definition of the surface proxy class.
+
+ Surface proxies are the connection between *one* source image
+ and *one or more* hardware surfaces (or textures). in a
+ logical structure surface proxies represent soley this
+ dependeny plus some simple cache management.
+ */
+ class SurfaceProxy : public ISurfaceProxy
+ {
+ public:
+
+ SurfaceProxy( const canvas::IColorBufferSharedPtr& pBuffer,
+ const PageManagerSharedPtr &pPageManager );
+
+ // ISurfaceProxy interface
+ virtual void setColorBufferDirty();
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rArea
+ Subset of the surface to render. Coordinate system are
+ surface area pixel, given area will be clipped to the
+ surface bounds.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Render the surface content to screen.
+
+ @param fAlpha
+ Overall alpha for content
+
+ @param rPos
+ Output position
+
+ @param rClipPoly
+ Clip polygon for the surface. The clip polygon is also
+ subject to the output transformation.
+
+ @param rTransform
+ Output transformation (does not affect output position)
+ */
+ virtual bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ private:
+ PageManagerSharedPtr mpPageManager;
+
+ // the pagemanager will distribute the image
+ // to one or more surfaces, this is why we
+ // need a list here.
+ std::vector<SurfaceSharedPtr> maSurfaceList;
+
+ // pointer to the source of image data
+ // which always is stored in system memory,
+ // 32bit rgba and can have any size.
+ canvas::IColorBufferSharedPtr mpBuffer;
+ };
+
+ typedef ::boost::shared_ptr< SurfaceProxy > SurfaceProxySharedPtr;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surfaceproxymanager.cxx b/canvas/source/tools/surfaceproxymanager.cxx
new file mode 100644
index 000000000000..1b6e8fba8589
--- /dev/null
+++ b/canvas/source/tools/surfaceproxymanager.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/rendering/isurfaceproxymanager.hxx>
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include "surfaceproxy.hxx"
+
+namespace canvas
+{
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceProxyManager
+ //////////////////////////////////////////////////////////////////////////////////
+
+ class SurfaceProxyManager : public ISurfaceProxyManager
+ {
+ public:
+
+ SurfaceProxyManager( const IRenderModuleSharedPtr pRenderModule ) :
+ mpPageManager( new PageManager(pRenderModule) )
+ {
+ }
+
+ /** the whole idea is build around the concept that you create
+ some arbitrary buffer which contains the image data and
+ tell the texture manager about it. from there on you can
+ draw this image using any kind of graphics api you want.
+ in the technical sense we allocate some space in local
+ videomemory or AGP memory which will be filled on demand,
+ which means if there exists any rendering operation that
+ needs to read from this memory location. this method
+ creates a logical hardware surface object which uses the
+ given color buffer as the image source. internally this
+ texture may be distributed to several real hardware
+ surfaces.
+ */
+ virtual ISurfaceProxySharedPtr createSurfaceProxy( const IColorBufferSharedPtr& pBuffer ) const
+ {
+ // not much to do for now, simply allocate a new surface
+ // proxy from our internal pool and initialize this thing
+ // properly. we *don't* create a hardware surface for now.
+ return SurfaceProxySharedPtr(new SurfaceProxy(pBuffer,mpPageManager));
+ }
+
+ private:
+ PageManagerSharedPtr mpPageManager;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // createSurfaceProxyManager
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ISurfaceProxyManagerSharedPtr createSurfaceProxyManager( const IRenderModuleSharedPtr& rRenderModule )
+ {
+ return ISurfaceProxyManagerSharedPtr(
+ new SurfaceProxyManager(
+ rRenderModule));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/surfacerect.hxx b/canvas/source/tools/surfacerect.hxx
new file mode 100644
index 000000000000..67b5ea464fc0
--- /dev/null
+++ b/canvas/source/tools/surfacerect.hxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_CANVAS_SURFACERECT_HXX
+#define INCLUDED_CANVAS_SURFACERECT_HXX
+
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+namespace canvas
+{
+ //////////////////////////////////////////////////////////////////////////////////
+ // SurfaceRect
+ //////////////////////////////////////////////////////////////////////////////////
+
+ struct SurfaceRect
+ {
+ ::basegfx::B2IPoint maPos;
+ ::basegfx::B2ISize maSize;
+ ::basegfx::B2IPoint maBackup;
+ bool bEnabled;
+
+ explicit SurfaceRect( const ::basegfx::B2ISize &rSize ) :
+ maPos(),
+ maSize(rSize),
+ maBackup(),
+ bEnabled(true)
+ {
+ }
+
+ // coordinates contained in this rectangle are
+ // constrained to the following rules:
+ // 1) p.x >= pos.x
+ // 2) p.x <= pos.x+size.x
+ // 3) p.y >= pos.y
+ // 4) p.y <= pos.y+size.y
+ // in other words, 'size' means the number of pixels
+ // this rectangle encloses plus one. for example with pos[0,0]
+ // and size[512,512], p[512,512] would return inside.
+ // a size of [0,0] therefore denotes a one-by-one rectangle.
+ bool pointInside( sal_Int32 px, sal_Int32 py ) const
+ {
+ const sal_Int32 x1(maPos.getX());
+ const sal_Int32 y1(maPos.getY());
+ const sal_Int32 x2(maPos.getX()+maSize.getX());
+ const sal_Int32 y2(maPos.getY()+maSize.getY());
+ if(px < x1) return false;
+ if(px >= x2) return false;
+ if(py < y1) return false;
+ if(py >= y2) return false;
+ return true;
+ }
+
+ // returns true if the horizontal line intersects the rect.
+ bool hLineIntersect( sal_Int32 lx1, sal_Int32 lx2, sal_Int32 ly ) const
+ {
+ const sal_Int32 x1(maPos.getX());
+ const sal_Int32 y1(maPos.getY());
+ const sal_Int32 x2(maPos.getX()+maSize.getX());
+ const sal_Int32 y2(maPos.getY()+maSize.getY());
+ if(ly < y1) return false;
+ if(ly >= y2) return false;
+ if((lx1 < x1) && (lx2 < x1)) return false;
+ if((lx1 >= x2) && (lx2 >= x2)) return false;
+ return true;
+ }
+
+ //! Returns true if the vertical line intersects the rect.
+ bool vLineIntersect( sal_Int32 lx, sal_Int32 ly1, sal_Int32 ly2 ) const
+ {
+ const sal_Int32 x1(maPos.getX());
+ const sal_Int32 y1(maPos.getY());
+ const sal_Int32 x2(maPos.getX()+maSize.getX());
+ const sal_Int32 y2(maPos.getY()+maSize.getY());
+ if(lx < x1) return false;
+ if(lx >= x2) return false;
+ if((ly1 < y1) && (ly2 < y1)) return false;
+ if((ly1 >= y2) && (ly2 >= y2)) return false;
+ return true;
+ }
+
+ // returns true if the passed rect intersects this one.
+ bool intersection( const SurfaceRect& r ) const
+ {
+ const sal_Int32 x1(maPos.getX());
+ const sal_Int32 y1(maPos.getY());
+ const sal_Int32 x2(maPos.getX()+maSize.getX());
+ const sal_Int32 y2(maPos.getY()+maSize.getY());
+ if(r.hLineIntersect(x1,x2,y1)) return true;
+ if(r.hLineIntersect(x1,x2,y2)) return true;
+ if(r.vLineIntersect(x1,y1,y2)) return true;
+ if(r.vLineIntersect(x2,y1,y2)) return true;
+ return false;
+ }
+
+ bool inside( const SurfaceRect& r ) const
+ {
+ const sal_Int32 x1(maPos.getX());
+ const sal_Int32 y1(maPos.getY());
+ const sal_Int32 x2(maPos.getX()+maSize.getX());
+ const sal_Int32 y2(maPos.getY()+maSize.getY());
+ if(!(r.pointInside(x1,y1))) return false;
+ if(!(r.pointInside(x2,y1))) return false;
+ if(!(r.pointInside(x2,y2))) return false;
+ if(!(r.pointInside(x1,y2))) return false;
+ return true;
+ }
+ };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/tools/verifyinput.cxx b/canvas/source/tools/verifyinput.cxx
new file mode 100644
index 000000000000..48a3b9bb6531
--- /dev/null
+++ b/canvas/source/tools/verifyinput.cxx
@@ -0,0 +1,929 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/geometry/AffineMatrix2D.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/geometry/RealSize2D.hpp>
+#include <com/sun/star/geometry/IntegerPoint2D.hpp>
+#include <com/sun/star/geometry/IntegerSize2D.hpp>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+#include <com/sun/star/geometry/RealBezierSegment2D.hpp>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/util/Endianness.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
+#include <com/sun/star/rendering/FloatingPointBitmapFormat.hpp>
+#include <com/sun/star/rendering/FloatingPointBitmapLayout.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+#include <canvas/verifyinput.hxx>
+#include <canvas/canvastools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace canvas
+{
+ namespace tools
+ {
+ void verifyInput( const geometry::RealPoint2D& rPoint,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ if( !::rtl::math::isFinite( rPoint.X ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): point X value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rPoint.Y ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): point X value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( rPoint.X ) ||
+ !::rtl::math::isFinite( rPoint.Y ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const geometry::RealSize2D& rSize,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ if( !::rtl::math::isFinite( rSize.Width ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): size.Width value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSize.Height ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): size.Height value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( rSize.Width ) ||
+ !::rtl::math::isFinite( rSize.Height ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const geometry::RealBezierSegment2D& rSegment,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ if( !::rtl::math::isFinite( rSegment.Px ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's Px value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSegment.Py ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's Py value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSegment.C1x ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's C1x value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSegment.C1y ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's C1y value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSegment.C2x ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's C2x value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rSegment.C2y ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bezier segment's C2y value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( rSegment.Px ) ||
+ !::rtl::math::isFinite( rSegment.Py ) ||
+ !::rtl::math::isFinite( rSegment.C1x ) ||
+ !::rtl::math::isFinite( rSegment.C1y ) ||
+ !::rtl::math::isFinite( rSegment.C2x ) ||
+ !::rtl::math::isFinite( rSegment.C2y ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const geometry::RealRectangle2D& rRect,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ if( !::rtl::math::isFinite( rRect.X1 ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): rectangle point X1 contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rRect.Y1 ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): rectangle point Y1 contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rRect.X2 ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): rectangle point X2 contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+
+ if( !::rtl::math::isFinite( rRect.Y2 ) )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): rectangle point Y2 contains infinite or NAN"),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( rRect.X1 ) ||
+ !::rtl::math::isFinite( rRect.Y1 ) ||
+ !::rtl::math::isFinite( rRect.X2 ) ||
+ !::rtl::math::isFinite( rRect.Y2 ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const geometry::AffineMatrix2D& matrix,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ const sal_Int32 nBinaryState(
+ 100000 * !::rtl::math::isFinite( matrix.m00 ) +
+ 10000 * !::rtl::math::isFinite( matrix.m01 ) +
+ 1000 * !::rtl::math::isFinite( matrix.m02 ) +
+ 100 * !::rtl::math::isFinite( matrix.m10 ) +
+ 10 * !::rtl::math::isFinite( matrix.m11 ) +
+ 1 * !::rtl::math::isFinite( matrix.m12 ) );
+
+ if( nBinaryState )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): AffineMatrix2D contains infinite or NAN value(s) at the following positions (m00-m12): ") +
+ ::rtl::OUString::valueOf(nBinaryState),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( matrix.m00 ) ||
+ !::rtl::math::isFinite( matrix.m01 ) ||
+ !::rtl::math::isFinite( matrix.m02 ) ||
+ !::rtl::math::isFinite( matrix.m10 ) ||
+ !::rtl::math::isFinite( matrix.m11 ) ||
+ !::rtl::math::isFinite( matrix.m12 ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const geometry::Matrix2D& matrix,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+#if OSL_DEBUG_LEVEL > 0
+ const sal_Int32 nBinaryState(
+ 1000 * !::rtl::math::isFinite( matrix.m00 ) +
+ 100 * !::rtl::math::isFinite( matrix.m01 ) +
+ 10 * !::rtl::math::isFinite( matrix.m10 ) +
+ 1 * !::rtl::math::isFinite( matrix.m11 ) );
+
+ if( nBinaryState )
+ {
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): Matrix2D contains infinite or NAN value(s) at the following positions (m00-m11): ") +
+ ::rtl::OUString::valueOf(nBinaryState),
+ xIf,
+ nArgPos );
+ }
+#else
+ if( !::rtl::math::isFinite( matrix.m00 ) ||
+ !::rtl::math::isFinite( matrix.m01 ) ||
+ !::rtl::math::isFinite( matrix.m10 ) ||
+ !::rtl::math::isFinite( matrix.m11 ) )
+ {
+ throw lang::IllegalArgumentException();
+ }
+#endif
+ }
+
+ void verifyInput( const rendering::ViewState& viewState,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ verifyInput( viewState.AffineTransform,
+ pStr, xIf, nArgPos );
+ }
+
+ void verifyInput( const rendering::RenderState& renderState,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos,
+ sal_Int32 nMinColorComponents )
+ {
+ verifyInput( renderState.AffineTransform,
+ pStr, xIf, nArgPos );
+
+ if( renderState.DeviceColor.getLength() < nMinColorComponents )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): render state's device color has too few components (") +
+ ::rtl::OUString::valueOf(nMinColorComponents) +
+ ::rtl::OUString::createFromAscii(" expected, ") +
+ ::rtl::OUString::valueOf(renderState.DeviceColor.getLength()) +
+ ::rtl::OUString::createFromAscii(" provided)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( renderState.CompositeOperation < rendering::CompositeOperation::CLEAR ||
+ renderState.CompositeOperation > rendering::CompositeOperation::SATURATE )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): render state's CompositeOperation value out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(renderState.CompositeOperation)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ void verifyInput( const rendering::Texture& texture,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ verifyInput( texture.AffineTransform,
+ pStr, xIf, nArgPos );
+
+ if( !::rtl::math::isFinite( texture.Alpha ) ||
+ texture.Alpha < 0.0 ||
+ texture.Alpha > 1.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): textures' alpha value out of range (is ") +
+ ::rtl::OUString::valueOf(texture.Alpha) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( texture.NumberOfHatchPolygons < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): textures' NumberOfHatchPolygons is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( texture.RepeatModeX < rendering::TexturingMode::NONE ||
+ texture.RepeatModeX > rendering::TexturingMode::REPEAT )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): textures' RepeatModeX value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(texture.RepeatModeX)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( texture.RepeatModeY < rendering::TexturingMode::NONE ||
+ texture.RepeatModeY > rendering::TexturingMode::REPEAT )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): textures' RepeatModeY value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(texture.RepeatModeY)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ namespace
+ {
+ struct VerifyDashValue
+ {
+ VerifyDashValue( const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos ) :
+ mpStr( pStr ),
+ mrIf( xIf ),
+ mnArgPos( nArgPos )
+ {
+ }
+
+ void operator()( const double& rVal )
+ {
+ if( !::rtl::math::isFinite( rVal ) || rVal < 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(mpStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): one of stroke attributes' DashArray value out of range (is ") +
+ ::rtl::OUString::valueOf(rVal) +
+ ::rtl::OUString::createFromAscii(")"),
+ mrIf,
+ mnArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ const char* mpStr;
+ const uno::Reference< uno::XInterface >& mrIf;
+ sal_Int16 mnArgPos;
+ };
+ }
+
+ void verifyInput( const rendering::StrokeAttributes& strokeAttributes,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ if( !::rtl::math::isFinite( strokeAttributes.StrokeWidth ) ||
+ strokeAttributes.StrokeWidth < 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): stroke attributes' StrokeWidth value out of range (is ") +
+ ::rtl::OUString::valueOf(strokeAttributes.StrokeWidth) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( !::rtl::math::isFinite( strokeAttributes.MiterLimit ) ||
+ strokeAttributes.MiterLimit < 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): stroke attributes' MiterLimit value out of range (is ") +
+ ::rtl::OUString::valueOf(strokeAttributes.MiterLimit) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ ::std::for_each( strokeAttributes.DashArray.getConstArray(),
+ strokeAttributes.DashArray.getConstArray() + strokeAttributes.DashArray.getLength(),
+ VerifyDashValue( pStr, xIf, nArgPos ) );
+
+ ::std::for_each( strokeAttributes.LineArray.getConstArray(),
+ strokeAttributes.LineArray.getConstArray() + strokeAttributes.LineArray.getLength(),
+ VerifyDashValue( pStr, xIf, nArgPos ) );
+
+ if( strokeAttributes.StartCapType < rendering::PathCapType::BUTT ||
+ strokeAttributes.StartCapType > rendering::PathCapType::SQUARE )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): stroke attributes' StartCapType value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(strokeAttributes.StartCapType)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( strokeAttributes.EndCapType < rendering::PathCapType::BUTT ||
+ strokeAttributes.EndCapType > rendering::PathCapType::SQUARE )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): stroke attributes' StartCapType value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(strokeAttributes.EndCapType)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( strokeAttributes.JoinType < rendering::PathJoinType::NONE ||
+ strokeAttributes.JoinType > rendering::PathJoinType::BEVEL )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): stroke attributes' JoinType value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(strokeAttributes.JoinType)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ void verifyInput( const rendering::IntegerBitmapLayout& bitmapLayout,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+ if( bitmapLayout.ScanLines < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ScanLines is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.ScanLineBytes < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ScanLineBytes is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( !bitmapLayout.ColorSpace.is() )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ColorSpace is invalid"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ else
+ {
+ if( bitmapLayout.ColorSpace->getBitsPerPixel() < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ColorSpace getBitsPerPixel() is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.ColorSpace->getEndianness() < util::Endianness::LITTLE ||
+ bitmapLayout.ColorSpace->getEndianness() > util::Endianness::BIG )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ColorSpace getEndianness() value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(bitmapLayout.ColorSpace->getEndianness())) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+ }
+
+ void verifyInput( const rendering::FloatingPointBitmapLayout& bitmapLayout,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ (void)pStr; (void)xIf; (void)nArgPos;
+
+ if( bitmapLayout.ScanLines < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ScanLines is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.ScanLineBytes < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ScanLineBytes is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( !bitmapLayout.ColorSpace.is() )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's ColorSpace is invalid"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.NumComponents < 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's NumComponents is negative"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.Endianness < util::Endianness::LITTLE ||
+ bitmapLayout.Endianness > util::Endianness::BIG )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's Endianness value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(bitmapLayout.Endianness)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( bitmapLayout.Format < rendering::FloatingPointBitmapFormat::HALFFLOAT ||
+ bitmapLayout.Format > rendering::FloatingPointBitmapFormat::DOUBLE )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): bitmap layout's Format value is out of range (") +
+ ::rtl::OUString::valueOf(sal::static_int_cast<sal_Int32>(bitmapLayout.Format)) +
+ ::rtl::OUString::createFromAscii(" not known)"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ void verifyInput( const rendering::FontInfo& /*fontInfo*/,
+ const char* /*pStr*/,
+ const uno::Reference< uno::XInterface >& /*xIf*/,
+ ::sal_Int16 /*nArgPos*/ )
+ {
+ // TODO(E3): Implement FontDescription checks, once the
+ // Panose stuff is ready.
+ }
+
+ void verifyInput( const rendering::FontRequest& fontRequest,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf,
+ ::sal_Int16 nArgPos )
+ {
+ verifyInput( fontRequest.FontDescription,
+ pStr, xIf, nArgPos );
+
+ if( !::rtl::math::isFinite( fontRequest.CellSize ) )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): font request's CellSize value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( !::rtl::math::isFinite( fontRequest.ReferenceAdvancement ) )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): font request's ReferenceAdvancement value contains infinite or NAN"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( fontRequest.CellSize != 0.0 &&
+ fontRequest.ReferenceAdvancement != 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyInput(): font request's CellSize and ReferenceAdvancement are mutually exclusive, one of them must be 0.0"),
+ xIf,
+ nArgPos );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ void verifyIndexRange( const geometry::IntegerRectangle2D& rect,
+ const geometry::IntegerSize2D& size )
+ {
+ const ::basegfx::B2IRange aRect(
+ ::basegfx::unotools::b2IRectangleFromIntegerRectangle2D(
+ rect ) );
+
+ if( aRect.getMinX() < 0 ||
+ aRect.getMaxX() > size.Width ||
+ aRect.getMinY() < 0 ||
+ aRect.getMaxY() > size.Height )
+ {
+ throw ::com::sun::star::lang::IndexOutOfBoundsException();
+ }
+ }
+
+ void verifyIndexRange( const geometry::IntegerPoint2D& pos,
+ const geometry::IntegerSize2D& size )
+ {
+ if( pos.X < 0 ||
+ pos.X > size.Width ||
+ pos.Y < 0 ||
+ pos.Y > size.Height )
+ {
+ throw ::com::sun::star::lang::IndexOutOfBoundsException();
+ }
+ }
+
+ void verifyBitmapSize( const geometry::IntegerSize2D& size,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf )
+ {
+ (void)pStr; (void)xIf;
+
+ if( size.Width <= 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyBitmapSize(): size has 0 or negative width (value: ") +
+ ::rtl::OUString::valueOf(size.Width) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ 0 );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( size.Height <= 0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifyBitmapSize(): size has 0 or negative height (value: ") +
+ ::rtl::OUString::valueOf(size.Height) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ 0 );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+ void verifySpriteSize( const geometry::RealSize2D& size,
+ const char* pStr,
+ const uno::Reference< uno::XInterface >& xIf )
+ {
+ (void)pStr; (void)xIf;
+
+ if( size.Width <= 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifySpriteSize(): size has 0 or negative width (value: ") +
+ ::rtl::OUString::valueOf(size.Width) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ 0 );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+
+ if( size.Height <= 0.0 )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ throw lang::IllegalArgumentException(
+ ::rtl::OUString::createFromAscii(pStr) +
+ ::rtl::OUString::createFromAscii(": verifySpriteSize(): size has 0 or negative height (value: ") +
+ ::rtl::OUString::valueOf(size.Height) +
+ ::rtl::OUString::createFromAscii(")"),
+ xIf,
+ 0 );
+#else
+ throw lang::IllegalArgumentException();
+#endif
+ }
+ }
+
+
+ } // namespace tools
+
+} // namespace canvas
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/backbuffer.cxx b/canvas/source/vcl/backbuffer.cxx
new file mode 100644
index 000000000000..83bd50262103
--- /dev/null
+++ b/canvas/source/vcl/backbuffer.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "backbuffer.hxx"
+
+
+namespace vclcanvas
+{
+ BackBuffer::BackBuffer( const OutputDevice& rRefDevice,
+ bool bMonochromeBuffer ) :
+ maVDev( new VirtualDevice( rRefDevice,
+ bMonochromeBuffer ) )
+ {
+ if( !bMonochromeBuffer )
+ {
+ // #i95645#
+#if defined( QUARTZ )
+ // use AA on VCLCanvas for Mac
+ maVDev->SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW | maVDev->GetAntialiasing() );
+#else
+ // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and
+ // is not required to do AA. It would need to be adapted to use it correctly
+ // (especially gradient painting). This will need extra work.
+ maVDev->SetAntialiasing( maVDev->GetAntialiasing() & !ANTIALIASING_ENABLE_B2DDRAW);
+#endif
+ }
+ }
+
+ OutputDevice& BackBuffer::getOutDev()
+ {
+ return maVDev.get();
+ }
+
+ const OutputDevice& BackBuffer::getOutDev() const
+ {
+ return maVDev.get();
+ }
+
+ void BackBuffer::setSize( const ::Size& rNewSize )
+ {
+ maVDev->SetOutputSizePixel( rNewSize );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/backbuffer.hxx b/canvas/source/vcl/backbuffer.hxx
new file mode 100644
index 000000000000..7834d374f7da
--- /dev/null
+++ b/canvas/source/vcl/backbuffer.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_BACKBUFFER_HXX_
+#define _VCLCANVAS_BACKBUFFER_HXX_
+
+#include <vcl/virdev.hxx>
+
+#include <canvas/vclwrapper.hxx>
+#include "outdevprovider.hxx"
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace vclcanvas
+{
+ /// Background buffer abstraction
+ class BackBuffer : public OutDevProvider
+ {
+ public:
+ /** Create a backbuffer for given reference device
+
+ @param bMonochromeBuffer
+ When false, default depth of reference device is
+ chosen. When true, the buffer will be monochrome, i.e. one
+ bit deep.
+ */
+ BackBuffer( const OutputDevice& rRefDevice,
+ bool bMonochromeBuffer=false );
+
+ virtual OutputDevice& getOutDev();
+ virtual const OutputDevice& getOutDev() const;
+
+ void setSize( const ::Size& rNewSize );
+
+ private:
+ ::canvas::vcltools::VCLObject<VirtualDevice> maVDev;
+ };
+
+ typedef ::boost::shared_ptr< BackBuffer > BackBufferSharedPtr;
+}
+
+#endif /* #ifndef _VCLCANVAS_BACKBUFFER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/bitmapbackbuffer.cxx b/canvas/source/vcl/bitmapbackbuffer.cxx
new file mode 100644
index 000000000000..a8023a750a40
--- /dev/null
+++ b/canvas/source/vcl/bitmapbackbuffer.cxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "bitmapbackbuffer.hxx"
+
+#include <osl/mutex.hxx>
+#include <osl/mutex.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+
+
+namespace vclcanvas
+{
+ BitmapBackBuffer::BitmapBackBuffer( const BitmapEx& rBitmap,
+ const OutputDevice& rRefDevice ) :
+ maBitmap( rBitmap ),
+ mpVDev( NULL ),
+ mrRefDevice( rRefDevice ),
+ mbBitmapContentIsCurrent( false ),
+ mbVDevContentIsCurrent( false )
+ {
+ }
+
+ BitmapBackBuffer::~BitmapBackBuffer()
+ {
+ // make sure solar mutex is held on deletion (other methods
+ // are supposed to be called with already locked solar mutex)
+ SolarMutexGuard aGuard;
+
+ if( mpVDev )
+ delete mpVDev;
+ }
+
+ OutputDevice& BitmapBackBuffer::getOutDev()
+ {
+ createVDev();
+ updateVDev();
+ return *mpVDev;
+ }
+
+ const OutputDevice& BitmapBackBuffer::getOutDev() const
+ {
+ createVDev();
+ updateVDev();
+ return *mpVDev;
+ }
+
+ void BitmapBackBuffer::clear()
+ {
+ // force current content to bitmap, make all transparent white
+ getBitmapReference().Erase(COL_TRANSPARENT);
+ }
+
+ BitmapEx& BitmapBackBuffer::getBitmapReference()
+ {
+ OSL_ENSURE( !mbBitmapContentIsCurrent || !mbVDevContentIsCurrent,
+ "BitmapBackBuffer::getBitmapReference(): Both bitmap and VDev are valid?!" );
+
+ if( mbVDevContentIsCurrent && mpVDev )
+ {
+ // VDev content is more current than bitmap - copy contents before!
+ mpVDev->EnableMapMode( FALSE );
+ const Point aEmptyPoint;
+ *maBitmap = mpVDev->GetBitmapEx( aEmptyPoint,
+ mpVDev->GetOutputSizePixel() );
+ }
+
+ // client queries bitmap, and will possibly alter content -
+ // next time, VDev needs to be updated
+ mbBitmapContentIsCurrent = true;
+ mbVDevContentIsCurrent = false;
+
+ return *maBitmap;
+ }
+
+ Size BitmapBackBuffer::getBitmapSizePixel() const
+ {
+ Size aSize = maBitmap->GetSizePixel();
+
+ if( mbVDevContentIsCurrent && mpVDev )
+ {
+ mpVDev->EnableMapMode( FALSE );
+ aSize = mpVDev->GetOutputSizePixel();
+ }
+
+ return aSize;
+ }
+
+ void BitmapBackBuffer::createVDev() const
+ {
+ if( !mpVDev )
+ {
+ // VDev not yet created, do it now. Create an alpha-VDev,
+ // if bitmap has transparency.
+ mpVDev = maBitmap->IsTransparent() ?
+ new VirtualDevice( mrRefDevice, 0, 0 ) :
+ new VirtualDevice( mrRefDevice );
+
+ OSL_ENSURE( mpVDev,
+ "BitmapBackBuffer::createVDev(): Unable to create VirtualDevice" );
+
+ mpVDev->SetOutputSizePixel( maBitmap->GetSizePixel() );
+
+ // #i95645#
+#if defined( QUARTZ )
+ // use AA on VCLCanvas for Mac
+ mpVDev->SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW | mpVDev->GetAntialiasing() );
+#else
+ // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and
+ // is not required to do AA. It would need to be adapted to use it correctly
+ // (especially gradient painting). This will need extra work.
+ mpVDev->SetAntialiasing(mpVDev->GetAntialiasing() & !ANTIALIASING_ENABLE_B2DDRAW);
+#endif
+ }
+ }
+
+ void BitmapBackBuffer::updateVDev() const
+ {
+ OSL_ENSURE( !mbBitmapContentIsCurrent || !mbVDevContentIsCurrent,
+ "BitmapBackBuffer::updateVDev(): Both bitmap and VDev are valid?!" );
+
+ if( mpVDev && mbBitmapContentIsCurrent )
+ {
+ // fill with bitmap content
+ mpVDev->EnableMapMode( FALSE );
+ const Point aEmptyPoint;
+ mpVDev->DrawBitmapEx( aEmptyPoint, *maBitmap );
+ }
+
+ // canvas queried the VDev, and will possibly paint into
+ // it. Next time, bitmap must be updated
+ mbBitmapContentIsCurrent = false;
+ mbVDevContentIsCurrent = true;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/bitmapbackbuffer.hxx b/canvas/source/vcl/bitmapbackbuffer.hxx
new file mode 100644
index 000000000000..c7023a41d762
--- /dev/null
+++ b/canvas/source/vcl/bitmapbackbuffer.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_BITMAPBACKBUFFER_HXX_
+#define _VCLCANVAS_BITMAPBACKBUFFER_HXX_
+
+#include <vcl/virdev.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <canvas/vclwrapper.hxx>
+#include "outdevprovider.hxx"
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace vclcanvas
+{
+ /** Backbuffer implementation for canvas bitmap.
+
+ This class abstracts away the renderable bitmap for the bitmap
+ canvas. The actual VirtualDevice is only created when
+ necessary, which makes read-only bitmaps a lot smaller.
+ */
+ class BitmapBackBuffer : public OutDevProvider
+ {
+ public:
+ /** Create a backbuffer for given reference device
+ */
+ BitmapBackBuffer( const BitmapEx& rBitmap,
+ const OutputDevice& rRefDevice );
+
+ ~BitmapBackBuffer();
+
+ virtual OutputDevice& getOutDev();
+ virtual const OutputDevice& getOutDev() const;
+
+ /// Clear the underlying bitmap to white, all transparent
+ void clear();
+
+ /** Exposing our internal bitmap. Only to be used from
+ CanvasBitmapHelper
+
+ @internal
+ */
+ BitmapEx& getBitmapReference();
+ Size getBitmapSizePixel() const;
+
+ private:
+ void createVDev() const;
+ void updateVDev() const;
+
+ ::canvas::vcltools::VCLObject<BitmapEx> maBitmap;
+ mutable VirtualDevice* mpVDev; // created only on demand
+
+ const OutputDevice& mrRefDevice;
+
+ /** When true, the bitmap contains the last valid
+ content. When false, and mbVDevContentIsCurrent is true,
+ the VDev contains the last valid content (which must be
+ copied back to the bitmap, when getBitmapReference() is
+ called). When both are false, this object is just
+ initialized.
+ */
+ mutable bool mbBitmapContentIsCurrent;
+
+ /** When true, and mpVDev is non-NULL, the VDev contains the
+ last valid content. When false, and
+ mbBitmapContentIsCurrent is true, the bitmap contains the
+ last valid content. When both are false, this object is
+ just initialized.
+ */
+ mutable bool mbVDevContentIsCurrent;
+ };
+
+ typedef ::boost::shared_ptr< BitmapBackBuffer > BitmapBackBufferSharedPtr;
+
+}
+
+#endif /* #ifndef _VCLCANVAS_BITMAPBACKBUFFER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/cachedbitmap.cxx b/canvas/source/vcl/cachedbitmap.cxx
new file mode 100644
index 000000000000..39debc51f836
--- /dev/null
+++ b/canvas/source/vcl/cachedbitmap.cxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "cachedbitmap.hxx"
+#include "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 ::com::sun::star;
+
+namespace vclcanvas
+{
+ CachedBitmap::CachedBitmap( const GraphicObjectSharedPtr& rGraphicObject,
+ const ::Point& rPoint,
+ const ::Size& rSize,
+ const GraphicAttr& rAttr,
+ const rendering::ViewState& rUsedViewState,
+ const rendering::RenderState& rUsedRenderState,
+ const uno::Reference< rendering::XCanvas >& rTarget ) :
+ CachedPrimitiveBase( rUsedViewState, rTarget, true ),
+ mpGraphicObject( rGraphicObject ),
+ maRenderState(rUsedRenderState),
+ maPoint( rPoint ),
+ maSize( rSize ),
+ maAttributes( rAttr )
+ {
+ }
+
+ void SAL_CALL CachedBitmap::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpGraphicObject.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)" );
+
+ // TODO(P1): Could adapt to modified clips as well
+ if( rNewState.Clip != rOldState.Clip )
+ return rendering::RepaintResult::FAILED;
+
+ RepaintTarget* pTarget = dynamic_cast< RepaintTarget* >(rTargetCanvas.get());
+
+ ENSURE_OR_THROW( pTarget,
+ "CachedBitmap::redraw(): cannot cast target to RepaintTarget" );
+
+ if( !pTarget->repaint( mpGraphicObject,
+ rNewState,
+ maRenderState,
+ maPoint,
+ maSize,
+ maAttributes ) )
+ {
+ // target failed to repaint
+ return rendering::RepaintResult::FAILED;
+ }
+
+ return rendering::RepaintResult::REDRAWN;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/cachedbitmap.hxx b/canvas/source/vcl/cachedbitmap.hxx
new file mode 100644
index 000000000000..5959371a8294
--- /dev/null
+++ b/canvas/source/vcl/cachedbitmap.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CACHEDBITMAP_HXX
+#define _VCLCANVAS_CACHEDBITMAP_HXX
+
+#include <canvas/base/cachedprimitivebase.hxx>
+
+#include <svtools/grfmgr.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of CachedBitmap class */
+
+namespace vclcanvas
+{
+ typedef ::boost::shared_ptr< GraphicObject > GraphicObjectSharedPtr;
+
+ class CachedBitmap : public ::canvas::CachedPrimitiveBase
+ {
+ public:
+
+ /** Create an XCachedPrimitive for given GraphicObject
+ */
+ CachedBitmap( const GraphicObjectSharedPtr& rGraphicObject,
+ const ::Point& rPoint,
+ const ::Size& rSize,
+ const GraphicAttr& rAttr,
+ 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 );
+
+
+ GraphicObjectSharedPtr mpGraphicObject;
+ const ::com::sun::star::rendering::RenderState maRenderState;
+ const ::Point maPoint;
+ const ::Size maSize;
+ const GraphicAttr maAttributes;
+ };
+}
+
+#endif /* _VCLCANVAS_CACHEDBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvas.cxx b/canvas/source/vcl/canvas.cxx
new file mode 100644
index 000000000000..87c4d6de2b81
--- /dev/null
+++ b/canvas/source/vcl/canvas.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <vcl/canvastools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <basegfx/tools/canvastools.hxx>
+
+#include <algorithm>
+
+#include "canvas.hxx"
+#include "windowoutdevholder.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ namespace
+ {
+ class OutDevHolder : public OutDevProvider,
+ private ::boost::noncopyable
+ {
+ public:
+ explicit OutDevHolder( OutputDevice& rOutDev ) :
+ mrOutDev(rOutDev)
+ {}
+
+ private:
+ virtual OutputDevice& getOutDev() { return mrOutDev; }
+ virtual const OutputDevice& getOutDev() const { return mrOutDev; }
+
+ // TODO(Q2): Lifetime issue. This _only_ works reliably,
+ // if disposing the Canvas correctly disposes all
+ // entities which hold this pointer.
+ OutputDevice& mrOutDev;
+ };
+ }
+
+ 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
+ */
+ SolarMutexGuard aGuard;
+
+ VERBOSE_TRACE( "VCLCanvas::initialize called" );
+
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER,
+ "Canvas::initialize: wrong number of arguments, or wrong types" );
+
+ sal_Int64 nPtr = 0;
+ maArguments[0] >>= nPtr;
+
+ OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr);
+ if( !pOutDev )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed OutDev invalid!")),
+ NULL);
+
+ OutDevProviderSharedPtr pOutdevProvider( new OutDevHolder(*pOutDev) );
+
+ // setup helper
+ maDeviceHelper.init( pOutdevProvider );
+ maCanvasHelper.init( *this,
+ pOutdevProvider,
+ true, // OutDev state preservation
+ false ); // no alpha on surface
+
+ maArguments.realloc(0);
+ }
+
+ Canvas::~Canvas()
+ {
+ OSL_TRACE( "Canvas destroyed" );
+ }
+
+ void SAL_CALL Canvas::disposing()
+ {
+ SolarMutexGuard aGuard;
+
+ mxComponentContext.clear();
+
+ // forward to parent
+ CanvasBaseT::disposing();
+ }
+
+ ::rtl::OUString SAL_CALL Canvas::getServiceName( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CANVAS_SERVICE_NAME ) );
+ }
+
+ bool Canvas::repaint( const GraphicObjectSharedPtr& rGrf,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const
+ {
+ SolarMutexGuard aGuard;
+
+ return maCanvasHelper.repaint( rGrf, viewState, renderState, rPt, rSz, rAttr );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvas.hxx b/canvas/source/vcl/canvas.hxx
new file mode 100644
index 000000000000..ea6b79a88073
--- /dev/null
+++ b/canvas/source/vcl/canvas.hxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVAS_HXX_
+#define _VCLCANVAS_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/XServiceName.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.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/basemutexhelper.hxx>
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/base/graphicdevicebase.hxx>
+
+#include "canvashelper.hxx"
+#include "impltools.hxx"
+#include "devicehelper.hxx"
+#include "repainttarget.hxx"
+
+#define CANVAS_SERVICE_NAME "com.sun.star.rendering.Canvas.VCL"
+#define CANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.Canvas.VCL"
+
+namespace vclcanvas
+{
+ 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,
+ tools::LocalGuard,
+ ::cppu::OWeakObject > CanvasBase_Base;
+ typedef ::canvas::IntegerBitmapBase< CanvasBase_Base,
+ CanvasHelper,
+ tools::LocalGuard,
+ ::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 GraphicObjectSharedPtr& rGrf,
+ const com::sun::star::rendering::ViewState& viewState,
+ const com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const;
+
+ 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasbitmap.cxx b/canvas/source/vcl/canvasbitmap.cxx
new file mode 100644
index 000000000000..fbf97f960475
--- /dev/null
+++ b/canvas/source/vcl/canvasbitmap.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 "canvasbitmap.hxx"
+
+#include <vcl/bmpacc.hxx>
+
+using namespace ::com::sun::star;
+
+
+namespace vclcanvas
+{
+ // Currently, the only way to generate an XBitmap is from
+ // XGraphicDevice.getCompatibleBitmap(). Therefore, we don't even
+ // take a bitmap here, but a VDev directly.
+ CanvasBitmap::CanvasBitmap( const ::Size& rSize,
+ bool bAlphaBitmap,
+ rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider )
+ {
+ // create bitmap for given reference device
+ // ========================================
+ const USHORT nBitCount( (USHORT)24U );
+ const BitmapPalette* pPalette = NULL;
+
+ Bitmap aBitmap( rSize, nBitCount, pPalette );
+
+ // only create alpha channel bitmap, if factory requested
+ // that. Providing alpha-channeled bitmaps by default has,
+ // especially under VCL, a huge performance penalty (have to
+ // use alpha VDev, then).
+ if( bAlphaBitmap )
+ {
+ AlphaMask aAlpha ( rSize );
+
+ maCanvasHelper.init( BitmapEx( aBitmap, aAlpha ),
+ rDevice,
+ rOutDevProvider );
+ }
+ else
+ {
+ maCanvasHelper.init( BitmapEx( aBitmap ),
+ rDevice,
+ rOutDevProvider );
+ }
+ }
+
+ CanvasBitmap::CanvasBitmap( const BitmapEx& rBitmap,
+ rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider )
+ {
+ maCanvasHelper.init( rBitmap, rDevice, rOutDevProvider );
+ }
+
+ void SAL_CALL CanvasBitmap::disposing()
+ {
+ // forward to base
+ CanvasBitmap_Base::disposing();
+ }
+
+#define IMPLEMENTATION_NAME "VCLCanvas.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;
+ }
+
+ BitmapEx CanvasBitmap::getBitmap() const
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(T3): Rework to use shared_ptr all over the place for
+ // BmpEx. This is highly un-threadsafe
+ return maCanvasHelper.getBitmap();
+ }
+
+ bool CanvasBitmap::repaint( const GraphicObjectSharedPtr& rGrf,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const
+ {
+ SolarMutexGuard aGuard;
+
+ mbSurfaceDirty = true;
+
+ return maCanvasHelper.repaint( rGrf, viewState, renderState, rPt, rSz, rAttr );
+ }
+
+ uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
+ {
+ if( nHandle == 0 ) {
+ BitmapEx* pBitmapEx = new BitmapEx( getBitmap() );
+
+ return uno::Any( reinterpret_cast<sal_Int64>( pBitmapEx ) );
+ }
+
+ return uno::Any( sal_Int64(0) );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasbitmap.hxx b/canvas/source/vcl/canvasbitmap.hxx
new file mode 100644
index 000000000000..a1162001d9d1
--- /dev/null
+++ b/canvas/source/vcl/canvasbitmap.hxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVASBITMAP_HXX
+#define _VCLCANVAS_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 <vcl/virdev.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <canvas/vclwrapper.hxx>
+
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvasbitmaphelper.hxx>
+
+#include "impltools.hxx"
+#include "repainttarget.hxx"
+#include "spritecanvas.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace vclcanvas
+{
+ 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;
+ typedef ::canvas::IntegerBitmapBase< ::canvas::BaseMutexHelper< CanvasBitmapBase_Base >,
+ CanvasBitmapHelper,
+ tools::LocalGuard,
+ ::cppu::OWeakObject > CanvasBitmap_Base;
+
+ class CanvasBitmap : public CanvasBitmap_Base,
+ public RepaintTarget
+ {
+ public:
+ /** Must be called with locked Solar mutex
+
+ @param rSize
+ Size in pixel of the bitmap to generate
+
+ @param bAlphaBitmap
+ When true, bitmap will have an alpha channel
+
+ @param rDevice
+ Reference device, with which bitmap should be compatible
+ */
+ CanvasBitmap( const ::Size& rSize,
+ bool bAlphaBitmap,
+ ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider );
+
+ /// Must be called with locked Solar mutex
+ CanvasBitmap( const BitmapEx& rBitmap,
+ ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider );
+
+ // overridden because of mpDevice
+ virtual void SAL_CALL disposing();
+
+ // 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);
+
+ // RepaintTarget interface
+ virtual bool repaint( const GraphicObjectSharedPtr& rGrf,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const;
+
+ /// Not threadsafe! Returned object is shared!
+ BitmapEx getBitmap() const;
+
+ // 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:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ ::com::sun::star::uno::Reference<com::sun::star::rendering::XGraphicDevice> mxDevice;
+ };
+}
+
+#endif /* _VCLCANVAS_CANVASBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasbitmaphelper.cxx b/canvas/source/vcl/canvasbitmaphelper.cxx
new file mode 100644
index 000000000000..66fe12eb3cad
--- /dev/null
+++ b/canvas/source/vcl/canvasbitmaphelper.cxx
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/util/Endianness.hpp>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#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/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include "canvasbitmap.hxx"
+#include "canvasbitmaphelper.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ CanvasBitmapHelper::CanvasBitmapHelper() :
+ mpBackBuffer(),
+ mpOutDevReference()
+ {
+ }
+
+ void CanvasBitmapHelper::setBitmap( const BitmapEx& rBitmap )
+ {
+ ENSURE_OR_THROW( mpOutDev,
+ "Invalid reference device" );
+
+ mpBackBuffer.reset( new BitmapBackBuffer( rBitmap,
+ mpOutDev->getOutDev() ) );
+
+ // tell canvas helper about the new target OutDev (don't
+ // protect state, it's our own VirDev, anyways)
+ setOutDev( mpBackBuffer, false );
+ }
+
+ void CanvasBitmapHelper::init( const BitmapEx& rBitmap,
+ rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevReference )
+ {
+ mpOutDevReference = rOutDevReference;
+ mpBackBuffer.reset( new BitmapBackBuffer( rBitmap, rOutDevReference->getOutDev() ));
+
+ // forward new settings to base class (ref device, output
+ // surface, no protection (own backbuffer), alpha depends on
+ // whether BmpEx is transparent or not)
+ CanvasHelper::init( rDevice,
+ mpBackBuffer,
+ false,
+ rBitmap.IsTransparent() );
+ }
+
+ void CanvasBitmapHelper::disposing()
+ {
+ mpBackBuffer.reset();
+ mpOutDevReference.reset();
+
+ // forward to base class
+ CanvasHelper::disposing();
+ }
+
+ geometry::IntegerSize2D CanvasBitmapHelper::getSize()
+ {
+ if( !mpBackBuffer )
+ return geometry::IntegerSize2D();
+
+ return ::vcl::unotools::integerSize2DFromSize( mpBackBuffer->getBitmapSizePixel() );
+ }
+
+ void CanvasBitmapHelper::clear()
+ {
+ // are we disposed?
+ if( mpBackBuffer )
+ mpBackBuffer->clear(); // alpha vdev needs special treatment
+ }
+
+ uno::Reference< rendering::XBitmap > CanvasBitmapHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
+ sal_Bool beFast )
+ {
+ ENSURE_OR_THROW( mpDevice,
+ "disposed CanvasHelper" );
+
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getScaledBitmap()" );
+
+ if( !mpBackBuffer || mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ BitmapEx aRes( mpBackBuffer->getBitmapReference() );
+
+ aRes.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize),
+ beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE );
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap( aRes, *mpDevice, mpOutDevReference ) );
+ }
+
+ uno::Sequence< sal_Int8 > CanvasBitmapHelper::getData( rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getData()" );
+
+ if( !mpBackBuffer )
+ return uno::Sequence< sal_Int8 >(); // we're disposed
+
+ rLayout = getMemoryLayout();
+ Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
+ Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+ ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
+ (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
+ aAlpha );
+
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "Could not acquire read access to bitmap" );
+
+ // TODO(F1): Support more formats.
+ const Size aBmpSize( aBitmap.GetSizePixel() );
+
+ rLayout.ScanLines = aBmpSize.Height();
+ rLayout.ScanLineBytes = aBmpSize.Width()*4;
+ rLayout.ScanLineStride = rLayout.ScanLineBytes;
+
+ // for the time being, always return as BGRA
+ uno::Sequence< sal_Int8 > aRes( 4*aBmpSize.Width()*aBmpSize.Height() );
+ sal_Int8* pRes = aRes.getArray();
+
+ int nCurrPos(0);
+ for( int y=rect.Y1;
+ y<aBmpSize.Height() && y<rect.Y2;
+ ++y )
+ {
+ if( pAlphaReadAccess.get() != NULL )
+ {
+ for( int x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
+ pRes[ nCurrPos++ ] = pAlphaReadAccess->GetPixel( y, x ).GetIndex();
+ }
+ }
+ else
+ {
+ for( int x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
+ pRes[ nCurrPos++ ] = sal_uInt8(255);
+ }
+ }
+ }
+
+ return aRes;
+ }
+
+ void CanvasBitmapHelper::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setData()" );
+
+ if( !mpBackBuffer )
+ return; // we're disposed
+
+ const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
+ ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
+ aRefLayout.ColorSpace != rLayout.ColorSpace ||
+ aRefLayout.Palette != rLayout.Palette ||
+ aRefLayout.IsMsbFirst != rLayout.IsMsbFirst,
+ "Mismatching memory layout" );
+
+ // retrieve local copies from the BitmapEx, which are later
+ // stored back. Unfortunately, the BitmapEx does not permit
+ // in-place modifications, as they are necessary here.
+ Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
+ Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
+
+ bool bCopyBack( false ); // only copy something back, if we
+ // actually changed a pixel
+
+ {
+ ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
+ aBitmap );
+ ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
+ (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
+ aAlpha );
+
+ if( pAlphaWriteAccess.get() )
+ {
+ DBG_ASSERT( pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
+ pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ "non-8bit alpha not supported!" );
+ }
+
+ ENSURE_OR_THROW( pWriteAccess.get() != NULL,
+ "Could not acquire write access to bitmap" );
+
+ // TODO(F1): Support more formats.
+ const Size aBmpSize( aBitmap.GetSizePixel() );
+
+ // for the time being, always read as BGRA
+ int x, y, nCurrPos(0);
+ for( y=rect.Y1;
+ y<aBmpSize.Height() && y<rect.Y2;
+ ++y )
+ {
+ if( pAlphaWriteAccess.get() != NULL )
+ {
+ switch( pWriteAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+ Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = (BYTE)pWriteAccess->GetBestPaletteIndex(
+ BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+
+ nCurrPos += 3;
+
+ // cast to unsigned byte, for correct subtraction result
+ *pAScan++ = static_cast<BYTE>(255 -
+ static_cast<sal_uInt8>(data[ nCurrPos++ ]));
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+ Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = data[ nCurrPos+2 ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos ];
+
+ nCurrPos += 3;
+
+ // cast to unsigned byte, for correct subtraction result
+ *pAScan++ = static_cast<BYTE>(255 -
+ static_cast<sal_uInt8>(data[ nCurrPos++ ]));
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_RGB:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+ Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = data[ nCurrPos ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos+2 ];
+
+ nCurrPos += 3;
+
+ // cast to unsigned byte, for correct subtraction result
+ *pAScan++ = static_cast<BYTE>(255 -
+ static_cast<sal_uInt8>(data[ nCurrPos++ ]));
+ }
+ }
+ break;
+
+ default:
+ {
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+ nCurrPos += 3;
+
+ // cast to unsigned byte, for correct subtraction result
+ pAlphaWriteAccess->SetPixel( y, x,
+ BitmapColor(
+ static_cast<BYTE>(255 -
+ static_cast<sal_uInt8>(data[ nCurrPos++ ])) ) );
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ // TODO(Q3): This is copy'n'pasted from
+ // canvashelper.cxx, unify!
+ switch( pWriteAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = (BYTE)pWriteAccess->GetBestPaletteIndex(
+ BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+
+ nCurrPos += 4; // skip three colors, _plus_ alpha
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = data[ nCurrPos+2 ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos ];
+
+ nCurrPos += 4; // skip three colors, _plus_ alpha
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_RGB:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ *pScan++ = data[ nCurrPos ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos+2 ];
+
+ nCurrPos += 4; // skip three colors, _plus_ alpha
+ }
+ }
+ break;
+
+ default:
+ {
+ for( x=rect.X1;
+ x<aBmpSize.Width() && x<rect.X2;
+ ++x )
+ {
+ pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+ nCurrPos += 4; // skip three colors, _plus_ alpha
+ }
+ }
+ break;
+ }
+ }
+
+ bCopyBack = true;
+ }
+ }
+
+ // copy back only here, since the BitmapAccessors must be
+ // destroyed beforehand
+ if( bCopyBack )
+ {
+ if( aAlpha.IsEmpty() )
+ setBitmap( BitmapEx( aBitmap ) );
+ else
+ setBitmap( BitmapEx( aBitmap,
+ AlphaMask( aAlpha ) ) );
+ }
+ }
+
+ void CanvasBitmapHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setPixel()" );
+
+ if( !mpBackBuffer )
+ return; // we're disposed
+
+ const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
+ "X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
+ "Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "not enough color components" );
+
+ const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
+ ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
+ aRefLayout.ColorSpace != rLayout.ColorSpace ||
+ aRefLayout.Palette != rLayout.Palette ||
+ aRefLayout.IsMsbFirst != rLayout.IsMsbFirst,
+ "Mismatching memory layout" );
+
+ // retrieve local copies from the BitmapEx, which are later
+ // stored back. Unfortunately, the BitmapEx does not permit
+ // in-place modifications, as they are necessary here.
+ Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
+ Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
+
+ bool bCopyBack( false ); // only copy something back, if we
+ // actually changed a pixel
+
+ {
+ ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
+ aBitmap );
+ ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
+ (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
+ aAlpha );
+
+ ENSURE_OR_THROW( pWriteAccess.get() != NULL,
+ "Could not acquire write access to bitmap" );
+
+ pWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( color[ 0 ],
+ color[ 1 ],
+ color[ 2 ] ) );
+
+ if( pAlphaWriteAccess.get() != NULL )
+ pAlphaWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( 255 - color[ 3 ] ) );
+
+ bCopyBack = true;
+ }
+
+ // copy back only here, since the BitmapAccessors must be
+ // destroyed beforehand
+ if( bCopyBack )
+ {
+ if( aAlpha.IsEmpty() )
+ setBitmap( BitmapEx( aBitmap ) );
+ else
+ setBitmap( BitmapEx( aBitmap,
+ AlphaMask( aAlpha ) ) );
+ }
+ }
+
+ uno::Sequence< sal_Int8 > CanvasBitmapHelper::getPixel( rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getPixel()" );
+
+ if( !mpBackBuffer )
+ return uno::Sequence< sal_Int8 >(); // we're disposed
+
+ rLayout = getMemoryLayout();
+ rLayout.ScanLines = 1;
+ rLayout.ScanLineBytes = 4;
+ rLayout.ScanLineStride = rLayout.ScanLineBytes;
+
+ const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
+ "X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
+ "Y coordinate out of bounds" );
+
+ Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
+ Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+ ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
+ (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
+ aAlpha );
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "Could not acquire read access to bitmap" );
+
+ uno::Sequence< sal_Int8 > aRes( 4 );
+ sal_Int8* pRes = aRes.getArray();
+
+ const BitmapColor aColor( pReadAccess->GetColor( pos.Y, pos.X ) );
+ pRes[ 0 ] = aColor.GetRed();
+ pRes[ 1 ] = aColor.GetGreen();
+ pRes[ 2 ] = aColor.GetBlue();
+
+ if( pAlphaReadAccess.get() != NULL )
+ pRes[ 3 ] = pAlphaReadAccess->GetPixel( pos.Y, pos.X ).GetIndex();
+ else
+ pRes[ 3 ] = sal_uInt8(255);
+
+ return aRes;
+ }
+
+ rendering::IntegerBitmapLayout CanvasBitmapHelper::getMemoryLayout()
+ {
+ if( !mpOutDev.get() )
+ return rendering::IntegerBitmapLayout(); // we're disposed
+
+ return ::canvas::tools::getStdMemoryLayout(getSize());
+ }
+
+ BitmapEx CanvasBitmapHelper::getBitmap() const
+ {
+ if( !mpBackBuffer )
+ return BitmapEx(); // we're disposed
+ else
+ return mpBackBuffer->getBitmapReference();
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasbitmaphelper.hxx b/canvas/source/vcl/canvasbitmaphelper.hxx
new file mode 100644
index 000000000000..bcd5a2b1c3b7
--- /dev/null
+++ b/canvas/source/vcl/canvasbitmaphelper.hxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVASBITMAPHELPER_HXX_
+#define _VCLCANVAS_CANVASBITMAPHELPER_HXX_
+
+#include <canvashelper.hxx>
+#include <canvas/vclwrapper.hxx>
+
+#include <vcl/bitmapex.hxx>
+
+#include "bitmapbackbuffer.hxx"
+#include "spritecanvas.hxx"
+
+
+namespace vclcanvas
+{
+ /** Helper class for basic canvasbitmap functionality. Extends
+ CanvasHelper with some CanvasBitmap specialities, such as alpha
+ support.
+
+ Note that a plain CanvasHelper, although it does support the
+ XBitmap interface, has no provision for alpha channel on VCL
+ (at least no efficient one. If the alpha VDev one day gets
+ part of SAL, we might change that).
+ */
+ class CanvasBitmapHelper : public CanvasHelper
+ {
+ public:
+ CanvasBitmapHelper();
+
+ /** Set a new bitmap on this helper.
+
+ This method late-initializes the bitmap canvas helper,
+ providing it with the necessary device and output
+ objects. The internally stored bitmap representation is
+ updated from the given bitmap, including any size
+ changes. Note that the CanvasHelper does <em>not</em> take
+ ownership of the SpriteCanvas object, nor does it perform
+ any reference counting. Thus, to prevent reference counted
+ objects from deletion, the user of this class is
+ responsible for holding ref-counted references to those
+ objects!
+
+ @param rBitmap
+ Content of this bitmap is used as our new content (our
+ internal size is adapted to the size of the bitmap given)
+
+ @param rDevice
+ Reference device for this canvas bitmap
+
+ @param rOutDevProvider
+ Reference output device. Used to create matching bitmap.
+ */
+ void init( const BitmapEx& rBitmap,
+ ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider );
+
+
+ // Overridden CanvasHelper functionality
+ // =====================================
+
+ void disposing();
+
+ void clear();
+
+ ::com::sun::star::geometry::IntegerSize2D getSize();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > queryBitmapCanvas();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap >
+ getScaledBitmap( const ::com::sun::star::geometry::RealSize2D& newSize,
+ sal_Bool beFast );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getData( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setData( const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setPixel( const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getPixel( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::rendering::IntegerBitmapLayout getMemoryLayout();
+
+ /// @internal
+ BitmapEx getBitmap() const;
+
+ private:
+
+ void setBitmap( const BitmapEx& rBitmap );
+
+ BitmapBackBufferSharedPtr mpBackBuffer;
+ OutDevProviderSharedPtr mpOutDevReference;
+ };
+}
+
+#endif /* _VCLCANVAS_CANVASBITMAPHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvascustomsprite.cxx b/canvas/source/vcl/canvascustomsprite.cxx
new file mode 100644
index 000000000000..b9e11d441ecf
--- /dev/null
+++ b/canvas/source/vcl/canvascustomsprite.cxx
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+
+#include <rtl/math.hxx>
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include "canvascustomsprite.hxx"
+
+
+using namespace ::com::sun::star;
+
+
+namespace vclcanvas
+{
+
+ CanvasCustomSprite::CanvasCustomSprite( const geometry::RealSize2D& rSpriteSize,
+ rendering::XGraphicDevice& rDevice,
+ const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
+ const OutDevProviderSharedPtr& rOutDevProvider,
+ bool bShowSpriteBounds )
+ {
+ ENSURE_OR_THROW( rOwningSpriteCanvas.get() &&
+ rOutDevProvider,
+ "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+ // setup back buffer
+ // -----------------
+
+ const ::Size aSize(
+ static_cast<sal_Int32>( ::std::max( 1.0,
+ ceil( rSpriteSize.Width ))), // round up to nearest int,
+ // enforce sprite to have at
+ // least (1,1) pixel size
+ static_cast<sal_Int32>( ::std::max( 1.0,
+ ceil( rSpriteSize.Height ))) );
+
+ // create content backbuffer in screen depth
+ BackBufferSharedPtr pBackBuffer( new BackBuffer( rOutDevProvider->getOutDev() ) );
+ pBackBuffer->setSize( aSize );
+
+ // create mask backbuffer, with one bit color depth
+ BackBufferSharedPtr pBackBufferMask( new BackBuffer( rOutDevProvider->getOutDev(),
+ true ) );
+ pBackBufferMask->setSize( aSize );
+
+ // TODO(F1): Implement alpha vdev (could prolly enable
+ // antialiasing again, then)
+
+ // disable font antialiasing (causes ugly shadows otherwise)
+ pBackBuffer->getOutDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
+ pBackBufferMask->getOutDev().SetAntialiasing( ANTIALIASING_DISABLE_TEXT );
+
+ // set mask vdev drawmode, such that everything is painted
+ // black. That leaves us with a binary image, white for
+ // background, black for painted content
+ pBackBufferMask->getOutDev().SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT |
+ DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP );
+
+
+ // setup canvas helper
+ // -------------------
+
+ // always render into back buffer, don't preserve state (it's
+ // our private VDev, after all), have notion of alpha
+ maCanvasHelper.init( rDevice,
+ pBackBuffer,
+ false,
+ true );
+ maCanvasHelper.setBackgroundOutDev( pBackBufferMask );
+
+
+ // setup sprite helper
+ // -------------------
+
+ maSpriteHelper.init( rSpriteSize,
+ rOwningSpriteCanvas,
+ pBackBuffer,
+ pBackBufferMask,
+ bShowSpriteBounds );
+
+ // clear sprite to 100% transparent
+ maCanvasHelper.clear();
+ }
+
+ void SAL_CALL CanvasCustomSprite::disposing()
+ {
+ SolarMutexGuard aGuard;
+
+ // forward to parent
+ CanvasCustomSpriteBaseT::disposing();
+ }
+
+#define IMPLEMENTATION_NAME "VCLCanvas.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;
+ }
+
+ // Sprite
+ void CanvasCustomSprite::redraw( OutputDevice& rOutDev,
+ bool bBufferedUpdate ) const
+ {
+ SolarMutexGuard aGuard;
+
+ redraw( rOutDev, maSpriteHelper.getPosPixel(), bBufferedUpdate );
+ }
+
+ void CanvasCustomSprite::redraw( OutputDevice& rOutDev,
+ const ::basegfx::B2DPoint& rOrigOutputPos,
+ bool bBufferedUpdate ) const
+ {
+ SolarMutexGuard aGuard;
+
+ maSpriteHelper.redraw( rOutDev,
+ rOrigOutputPos,
+ mbSurfaceDirty,
+ bBufferedUpdate );
+
+ mbSurfaceDirty = false;
+ }
+
+ bool CanvasCustomSprite::repaint( const GraphicObjectSharedPtr& rGrf,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const
+ {
+ SolarMutexGuard aGuard;
+
+ mbSurfaceDirty = true;
+
+ return maCanvasHelper.repaint( rGrf, viewState, renderState, rPt, rSz, rAttr );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvascustomsprite.hxx b/canvas/source/vcl/canvascustomsprite.hxx
new file mode 100644
index 000000000000..0990e950e16d
--- /dev/null
+++ b/canvas/source/vcl/canvascustomsprite.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVASCUSTOMSPRITE_HXX
+#define _VCLCANVAS_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 <vcl/virdev.hxx>
+
+#include <canvas/vclwrapper.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/spritesurface.hxx>
+#include <canvas/base/canvascustomspritebase.hxx>
+
+#include "sprite.hxx"
+#include "canvashelper.hxx"
+#include "spritehelper.hxx"
+#include "backbuffer.hxx"
+#include "impltools.hxx"
+#include "spritecanvas.hxx"
+#include "repainttarget.hxx"
+
+
+namespace vclcanvas
+{
+ 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
+ {
+ };
+
+ typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
+ SpriteHelper,
+ CanvasHelper,
+ tools::LocalGuard,
+ ::cppu::OWeakObject > CanvasCustomSpriteBaseT;
+
+ /* Definition of CanvasCustomSprite class */
+
+ class CanvasCustomSprite : public CanvasCustomSpriteBaseT,
+ public RepaintTarget
+ {
+ public:
+ CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
+ const OutDevProviderSharedPtr& rOutDevProvider,
+ bool bShowSpriteBounds );
+
+ 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( OutputDevice& rOutDev,
+ bool bBufferedUpdate ) const;
+ virtual void redraw( OutputDevice& rOutDev,
+ const ::basegfx::B2DPoint& rPos,
+ bool bBufferedUpdate ) const;
+
+ // RepaintTarget
+ virtual bool repaint( const GraphicObjectSharedPtr& rGrf,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const;
+ };
+}
+
+#endif /* _VCLCANVAS_CANVASCUSTOMSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasfont.cxx b/canvas/source/vcl/canvasfont.cxx
new file mode 100644
index 000000000000..c968150705f2
--- /dev/null
+++ b/canvas/source/vcl/canvasfont.cxx
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <i18npool/mslangid.hxx>
+#include <vcl/metric.hxx>
+
+#include <com/sun/star/rendering/PanoseProportion.hpp>
+
+#include "canvasfont.hxx"
+#include "textlayout.hxx"
+
+using namespace ::com::sun::star;
+
+
+namespace vclcanvas
+{
+ CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
+ const uno::Sequence< beans::PropertyValue >& ,
+ const geometry::Matrix2D& rFontMatrix,
+ rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider ) :
+ CanvasFont_Base( m_aMutex ),
+ maFont( Font( rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ),
+ maFontRequest( rFontRequest ),
+ mpRefDevice( &rDevice ),
+ mpOutDevProvider( rOutDevProvider )
+ {
+ 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->SetPitch(
+ rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
+ ? PITCH_FIXED : PITCH_VARIABLE);
+
+ maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
+
+ // adjust to stretched/shrinked font
+ if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
+ {
+ OutputDevice& rOutDev( rOutDevProvider->getOutDev() );
+
+ const bool bOldMapState( rOutDev.IsMapModeEnabled() );
+ rOutDev.EnableMapMode(FALSE);
+
+ const Size aSize = rOutDev.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 );
+
+ rOutDev.EnableMapMode(bOldMapState);
+ }
+ }
+
+ void SAL_CALL CanvasFont::disposing()
+ {
+ SolarMutexGuard aGuard;
+
+ mpOutDevProvider.reset();
+ mpRefDevice.clear();
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ if( !mpRefDevice.is() )
+ return uno::Reference< rendering::XTextLayout >(); // we're disposed
+
+ return new TextLayout( aText,
+ nDirection,
+ nRandomSeed,
+ Reference( this ),
+ mpRefDevice,
+ mpOutDevProvider);
+ }
+
+ rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
+ VirtualDevice aVDev( rOutDev );
+ aVDev.SetFont(getVCLFont());
+ const ::FontMetric& aMetric( aVDev.GetFontMetric() );
+
+ return rendering::FontMetrics(
+ aMetric.GetAscent(),
+ aMetric.GetDescent(),
+ aMetric.GetIntLeading(),
+ aMetric.GetExtLeading(),
+ 0,
+ aMetric.GetDescent() / 2.0,
+ aMetric.GetAscent() / 2.0);
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+#define IMPLEMENTATION_NAME "VCLCanvas::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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvasfont.hxx b/canvas/source/vcl/canvasfont.hxx
new file mode 100644
index 000000000000..b58d0c8939a7
--- /dev/null
+++ b/canvas/source/vcl/canvasfont.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVASFONT_HXX
+#define _VCLCANVAS_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 <com/sun/star/rendering/XGraphicDevice.hpp>
+
+#include <vcl/font.hxx>
+
+#include <canvas/vclwrapper.hxx>
+
+#include "spritecanvas.hxx"
+#include "impltools.hxx"
+
+#include <boost/utility.hpp>
+
+
+/* Definition of CanvasFont class */
+
+namespace vclcanvas
+{
+ 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,
+ ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDevProvider );
+
+ /// 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;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice> mpRefDevice;
+ OutDevProviderSharedPtr mpOutDevProvider;
+ };
+
+}
+
+#endif /* _VCLCANVAS_CANVASFONT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx
new file mode 100644
index 000000000000..6946d256b387
--- /dev/null
+++ b/canvas/source/vcl/canvashelper.cxx
@@ -0,0 +1,1431 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/math.hxx>
+
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/util/Endianness.hpp>
+#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 "textlayout.hxx"
+#include "canvashelper.hxx"
+#include "canvasbitmap.hxx"
+#include "impltools.hxx"
+#include "canvasfont.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ namespace
+ {
+ basegfx::B2DLineJoin b2DJoineFromJoin( sal_Int8 nJoinType )
+ {
+ switch( nJoinType )
+ {
+ case rendering::PathJoinType::NONE:
+ return basegfx::B2DLINEJOIN_NONE;
+
+ case rendering::PathJoinType::MITER:
+ return basegfx::B2DLINEJOIN_MITER;
+
+ case rendering::PathJoinType::ROUND:
+ return basegfx::B2DLINEJOIN_ROUND;
+
+ case rendering::PathJoinType::BEVEL:
+ return basegfx::B2DLINEJOIN_BEVEL;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "b2DJoineFromJoin(): Unexpected join type" );
+ }
+
+ return basegfx::B2DLINEJOIN_NONE;
+ }
+ }
+
+ CanvasHelper::CanvasHelper() :
+ mpDevice(),
+ mpProtectedOutDev(),
+ mpOutDev(),
+ mp2ndOutDev(),
+ mbHaveAlpha( false )
+ {
+ }
+
+ void CanvasHelper::disposing()
+ {
+ mpDevice = NULL;
+ mpProtectedOutDev.reset();
+ mpOutDev.reset();
+ mp2ndOutDev.reset();
+ }
+
+ void CanvasHelper::init( rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDev,
+ bool bProtect,
+ bool bHaveAlpha )
+ {
+ // cast away const, need to change refcount (as this is
+ // ~invisible to client code, still logically const)
+ mpDevice = &rDevice;
+ mbHaveAlpha = bHaveAlpha;
+
+ setOutDev( rOutDev, bProtect );
+ }
+
+ void CanvasHelper::setOutDev( const OutDevProviderSharedPtr& rOutDev,
+ bool bProtect )
+ {
+ if( bProtect )
+ mpProtectedOutDev = rOutDev;
+ else
+ mpProtectedOutDev.reset();
+
+ mpOutDev = rOutDev;
+ }
+
+ void CanvasHelper::setBackgroundOutDev( const OutDevProviderSharedPtr& rOutDev )
+ {
+ mp2ndOutDev = rOutDev;
+ mp2ndOutDev->getOutDev().EnableMapMode( FALSE );
+ }
+
+ void CanvasHelper::clear()
+ {
+ // are we disposed?
+ if( mpOutDev )
+ {
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ rOutDev.EnableMapMode( FALSE );
+ rOutDev.SetLineColor( COL_TRANSPARENT );
+ rOutDev.SetFillColor( COL_TRANSPARENT );
+ rOutDev.DrawRect( Rectangle( Point(),
+ rOutDev.GetOutputSizePixel()) );
+
+ if( mp2ndOutDev )
+ {
+ OutputDevice& rOutDev2( mp2ndOutDev->getOutDev() );
+
+ rOutDev2.SetDrawMode( DRAWMODE_DEFAULT );
+ rOutDev2.EnableMapMode( FALSE );
+ rOutDev2.SetLineColor( COL_TRANSPARENT );
+ rOutDev2.SetFillColor( COL_TRANSPARENT );
+ rOutDev2.DrawRect( Rectangle( Point(),
+ rOutDev2.GetOutputSizePixel()) );
+ rOutDev2.SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT |
+ DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP );
+ }
+ }
+ }
+
+ void CanvasHelper::drawPoint( const rendering::XCanvas* ,
+ const geometry::RealPoint2D& aPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ // are we disposed?
+ if( mpOutDev )
+ {
+ // nope, render
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, LINE_COLOR );
+
+ const Point aOutPoint( tools::mapRealPoint2D( aPoint,
+ viewState, renderState ) );
+ // TODO(F1): alpha
+ mpOutDev->getOutDev().DrawPixel( aOutPoint );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawPixel( aOutPoint );
+ }
+ }
+
+ void CanvasHelper::drawLine( const rendering::XCanvas* ,
+ const geometry::RealPoint2D& aStartRealPoint2D,
+ const geometry::RealPoint2D& aEndRealPoint2D,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ // are we disposed?
+ if( mpOutDev )
+ {
+ // nope, render
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, LINE_COLOR );
+
+ const Point aStartPoint( tools::mapRealPoint2D( aStartRealPoint2D,
+ viewState, renderState ) );
+ const Point aEndPoint( tools::mapRealPoint2D( aEndRealPoint2D,
+ viewState, renderState ) );
+ // TODO(F2): alpha
+ mpOutDev->getOutDev().DrawLine( aStartPoint, aEndPoint );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawLine( aStartPoint, aEndPoint );
+ }
+ }
+
+ void CanvasHelper::drawBezier( const rendering::XCanvas* ,
+ const geometry::RealBezierSegment2D& aBezierSegment,
+ const geometry::RealPoint2D& _aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, LINE_COLOR );
+
+ const Point& rStartPoint( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.Px,
+ aBezierSegment.Py),
+ viewState, renderState ) );
+ const Point& rCtrlPoint1( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C1x,
+ aBezierSegment.C1y),
+ viewState, renderState ) );
+ const Point& rCtrlPoint2( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C2x,
+ aBezierSegment.C2y),
+ viewState, renderState ) );
+ const Point& rEndPoint( tools::mapRealPoint2D( _aEndPoint,
+ viewState, renderState ) );
+
+ ::Polygon aPoly(4);
+ aPoly.SetPoint( rStartPoint, 0 );
+ aPoly.SetFlags( 0, POLY_NORMAL );
+ aPoly.SetPoint( rCtrlPoint1, 1 );
+ aPoly.SetFlags( 1, POLY_CONTROL );
+ aPoly.SetPoint( rCtrlPoint2, 2 );
+ aPoly.SetFlags( 2, POLY_CONTROL );
+ aPoly.SetPoint( rEndPoint, 3 );
+ aPoly.SetFlags( 3, POLY_NORMAL );
+
+ // TODO(F2): alpha
+ mpOutDev->getOutDev().DrawPolygon( aPoly );
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawPolygon( aPoly );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
+ "polygon is NULL");
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, LINE_COLOR );
+
+ const ::basegfx::B2DPolyPolygon& rPolyPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
+ const PolyPolygon aPolyPoly( tools::mapPolyPolygon( rPolyPoly, viewState, renderState ) );
+
+ if( rPolyPoly.isClosed() )
+ {
+ mpOutDev->getOutDev().DrawPolyPolygon( aPolyPoly );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly );
+ }
+ else
+ {
+ // mixed open/closed state. Cannot render open polygon
+ // via DrawPolyPolygon(), since that implicitley
+ // closed every polygon. OTOH, no need to distinguish
+ // further and render closed polygons via
+ // DrawPolygon(), and open ones via DrawPolyLine():
+ // closed polygons will simply already contain the
+ // closing segment.
+ USHORT nSize( aPolyPoly.Count() );
+
+ for( USHORT i=0; i<nSize; ++i )
+ {
+ mpOutDev->getOutDev().DrawPolyLine( aPolyPoly[i] );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawPolyLine( aPolyPoly[i] );
+ }
+ }
+ }
+
+ // TODO(P1): Provide caching here.
+ 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 )
+ {
+ ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
+ "polygon is NULL");
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState);
+
+ ::basegfx::B2DSize aLinePixelSize(strokeAttributes.StrokeWidth,
+ strokeAttributes.StrokeWidth);
+ aLinePixelSize *= aMatrix;
+
+ ::basegfx::B2DPolyPolygon aPolyPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
+
+ if( aPolyPoly.areControlPointsUsed() )
+ {
+ // AW: Not needed for ApplyLineDashing anymore; should be removed
+ aPolyPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly);
+ }
+
+ // apply dashing, if any
+ if( strokeAttributes.DashArray.getLength() )
+ {
+ const ::std::vector<double>& aDashArray(
+ ::comphelper::sequenceToContainer< ::std::vector<double> >(strokeAttributes.DashArray) );
+
+ ::basegfx::B2DPolyPolygon aDashedPolyPoly;
+
+ for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
+ {
+ // AW: new interface; You may also get gaps in the same run now
+ basegfx::tools::applyLineDashing(aPolyPoly.getB2DPolygon(i), aDashArray, &aDashedPolyPoly);
+ //aDashedPolyPoly.append(
+ // ::basegfx::tools::applyLineDashing( aPolyPoly.getB2DPolygon(i),
+ // aDashArray ) );
+ }
+
+ aPolyPoly = aDashedPolyPoly;
+ }
+
+ ::basegfx::B2DPolyPolygon aStrokedPolyPoly;
+ if( aLinePixelSize.getLength() < 1.42 )
+ {
+ // line width < 1.0 in device pixel, thus, output as a
+ // simple hairline poly-polygon
+ setupOutDevState( viewState, renderState, LINE_COLOR );
+
+ aStrokedPolyPoly = aPolyPoly;
+ }
+ else
+ {
+ // render as a 'thick' line
+ setupOutDevState( viewState, renderState, FILL_COLOR );
+
+ for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
+ {
+ // TODO(F2): Use MiterLimit from StrokeAttributes,
+ // need to convert it here to angle.
+
+ // TODO(F2): Also use Cap settings from
+ // StrokeAttributes, the
+ // createAreaGeometryForLineStartEnd() method does not
+ // seem to fit very well here
+
+ // AW: New interface, will create bezier polygons now
+ aStrokedPolyPoly.append(basegfx::tools::createAreaGeometry(
+ aPolyPoly.getB2DPolygon(i), strokeAttributes.StrokeWidth*0.5, b2DJoineFromJoin(strokeAttributes.JoinType)));
+ //aStrokedPolyPoly.append(
+ // ::basegfx::tools::createAreaGeometryForPolygon( aPolyPoly.getB2DPolygon(i),
+ // strokeAttributes.StrokeWidth*0.5,
+ // b2DJoineFromJoin(strokeAttributes.JoinType) ) );
+ }
+ }
+
+ // transform only _now_, all the StrokeAttributes are in
+ // user coordinates.
+ aStrokedPolyPoly.transform( aMatrix );
+
+ const PolyPolygon aVCLPolyPoly( aStrokedPolyPoly );
+
+ // TODO(F2): When using alpha here, must handle that via
+ // temporary surface or somesuch.
+
+ // Note: the generated stroke poly-polygon is NOT free of
+ // self-intersections. Therefore, if we would render it
+ // via OutDev::DrawPolyPolygon(), on/off fill would
+ // generate off areas on those self-intersections.
+ USHORT nSize( aVCLPolyPoly.Count() );
+
+ for( USHORT i=0; i<nSize; ++i )
+ {
+ if( aStrokedPolyPoly.getB2DPolygon( i ).isClosed() ) {
+ mpOutDev->getOutDev().DrawPolygon( aVCLPolyPoly[i] );
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawPolygon( aVCLPolyPoly[i] );
+ } else {
+ const USHORT nPolySize = aVCLPolyPoly[i].GetSize();
+ if( nPolySize ) {
+ Point rPrevPoint = aVCLPolyPoly[i].GetPoint( 0 );
+ Point rPoint;
+
+ for( USHORT j=1; j<nPolySize; j++ ) {
+ rPoint = aVCLPolyPoly[i].GetPoint( j );
+ mpOutDev->getOutDev().DrawLine( rPrevPoint, rPoint );
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawLine( rPrevPoint, rPoint );
+ rPrevPoint = rPoint;
+ }
+ }
+ }
+ }
+ }
+
+ // 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 >& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& ,
+ const uno::Sequence< rendering::Texture >& ,
+ const rendering::StrokeAttributes& )
+ {
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& ,
+ const uno::Sequence< rendering::Texture >& ,
+ const uno::Reference< geometry::XMapping2D >& ,
+ const rendering::StrokeAttributes& )
+ {
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& ,
+ const rendering::StrokeAttributes& )
+ {
+ 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 )
+ {
+ ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
+ "polygon is NULL");
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ const int nTransparency( setupOutDevState( viewState, renderState, FILL_COLOR ) );
+ const int nTransPercent( (nTransparency * 100 + 128) / 255 ); // normal rounding, no truncation here
+ ::basegfx::B2DPolyPolygon aB2DPolyPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
+ aB2DPolyPoly.setClosed(true); // ensure closed poly, otherwise VCL does not fill
+ const PolyPolygon aPolyPoly( tools::mapPolyPolygon(
+ aB2DPolyPoly,
+ viewState, renderState ) );
+ const bool bSourceAlpha( renderState.CompositeOperation == rendering::CompositeOperation::SOURCE );
+ if( !nTransparency || bSourceAlpha )
+ {
+ mpOutDev->getOutDev().DrawPolyPolygon( aPolyPoly );
+ }
+ else
+ {
+ mpOutDev->getOutDev().DrawTransparent( aPolyPoly, (USHORT)nTransPercent );
+ }
+
+ if( mp2ndOutDev )
+ {
+ if( !nTransparency || bSourceAlpha )
+ {
+ // HACK. Normally, CanvasHelper does not care
+ // about actually what mp2ndOutDev is...
+ if( bSourceAlpha && nTransparency == 255 )
+ {
+ mp2ndOutDev->getOutDev().SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
+ DRAWMODE_WHITEGRADIENT | DRAWMODE_WHITEBITMAP );
+ mp2ndOutDev->getOutDev().SetFillColor( COL_WHITE );
+ mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly );
+ mp2ndOutDev->getOutDev().SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT |
+ DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP );
+ }
+ else
+ {
+ mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly );
+ }
+ }
+ else
+ {
+ mp2ndOutDev->getOutDev().DrawTransparent( aPolyPoly, (USHORT)nTransPercent );
+ }
+ }
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XPolyPolygon2D >& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& ,
+ const uno::Sequence< rendering::Texture >& ,
+ const uno::Reference< geometry::XMapping2D >& )
+ {
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* ,
+ const rendering::FontRequest& fontRequest,
+ const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+ const geometry::Matrix2D& fontMatrix )
+ {
+ if( mpOutDev && mpDevice )
+ {
+ // TODO(F2): font properties and font matrix
+ return uno::Reference< rendering::XCanvasFont >(
+ new CanvasFont(fontRequest, extraFontProperties, fontMatrix,
+ *mpDevice, mpOutDev) );
+ }
+
+ return uno::Reference< rendering::XCanvasFont >();
+ }
+
+ uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* ,
+ const rendering::FontInfo& ,
+ const uno::Sequence< beans::PropertyValue >& )
+ {
+ // TODO(F2)
+ return uno::Sequence< rendering::FontInfo >();
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* ,
+ const rendering::StringContext& text,
+ const uno::Reference< rendering::XCanvasFont >& xFont,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ sal_Int8 textDirection )
+ {
+ ENSURE_ARG_OR_THROW( xFont.is(),
+ "font is NULL");
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ ::Point aOutpos;
+ if( !setupTextOutput( 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
+ mpOutDev->getOutDev().SetLayoutMode( nLayoutMode );
+ mpOutDev->getOutDev().DrawText( aOutpos,
+ text.Text,
+ ::canvas::tools::numeric_cast<USHORT>(text.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(text.Length) );
+
+ if( mp2ndOutDev )
+ {
+ mp2ndOutDev->getOutDev().SetLayoutMode( nLayoutMode );
+ mp2ndOutDev->getOutDev().DrawText( aOutpos,
+ text.Text,
+ ::canvas::tools::numeric_cast<USHORT>(text.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(text.Length) );
+ }
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XTextLayout >& xLayoutedText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_ARG_OR_THROW( xLayoutedText.is(),
+ "layout is NULL");
+
+ TextLayout* pTextLayout = dynamic_cast< TextLayout* >( xLayoutedText.get() );
+
+ if( pTextLayout )
+ {
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ // 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( aOutpos, viewState, renderState, xLayoutedText->getFont() ) )
+ return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary
+
+ // TODO(F2): What about the offset scalings?
+ // TODO(F2): alpha
+ pTextLayout->draw( mpOutDev->getOutDev(), aOutpos, viewState, renderState );
+
+ if( mp2ndOutDev )
+ pTextLayout->draw( mp2ndOutDev->getOutDev(), aOutpos, viewState, renderState );
+ }
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( false,
+ "TextLayout not compatible with this canvas" );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::implDrawBitmap( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ bool bModulateColors )
+ {
+ ENSURE_ARG_OR_THROW( xBitmap.is(),
+ "bitmap is NULL");
+
+ ::canvas::tools::verifyInput( renderState,
+ BOOST_CURRENT_FUNCTION,
+ mpDevice,
+ 4,
+ bModulateColors ? 3 : 0 );
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, IGNORE_COLOR );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState);
+
+ ::basegfx::B2DPoint aOutputPos( 0.0, 0.0 );
+ aOutputPos *= aMatrix;
+
+ BitmapEx aBmpEx( tools::bitmapExFromXBitmap(xBitmap) );
+
+ // TODO(F2): Implement modulation again for other color
+ // channels (currently, works only for alpha). Note: this
+ // is already implemented in transformBitmap()
+ if( bModulateColors &&
+ renderState.DeviceColor.getLength() > 3 )
+ {
+ // optimize away the case where alpha modulation value
+ // is 1.0 - we then simply switch off modulation at all
+ bModulateColors = !::rtl::math::approxEqual(
+ renderState.DeviceColor[3], 1.0);
+ }
+
+ // check whether we can render bitmap as-is: must not
+ // modulate colors, matrix must either be the identity
+ // transform (that's clear), _or_ contain only
+ // translational components.
+ if( !bModulateColors &&
+ (aMatrix.isIdentity() ||
+ (::basegfx::fTools::equalZero( aMatrix.get(0,1) ) &&
+ ::basegfx::fTools::equalZero( aMatrix.get(1,0) ) &&
+ ::rtl::math::approxEqual(aMatrix.get(0,0), 1.0) &&
+ ::rtl::math::approxEqual(aMatrix.get(1,1), 1.0)) ) )
+ {
+ // optimized case: identity matrix, or only
+ // translational components.
+ mpOutDev->getOutDev().DrawBitmapEx( ::vcl::unotools::pointFromB2DPoint( aOutputPos ),
+ aBmpEx );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawBitmapEx( ::vcl::unotools::pointFromB2DPoint( aOutputPos ),
+ aBmpEx );
+
+ // Returning a cache object is not useful, the XBitmap
+ // itself serves this purpose
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+ else
+ {
+ // Matrix contains non-trivial transformation (or
+ // color modulation is requested), decompose to check
+ // whether GraphicObject suffices
+ ::basegfx::B2DVector aScale;
+ double nRotate;
+ double nShearX;
+ aMatrix.decompose( aScale, aOutputPos, nRotate, nShearX );
+
+ GraphicAttr aGrfAttr;
+ GraphicObjectSharedPtr pGrfObj;
+
+ ::Size aBmpSize( aBmpEx.GetSizePixel() );
+
+ // setup alpha modulation
+ if( bModulateColors )
+ {
+ const double nAlphaModulation( renderState.DeviceColor[3] );
+
+ // TODO(F1): Note that the GraphicManager has a
+ // subtle difference in how it calculates the
+ // resulting alpha value: it's using the inverse
+ // alpha values (i.e. 'transparency'), and
+ // calculates transOrig + transModulate, instead
+ // of transOrig + transModulate -
+ // transOrig*transModulate (which would be
+ // equivalent to the origAlpha*modulateAlpha the
+ // DX canvas performs)
+ aGrfAttr.SetTransparency(
+ static_cast< BYTE >(
+ ::basegfx::fround( 255.0*( 1.0 - nAlphaModulation ) ) ) );
+ }
+
+ if( ::basegfx::fTools::equalZero( nShearX ) )
+ {
+ // no shear, GraphicObject is enough (the
+ // GraphicObject only supports scaling, rotation
+ // and translation)
+
+ // #i75339# don't apply mirror flags, having
+ // negative size values is enough to make
+ // GraphicObject flip the bitmap
+
+ // The angle has to be mapped from radian to tenths of
+ // degress with the orientation reversed: [0,2Pi) ->
+ // (3600,0]. Note that the original angle may have
+ // values outside the [0,2Pi) interval.
+ const double nAngleInTenthOfDegrees (3600.0 - nRotate * 3600.0 / (2*M_PI));
+ aGrfAttr.SetRotation( static_cast< USHORT >(::basegfx::fround(nAngleInTenthOfDegrees)) );
+
+ pGrfObj.reset( new GraphicObject( aBmpEx ) );
+ }
+ else
+ {
+ // modify output position, to account for the fact
+ // that transformBitmap() always normalizes its output
+ // bitmap into the smallest enclosing box.
+ ::basegfx::B2DRectangle aDestRect;
+ ::canvas::tools::calcTransformedRectBounds( aDestRect,
+ ::basegfx::B2DRectangle(0,
+ 0,
+ aBmpSize.Width(),
+ aBmpSize.Height()),
+ aMatrix );
+
+ aOutputPos.setX( aDestRect.getMinX() );
+ aOutputPos.setY( aDestRect.getMinY() );
+
+ // complex transformation, use generic affine bitmap
+ // transformation
+ aBmpEx = tools::transformBitmap( aBmpEx,
+ aMatrix,
+ renderState.DeviceColor,
+ tools::MODULATE_NONE );
+
+ pGrfObj.reset( new GraphicObject( aBmpEx ) );
+
+ // clear scale values, generated bitmap already
+ // contains scaling
+ aScale.setX( 1.0 ); aScale.setY( 1.0 );
+
+ // update bitmap size, bitmap has changed above.
+ aBmpSize = aBmpEx.GetSizePixel();
+ }
+
+ // output GraphicObject
+ const ::Point aPt( ::vcl::unotools::pointFromB2DPoint( aOutputPos ) );
+ const ::Size aSz( ::basegfx::fround( aScale.getX() * aBmpSize.Width() ),
+ ::basegfx::fround( aScale.getY() * aBmpSize.Height() ) );
+
+ pGrfObj->Draw( &mpOutDev->getOutDev(),
+ aPt,
+ aSz,
+ &aGrfAttr );
+
+ if( mp2ndOutDev )
+ pGrfObj->Draw( &mp2ndOutDev->getOutDev(),
+ aPt,
+ aSz,
+ &aGrfAttr );
+
+ // created GraphicObject, which possibly cached
+ // display bitmap - return cache object, to retain
+ // that information.
+ return uno::Reference< rendering::XCachedPrimitive >(
+ new CachedBitmap( pGrfObj,
+ aPt,
+ aSz,
+ aGrfAttr,
+ viewState,
+ renderState,
+ // cast away const, need to
+ // change refcount (as this is
+ // ~invisible to client code,
+ // still logically const)
+ const_cast< rendering::XCanvas* >(pCanvas)) );
+ }
+ }
+
+ // Nothing rendered
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return implDrawBitmap( pCanvas,
+ xBitmap,
+ viewState,
+ renderState,
+ false );
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ return implDrawBitmap( pCanvas,
+ xBitmap,
+ viewState,
+ renderState,
+ true );
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+ {
+ // cast away const, need to change refcount (as this is
+ // ~invisible to client code, still logically const)
+ return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+ }
+
+ void CanvasHelper::copyRect( const rendering::XCanvas* ,
+ const uno::Reference< rendering::XBitmapCanvas >& ,
+ const geometry::RealRectangle2D& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& ,
+ const geometry::RealRectangle2D& ,
+ const rendering::ViewState& ,
+ const rendering::RenderState& )
+ {
+ // TODO(F1)
+ }
+
+ geometry::IntegerSize2D CanvasHelper::getSize()
+ {
+ if( !mpOutDev.get() )
+ return geometry::IntegerSize2D(); // we're disposed
+
+ return ::vcl::unotools::integerSize2DFromSize( mpOutDev->getOutDev().GetOutputSizePixel() );
+ }
+
+ uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
+ sal_Bool beFast )
+ {
+ if( !mpOutDev.get() || !mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ rOutDev.EnableMapMode( FALSE );
+
+ // TODO(F2): Support alpha vdev canvas here
+ const Point aEmptyPoint(0,0);
+ const Size aBmpSize( rOutDev.GetOutputSizePixel() );
+
+ Bitmap aBitmap( rOutDev.GetBitmap(aEmptyPoint, aBmpSize) );
+
+ aBitmap.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize),
+ beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE );
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap( aBitmap, *mpDevice, mpOutDev ) );
+ }
+
+ uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if( !mpOutDev.get() )
+ return uno::Sequence< sal_Int8 >(); // we're disposed
+
+ rLayout = getMemoryLayout();
+
+ // TODO(F2): Support alpha canvas here
+ const Rectangle aRect( ::vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ rOutDev.EnableMapMode( FALSE );
+
+ Bitmap aBitmap( rOutDev.GetBitmap(aRect.TopLeft(),
+ aRect.GetSize()) );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "Could not acquire read access to OutDev bitmap" );
+
+ const sal_Int32 nWidth( rect.X2 - rect.X1 );
+ const sal_Int32 nHeight( rect.Y2 - rect.Y1 );
+
+ rLayout.ScanLines = nHeight;
+ rLayout.ScanLineBytes = nWidth*4;
+ rLayout.ScanLineStride = rLayout.ScanLineBytes;
+
+ uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight );
+ sal_Int8* pRes = aRes.getArray();
+
+ int nCurrPos(0);
+ for( int y=0; y<nHeight; ++y )
+ {
+ for( int x=0; x<nWidth; ++x )
+ {
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
+ pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
+ pRes[ nCurrPos++ ] = -1;
+ }
+ }
+
+ return aRes;
+ }
+
+ void CanvasHelper::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& aLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if( !mpOutDev.get() )
+ return; // we're disposed
+
+ const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
+ ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != aLayout.PlaneStride ||
+ aRefLayout.ColorSpace != aLayout.ColorSpace ||
+ aRefLayout.Palette != aLayout.Palette ||
+ aRefLayout.IsMsbFirst != aLayout.IsMsbFirst,
+ "Mismatching memory layout" );
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ rOutDev.EnableMapMode( FALSE );
+
+ const Rectangle aRect( ::vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
+ const USHORT nBitCount( ::std::min( (USHORT)24U,
+ (USHORT)rOutDev.GetBitCount() ) );
+ const BitmapPalette* pPalette = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ // TODO(Q1): Extract this to a common place, e.g. GraphicDevice
+
+ // try to determine palette from output device (by
+ // extracting a 1,1 bitmap, and querying it)
+ const Point aEmptyPoint;
+ const Size aSize(1,1);
+ Bitmap aTmpBitmap( rOutDev.GetBitmap( aEmptyPoint,
+ aSize ) );
+
+ ScopedBitmapReadAccess pReadAccess( aTmpBitmap.AcquireReadAccess(),
+ aTmpBitmap );
+
+ pPalette = &pReadAccess->GetPalette();
+ }
+
+ // TODO(F2): Support alpha canvas here
+ Bitmap aBitmap( aRect.GetSize(), nBitCount, pPalette );
+
+ bool bCopyBack( false ); // only copy something back, if we
+ // actually changed some pixel
+ {
+ ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
+ aBitmap );
+
+ ENSURE_OR_THROW( pWriteAccess.get() != NULL,
+ "Could not acquire write access to OutDev bitmap" );
+
+ // for the time being, always read as RGB
+ const sal_Int32 nWidth( rect.X2 - rect.X1 );
+ const sal_Int32 nHeight( rect.Y2 - rect.Y1 );
+ int x, y, nCurrPos(0);
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pWriteAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ *pScan++ = (BYTE)pWriteAccess->GetBestPaletteIndex(
+ BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+
+ nCurrPos += 4;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ *pScan++ = data[ nCurrPos+2 ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos ];
+
+ nCurrPos += 4;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_RGB:
+ {
+ Scanline pScan = pWriteAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ *pScan++ = data[ nCurrPos ];
+ *pScan++ = data[ nCurrPos+1 ];
+ *pScan++ = data[ nCurrPos+2 ];
+
+ nCurrPos += 4;
+ }
+ }
+ break;
+
+ default:
+ {
+ for( x=0; x<nWidth; ++x )
+ {
+ pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ],
+ data[ nCurrPos+1 ],
+ data[ nCurrPos+2 ] ) );
+ nCurrPos += 4;
+ }
+ }
+ break;
+ }
+ }
+
+ bCopyBack = true;
+ }
+
+ // copy back only here, since the BitmapAccessors must be
+ // destroyed beforehand
+ if( bCopyBack )
+ {
+ // TODO(F2): Support alpha canvas here
+ rOutDev.DrawBitmap(aRect.TopLeft(), aBitmap);
+ }
+ }
+
+ void CanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if( !mpOutDev.get() )
+ return; // we're disposed
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ rOutDev.EnableMapMode( FALSE );
+
+ const Size aBmpSize( rOutDev.GetOutputSizePixel() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
+ "X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
+ "Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "not enough color components" );
+
+ const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
+ ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
+ aRefLayout.ColorSpace != rLayout.ColorSpace ||
+ aRefLayout.Palette != rLayout.Palette ||
+ aRefLayout.IsMsbFirst != rLayout.IsMsbFirst,
+ "Mismatching memory layout" );
+
+ // TODO(F2): Support alpha canvas here
+ rOutDev.DrawPixel( ::vcl::unotools::pointFromIntegerPoint2D( pos ),
+ ::canvas::tools::stdIntSequenceToColor( color ));
+ }
+
+ uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& rLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if( !mpOutDev.get() )
+ return uno::Sequence< sal_Int8 >(); // we're disposed
+
+ rLayout = getMemoryLayout();
+ rLayout.ScanLines = 1;
+ rLayout.ScanLineBytes = 4;
+ rLayout.ScanLineStride = rLayout.ScanLineBytes;
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ rOutDev.EnableMapMode( FALSE );
+
+ const Size aBmpSize( rOutDev.GetOutputSizePixel() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
+ "X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
+ "Y coordinate out of bounds" );
+
+ // TODO(F2): Support alpha canvas here
+ return ::canvas::tools::colorToStdIntSequence(
+ rOutDev.GetPixel(
+ ::vcl::unotools::pointFromIntegerPoint2D( pos )));
+ }
+
+ rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout()
+ {
+ if( !mpOutDev.get() )
+ return rendering::IntegerBitmapLayout(); // we're disposed
+
+ return ::canvas::tools::getStdMemoryLayout(getSize());
+ }
+
+ int CanvasHelper::setupOutDevState( const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ ColorType eColorType ) const
+ {
+ ENSURE_OR_THROW( mpOutDev.get(),
+ "outdev null. Are we disposed?" );
+
+ ::canvas::tools::verifyInput( renderState,
+ BOOST_CURRENT_FUNCTION,
+ mpDevice,
+ 2,
+ eColorType == IGNORE_COLOR ? 0 : 3 );
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+ OutputDevice* p2ndOutDev = NULL;
+
+ rOutDev.EnableMapMode( FALSE );
+
+ if( mp2ndOutDev )
+ p2ndOutDev = &mp2ndOutDev->getOutDev();
+
+ 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( REGION_NULL );
+
+ 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 ) );
+ }
+ else
+ {
+ // clip polygon is empty
+ aClipRegion.SetEmpty();
+ }
+ }
+
+ 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 ) );
+ 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.IsNull() )
+ {
+ rOutDev.SetClipRegion();
+
+ if( p2ndOutDev )
+ p2ndOutDev->SetClipRegion();
+ }
+ else
+ {
+ rOutDev.SetClipRegion( aClipRegion );
+
+ if( p2ndOutDev )
+ p2ndOutDev->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();
+
+ if( p2ndOutDev )
+ {
+ p2ndOutDev->SetLineColor( aColor );
+ p2ndOutDev->SetFillColor();
+ }
+ break;
+
+ case FILL_COLOR:
+ rOutDev.SetFillColor( aColor );
+ rOutDev.SetLineColor();
+
+ if( p2ndOutDev )
+ {
+ p2ndOutDev->SetFillColor( aColor );
+ p2ndOutDev->SetLineColor();
+ }
+ break;
+
+ case TEXT_COLOR:
+ rOutDev.SetTextColor( aColor );
+
+ if( p2ndOutDev )
+ p2ndOutDev->SetTextColor( aColor );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "Unexpected color type");
+ break;
+ }
+ }
+
+ return nTransparency;
+ }
+
+ bool CanvasHelper::setupTextOutput( ::Point& o_rOutPos,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Reference< rendering::XCanvasFont >& xFont ) const
+ {
+ ENSURE_OR_THROW( mpOutDev.get(),
+ "outdev null. Are we disposed?" );
+
+ setupOutDevState( viewState, renderState, TEXT_COLOR );
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ ::Font aVCLFont;
+
+ CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
+
+ ENSURE_ARG_OR_THROW( pFont,
+ "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( !tools::setupFontTransform( o_rOutPos, aVCLFont, viewState, renderState, rOutDev ) )
+ return false;
+
+ rOutDev.SetFont( aVCLFont );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().SetFont( aVCLFont );
+
+ return true;
+ }
+
+ bool CanvasHelper::repaint( const GraphicObjectSharedPtr& rGrf,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const
+ {
+ ENSURE_OR_RETURN_FALSE( rGrf,
+ "Invalid Graphic" );
+
+ if( !mpOutDev )
+ return false; // disposed
+ else
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+ setupOutDevState( viewState, renderState, IGNORE_COLOR );
+
+ if( !rGrf->Draw( &mpOutDev->getOutDev(), rPt, rSz, &rAttr ) )
+ return false;
+
+ // #i80779# Redraw also into mask outdev
+ if( mp2ndOutDev )
+ return rGrf->Draw( &mp2ndOutDev->getOutDev(), rPt, rSz, &rAttr );
+
+ return true;
+ }
+ }
+
+ void CanvasHelper::flush() const
+ {
+ if( mpOutDev && mpOutDev->getOutDev().GetOutDevType() == OUTDEV_WINDOW )
+ {
+ // TODO(Q3): Evil downcast. And what's more, Window::Flush is
+ // not even const. Wah.
+ static_cast<Window&>(mpOutDev->getOutDev()).Flush();
+ }
+
+ if( mp2ndOutDev && mp2ndOutDev->getOutDev().GetOutDevType() == OUTDEV_WINDOW )
+ {
+ // TODO(Q3): Evil downcast. And what's more, Window::Flush is
+ // not even const. Wah.
+ static_cast<Window&>(mp2ndOutDev->getOutDev()).Flush();
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvashelper.hxx b/canvas/source/vcl/canvashelper.hxx
new file mode 100644
index 000000000000..a54491ca256e
--- /dev/null
+++ b/canvas/source/vcl/canvashelper.hxx
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_CANVASHELPER_HXX_
+#define _VCLCANVAS_CANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <vcl/outdev.hxx>
+
+#include <canvas/vclwrapper.hxx>
+
+#include "cachedbitmap.hxx"
+#include "outdevprovider.hxx"
+
+#include <boost/utility.hpp>
+
+
+namespace vclcanvas
+{
+ class SpriteCanvas;
+
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ OutputDevice to render into.
+ */
+ class CanvasHelper : private ::boost::noncopyable
+ {
+ public:
+ /** Create canvas helper
+ */
+ CanvasHelper();
+
+ /// Release all references
+ void disposing();
+
+ /** Initialize canvas helper
+
+ This method late-initializes the canvas helper, providing
+ it with the necessary device and output objects. Note that
+ the CanvasHelper does <em>not</em> take ownership of the
+ passed rDevice reference, nor does it perform any
+ reference counting. Thus, to prevent the reference counted
+ SpriteCanvas object from deletion, the user of this class
+ is responsible for holding ref-counted references itself!
+
+ @param rDevice
+ Reference device this canvas is associated with
+
+ @param rOutDev
+ Set primary output device for this canvas. That's where
+ all content is output to.
+
+ @param bProtect
+ When true, all output operations preserve outdev
+ state. When false, outdev state might change at any time.
+
+ @param bHaveAlpha
+ When true, hasAlpha() will always return true, otherwise, false.
+ */
+ void init( ::com::sun::star::rendering::XGraphicDevice& rDevice,
+ const OutDevProviderSharedPtr& rOutDev,
+ bool bProtect,
+ bool bHaveAlpha );
+
+ /** Set primary output device
+
+ This changes the primary output device, where rendering is
+ sent to.
+ */
+ void setOutDev( const OutDevProviderSharedPtr& rOutDev,
+ bool bProtect);
+
+ /** Set secondary output device
+
+ Used for sprites, to generate mask bitmap.
+ */
+ void setBackgroundOutDev( const OutDevProviderSharedPtr& rOutDev );
+
+
+ // 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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 >
+ createFont( const ::com::sun::star::rendering::XCanvas* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ 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* rCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmapCanvas >& sourceCanvas,
+ const ::com::sun::star::geometry::RealRectangle2D& sourceRect,
+ const ::com::sun::star::rendering::ViewState& sourceViewState,
+ const ::com::sun::star::rendering::RenderState& sourceRenderState,
+ const ::com::sun::star::geometry::RealRectangle2D& destRect,
+ const ::com::sun::star::rendering::ViewState& destViewState,
+ const ::com::sun::star::rendering::RenderState& destRenderState );
+
+ ::com::sun::star::geometry::IntegerSize2D getSize();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > queryBitmapCanvas();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap >
+ getScaledBitmap( const ::com::sun::star::geometry::RealSize2D& newSize,
+ sal_Bool beFast );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getData( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setData( const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setPixel( const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getPixel( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::rendering::IntegerBitmapLayout getMemoryLayout();
+
+ /// Repaint a cached bitmap
+ bool repaint( const GraphicObjectSharedPtr& rGrf,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const;
+
+ /** Flush drawing queue.
+
+ This only works for Window canvases, and ensures that all
+ pending render operations are flushed to the
+ driver/hardware.
+ */
+ void flush() const;
+
+ enum ColorType
+ {
+ LINE_COLOR, FILL_COLOR, TEXT_COLOR, IGNORE_COLOR
+ };
+
+ // returns transparency of color
+ int setupOutDevState( const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ ColorType eColorType ) const;
+
+ /** Called from XCanvas base classes, to notify that content
+ is _about_ to change
+ */
+ void modifying() {}
+
+ bool hasAlpha() const { return mbHaveAlpha; }
+
+ protected:
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for spritecanvas.
+ */
+ ::com::sun::star::rendering::XGraphicDevice* mpDevice;
+
+ /// Rendering to this outdev preserves its state
+ OutDevProviderSharedPtr mpProtectedOutDev;
+
+ /// Rendering to this outdev does not preserve its state
+ OutDevProviderSharedPtr mpOutDev;
+
+ /// Rendering to this outdev does not preserve its state
+ OutDevProviderSharedPtr mp2ndOutDev;
+
+ /// When true, content is able to represent alpha
+ bool mbHaveAlpha;
+
+ private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ implDrawBitmap( const ::com::sun::star::rendering::XCanvas* rCanvas,
+ 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,
+ bool bModulateColors );
+
+ bool setupTextOutput( ::Point& o_rOutPos,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont >& xFont ) const;
+
+ };
+}
+
+#endif /* _VCLCANVAS_CANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/canvashelper_texturefill.cxx b/canvas/source/vcl/canvashelper_texturefill.cxx
new file mode 100644
index 000000000000..a616ec7c6a9e
--- /dev/null
+++ b/canvas/source/vcl/canvashelper_texturefill.cxx
@@ -0,0 +1,1185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/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/virdev.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/tools.hxx>
+#include <basegfx/tools/lerp.hxx>
+#include <basegfx/tools/keystoplerp.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <comphelper/sequence.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <canvas/parametricpolypolygon.hxx>
+
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include "spritecanvas.hxx"
+#include "canvashelper.hxx"
+#include "impltools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ 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;
+ }
+
+
+ /** Fill linear or axial gradient
+
+ Since most of the code for linear and axial gradients are
+ the same, we've a unified method here
+ */
+ void fillLinearGradient( OutputDevice& rOutDev,
+ const ::basegfx::B2DHomMatrix& rTextureTransform,
+ const ::Rectangle& rBounds,
+ unsigned int nStepCount,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors )
+ {
+ // determine general position of gradient in relation to
+ // the bound rect
+ // =====================================================
+
+ ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
+ ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
+ ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
+ ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
+
+ aLeftTop *= rTextureTransform;
+ aLeftBottom *= rTextureTransform;
+ aRightTop *= rTextureTransform;
+ aRightBottom*= rTextureTransform;
+
+ // calc length of bound rect diagonal
+ const ::basegfx::B2DVector aBoundRectDiagonal(
+ ::vcl::unotools::b2DPointFromPoint( rBounds.TopLeft() ) -
+ ::vcl::unotools::b2DPointFromPoint( rBounds.BottomRight() ) );
+ const double nDiagonalLength( aBoundRectDiagonal.getLength() );
+
+ // create direction of gradient:
+ // _______
+ // | | |
+ // -> | | | ...
+ // | | |
+ // -------
+ ::basegfx::B2DVector aDirection( aRightTop - aLeftTop );
+ aDirection.normalize();
+
+ // now, we potentially have to enlarge our gradient area
+ // atop and below the transformed [0,1]x[0,1] unit rect,
+ // for the gradient to fill the complete bound rect.
+ ::basegfx::tools::infiniteLineFromParallelogram( aLeftTop,
+ aLeftBottom,
+ aRightTop,
+ aRightBottom,
+ ::vcl::unotools::b2DRectangleFromRectangle( rBounds ) );
+
+
+ // render gradient
+ // ===============
+
+ // for linear gradients, it's easy to render
+ // non-overlapping polygons: just split the gradient into
+ // nStepCount small strips. Prepare the strip now.
+
+ // For performance reasons, we create a temporary VCL
+ // polygon here, keep it all the way and only change the
+ // vertex values in the loop below (as ::Polygon is a
+ // pimpl class, creating one every loop turn would really
+ // stress the mem allocator)
+ ::Polygon aTempPoly( static_cast<USHORT>(5) );
+
+ OSL_ENSURE( nStepCount >= 3,
+ "fillLinearGradient(): stepcount smaller than 3" );
+
+
+ // fill initial strip (extending two times the bound rect's
+ // diagonal to the 'left'
+ // ------------------------------------------------------
+
+ // calculate left edge, by moving left edge of the
+ // gradient rect two times the bound rect's diagonal to
+ // the 'left'. Since we postpone actual rendering into the
+ // loop below, we set the _right_ edge here, which will be
+ // readily copied into the left edge in the loop below
+ const ::basegfx::B2DPoint& rPoint1( aLeftTop - 2.0*nDiagonalLength*aDirection );
+ aTempPoly[1] = ::Point( ::basegfx::fround( rPoint1.getX() ),
+ ::basegfx::fround( rPoint1.getY() ) );
+
+ const ::basegfx::B2DPoint& rPoint2( aLeftBottom - 2.0*nDiagonalLength*aDirection );
+ aTempPoly[2] = ::Point( ::basegfx::fround( rPoint2.getX() ),
+ ::basegfx::fround( rPoint2.getY() ) );
+
+
+ // iteratively render all other strips
+ // -----------------------------------
+
+ // ensure that nStepCount matches color stop parity, to
+ // have a well-defined middle color e.g. for axial
+ // gradients.
+ if( (rColors.size() % 2) != (nStepCount % 2) )
+ ++nStepCount;
+
+ basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
+
+ // only iterate nStepCount-1 steps, as the last strip is
+ // explicitely painted below
+ for( unsigned int i=0; i<nStepCount-1; ++i )
+ {
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(double(i)/nStepCount);
+
+ rOutDev.SetFillColor(
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
+
+ // copy right egde of polygon to left edge (and also
+ // copy the closing point)
+ aTempPoly[0] = aTempPoly[4] = aTempPoly[1];
+ aTempPoly[3] = aTempPoly[2];
+
+ // calculate new right edge, from interpolating
+ // between start and end line. Note that i is
+ // increased by one, to account for the fact that we
+ // calculate the right border here (whereas the fill
+ // color is governed by the left edge)
+ const ::basegfx::B2DPoint& rPoint3(
+ (nStepCount - i-1)/double(nStepCount)*aLeftTop +
+ (i+1)/double(nStepCount)*aRightTop );
+ aTempPoly[1] = ::Point( ::basegfx::fround( rPoint3.getX() ),
+ ::basegfx::fround( rPoint3.getY() ) );
+
+ const ::basegfx::B2DPoint& rPoint4(
+ (nStepCount - i-1)/double(nStepCount)*aLeftBottom +
+ (i+1)/double(nStepCount)*aRightBottom );
+ aTempPoly[2] = ::Point( ::basegfx::fround( rPoint4.getX() ),
+ ::basegfx::fround( rPoint4.getY() ) );
+
+ rOutDev.DrawPolygon( aTempPoly );
+ }
+
+ // fill final strip (extending two times the bound rect's
+ // diagonal to the 'right'
+ // ------------------------------------------------------
+
+ // copy right egde of polygon to left edge (and also
+ // copy the closing point)
+ aTempPoly[0] = aTempPoly[4] = aTempPoly[1];
+ aTempPoly[3] = aTempPoly[2];
+
+ // calculate new right edge, by moving right edge of the
+ // gradient rect two times the bound rect's diagonal to
+ // the 'right'.
+ const ::basegfx::B2DPoint& rPoint3( aRightTop + 2.0*nDiagonalLength*aDirection );
+ aTempPoly[0] = aTempPoly[4] = ::Point( ::basegfx::fround( rPoint3.getX() ),
+ ::basegfx::fround( rPoint3.getY() ) );
+
+ const ::basegfx::B2DPoint& rPoint4( aRightBottom + 2.0*nDiagonalLength*aDirection );
+ aTempPoly[3] = ::Point( ::basegfx::fround( rPoint4.getX() ),
+ ::basegfx::fround( rPoint4.getY() ) );
+
+ rOutDev.SetFillColor( rColors.back() );
+
+ rOutDev.DrawPolygon( aTempPoly );
+ }
+
+ void fillPolygonalGradient( OutputDevice& rOutDev,
+ const ::basegfx::B2DHomMatrix& rTextureTransform,
+ const ::Rectangle& rBounds,
+ unsigned int nStepCount,
+ bool bFillNonOverlapping,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors )
+ {
+ const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
+
+ ENSURE_OR_THROW( rGradientPoly.count() > 2,
+ "fillPolygonalGradient(): polygon without area given" );
+
+ // For performance reasons, we create a temporary VCL polygon
+ // here, keep it all the way and only change the vertex values
+ // in the loop below (as ::Polygon is a pimpl class, creating
+ // one every loop turn would really stress the mem allocator)
+ ::basegfx::B2DPolygon aOuterPoly( rGradientPoly );
+ ::basegfx::B2DPolygon aInnerPoly;
+
+ // subdivide polygon _before_ rendering, would otherwise have
+ // to be performed on every loop turn.
+ if( aOuterPoly.areControlPointsUsed() )
+ aOuterPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aOuterPoly);
+
+ aInnerPoly = aOuterPoly;
+
+ // only transform outer polygon _after_ copying it into
+ // aInnerPoly, because inner polygon has to be scaled before
+ // the actual texture transformation takes place
+ aOuterPoly.transform( rTextureTransform );
+
+ // determine overall transformation for inner polygon (might
+ // have to be prefixed by anisotrophic scaling)
+ ::basegfx::B2DHomMatrix aInnerPolygonTransformMatrix;
+
+
+ // apply scaling (possibly anisotrophic) to inner polygon
+ // ------------------------------------------------------
+
+ // scale inner polygon according to aspect ratio: for
+ // wider-than-tall bounds (nAspectRatio > 1.0), the inner
+ // polygon, representing the gradient focus, must have
+ // non-zero width. Specifically, a bound rect twice as wide as
+ // tall has a focus polygon of half it's width.
+ const double nAspectRatio( rValues.mnAspectRatio );
+ if( nAspectRatio > 1.0 )
+ {
+ // width > height case
+ aInnerPolygonTransformMatrix.scale( 1.0 - 1.0/nAspectRatio,
+ 0.0 );
+ }
+ else if( nAspectRatio < 1.0 )
+ {
+ // width < height case
+ aInnerPolygonTransformMatrix.scale( 0.0,
+ 1.0 - nAspectRatio );
+ }
+ else
+ {
+ // isotrophic case
+ aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
+ }
+
+ // and finally, add texture transform to it.
+ aInnerPolygonTransformMatrix *= rTextureTransform;
+
+ // apply final matrix to polygon
+ aInnerPoly.transform( aInnerPolygonTransformMatrix );
+
+
+ const sal_uInt32 nNumPoints( aOuterPoly.count() );
+ ::Polygon aTempPoly( static_cast<USHORT>(nNumPoints+1) );
+
+ // increase number of steps by one: polygonal gradients have
+ // the outermost polygon rendered in rColor2, and the
+ // innermost in rColor1. The innermost polygon will never
+ // have zero area, thus, we must divide the interval into
+ // nStepCount+1 steps. For example, to create 3 steps:
+ //
+ // | |
+ // |-------|-------|-------|
+ // | |
+ // 3 2 1 0
+ //
+ // This yields 4 tick marks, where 0 is never attained (since
+ // zero-area polygons typically don't display perceivable
+ // color).
+ ++nStepCount;
+
+ basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
+
+ if( !bFillNonOverlapping )
+ {
+ // fill background
+ rOutDev.SetFillColor( rColors.front() );
+ rOutDev.DrawRect( rBounds );
+
+ // render polygon
+ // ==============
+
+ for( unsigned int i=1,p; i<nStepCount; ++i )
+ {
+ const double fT( i/double(nStepCount) );
+
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
+ // lerp color
+ rOutDev.SetFillColor(
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
+
+ // scale and render polygon, by interpolating between
+ // outer and inner polygon.
+
+ for( p=0; p<nNumPoints; ++p )
+ {
+ const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
+ const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
+
+ aTempPoly[(USHORT)p] = ::Point(
+ basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
+ basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
+ }
+
+ // close polygon explicitely
+ aTempPoly[(USHORT)p] = aTempPoly[0];
+
+ // TODO(P1): compare with vcl/source/gdi/outdev4.cxx,
+ // OutputDevice::ImplDrawComplexGradient(), there's a note
+ // that on some VDev's, rendering disjunct poly-polygons
+ // is faster!
+ rOutDev.DrawPolygon( aTempPoly );
+ }
+ }
+ else
+ {
+ // render polygon
+ // ==============
+
+ // For performance reasons, we create a temporary VCL polygon
+ // here, keep it all the way and only change the vertex values
+ // in the loop below (as ::Polygon is a pimpl class, creating
+ // one every loop turn would really stress the mem allocator)
+ ::PolyPolygon aTempPolyPoly;
+ ::Polygon aTempPoly2( static_cast<USHORT>(nNumPoints+1) );
+
+ aTempPoly2[0] = rBounds.TopLeft();
+ aTempPoly2[1] = rBounds.TopRight();
+ aTempPoly2[2] = rBounds.BottomRight();
+ aTempPoly2[3] = rBounds.BottomLeft();
+ aTempPoly2[4] = rBounds.TopLeft();
+
+ aTempPolyPoly.Insert( aTempPoly );
+ aTempPolyPoly.Insert( aTempPoly2 );
+
+ for( unsigned int i=0,p; i<nStepCount; ++i )
+ {
+ const double fT( (i+1)/double(nStepCount) );
+
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
+ // lerp color
+ rOutDev.SetFillColor(
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
+
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ if( i && !(i % 10) )
+ rOutDev.SetFillColor( COL_RED );
+#endif
+
+ // scale and render polygon. Note that here, we
+ // calculate the inner polygon, which is actually the
+ // start of the _next_ color strip. Thus, i+1
+
+ for( p=0; p<nNumPoints; ++p )
+ {
+ const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
+ const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
+
+ aTempPoly[(USHORT)p] = ::Point(
+ basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
+ basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
+ }
+
+ // close polygon explicitely
+ aTempPoly[(USHORT)p] = aTempPoly[0];
+
+ // swap inner and outer polygon
+ aTempPolyPoly.Replace( aTempPolyPoly.GetObject( 1 ), 0 );
+
+ if( i+1<nStepCount )
+ {
+ // assign new inner polygon. Note that with this
+ // formulation, the internal pimpl objects for both
+ // temp polygons and the polypolygon remain identical,
+ // minimizing heap accesses (only a Polygon wrapper
+ // object is freed and deleted twice during this swap).
+ aTempPolyPoly.Replace( aTempPoly, 1 );
+ }
+ else
+ {
+ // last, i.e. inner strip. Now, the inner polygon
+ // has zero area anyway, and to not leave holes in
+ // the gradient, finally render a simple polygon:
+ aTempPolyPoly.Remove( 1 );
+ }
+
+ rOutDev.DrawPolyPolygon( aTempPolyPoly );
+ }
+ }
+ }
+
+ void doGradientFill( OutputDevice& rOutDev,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors,
+ const ::basegfx::B2DHomMatrix& rTextureTransform,
+ const ::Rectangle& rBounds,
+ unsigned int nStepCount,
+ bool bFillNonOverlapping )
+ {
+ switch( rValues.meType )
+ {
+ case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
+ fillLinearGradient( rOutDev,
+ rTextureTransform,
+ rBounds,
+ nStepCount,
+ rValues,
+ rColors );
+ break;
+
+ case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
+ // FALLTHROUGH intended
+ case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
+ fillPolygonalGradient( rOutDev,
+ rTextureTransform,
+ rBounds,
+ nStepCount,
+ bFillNonOverlapping,
+ rValues,
+ rColors );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "CanvasHelper::doGradientFill(): Unexpected case" );
+ }
+ }
+
+ int numColorSteps( const ::Color& rColor1, const ::Color& rColor2 )
+ {
+ return ::std::max(
+ labs( rColor1.GetRed() - rColor2.GetRed() ),
+ ::std::max(
+ labs( rColor1.GetGreen() - rColor2.GetGreen() ),
+ labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) );
+ }
+
+ bool gradientFill( OutputDevice& rOutDev,
+ OutputDevice* p2ndOutDev,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors,
+ const PolyPolygon& rPoly,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::Texture& texture,
+ int nTransparency )
+ {
+ (void)nTransparency;
+
+ // TODO(T2): It is maybe necessary to lock here, should
+ // maGradientPoly someday cease to be const. But then, beware of
+ // deadlocks, canvashelper calls this method with locked own
+ // mutex.
+
+ // calc step size
+ // --------------
+ int nColorSteps = 0;
+ for( size_t i=0; i<rColors.size()-1; ++i )
+ nColorSteps += numColorSteps(rColors[i],rColors[i+1]);
+
+ ::basegfx::B2DHomMatrix aTotalTransform;
+ const int nStepCount=
+ ::canvas::tools::calcGradientStepCount(aTotalTransform,
+ viewState,
+ renderState,
+ texture,
+ nColorSteps);
+
+ rOutDev.SetLineColor();
+
+ // determine maximal bound rect of texture-filled
+ // polygon
+ const ::Rectangle aPolygonDeviceRectOrig(
+ rPoly.GetBoundRect() );
+
+ if( tools::isRectangle( rPoly ) )
+ {
+ // use optimized output path
+ // -------------------------
+
+ // this distinction really looks like a
+ // micro-optimisation, but in fact greatly speeds up
+ // especially complex gradients. That's because when using
+ // clipping, we can output polygons instead of
+ // poly-polygons, and don't have to output the gradient
+ // twice for XOR
+
+ rOutDev.Push( PUSH_CLIPREGION );
+ rOutDev.IntersectClipRegion( aPolygonDeviceRectOrig );
+ doGradientFill( rOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ false );
+ rOutDev.Pop();
+
+ if( p2ndOutDev )
+ {
+ p2ndOutDev->Push( PUSH_CLIPREGION );
+ p2ndOutDev->IntersectClipRegion( aPolygonDeviceRectOrig );
+ doGradientFill( *p2ndOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ false );
+ p2ndOutDev->Pop();
+ }
+ }
+ else
+#if defined(QUARTZ) // TODO: other ports should avoid the XOR-trick too (implementation vs. interface!)
+ {
+ const Region aPolyClipRegion( rPoly );
+
+ rOutDev.Push( PUSH_CLIPREGION );
+ rOutDev.SetClipRegion( aPolyClipRegion );
+
+ doGradientFill( rOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ false );
+ rOutDev.Pop();
+
+ if( p2ndOutDev )
+ {
+ p2ndOutDev->Push( PUSH_CLIPREGION );
+ p2ndOutDev->SetClipRegion( aPolyClipRegion );
+ doGradientFill( *p2ndOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ false );
+ p2ndOutDev->Pop();
+ }
+ }
+#else // TODO: remove once doing the XOR-trick in the canvas-layer becomes redundant
+ {
+ // output gradient the hard way: XORing out the polygon
+ rOutDev.Push( PUSH_RASTEROP );
+ rOutDev.SetRasterOp( ROP_XOR );
+ doGradientFill( rOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ true );
+ rOutDev.SetFillColor( COL_BLACK );
+ rOutDev.SetRasterOp( ROP_0 );
+ rOutDev.DrawPolyPolygon( rPoly );
+ rOutDev.SetRasterOp( ROP_XOR );
+ doGradientFill( rOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ true );
+ rOutDev.Pop();
+
+ if( p2ndOutDev )
+ {
+ p2ndOutDev->Push( PUSH_RASTEROP );
+ p2ndOutDev->SetRasterOp( ROP_XOR );
+ doGradientFill( *p2ndOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ true );
+ p2ndOutDev->SetFillColor( COL_BLACK );
+ p2ndOutDev->SetRasterOp( ROP_0 );
+ p2ndOutDev->DrawPolyPolygon( rPoly );
+ p2ndOutDev->SetRasterOp( ROP_XOR );
+ doGradientFill( *p2ndOutDev,
+ rValues,
+ rColors,
+ aTotalTransform,
+ aPolygonDeviceRectOrig,
+ nStepCount,
+ true );
+ p2ndOutDev->Pop();
+ }
+ }
+#endif // complex-clipping vs. XOR-trick
+
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ {
+ ::basegfx::B2DRectangle aRect(0.0, 0.0, 1.0, 1.0);
+ ::basegfx::B2DRectangle aTextureDeviceRect;
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::canvas::tools::calcTransformedRectBounds( aTextureDeviceRect,
+ aRect,
+ aTextureTransform );
+ rOutDev.SetLineColor( COL_RED );
+ rOutDev.SetFillColor();
+ rOutDev.DrawRect( ::vcl::unotools::rectangleFromB2DRectangle( aTextureDeviceRect ) );
+
+ rOutDev.SetLineColor( COL_BLUE );
+ ::Polygon aPoly1(
+ ::vcl::unotools::rectangleFromB2DRectangle( aRect ));
+ ::basegfx::B2DPolygon aPoly2( aPoly1.getB2DPolygon() );
+ aPoly2.transform( aTextureTransform );
+ ::Polygon aPoly3( aPoly2 );
+ rOutDev.DrawPolygon( aPoly3 );
+ }
+#endif
+
+ return true;
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Sequence< rendering::Texture >& textures )
+ {
+ ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillPolyPolygon(): polygon is NULL");
+ ENSURE_ARG_OR_THROW( textures.getLength(),
+ "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
+
+ if( mpOutDev )
+ {
+ tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev );
+
+ const int nTransparency( setupOutDevState( viewState, renderState, IGNORE_COLOR ) );
+ PolyPolygon aPolyPoly( tools::mapPolyPolygon(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon),
+ viewState, renderState ) );
+
+ // TODO(F1): Multi-texturing
+ if( textures[0].Gradient.is() )
+ {
+ // try to cast XParametricPolyPolygon2D reference to
+ // our implementation class.
+ ::canvas::ParametricPolyPolygon* pGradient =
+ dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
+
+ if( pGradient && pGradient->getValues().maColors.getLength() )
+ {
+ // copy state from Gradient polypoly locally
+ // (given object might change!)
+ const ::canvas::ParametricPolyPolygon::Values& rValues(
+ pGradient->getValues() );
+
+ if( rValues.maColors.getLength() < 2 )
+ {
+ rendering::RenderState aTempState=renderState;
+ aTempState.DeviceColor = rValues.maColors[0];
+ fillPolyPolygon(pCanvas, xPolyPolygon, viewState, aTempState);
+ }
+ else
+ {
+ std::vector< ::Color > aColors(rValues.maColors.getLength());
+ std::transform(&rValues.maColors[0],
+ &rValues.maColors[0]+rValues.maColors.getLength(),
+ aColors.begin(),
+ boost::bind(
+ &vcl::unotools::stdColorSpaceSequenceToColor,
+ _1));
+
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ gradientFill( mpOutDev->getOutDev(),
+ mp2ndOutDev.get() ? &mp2ndOutDev->getOutDev() : (OutputDevice*)NULL,
+ rValues,
+ aColors,
+ aPolyPoly,
+ viewState,
+ renderState,
+ textures[0],
+ nTransparency );
+ }
+ }
+ else
+ {
+ // TODO(F1): The generic case is missing here
+ ENSURE_OR_THROW( false,
+ "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered" );
+ }
+ }
+ else if( textures[0].Bitmap.is() )
+ {
+ const geometry::IntegerSize2D aBmpSize( textures[0].Bitmap->getSize() );
+
+ ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 &&
+ aBmpSize.Height != 0,
+ "CanvasHelper::fillTexturedPolyPolygon(): zero-sized texture bitmap" );
+
+ // determine maximal bound rect of texture-filled
+ // polygon
+ const ::Rectangle aPolygonDeviceRect(
+ aPolyPoly.GetBoundRect() );
+
+
+ // first of all, determine whether we have a
+ // drawBitmap() in disguise
+ // =========================================
+
+ const bool bRectangularPolygon( tools::isRectangle( aPolyPoly ) );
+
+ ::basegfx::B2DHomMatrix aTotalTransform;
+ ::canvas::tools::mergeViewAndRenderTransform(aTotalTransform,
+ viewState,
+ renderState);
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+ textures[0].AffineTransform );
+
+ aTotalTransform *= aTextureTransform;
+
+ const ::basegfx::B2DRectangle aRect(0.0, 0.0, 1.0, 1.0);
+ ::basegfx::B2DRectangle aTextureDeviceRect;
+ ::canvas::tools::calcTransformedRectBounds( aTextureDeviceRect,
+ aRect,
+ aTotalTransform );
+
+ const ::Rectangle aIntegerTextureDeviceRect(
+ ::vcl::unotools::rectangleFromB2DRectangle( aTextureDeviceRect ) );
+
+ if( bRectangularPolygon &&
+ aIntegerTextureDeviceRect == aPolygonDeviceRect )
+ {
+ rendering::RenderState aLocalState( renderState );
+ ::canvas::tools::appendToRenderState(aLocalState,
+ aTextureTransform);
+ ::basegfx::B2DHomMatrix aScaleCorrection;
+ aScaleCorrection.scale( 1.0/aBmpSize.Width,
+ 1.0/aBmpSize.Height );
+ ::canvas::tools::appendToRenderState(aLocalState,
+ aScaleCorrection);
+
+ // need alpha modulation?
+ if( !::rtl::math::approxEqual( textures[0].Alpha,
+ 1.0 ) )
+ {
+ // setup alpha modulation values
+ aLocalState.DeviceColor.realloc(4);
+ double* pColor = aLocalState.DeviceColor.getArray();
+ pColor[0] =
+ pColor[1] =
+ pColor[2] = 0.0;
+ pColor[3] = textures[0].Alpha;
+
+ return drawBitmapModulated( pCanvas,
+ textures[0].Bitmap,
+ viewState,
+ aLocalState );
+ }
+ else
+ {
+ return drawBitmap( pCanvas,
+ textures[0].Bitmap,
+ viewState,
+ aLocalState );
+ }
+ }
+ else
+ {
+ // No easy mapping to drawBitmap() - calculate
+ // texturing parameters
+ // ===========================================
+
+ BitmapEx aBmpEx( tools::bitmapExFromXBitmap( textures[0].Bitmap ) );
+
+ // scale down bitmap to [0,1]x[0,1] rect, as required
+ // from the XCanvas interface.
+ ::basegfx::B2DHomMatrix aScaling;
+ ::basegfx::B2DHomMatrix aPureTotalTransform; // pure view*render*texture transform
+ aScaling.scale( 1.0/aBmpSize.Width,
+ 1.0/aBmpSize.Height );
+
+ aTotalTransform = aTextureTransform * aScaling;
+ aPureTotalTransform = aTextureTransform;
+
+ // combine with view and render transform
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState);
+
+ // combine all three transformations into one
+ // global texture-to-device-space transformation
+ aTotalTransform *= aMatrix;
+ aPureTotalTransform *= aMatrix;
+
+ // analyze transformation, and setup an
+ // appropriate GraphicObject
+ ::basegfx::B2DVector aScale;
+ ::basegfx::B2DPoint aOutputPos;
+ double nRotate;
+ double nShearX;
+ aTotalTransform.decompose( aScale, aOutputPos, nRotate, nShearX );
+
+ GraphicAttr aGrfAttr;
+ GraphicObjectSharedPtr pGrfObj;
+
+ if( ::basegfx::fTools::equalZero( nShearX ) )
+ {
+ // no shear, GraphicObject is enough (the
+ // GraphicObject only supports scaling, rotation
+ // and translation)
+
+ // setup GraphicAttr
+ aGrfAttr.SetMirrorFlags(
+ ( aScale.getX() < 0.0 ? BMP_MIRROR_HORZ : 0 ) |
+ ( aScale.getY() < 0.0 ? BMP_MIRROR_VERT : 0 ) );
+ aGrfAttr.SetRotation( static_cast< USHORT >(::basegfx::fround( nRotate*10.0 )) );
+
+ pGrfObj.reset( new GraphicObject( aBmpEx ) );
+ }
+ else
+ {
+ // complex transformation, use generic affine bitmap
+ // transformation
+ aBmpEx = tools::transformBitmap( aBmpEx,
+ aTotalTransform,
+ uno::Sequence< double >(),
+ tools::MODULATE_NONE);
+
+ pGrfObj.reset( new GraphicObject( aBmpEx ) );
+
+ // clear scale values, generated bitmap already
+ // contains scaling
+ aScale.setX( 0.0 ); aScale.setY( 0.0 );
+ }
+
+
+ // render texture tiled into polygon
+ // =================================
+
+ // calc device space direction vectors. We employ
+ // the followin approach for tiled output: the
+ // texture bitmap is output in texture space
+ // x-major order, i.e. tile neighbors in texture
+ // space x direction are rendered back-to-back in
+ // device coordinate space (after the full device
+ // transformation). Thus, the aNextTile* vectors
+ // denote the output position updates in device
+ // space, to get from one tile to the next.
+ ::basegfx::B2DVector aNextTileX( 1.0, 0.0 );
+ ::basegfx::B2DVector aNextTileY( 0.0, 1.0 );
+ aNextTileX *= aPureTotalTransform;
+ aNextTileY *= aPureTotalTransform;
+
+ ::basegfx::B2DHomMatrix aInverseTextureTransform( aPureTotalTransform );
+
+ ENSURE_ARG_OR_THROW( aInverseTextureTransform.isInvertible(),
+ "CanvasHelper::fillTexturedPolyPolygon(): singular texture matrix" );
+
+ aInverseTextureTransform.invert();
+
+ // calc bound rect of extended texture area in
+ // device coordinates. Therefore, we first calc
+ // the area of the polygon bound rect in texture
+ // space. To maintain texture phase, this bound
+ // rect is then extended to integer coordinates
+ // (extended, because shrinking might leave some
+ // inner polygon areas unfilled).
+ // Finally, the bound rect is transformed back to
+ // device coordinate space, were we determine the
+ // start point from it.
+ ::basegfx::B2DRectangle aTextureSpacePolygonRect;
+ ::canvas::tools::calcTransformedRectBounds( aTextureSpacePolygonRect,
+ ::vcl::unotools::b2DRectangleFromRectangle(
+ aPolygonDeviceRect ),
+ aInverseTextureTransform );
+
+ // calc left, top of extended polygon rect in
+ // texture space, create one-texture instance rect
+ // from it (i.e. rect from start point extending
+ // 1.0 units to the right and 1.0 units to the
+ // bottom). Note that the rounding employed here
+ // is a bit subtle, since we need to round up/down
+ // as _soon_ as any fractional amount is
+ // encountered. This is to ensure that the full
+ // polygon area is filled with texture tiles.
+ const sal_Int32 nX1( ::canvas::tools::roundDown( aTextureSpacePolygonRect.getMinX() ) );
+ const sal_Int32 nY1( ::canvas::tools::roundDown( aTextureSpacePolygonRect.getMinY() ) );
+ const sal_Int32 nX2( ::canvas::tools::roundUp( aTextureSpacePolygonRect.getMaxX() ) );
+ const sal_Int32 nY2( ::canvas::tools::roundUp( aTextureSpacePolygonRect.getMaxY() ) );
+ const ::basegfx::B2DRectangle aSingleTextureRect(
+ nX1, nY1,
+ nX1 + 1.0,
+ nY1 + 1.0 );
+
+ // and convert back to device space
+ ::basegfx::B2DRectangle aSingleDeviceTextureRect;
+ ::canvas::tools::calcTransformedRectBounds( aSingleDeviceTextureRect,
+ aSingleTextureRect,
+ aPureTotalTransform );
+
+ const ::Point aPtRepeat( ::vcl::unotools::pointFromB2DPoint(
+ aSingleDeviceTextureRect.getMinimum() ) );
+ const ::Size aSz( ::basegfx::fround( aScale.getX() * aBmpSize.Width ),
+ ::basegfx::fround( aScale.getY() * aBmpSize.Height ) );
+ const ::Size aIntegerNextTileX( ::vcl::unotools::sizeFromB2DSize(aNextTileX) );
+ const ::Size aIntegerNextTileY( ::vcl::unotools::sizeFromB2DSize(aNextTileY) );
+
+ const ::Point aPt( textures[0].RepeatModeX == rendering::TexturingMode::NONE ?
+ ::basegfx::fround( aOutputPos.getX() ) : aPtRepeat.X(),
+ textures[0].RepeatModeY == rendering::TexturingMode::NONE ?
+ ::basegfx::fround( aOutputPos.getY() ) : aPtRepeat.Y() );
+ const sal_Int32 nTilesX( textures[0].RepeatModeX == rendering::TexturingMode::NONE ?
+ 1 : nX2 - nX1 );
+ const sal_Int32 nTilesY( textures[0].RepeatModeX == rendering::TexturingMode::NONE ?
+ 1 : nY2 - nY1 );
+
+ OutputDevice& rOutDev( mpOutDev->getOutDev() );
+
+ if( bRectangularPolygon )
+ {
+ // use optimized output path
+ // -------------------------
+
+ // this distinction really looks like a
+ // micro-optimisation, but in fact greatly speeds up
+ // especially complex fills. That's because when using
+ // clipping, we can output polygons instead of
+ // poly-polygons, and don't have to output the gradient
+ // twice for XOR
+
+ // setup alpha modulation
+ if( !::rtl::math::approxEqual( textures[0].Alpha,
+ 1.0 ) )
+ {
+ // TODO(F1): Note that the GraphicManager has
+ // a subtle difference in how it calculates
+ // the resulting alpha value: it's using the
+ // inverse alpha values (i.e. 'transparency'),
+ // and calculates transOrig + transModulate,
+ // instead of transOrig + transModulate -
+ // transOrig*transModulate (which would be
+ // equivalent to the origAlpha*modulateAlpha
+ // the DX canvas performs)
+ aGrfAttr.SetTransparency(
+ static_cast< BYTE >(
+ ::basegfx::fround( 255.0*( 1.0 - textures[0].Alpha ) ) ) );
+ }
+
+ rOutDev.IntersectClipRegion( aPolygonDeviceRect );
+ textureFill( rOutDev,
+ *pGrfObj,
+ aPt,
+ aIntegerNextTileX,
+ aIntegerNextTileY,
+ nTilesX,
+ nTilesY,
+ aSz,
+ aGrfAttr );
+
+ if( mp2ndOutDev )
+ {
+ OutputDevice& r2ndOutDev( mp2ndOutDev->getOutDev() );
+ r2ndOutDev.IntersectClipRegion( aPolygonDeviceRect );
+ textureFill( r2ndOutDev,
+ *pGrfObj,
+ aPt,
+ aIntegerNextTileX,
+ aIntegerNextTileY,
+ nTilesX,
+ nTilesY,
+ aSz,
+ aGrfAttr );
+ }
+ }
+ else
+ {
+ // output texture the hard way: XORing out the
+ // polygon
+ // ===========================================
+
+ if( !::rtl::math::approxEqual( textures[0].Alpha,
+ 1.0 ) )
+ {
+ // uh-oh. alpha blending is required,
+ // cannot do direct XOR, but have to
+ // prepare the filled polygon within a
+ // VDev
+ VirtualDevice aVDev( rOutDev );
+ aVDev.SetOutputSizePixel( aPolygonDeviceRect.GetSize() );
+
+ // shift output to origin of VDev
+ const ::Point aOutPos( aPt - aPolygonDeviceRect.TopLeft() );
+ aPolyPoly.Translate( ::Point( -aPolygonDeviceRect.Left(),
+ -aPolygonDeviceRect.Top() ) );
+
+ const Region aPolyClipRegion( aPolyPoly );
+
+ aVDev.SetClipRegion( aPolyClipRegion );
+ textureFill( aVDev,
+ *pGrfObj,
+ aOutPos,
+ aIntegerNextTileX,
+ aIntegerNextTileY,
+ nTilesX,
+ nTilesY,
+ aSz,
+ aGrfAttr );
+
+ // output VDev content alpha-blended to
+ // target position.
+ const ::Point aEmptyPoint;
+ Bitmap aContentBmp(
+ aVDev.GetBitmap( aEmptyPoint,
+ aVDev.GetOutputSizePixel() ) );
+
+ BYTE nCol( static_cast< BYTE >(
+ ::basegfx::fround( 255.0*( 1.0 - textures[0].Alpha ) ) ) );
+ AlphaMask aAlpha( aVDev.GetOutputSizePixel(),
+ &nCol );
+
+ BitmapEx aOutputBmpEx( aContentBmp, aAlpha );
+ rOutDev.DrawBitmapEx( aPolygonDeviceRect.TopLeft(),
+ aOutputBmpEx );
+
+ if( mp2ndOutDev )
+ mp2ndOutDev->getOutDev().DrawBitmapEx( aPolygonDeviceRect.TopLeft(),
+ aOutputBmpEx );
+ }
+ else
+ {
+ const Region aPolyClipRegion( aPolyPoly );
+
+ rOutDev.Push( PUSH_CLIPREGION );
+ rOutDev.SetClipRegion( aPolyClipRegion );
+
+ textureFill( rOutDev,
+ *pGrfObj,
+ aPt,
+ aIntegerNextTileX,
+ aIntegerNextTileY,
+ nTilesX,
+ nTilesY,
+ aSz,
+ aGrfAttr );
+ rOutDev.Pop();
+
+ if( mp2ndOutDev )
+ {
+ OutputDevice& r2ndOutDev( mp2ndOutDev->getOutDev() );
+ r2ndOutDev.Push( PUSH_CLIPREGION );
+
+ r2ndOutDev.SetClipRegion( aPolyClipRegion );
+ textureFill( r2ndOutDev,
+ *pGrfObj,
+ aPt,
+ aIntegerNextTileX,
+ aIntegerNextTileY,
+ nTilesX,
+ nTilesY,
+ aSz,
+ aGrfAttr );
+ r2ndOutDev.Pop();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/devicehelper.cxx b/canvas/source/vcl/devicehelper.cxx
new file mode 100644
index 000000000000..3994517d74e4
--- /dev/null
+++ b/canvas/source/vcl/devicehelper.cxx
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/canvastools.hxx>
+
+#include <rtl/instance.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/canvastools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include "devicehelper.hxx"
+#include "spritecanvas.hxx"
+#include "spritecanvashelper.hxx"
+#include "canvasbitmap.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ DeviceHelper::DeviceHelper() :
+ mpOutDev()
+ {}
+
+ void DeviceHelper::init( const OutDevProviderSharedPtr& rOutDev )
+ {
+ mpOutDev = rOutDev;
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalResolution()
+ {
+ if( !mpOutDev )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ // Map a one-by-one millimeter box to pixel
+ OutputDevice& rOutDev = mpOutDev->getOutDev();
+ const MapMode aOldMapMode( rOutDev.GetMapMode() );
+ rOutDev.SetMapMode( MapMode(MAP_MM) );
+ const Size aPixelSize( rOutDev.LogicToPixel(Size(1,1)) );
+ rOutDev.SetMapMode( aOldMapMode );
+
+ return ::vcl::unotools::size2DFromSize( aPixelSize );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalSize()
+ {
+ if( !mpOutDev )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ // Map the pixel dimensions of the output window to millimeter
+ OutputDevice& rOutDev = mpOutDev->getOutDev();
+ const MapMode aOldMapMode( rOutDev.GetMapMode() );
+ rOutDev.SetMapMode( MapMode(MAP_MM) );
+ const Size aLogSize( rOutDev.PixelToLogic(rOutDev.GetOutputSizePixel()) );
+ rOutDev.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 )
+ {
+ uno::Reference< rendering::XLinePolyPolygon2D > xPoly;
+ if( !mpOutDev )
+ return xPoly; // we're disposed
+
+ xPoly.set( new ::basegfx::unotools::UnoPolyPolygon(
+ ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
+ // vcl only handles even_odd polygons
+ xPoly->setFillRule(rendering::FillRule_EVEN_ODD);
+
+ return xPoly;
+ }
+
+ uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
+ {
+ uno::Reference< rendering::XBezierPolyPolygon2D > xPoly;
+ if( !mpOutDev )
+ return xPoly; // we're disposed
+
+ xPoly.set( new ::basegfx::unotools::UnoPolyPolygon(
+ ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
+ // vcl only handles even_odd polygons
+ xPoly->setFillRule(rendering::FillRule_EVEN_ODD);
+
+ return xPoly;
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !mpOutDev )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap( ::vcl::unotools::sizeFromIntegerSize2D(size),
+ false,
+ *rDevice.get(),
+ mpOutDev ) );
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const geometry::IntegerSize2D& )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !mpOutDev )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ return uno::Reference< rendering::XBitmap >(
+ new CanvasBitmap( ::vcl::unotools::sizeFromIntegerSize2D(size),
+ true,
+ *rDevice.get(),
+ mpOutDev ) );
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& ,
+ const geometry::IntegerSize2D& )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool DeviceHelper::hasFullScreenMode()
+ {
+ return false;
+ }
+
+ sal_Bool DeviceHelper::enterFullScreenMode( sal_Bool bEnter )
+ {
+ (void)bEnter;
+ return false;
+ }
+
+ void DeviceHelper::disposing()
+ {
+ // release all references
+ mpOutDev.reset();
+ }
+
+ uno::Any DeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(false);
+ }
+
+ uno::Any DeviceHelper::getDeviceHandle() const
+ {
+ if( !mpOutDev )
+ return uno::Any();
+
+ return uno::makeAny(
+ reinterpret_cast< sal_Int64 >(&mpOutDev->getOutDev()) );
+ }
+
+ uno::Any DeviceHelper::getSurfaceHandle() const
+ {
+ return getDeviceHandle();
+ }
+
+ 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( mpOutDev )
+ {
+ String aFilename( String::CreateFromAscii("dbg_frontbuffer") );
+ aFilename += String::CreateFromInt32(nFilePostfixCount);
+ aFilename += String::CreateFromAscii(".bmp");
+
+ SvFileStream aStream( aFilename, STREAM_STD_READWRITE );
+
+ const ::Point aEmptyPoint;
+ OutputDevice& rOutDev = mpOutDev->getOutDev();
+ bool bOldMap( rOutDev.IsMapModeEnabled() );
+ rOutDev.EnableMapMode( FALSE );
+ aStream << rOutDev.GetBitmap(aEmptyPoint,
+ rOutDev.GetOutputSizePixel());
+ rOutDev.EnableMapMode( bOldMap );
+
+ ++nFilePostfixCount;
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/devicehelper.hxx b/canvas/source/vcl/devicehelper.hxx
new file mode 100644
index 000000000000..025e974d24e6
--- /dev/null
+++ b/canvas/source/vcl/devicehelper.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_DEVICEHELPER_HXX
+#define _VCLCANVAS_DEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+
+#include "outdevprovider.hxx"
+
+#include <boost/utility.hpp>
+
+
+/* Definition of DeviceHelper class */
+
+namespace vclcanvas
+{
+ class Canvas;
+
+ class DeviceHelper : private ::boost::noncopyable
+ {
+ public:
+ DeviceHelper();
+
+ void init( const OutDevProviderSharedPtr& rOutDev );
+
+ /// 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;
+
+ OutDevProviderSharedPtr getOutDev() const { return mpOutDev; }
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const;
+
+ private:
+ /// For retrieving device info
+ OutDevProviderSharedPtr mpOutDev;
+ };
+}
+
+#endif /* _VCLCANVAS_DEVICEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/exports.dxp b/canvas/source/vcl/exports.dxp
new file mode 100644
index 000000000000..0c2e3e7cddd7
--- /dev/null
+++ b/canvas/source/vcl/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory \ No newline at end of file
diff --git a/canvas/source/vcl/impltools.cxx b/canvas/source/vcl/impltools.cxx
new file mode 100644
index 000000000000..86d82098ef32
--- /dev/null
+++ b/canvas/source/vcl/impltools.cxx
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/math.hxx>
+#include <rtl/logfile.hxx>
+
+#include <com/sun/star/geometry/RealSize2D.hpp>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/geometry/RealBezierSegment2D.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <vcl/salbtype.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include "impltools.hxx"
+#include "canvasbitmap.hxx"
+
+#include <numeric>
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ namespace tools
+ {
+ ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ // TODO(F3): CanvasCustomSprite should also be tunnelled
+ // through (also implements XIntegerBitmap interface)
+ CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() );
+
+ if( pBitmapImpl )
+ {
+ return pBitmapImpl->getBitmap();
+ }
+ else
+ {
+ SpriteCanvas* pCanvasImpl = dynamic_cast< SpriteCanvas* >( xBitmap.get() );
+ if( pCanvasImpl && pCanvasImpl->getBackBuffer() )
+ {
+ // TODO(F3): mind the plain Canvas impl. Consolidate with CWS canvas05
+ const ::OutputDevice& rDev( pCanvasImpl->getBackBuffer()->getOutDev() );
+ const ::Point aEmptyPoint;
+ return rDev.GetBitmapEx( aEmptyPoint,
+ rDev.GetOutputSizePixel() );
+ }
+
+ // TODO(F2): 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 bitmap" );
+ }
+
+ return ::BitmapEx();
+ }
+
+ bool setupFontTransform( ::Point& o_rPoint,
+ ::Font& io_rVCLFont,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState,
+ ::OutputDevice& rOutDev )
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ rViewState,
+ rRenderState);
+
+ ::basegfx::B2DTuple aScale;
+ ::basegfx::B2DTuple aTranslate;
+ double nRotate, nShearX;
+
+ aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );
+
+ // #i72417# detecting the 180 degree rotation case manually here.
+ if( aScale.getX() < 0.0 &&
+ aScale.getY() < 0.0 &&
+ basegfx::fTools::equalZero(nRotate) )
+ {
+ aScale *= -1.0;
+ nRotate += M_PI;
+ }
+
+ // 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;
+ }
+
+ bool isRectangle( const PolyPolygon& rPolyPoly )
+ {
+ // exclude some cheap cases first
+ if( rPolyPoly.Count() != 1 )
+ return false;
+
+ const ::Polygon& rPoly( rPolyPoly[0] );
+
+ USHORT nCount( rPoly.GetSize() );
+ if( nCount < 4 )
+ return false;
+
+ // delegate to basegfx
+ return ::basegfx::tools::isRectangle( rPoly.getB2DPolygon() );
+ }
+
+
+ // VCL-Canvas related
+ //---------------------------------------------------------------------
+
+ ::Point mapRealPoint2D( const geometry::RealPoint2D& rPoint,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState )
+ {
+ ::basegfx::B2DPoint aPoint( ::basegfx::unotools::b2DPointFromRealPoint2D(rPoint) );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ aPoint *= ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ rViewState,
+ rRenderState);
+
+ return ::vcl::unotools::pointFromB2DPoint( aPoint );
+ }
+
+ ::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState )
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
+ rViewState,
+ rRenderState);
+
+ ::basegfx::B2DPolyPolygon aTemp( rPoly );
+
+ aTemp.transform( aMatrix );
+
+ return ::PolyPolygon( aTemp );
+ }
+
+ ::BitmapEx transformBitmap( const BitmapEx& rBitmap,
+ const ::basegfx::B2DHomMatrix& rTransform,
+ const uno::Sequence< double >& rDeviceColor,
+ ModulationMode eModulationMode )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::tools::transformBitmap()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::vclcanvas::tools::transformBitmap: 0x%X", &rBitmap );
+
+ // calc transformation and size of bitmap to be
+ // generated. Note, that the translational components are
+ // deleted from the transformation; this can be handled by
+ // an offset when painting the bitmap
+ const Size aBmpSize( rBitmap.GetSizePixel() );
+ ::basegfx::B2DRectangle aDestRect;
+
+ bool bCopyBack( false );
+
+ // calc effective transformation for bitmap
+ const ::basegfx::B2DRectangle aSrcRect( 0, 0,
+ aBmpSize.Width(),
+ aBmpSize.Height() );
+ ::canvas::tools::calcTransformedRectBounds( aDestRect,
+ aSrcRect,
+ rTransform );
+
+ // re-center bitmap, such that it's left, top border is
+ // aligned with (0,0). The method takes the given
+ // rectangle, and calculates a transformation that maps
+ // this rectangle unscaled to the origin.
+ ::basegfx::B2DHomMatrix aLocalTransform;
+ ::canvas::tools::calcRectToOriginTransform( aLocalTransform,
+ aSrcRect,
+ rTransform );
+
+ const bool bModulateColors( eModulationMode == MODULATE_WITH_DEVICECOLOR &&
+ rDeviceColor.getLength() > 2 );
+ const double nRedModulation( bModulateColors ? rDeviceColor[0] : 1.0 );
+ const double nGreenModulation( bModulateColors ? rDeviceColor[1] : 1.0 );
+ const double nBlueModulation( bModulateColors ? rDeviceColor[2] : 1.0 );
+ const double nAlphaModulation( bModulateColors && rDeviceColor.getLength() > 3 ?
+ rDeviceColor[3] : 1.0 );
+
+ Bitmap aSrcBitmap( rBitmap.GetBitmap() );
+ Bitmap aSrcAlpha;
+
+ // differentiate mask and alpha channel (on-off
+ // vs. multi-level transparency)
+ if( rBitmap.IsTransparent() )
+ {
+ if( rBitmap.IsAlpha() )
+ aSrcAlpha = rBitmap.GetAlpha().GetBitmap();
+ else
+ aSrcAlpha = rBitmap.GetMask();
+ }
+
+ ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(),
+ aSrcBitmap );
+ ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ?
+ aSrcAlpha.AcquireReadAccess() :
+ (BitmapReadAccess*)NULL,
+ aSrcAlpha );
+
+ if( pReadAccess.get() == NULL ||
+ (pAlphaReadAccess.get() == NULL && rBitmap.IsTransparent()) )
+ {
+ // TODO(E2): Error handling!
+ ENSURE_OR_THROW( false,
+ "transformBitmap(): could not access source bitmap" );
+ }
+
+ // mapping table, to translate pAlphaReadAccess' pixel
+ // values into destination alpha values (needed e.g. for
+ // paletted 1-bit masks).
+ sal_uInt8 aAlphaMap[256];
+
+ if( rBitmap.IsTransparent() )
+ {
+ if( rBitmap.IsAlpha() )
+ {
+ // source already has alpha channel - 1:1 mapping,
+ // i.e. aAlphaMap[0]=0,...,aAlphaMap[255]=255.
+ ::std::iota( aAlphaMap, &aAlphaMap[256], 0 );
+ }
+ else
+ {
+ // mask transparency - determine used palette colors
+ const BitmapColor& rCol0( pAlphaReadAccess->GetPaletteColor( 0 ) );
+ const BitmapColor& rCol1( pAlphaReadAccess->GetPaletteColor( 1 ) );
+
+ // shortcut for true luminance calculation
+ // (assumes that palette is grey-level)
+ aAlphaMap[0] = rCol0.GetRed();
+ aAlphaMap[1] = rCol1.GetRed();
+ }
+ }
+ // else: mapping table is not used
+
+ const Size aDestBmpSize( ::basegfx::fround( aDestRect.getWidth() ),
+ ::basegfx::fround( aDestRect.getHeight() ) );
+
+ if( aDestBmpSize.Width() == 0 || aDestBmpSize.Height() == 0 )
+ return BitmapEx();
+
+ Bitmap aDstBitmap( aDestBmpSize, aSrcBitmap.GetBitCount(), &pReadAccess->GetPalette() );
+ Bitmap aDstAlpha( AlphaMask( aDestBmpSize ).GetBitmap() );
+
+ {
+ // just to be on the safe side: let the
+ // ScopedAccessors get destructed before
+ // copy-constructing the resulting bitmap. This will
+ // rule out the possibility that cached accessor data
+ // is not yet written back.
+ ScopedBitmapWriteAccess pWriteAccess( aDstBitmap.AcquireWriteAccess(),
+ aDstBitmap );
+ ScopedBitmapWriteAccess pAlphaWriteAccess( aDstAlpha.AcquireWriteAccess(),
+ aDstAlpha );
+
+
+ if( pWriteAccess.get() != NULL &&
+ pAlphaWriteAccess.get() != NULL &&
+ rTransform.isInvertible() )
+ {
+ // we're doing inverse mapping here, i.e. mapping
+ // points from the destination bitmap back to the
+ // source
+ ::basegfx::B2DHomMatrix aTransform( aLocalTransform );
+ aTransform.invert();
+
+ // for the time being, always read as ARGB
+ for( int y=0; y<aDestBmpSize.Height(); ++y )
+ {
+ if( bModulateColors )
+ {
+ // TODO(P2): Have different branches for
+ // alpha-only modulation (color
+ // modulations eq. 1.0)
+
+ // modulate all color channels with given
+ // values
+
+ // differentiate mask and alpha channel (on-off
+ // vs. multi-level transparency)
+ if( rBitmap.IsTransparent() )
+ {
+ // Handling alpha and mask just the same...
+ for( int x=0; x<aDestBmpSize.Width(); ++x )
+ {
+ ::basegfx::B2DPoint aPoint(x,y);
+ aPoint *= aTransform;
+
+ const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
+ const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
+ if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
+ nSrcY < 0 || nSrcY >= aBmpSize.Height() )
+ {
+ pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
+ }
+ else
+ {
+ // modulate alpha with
+ // nAlphaModulation. This is a
+ // little bit verbose, formula
+ // is 255 - (255-pixAlpha)*nAlphaModulation
+ // (invert 'alpha' pixel value,
+ // to get the standard alpha
+ // channel behaviour)
+ pAlphaWriteAccess->SetPixel( y, x,
+ BitmapColor(
+ 255U -
+ static_cast<BYTE>(
+ nAlphaModulation*
+ (255U
+ - aAlphaMap[ pAlphaReadAccess->GetPixel(
+ nSrcY,
+ nSrcX ).GetIndex() ] ) + .5 ) ) );
+
+ BitmapColor aColor( pReadAccess->GetPixel( nSrcY,
+ nSrcX ) );
+
+ aColor.SetRed(
+ static_cast<BYTE>(
+ nRedModulation *
+ aColor.GetRed() + .5 ));
+ aColor.SetGreen(
+ static_cast<BYTE>(
+ nGreenModulation *
+ aColor.GetGreen() + .5 ));
+ aColor.SetBlue(
+ static_cast<BYTE>(
+ nBlueModulation *
+ aColor.GetBlue() + .5 ));
+
+ pWriteAccess->SetPixel( y, x,
+ aColor );
+ }
+ }
+ }
+ else
+ {
+ for( int x=0; x<aDestBmpSize.Width(); ++x )
+ {
+ ::basegfx::B2DPoint aPoint(x,y);
+ aPoint *= aTransform;
+
+ const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
+ const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
+ if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
+ nSrcY < 0 || nSrcY >= aBmpSize.Height() )
+ {
+ pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
+ }
+ else
+ {
+ // modulate alpha with
+ // nAlphaModulation. This is a
+ // little bit verbose, formula
+ // is 255 - 255*nAlphaModulation
+ // (invert 'alpha' pixel value,
+ // to get the standard alpha
+ // channel behaviour)
+ pAlphaWriteAccess->SetPixel( y, x,
+ BitmapColor(
+ 255U -
+ static_cast<BYTE>(
+ nAlphaModulation*255.0
+ + .5 ) ) );
+
+ BitmapColor aColor( pReadAccess->GetPixel( nSrcY,
+ nSrcX ) );
+
+ aColor.SetRed(
+ static_cast<BYTE>(
+ nRedModulation *
+ aColor.GetRed() + .5 ));
+ aColor.SetGreen(
+ static_cast<BYTE>(
+ nGreenModulation *
+ aColor.GetGreen() + .5 ));
+ aColor.SetBlue(
+ static_cast<BYTE>(
+ nBlueModulation *
+ aColor.GetBlue() + .5 ));
+
+ pWriteAccess->SetPixel( y, x,
+ aColor );
+ }
+ }
+ }
+ }
+ else
+ {
+ // differentiate mask and alpha channel (on-off
+ // vs. multi-level transparency)
+ if( rBitmap.IsTransparent() )
+ {
+ // Handling alpha and mask just the same...
+ for( int x=0; x<aDestBmpSize.Width(); ++x )
+ {
+ ::basegfx::B2DPoint aPoint(x,y);
+ aPoint *= aTransform;
+
+ const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
+ const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
+ if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
+ nSrcY < 0 || nSrcY >= aBmpSize.Height() )
+ {
+ pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
+ }
+ else
+ {
+ pAlphaWriteAccess->SetPixel( y, x,
+ aAlphaMap[
+ pAlphaReadAccess->GetPixel( nSrcY,
+ nSrcX ) ] );
+
+ pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
+ nSrcX ) );
+ }
+ }
+ }
+ else
+ {
+ for( int x=0; x<aDestBmpSize.Width(); ++x )
+ {
+ ::basegfx::B2DPoint aPoint(x,y);
+ aPoint *= aTransform;
+
+ const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
+ const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
+ if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
+ nSrcY < 0 || nSrcY >= aBmpSize.Height() )
+ {
+ pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
+ }
+ else
+ {
+ pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) );
+ pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
+ nSrcX ) );
+ }
+ }
+ }
+ }
+ }
+
+ bCopyBack = true;
+ }
+ else
+ {
+ // TODO(E2): Error handling!
+ ENSURE_OR_THROW( false,
+ "transformBitmap(): could not access bitmap" );
+ }
+ }
+
+ if( bCopyBack )
+ return BitmapEx( aDstBitmap, AlphaMask( aDstAlpha ) );
+ else
+ return BitmapEx();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/impltools.hxx b/canvas/source/vcl/impltools.hxx
new file mode 100644
index 000000000000..22ea4e2c07f9
--- /dev/null
+++ b/canvas/source/vcl/impltools.hxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_TOOLS_HXX
+#define _VCLCANVAS_TOOLS_HXX
+
+#include <osl/mutex.hxx>
+#include <osl/mutex.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/solarmutex.hxx>
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <canvas/vclwrapper.hxx>
+#include "outdevprovider.hxx"
+
+
+class OutputDevice;
+class Point;
+class Size;
+
+namespace basegfx
+{
+ namespace matrix
+ {
+ class B2DHomMatrix;
+ }
+ namespace vector
+ {
+ class B2DVector;
+ }
+ namespace point
+ {
+ class B2DPoint;
+ }
+}
+
+namespace com { namespace sun { namespace star { namespace awt
+{
+ struct Point;
+ struct Size;
+ struct Rectangle;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ struct HomogenMatrix3;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace geometry
+{
+ struct RealPoint2D;
+ struct RealSize2D;
+ struct RealRectangle2D;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct RenderState;
+ struct ViewState;
+ class XCanvas;
+ class XBitmap;
+ class XPolyPolygon2D;
+} } } }
+
+
+namespace vclcanvas
+{
+ namespace tools
+ {
+ ::BitmapEx
+ bitmapExFromXBitmap( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& );
+
+ /** Setup VCL font and output position
+
+ @returns false, if no text output should happen
+ */
+ bool setupFontTransform( ::Point& o_rPoint,
+ ::Font& io_rVCLFont,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ ::OutputDevice& rOutDev );
+
+ /** Predicate, to determine whether polygon is actually an axis-aligned rectangle
+
+ @return true, if the polygon is a rectangle.
+ */
+ bool isRectangle( const PolyPolygon& rPolyPoly );
+
+
+ // Little helper to encapsulate locking into policy class
+ class LocalGuard
+ {
+ public:
+ LocalGuard() :
+ aSolarGuard()
+ {
+ }
+
+ /// To be compatible with CanvasBase mutex concept
+ LocalGuard( const ::osl::Mutex& ) :
+ aSolarGuard()
+ {
+ }
+
+ private:
+ SolarMutexGuard aSolarGuard;
+ };
+
+ class OutDevStateKeeper
+ {
+ public:
+ explicit OutDevStateKeeper( OutputDevice& rOutDev ) :
+ mpOutDev( &rOutDev ),
+ mbMappingWasEnabled( mpOutDev->IsMapModeEnabled() )
+ {
+ init();
+ }
+
+ explicit OutDevStateKeeper( const OutDevProviderSharedPtr& rOutDev ) :
+ mpOutDev( rOutDev.get() ? &(rOutDev->getOutDev()) : NULL ),
+ mbMappingWasEnabled( mpOutDev ? mpOutDev->IsMapModeEnabled() : false )
+ {
+ init();
+ }
+
+ ~OutDevStateKeeper()
+ {
+ if( mpOutDev )
+ {
+ mpOutDev->EnableMapMode( mbMappingWasEnabled );
+ mpOutDev->Pop();
+ }
+ }
+
+ private:
+ void init()
+ {
+ if( mpOutDev )
+ {
+ mpOutDev->Push();
+ mpOutDev->EnableMapMode(FALSE);
+ }
+ }
+
+ OutputDevice* mpOutDev;
+ const bool mbMappingWasEnabled;
+ };
+
+ ::Point mapRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState );
+
+ ::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState );
+
+ enum ModulationMode
+ {
+ MODULATE_NONE,
+ MODULATE_WITH_DEVICECOLOR
+ };
+
+ ::BitmapEx transformBitmap( const BitmapEx& rBitmap,
+ const ::basegfx::B2DHomMatrix& rTransform,
+ const ::com::sun::star::uno::Sequence< double >& rDeviceColor,
+ ModulationMode eModulationMode );
+
+ }
+}
+
+#endif /* _VCLCANVAS_TOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/makefile.mk b/canvas/source/vcl/makefile.mk
new file mode 100644
index 000000000000..be2fc69894a4
--- /dev/null
+++ b/canvas/source/vcl/makefile.mk
@@ -0,0 +1,85 @@
+#*************************************************************************
+#
+# 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=vclcanvas
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+# Disable optimization for SunCC SPARC
+.IF "$(OS)$(CPU)"=="SOLARISS" && "$(COM)"!="GCC"
+NOOPTFILES = $(SLO)$/canvashelper_texturefill.obj
+.ENDIF
+
+SLOFILES = $(SLO)$/backbuffer.obj \
+ $(SLO)$/bitmapbackbuffer.obj \
+ $(SLO)$/cachedbitmap.obj \
+ $(SLO)$/canvas.obj \
+ $(SLO)$/canvasbitmap.obj \
+ $(SLO)$/canvasbitmaphelper.obj \
+ $(SLO)$/canvascustomsprite.obj \
+ $(SLO)$/canvasfont.obj \
+ $(SLO)$/canvashelper.obj \
+ $(SLO)$/canvashelper_texturefill.obj \
+ $(SLO)$/devicehelper.obj \
+ $(SLO)$/impltools.obj \
+ $(SLO)$/services.obj \
+ $(SLO)$/spritecanvas.obj \
+ $(SLO)$/spritecanvashelper.obj \
+ $(SLO)$/spritedevicehelper.obj \
+ $(SLO)$/spritehelper.obj \
+ $(SLO)$/textlayout.obj \
+ $(SLO)$/windowoutdevholder.obj
+
+SHL1TARGET=$(TARGET).uno
+
+SHL1STDLIBS= $(TOOLSLIB) $(TKLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(SVTOOLLIB) $(I18NISOLANGLIB)
+
+SHL1IMPLIB=i$(TARGET)
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1VERSIONMAP=$(SOLARENV)/src/component.map
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/canvas/source/vcl/outdevprovider.hxx b/canvas/source/vcl/outdevprovider.hxx
new file mode 100644
index 000000000000..a49f16f5d945
--- /dev/null
+++ b/canvas/source/vcl/outdevprovider.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_OUTDEVPROVIDER_HXX
+#define _VCLCANVAS_OUTDEVPROVIDER_HXX
+
+#include <sal/types.h>
+#include <boost/shared_ptr.hpp>
+
+
+class OutputDevice;
+
+namespace vclcanvas
+{
+ /* Definition of OutDevProvider interface */
+
+ /** Implementers of this interface provide the CanvasHelper
+ with its OutputDevice.
+
+ This additional level of indirection was necessary, as the
+ OutputDevice is not an interface. There had to be a mechanism
+ to detect the moment when an OutputDevice is rendered to
+ (e.g. for the BitmapBackBuffer).
+ */
+ class OutDevProvider
+ {
+ public:
+ virtual ~OutDevProvider() {}
+
+ virtual OutputDevice& getOutDev() = 0;
+ virtual const OutputDevice& getOutDev() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< OutDevProvider > OutDevProviderSharedPtr;
+}
+
+#endif /* _VCLCANVAS_OUTDEVPROVIDER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/repainttarget.hxx b/canvas/source/vcl/repainttarget.hxx
new file mode 100644
index 000000000000..fb90d9e70197
--- /dev/null
+++ b/canvas/source/vcl/repainttarget.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_REPAINTTARGET_HXX
+#define _VCLCANVAS_REPAINTTARGET_HXX
+
+#include <rtl/ref.hxx>
+
+#include "cachedbitmap.hxx"
+
+class Point;
+class Size;
+class GraphicAttr;
+
+namespace vclcanvas
+{
+ /* 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 GraphicObjectSharedPtr& rGrf,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const = 0;
+ };
+}
+
+#endif /* _VCLCANVAS_REPAINTTARGET_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/services.cxx b/canvas/source/vcl/services.cxx
new file mode 100644
index 000000000000..fc79b5c5ea89
--- /dev/null
+++ b/canvas/source/vcl/services.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <vcl/canvastools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <basegfx/tools/canvastools.hxx>
+
+#include <algorithm>
+
+#include "canvas.hxx"
+#include "spritecanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ namespace sdecl = comphelper::service_decl;
+
+ static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ sdecl::class_<Canvas, sdecl::with_args<true> > serviceImpl1(&initCanvas);
+ const sdecl::ServiceDecl vclCanvasDecl(
+ 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;
+ }
+
+ sdecl::class_<SpriteCanvas, sdecl::with_args<true> > serviceImpl2(&initSpriteCanvas);
+ const sdecl::ServiceDecl vclSpriteCanvasDecl(
+ serviceImpl2,
+ SPRITECANVAS_IMPLEMENTATION_NAME,
+ SPRITECANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS2(vclcanvas::vclCanvasDecl, vclcanvas::vclSpriteCanvasDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/sprite.hxx b/canvas/source/vcl/sprite.hxx
new file mode 100644
index 000000000000..72d108efaa28
--- /dev/null
+++ b/canvas/source/vcl/sprite.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 INCLUDED_VCLCANVAS_SPRITE_HXX
+#define INCLUDED_VCLCANVAS_SPRITE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+class OutputDevice;
+
+namespace vclcanvas
+{
+ /** 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( OutputDevice& rOutDev,
+ 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( OutputDevice& rOutDev,
+ const ::basegfx::B2DPoint& rPos,
+ bool bBufferedUpdate ) const = 0;
+ };
+}
+
+#endif /* INCLUDED_VCLCANVAS_SPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritecanvas.cxx b/canvas/source/vcl/spritecanvas.cxx
new file mode 100644
index 000000000000..2e2e73560484
--- /dev/null
+++ b/canvas/source/vcl/spritecanvas.cxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <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 <vcl/canvastools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <basegfx/tools/canvastools.hxx>
+
+#include <algorithm>
+
+#include "spritecanvas.hxx"
+#include "windowoutdevholder.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void SpriteCanvas::initialize()
+ {
+ SolarMutexGuard aGuard;
+
+ // #i64742# Only call initialize when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ OSL_TRACE( "SpriteCanvas created" );
+
+ // add our own property to GraphicDevice
+ maPropHelper.addProperties(
+ ::canvas::PropertySetHelper::MakeMap
+ ("UnsafeScrolling",
+ boost::bind(&SpriteCanvasHelper::isUnsafeScrolling,
+ boost::ref(maCanvasHelper)),
+ boost::bind(&SpriteCanvasHelper::enableUnsafeScrolling,
+ boost::ref(maCanvasHelper),
+ _1))
+ ("SpriteBounds",
+ boost::bind(&SpriteCanvasHelper::isSpriteBounds,
+ boost::ref(maCanvasHelper)),
+ boost::bind(&SpriteCanvasHelper::enableSpriteBounds,
+ boost::ref(maCanvasHelper),
+ _1)));
+
+ VERBOSE_TRACE( "VCLSpriteCanvas::initialize called" );
+
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 1,
+ "VCLSpriteCanvas::initialize: wrong number of arguments" );
+
+ /* 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,
+ "VCLSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Reference< awt::XWindow > xParentWindow;
+ maArguments[4] >>= xParentWindow;
+
+ OutDevProviderSharedPtr pOutDev( new WindowOutDevHolder(xParentWindow) );
+
+ // setup helper
+ maDeviceHelper.init( pOutDev );
+ setWindow(uno::Reference<awt::XWindow2>(xParentWindow, uno::UNO_QUERY_THROW));
+ maCanvasHelper.init( maDeviceHelper.getBackBuffer(),
+ *this,
+ maRedrawManager,
+ false, // no OutDev state preservation
+ false ); // no alpha on surface
+
+ maArguments.realloc(0);
+ }
+
+ SpriteCanvas::~SpriteCanvas()
+ {
+ OSL_TRACE( "SpriteCanvas destroyed" );
+ }
+
+
+ void SAL_CALL SpriteCanvas::disposing()
+ {
+ SolarMutexGuard aGuard;
+
+ 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)
+ {
+ SolarMutexGuard aGuard;
+
+ // 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(bUpdateAll,
+ mbSurfaceDirty);
+ }
+
+ ::rtl::OUString SAL_CALL SpriteCanvas::getServiceName( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SPRITECANVAS_SERVICE_NAME ) );
+ }
+
+ bool SpriteCanvas::repaint( const GraphicObjectSharedPtr& rGrf,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const
+ {
+ SolarMutexGuard aGuard;
+
+ return maCanvasHelper.repaint( rGrf, viewState, renderState, rPt, rSz, rAttr );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritecanvas.hxx b/canvas/source/vcl/spritecanvas.hxx
new file mode 100644
index 000000000000..fcad1a171e2f
--- /dev/null
+++ b/canvas/source/vcl/spritecanvas.hxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_SPRITECANVAS_HXX_
+#define _VCLCANVAS_SPRITECANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.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 "spritecanvashelper.hxx"
+#include "impltools.hxx"
+#include "spritedevicehelper.hxx"
+#include "repainttarget.hxx"
+
+
+#define SPRITECANVAS_SERVICE_NAME "com.sun.star.rendering.SpriteCanvas.VCL"
+#define SPRITECANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.SpriteCanvas.VCL"
+
+namespace vclcanvas
+{
+ 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,
+ tools::LocalGuard,
+ ::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
+ {
+ };
+
+ typedef ::canvas::SpriteCanvasBase< SpriteCanvasBaseSpriteSurface_Base,
+ SpriteCanvasHelper,
+ tools::LocalGuard,
+ ::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();
+
+ /// For resource tracking
+ ~SpriteCanvas();
+
+#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);
+
+ // RepaintTarget
+ virtual bool repaint( const GraphicObjectSharedPtr& rGrf,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::Point& rPt,
+ const ::Size& rSz,
+ const GraphicAttr& rAttr ) const;
+
+ /// Get backbuffer for this canvas
+ OutDevProviderSharedPtr getFrontBuffer() const { return maDeviceHelper.getOutDev(); }
+ /// Get window for this canvas
+ BackBufferSharedPtr getBackBuffer() const { return maDeviceHelper.getBackBuffer(); }
+
+ 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;
+ typedef ::rtl::Reference< SpriteCanvas > DeviceRef;
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritecanvashelper.cxx b/canvas/source/vcl/spritecanvashelper.cxx
new file mode 100644
index 000000000000..33fd5987de2c
--- /dev/null
+++ b/canvas/source/vcl/spritecanvashelper.cxx
@@ -0,0 +1,721 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <vcl/canvastools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bitmapex.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/cast.hpp>
+
+#include "spritecanvashelper.hxx"
+#include "canvascustomsprite.hxx"
+
+
+using namespace ::com::sun::star;
+
+#define FPS_BOUNDS Rectangle(0,0,130,90)
+#define INFO_COLOR COL_RED
+
+namespace vclcanvas
+{
+ namespace
+ {
+ /** Sprite redraw at original position
+
+ Used to repaint the whole canvas (background and all
+ sprites)
+ */
+ void spriteRedraw( OutputDevice& rOutDev,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ // downcast to derived vclcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw(rOutDev,
+ true);
+ }
+
+ double calcNumPixel( const ::canvas::Sprite::Reference& rSprite )
+ {
+ const ::basegfx::B2DSize& rSize(
+ ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->getSizePixel() );
+
+ return rSize.getX() * rSize.getY();
+ }
+
+ void repaintBackground( OutputDevice& rOutDev,
+ OutputDevice& rBackBuffer,
+ const ::basegfx::B2DRange& rArea )
+ {
+ const ::Point& rPos( ::vcl::unotools::pointFromB2DPoint( rArea.getMinimum()) );
+ const ::Size& rSize( ::vcl::unotools::sizeFromB2DSize( rArea.getRange()) );
+
+ rOutDev.DrawOutDev( rPos, rSize, rPos, rSize, rBackBuffer );
+ }
+
+ void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
+ OutputDevice& rOutDev,
+ const ::basegfx::B2IRange& rArea )
+ {
+ const Rectangle& rRequestedArea(
+ ::vcl::unotools::rectangleFromB2IRectangle( 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)
+ rOutDev.EnableMapMode( FALSE );
+ rOutDev.SetClipRegion( rRequestedArea );
+
+ // repaint affected sprite directly to output device (at
+ // the actual screen output position)
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw( rOutDev,
+ false ); // rendering
+ // directly to
+ // frontbuffer
+ }
+
+ /** Repaint sprite at original position
+
+ Used for opaque updates, which render directly to the
+ front buffer.
+ */
+ void spriteRedrawStub( OutputDevice& rOutDev,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw( rOutDev,
+ false );
+ }
+ }
+
+ /** Repaint sprite at given position
+
+ Used for generic update, which renders into vdev of
+ adapted size.
+ */
+ void spriteRedrawStub2( OutputDevice& rOutDev,
+ const ::basegfx::B2DPoint& rOutPos,
+ const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ Sprite* pSprite = ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() );
+
+ // calc relative sprite position in rUpdateArea (which
+ // need not be the whole screen!)
+ const ::basegfx::B2DPoint& rSpriteScreenPos( pSprite->getPosPixel() );
+ const ::basegfx::B2DPoint& rSpriteRenderPos( rSpriteScreenPos - rOutPos );
+
+ pSprite->redraw( rOutDev, rSpriteRenderPos, true );
+ }
+ }
+
+ /** Repaint sprite at original position
+
+ Used for opaque updates from scrollUpdate(), which render
+ directly to the front buffer.
+ */
+ void spriteRedrawStub3( OutputDevice& rOutDev,
+ const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
+ {
+ const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
+
+ if( rSprite.is() )
+ {
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw( rOutDev,
+ false );
+ }
+ }
+
+ void renderInfoText( OutputDevice& rOutDev,
+ const ::rtl::OUString& rStr,
+ const Point& rPos )
+ {
+ Font aVCLFont;
+ aVCLFont.SetHeight( 20 );
+ aVCLFont.SetColor( Color( INFO_COLOR ) );
+
+ rOutDev.SetTextAlign(ALIGN_TOP);
+ rOutDev.SetTextColor( Color( INFO_COLOR ) );
+ rOutDev.SetFont( aVCLFont );
+
+ rOutDev.DrawText( rPos, rStr );
+ }
+
+ }
+
+ SpriteCanvasHelper::SpriteCanvasHelper() :
+ mpRedrawManager( NULL ),
+ mpOwningSpriteCanvas( NULL ),
+ maVDev(),
+ maLastUpdate(),
+ mbShowFrameInfo( false ),
+ mbShowSpriteBounds( false ),
+ mbIsUnsafeScrolling( false )
+ {
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ // inverse defaults for verbose debug mode
+ mbShowSpriteBounds = mbShowFrameInfo = true;
+#endif
+ }
+
+ void SpriteCanvasHelper::init( const OutDevProviderSharedPtr& rOutDev,
+ SpriteCanvas& rOwningSpriteCanvas,
+ ::canvas::SpriteRedrawManager& rManager,
+ bool bProtect,
+ bool bHaveAlpha )
+ {
+ mpOwningSpriteCanvas = &rOwningSpriteCanvas;
+ mpRedrawManager = &rManager;
+
+ CanvasHelper::init(rOwningSpriteCanvas,rOutDev,bProtect,bHaveAlpha);
+ }
+
+ void SpriteCanvasHelper::disposing()
+ {
+ mpRedrawManager = NULL;
+ mpOwningSpriteCanvas = 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 > >& ,
+ sal_Int8 )
+ {
+ return uno::Reference< rendering::XAnimatedSprite >();
+ }
+
+ uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
+ {
+ if( !mpRedrawManager || !mpDevice )
+ return uno::Reference< rendering::XCustomSprite >(); // we're disposed
+
+ return uno::Reference< rendering::XCustomSprite >(
+ new CanvasCustomSprite( spriteSize,
+ *mpDevice,
+ mpOwningSpriteCanvas,
+ mpOwningSpriteCanvas->getFrontBuffer(),
+ mbShowSpriteBounds ) );
+ }
+
+ uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& )
+ {
+ return uno::Reference< rendering::XSprite >();
+ }
+
+ sal_Bool SpriteCanvasHelper::updateScreen( sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty )
+ {
+ if( !mpRedrawManager ||
+ !mpOwningSpriteCanvas ||
+ !mpOwningSpriteCanvas->getFrontBuffer() ||
+ !mpOwningSpriteCanvas->getBackBuffer() )
+ {
+ return sal_False; // disposed, or otherwise dysfunctional
+ }
+
+ // commit to backbuffer
+ flush();
+
+ OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
+ BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
+ OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
+
+ // actual OutputDevice is a shared resource - restore its
+ // state when done.
+ tools::OutDevStateKeeper aStateKeeper( rOutDev );
+
+ const Size aOutDevSize( rBackOutDev.GetOutputSizePixel() );
+ const Point aEmptyPoint(0,0);
+
+ Window* pTargetWindow = NULL;
+ if( rOutDev.GetOutDevType() == OUTDEV_WINDOW )
+ {
+ pTargetWindow = &static_cast<Window&>(rOutDev); // TODO(Q3): Evil downcast.
+
+ // we're double-buffered, thus no need for paint area-limiting
+ // clips. besides that, will interfere with animations (as for
+ // Window-invalidate repaints, only parts of the window will
+ // be redrawn otherwise)
+ const Region aFullWindowRegion( Rectangle(aEmptyPoint,
+ aOutDevSize) );
+ pTargetWindow->ExpandPaintClipRegion(aFullWindowRegion);
+ }
+
+ // TODO(P1): Might be worthwile to track areas of background
+ // changes, too.
+ if( !bUpdateAll && !io_bSurfaceDirty )
+ {
+ if( mbShowFrameInfo )
+ {
+ // also repaint background below frame counter (fake
+ // that as a sprite vanishing in this area)
+ mpRedrawManager->updateSprite( ::canvas::Sprite::Reference(),
+ ::basegfx::B2DPoint(),
+ ::basegfx::B2DRectangle( 0.0, 0.0,
+ FPS_BOUNDS.Right(),
+ FPS_BOUNDS.Bottom() ) );
+ }
+
+ // 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
+ {
+ // background has changed, so we currently have no choice
+ // but repaint everything (or caller requested that)
+
+ maVDev->SetOutputSizePixel( aOutDevSize );
+ maVDev->EnableMapMode( FALSE );
+ maVDev->DrawOutDev( aEmptyPoint, aOutDevSize,
+ aEmptyPoint, aOutDevSize,
+ rBackOutDev );
+
+ // repaint all active sprites on top of background into
+ // VDev.
+ mpRedrawManager->forEachSprite(
+ ::boost::bind(
+ &spriteRedraw,
+ ::boost::ref( maVDev.get() ),
+ _1 ) );
+
+ // flush to screen
+ rOutDev.EnableMapMode( FALSE );
+ rOutDev.SetClipRegion();
+ rOutDev.DrawOutDev( aEmptyPoint, aOutDevSize,
+ aEmptyPoint, aOutDevSize,
+ *maVDev );
+ }
+
+ // change record vector must be cleared, for the next turn of
+ // rendering and sprite changing
+ mpRedrawManager->clearChangeRecords();
+
+ io_bSurfaceDirty = false;
+
+ if( mbShowFrameInfo )
+ {
+ renderFrameCounter( rOutDev );
+ renderSpriteCount( rOutDev );
+ renderMemUsage( rOutDev );
+ }
+
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ static ::canvas::tools::ElapsedTime aElapsedTime;
+
+ // log time immediately after surface flip
+ OSL_TRACE( "SpriteCanvasHelper::updateScreen(): flip done at %f",
+ aElapsedTime.getElapsedTime() );
+#endif
+
+ // sync output with screen, to ensure that we don't queue up
+ // render requests (calling code might rely on timing,
+ // i.e. assume that things are visible on screen after
+ // updateScreen() returns).
+ if( pTargetWindow )
+ {
+ // commit to screen
+ pTargetWindow->Sync();
+ }
+
+ return sal_True;
+ }
+
+ void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
+ {
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBackBuffer() &&
+ mpOwningSpriteCanvas->getFrontBuffer(),
+ "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
+
+ OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
+ BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
+ OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
+
+ repaintBackground( rOutDev, rBackOutDev, rUpdateRect );
+ }
+
+ void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
+ {
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBackBuffer() &&
+ mpOwningSpriteCanvas->getFrontBuffer(),
+ "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
+
+ OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
+ BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
+ OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
+
+ const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
+ const ::basegfx::B2IRange aOutputBounds( 0,0,
+ rTargetSizePixel.Width(),
+ rTargetSizePixel.Height() );
+
+ // 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;
+
+ // Since strictly speaking, this scroll algorithm is plain
+ // buggy, the scrolled area might actually lie _below_ another
+ // window - we've made this feature configurable via
+ // mbIsUnsafeScrolling.
+
+ // clip to output bounds (cannot properly scroll stuff
+ // _outside_ our screen area)
+ if( !mbIsUnsafeScrolling ||
+ !::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::ref( rOutDev ),
+ _1 ) );
+ }
+ else
+ {
+ // scroll rOutDev content
+ rOutDev.CopyArea( ::vcl::unotools::pointFromB2IPoint( aDestPos ),
+ ::vcl::unotools::pointFromB2IPoint( aSourceRect.getMinimum() ),
+ // TODO(Q2): use numeric_cast to check range
+ ::Size( static_cast<sal_Int32>(aSourceRect.getRange().getX()),
+ static_cast<sal_Int32>(aSourceRect.getRange().getY()) ) );
+
+ 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
+ rOutDev.Push( PUSH_CLIPREGION );
+ ::std::for_each( aUnscrollableAreas.begin(),
+ aUnscrollableAreas.end(),
+ ::boost::bind( &opaqueUpdateSpriteArea,
+ ::boost::cref(aFirst->second.getSprite()),
+ ::boost::ref(rOutDev),
+ _1 ) );
+ rOutDev.Pop();
+ }
+
+ // 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::ref(rOutDev),
+ ::boost::ref(rBackOutDev),
+ _1 ) );
+ }
+
+ void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ (void)rTotalArea;
+
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBackBuffer() &&
+ mpOwningSpriteCanvas->getFrontBuffer(),
+ "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
+
+ OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
+
+ // no need to clip output to actual update region - there will
+ // always be ALL sprites contained in the rectangular update
+ // area containd in rTotalArea (that's the way
+ // B2DConnectedRanges work). If rTotalArea appears to be
+ // smaller than the sprite - then this sprite carries a clip,
+ // and the update will be constrained to that rect.
+
+ // repaint all affected sprites directly to output device
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::boost::bind(
+ &spriteRedrawStub,
+ ::boost::ref( rOutDev ),
+ _1 ) );
+ }
+
+ void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rRequestedArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpOwningSpriteCanvas &&
+ mpOwningSpriteCanvas->getBackBuffer() &&
+ mpOwningSpriteCanvas->getFrontBuffer(),
+ "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
+
+ OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
+ BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
+ OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
+
+ // limit size of update VDev to target outdev's size
+ const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
+
+ // 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 coverage of VDev to
+ // output device's area (i.e. not only to total size, but to
+ // cover _only_ the visible parts).
+ const ::Size aOutputSize(
+ ::std::max( sal_Int32( 0 ),
+ ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Width() - aOutputPosition.X()),
+ ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X() ))),
+ ::std::max( sal_Int32( 0 ),
+ ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Height() - aOutputPosition.Y()),
+ ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y() ))));
+
+ // early exit for empty output area.
+ if( aOutputSize.Width() == 0 &&
+ aOutputSize.Height() == 0 )
+ {
+ return;
+ }
+
+ const Point aEmptyPoint(0,0);
+ const Size aCurrOutputSize( maVDev->GetOutputSizePixel() );
+
+ // adapt maVDev's size to the area that actually needs the
+ // repaint.
+ if( aCurrOutputSize.Width() < aOutputSize.Width() ||
+ aCurrOutputSize.Height() < aOutputSize.Height() )
+ {
+ // TODO(P1): Come up with a clever tactic to reduce maVDev
+ // from time to time. Reduction with threshold (say, if
+ // maVDev is more than twice too large) is not wise, as
+ // this might then toggle within the same updateScreen(),
+ // but for different disjunct sprite areas.
+ maVDev->SetOutputSizePixel( aOutputSize );
+ }
+
+ // paint background
+ maVDev->EnableMapMode( FALSE );
+ maVDev->SetClipRegion();
+ maVDev->DrawOutDev( aEmptyPoint, aOutputSize,
+ aOutputPosition, aOutputSize,
+ rBackOutDev );
+
+ // repaint all affected sprites on top of background into
+ // VDev.
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::boost::bind( &spriteRedrawStub2,
+ ::boost::ref( maVDev.get() ),
+ ::boost::cref(
+ ::vcl::unotools::b2DPointFromPoint(aOutputPosition)),
+ _1 ) );
+
+ // flush to screen
+ rOutDev.EnableMapMode( FALSE );
+ rOutDev.DrawOutDev( aOutputPosition, aOutputSize,
+ aEmptyPoint, aOutputSize,
+ *maVDev );
+ }
+
+ void SpriteCanvasHelper::renderFrameCounter( OutputDevice& rOutDev )
+ {
+ const double denominator( maLastUpdate.getElapsedTime() );
+ maLastUpdate.reset();
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" fps"));
+
+ renderInfoText( rOutDev,
+ text,
+ Point(0, 0) );
+ }
+
+ namespace
+ {
+ template< typename T > struct Adder
+ {
+ typedef void result_type;
+
+ Adder( T& rAdderTarget,
+ T nIncrement ) :
+ mpTarget( &rAdderTarget ),
+ mnIncrement( nIncrement )
+ {
+ }
+
+ void operator()() { *mpTarget += mnIncrement; }
+ void operator()( const ::canvas::Sprite::Reference& ) { *mpTarget += mnIncrement; }
+ void operator()( T nIncrement ) { *mpTarget += nIncrement; }
+
+ T* mpTarget;
+ T mnIncrement;
+ };
+
+ template< typename T> Adder<T> makeAdder( T& rAdderTarget,
+ T nIncrement )
+ {
+ return Adder<T>(rAdderTarget, nIncrement);
+ }
+ }
+
+ void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev )
+ {
+ if( mpRedrawManager )
+ {
+ sal_Int32 nCount(0);
+
+ mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
+ ::rtl::OUString text(
+ ::rtl::OUString::valueOf(
+ // disambiguate overload...
+ static_cast<sal_Int64>(nCount) ) );
+
+ // pad with leading space
+ while( text.getLength() < 3 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("Sprites: ")) + text;
+
+ renderInfoText( rOutDev,
+ text,
+ Point(0, 30) );
+ }
+ }
+
+ void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev )
+ {
+ BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
+
+ if( mpRedrawManager &&
+ pBackBuffer )
+ {
+ double nPixel(0.0);
+
+ // accumulate pixel count for each sprite into fCount
+ mpRedrawManager->forEachSprite( ::boost::bind(
+ makeAdder(nPixel,1.0),
+ ::boost::bind(
+ &calcNumPixel,
+ _1 ) ) );
+
+ static const int NUM_VIRDEV(2);
+ static const int BYTES_PER_PIXEL(3);
+
+ const Size& rVDevSize( maVDev->GetOutputSizePixel() );
+ const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
+
+ const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
+ rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
+ rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 4 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("Mem: ")) +
+ text +
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("MB"));
+
+ renderInfoText( rOutDev,
+ text,
+ Point(0, 60) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritecanvashelper.hxx b/canvas/source/vcl/spritecanvashelper.hxx
new file mode 100644
index 000000000000..da33592f4bc3
--- /dev/null
+++ b/canvas/source/vcl/spritecanvashelper.hxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_SPRITECANVASHELPER_HXX_
+#define _VCLCANVAS_SPRITECANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <vcl/virdev.hxx>
+
+#include <canvas/spriteredrawmanager.hxx>
+#include <canvas/elapsedtime.hxx>
+#include <canvas/vclwrapper.hxx>
+#include "canvashelper.hxx"
+#include "impltools.hxx"
+
+
+namespace vclcanvas
+{
+ class RedrawManager;
+ class SpriteCanvas;
+
+ class SpriteCanvasHelper : public CanvasHelper
+ {
+ public:
+ SpriteCanvasHelper();
+
+ void init( const OutDevProviderSharedPtr& rOutDev,
+ SpriteCanvas& rOwningSpriteCanvas,
+ ::canvas::SpriteRedrawManager& rManager,
+ bool bProtect,
+ bool bHaveAlpha );
+
+ /// 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 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( 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 );
+
+ ::com::sun::star::uno::Any isUnsafeScrolling() const
+ {
+ return ::com::sun::star::uno::makeAny(mbIsUnsafeScrolling);
+ }
+ void enableUnsafeScrolling( const ::com::sun::star::uno::Any& rAny )
+ {
+ mbIsUnsafeScrolling = rAny.get<bool>();
+ }
+
+ ::com::sun::star::uno::Any isSpriteBounds() const
+ {
+ return ::com::sun::star::uno::makeAny(mbShowSpriteBounds);
+ }
+ void enableSpriteBounds( const ::com::sun::star::uno::Any& rAny )
+ {
+ mbShowSpriteBounds = rAny.get<bool>();
+ }
+
+ private:
+ void renderFrameCounter( OutputDevice& rOutDev );
+ void renderSpriteCount( OutputDevice& rOutDev );
+ void renderMemUsage( OutputDevice& rOutDev );
+
+ /// Set from the SpriteCanvas: instance coordinating sprite redraw
+ ::canvas::SpriteRedrawManager* mpRedrawManager;
+
+ /// Set from the init method. used to generate sprites
+ SpriteCanvas* mpOwningSpriteCanvas;
+
+ /** Background compositing surface.
+
+ Typically, sprites will be composited in the background,
+ before pushing them to screen. This happens here.
+ */
+ ::canvas::vcltools::VCLObject< VirtualDevice > maVDev;
+
+ /// For the frame counter timings
+ ::canvas::tools::ElapsedTime maLastUpdate;
+
+ /// When true, canvas displays debug info on each frame
+ bool mbShowFrameInfo;
+
+ /// When true, canvas creates all new sprites with red lines in the corners
+ bool mbShowSpriteBounds;
+
+ /// When true, canvas uses the scroll optimization (direct scrolls in front buffer)
+ bool mbIsUnsafeScrolling;
+ };
+}
+
+#endif /* _VCLCANVAS_SPRITECANVASHELPER_HXX_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritedevicehelper.cxx b/canvas/source/vcl/spritedevicehelper.cxx
new file mode 100644
index 000000000000..2e07f38dfc9c
--- /dev/null
+++ b/canvas/source/vcl/spritedevicehelper.cxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <toolkit/helper/vclunohelper.hxx>
+#include <vcl/canvastools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include "spritedevicehelper.hxx"
+#include "spritecanvas.hxx"
+#include "spritecanvashelper.hxx"
+#include "canvasbitmap.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ SpriteDeviceHelper::SpriteDeviceHelper() :
+ mpBackBuffer()
+ {
+ }
+
+ void SpriteDeviceHelper::init( const OutDevProviderSharedPtr& pOutDev )
+ {
+ DeviceHelper::init(pOutDev);
+
+ // setup back buffer
+ OutputDevice& rOutDev( pOutDev->getOutDev() );
+ mpBackBuffer.reset( new BackBuffer( rOutDev ));
+ mpBackBuffer->setSize( rOutDev.GetOutputSizePixel() );
+
+ // #i95645#
+#if defined( QUARTZ )
+ // use AA on VCLCanvas for Mac
+ mpBackBuffer->getOutDev().SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW | mpBackBuffer->getOutDev().GetAntialiasing() );
+#else
+ // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and
+ // is not required to do AA. It would need to be adapted to use it correctly
+ // (especially gradient painting). This will need extra work.
+ mpBackBuffer->getOutDev().SetAntialiasing(mpBackBuffer->getOutDev().GetAntialiasing() & !ANTIALIASING_ENABLE_B2DDRAW);
+#endif
+ }
+
+ ::sal_Int32 SpriteDeviceHelper::createBuffers( ::sal_Int32 nBuffers )
+ {
+ (void)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;
+ }
+
+ void SpriteDeviceHelper::disposing()
+ {
+ // release all references
+ mpBackBuffer.reset();
+
+ DeviceHelper::disposing();
+ }
+
+ uno::Any SpriteDeviceHelper::isAccelerated() const
+ {
+ return DeviceHelper::isAccelerated();
+ }
+
+ uno::Any SpriteDeviceHelper::getDeviceHandle() const
+ {
+ return DeviceHelper::getDeviceHandle();
+ }
+
+ uno::Any SpriteDeviceHelper::getSurfaceHandle() const
+ {
+ if( !mpBackBuffer )
+ return uno::Any();
+
+ return uno::makeAny(
+ reinterpret_cast< sal_Int64 >(&mpBackBuffer->getOutDev()) );
+ }
+
+ void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
+ {
+ if( mpBackBuffer )
+ mpBackBuffer->setSize( ::Size(rBounds.Width,
+ rBounds.Height) );
+ }
+
+ void SpriteDeviceHelper::dumpScreenContent() const
+ {
+ DeviceHelper::dumpScreenContent();
+
+ static sal_uInt32 nFilePostfixCount(0);
+
+ if( mpBackBuffer )
+ {
+ String aFilename( String::CreateFromAscii("dbg_backbuffer") );
+ aFilename += String::CreateFromInt32(nFilePostfixCount);
+ aFilename += String::CreateFromAscii(".bmp");
+
+ SvFileStream aStream( aFilename, STREAM_STD_READWRITE );
+
+ const ::Point aEmptyPoint;
+ mpBackBuffer->getOutDev().EnableMapMode( FALSE );
+ aStream << mpBackBuffer->getOutDev().GetBitmap(aEmptyPoint,
+ mpBackBuffer->getOutDev().GetOutputSizePixel());
+ }
+
+ ++nFilePostfixCount;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritedevicehelper.hxx b/canvas/source/vcl/spritedevicehelper.hxx
new file mode 100644
index 000000000000..d0f8dbcbe37f
--- /dev/null
+++ b/canvas/source/vcl/spritedevicehelper.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_SPRITEDEVICEHELPER_HXX
+#define _VCLCANVAS_SPRITEDEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+
+#include "backbuffer.hxx"
+#include "devicehelper.hxx"
+
+#include <boost/utility.hpp>
+
+
+/* Definition of DeviceHelper class */
+
+namespace vclcanvas
+{
+ class SpriteCanvas;
+ class SpriteCanvasHelper;
+
+ class SpriteDeviceHelper : public DeviceHelper
+ {
+ public:
+ SpriteDeviceHelper();
+
+ void init( const OutDevProviderSharedPtr& rOutDev );
+
+ /// Dispose all internal references
+ void disposing();
+
+ ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
+ void destroyBuffers( );
+ ::sal_Bool showBuffer( bool bWindowVisible, ::sal_Bool bUpdateAll );
+ ::sal_Bool switchBuffer( bool bWindowVisible, ::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 dumpScreenContent() const;
+ BackBufferSharedPtr getBackBuffer() const { return mpBackBuffer; }
+
+ void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
+
+ private:
+ /// This buffer holds the background content for all associated canvases
+ BackBufferSharedPtr mpBackBuffer;
+ };
+}
+
+#endif /* _VCLCANVAS_SPRITEDEVICEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritehelper.cxx b/canvas/source/vcl/spritehelper.cxx
new file mode 100644
index 000000000000..240dbbf80ac7
--- /dev/null
+++ b/canvas/source/vcl/spritehelper.cxx
@@ -0,0 +1,446 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/verbosetrace.hxx>
+
+#include <rtl/math.hxx>
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include "spritehelper.hxx"
+
+using namespace ::com::sun::star;
+
+
+namespace vclcanvas
+{
+ SpriteHelper::SpriteHelper() :
+ mpBackBuffer(),
+ mpBackBufferMask(),
+ maContent(),
+ mbShowSpriteBounds(false)
+ {
+ }
+
+ void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
+ const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
+ const BackBufferSharedPtr& rBackBuffer,
+ const BackBufferSharedPtr& rBackBufferMask,
+ bool bShowSpriteBounds )
+ {
+ ENSURE_OR_THROW( rOwningSpriteCanvas.get() && rBackBuffer && rBackBufferMask,
+ "SpriteHelper::init(): Invalid sprite canvas or back buffer" );
+
+ mpBackBuffer = rBackBuffer;
+ mpBackBufferMask = rBackBufferMask;
+ mbShowSpriteBounds = bShowSpriteBounds;
+
+ init( rSpriteSize, rOwningSpriteCanvas );
+ }
+
+ void SpriteHelper::disposing()
+ {
+ mpBackBuffer.reset();
+ mpBackBufferMask.reset();
+
+ // forward to parent
+ CanvasCustomSpriteHelper::disposing();
+ }
+
+ void SpriteHelper::redraw( OutputDevice& rTargetSurface,
+ const ::basegfx::B2DPoint& rPos,
+ bool& io_bSurfacesDirty,
+ bool bBufferedUpdate ) const
+ {
+ (void)bBufferedUpdate; // not used on every platform
+
+ if( !mpBackBuffer ||
+ !mpBackBufferMask )
+ {
+ return; // we're disposed
+ }
+
+ // log output pos in device pixel
+ VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
+ rPos.getX(),
+ rPos.getY() );
+
+ const double fAlpha( getAlpha() );
+
+ if( isActive() &&
+ !::basegfx::fTools::equalZero( fAlpha ) )
+ {
+ const Point aEmptyPoint;
+ const ::basegfx::B2DVector& rOrigOutputSize( getSizePixel() );
+
+ // might get changed below (e.g. adapted for
+ // transformations). IMPORTANT: both position and size are
+ // rounded to integer values. From now on, only those
+ // rounded values are used, to keep clip and content in
+ // sync.
+ ::Size aOutputSize( ::vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
+ ::Point aOutPos( ::vcl::unotools::pointFromB2DPoint( rPos ) );
+
+
+ // TODO(F3): Support for alpha-VDev
+
+ // Do we have to update our bitmaps (necessary if virdev
+ // was painted to, or transformation changed)?
+ const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
+ hasTransformChanged() ||
+ maContent->IsEmpty() );
+
+ // updating content of sprite cache - surface is no
+ // longer dirty in relation to our cache
+ io_bSurfacesDirty = false;
+ transformUpdated();
+
+ if( bNeedBitmapUpdate )
+ {
+ Bitmap aBmp( mpBackBuffer->getOutDev().GetBitmap( aEmptyPoint,
+ aOutputSize ) );
+
+ if( isContentFullyOpaque() )
+ {
+ // optimized case: content canvas is fully
+ // opaque. Note: since we retrieved aBmp directly
+ // from an OutDev, it's already a 'display bitmap'
+ // on windows.
+ maContent = BitmapEx( aBmp );
+ }
+ else
+ {
+ // sprite content might contain alpha, create
+ // BmpEx, then.
+ Bitmap aMask( mpBackBufferMask->getOutDev().GetBitmap( aEmptyPoint,
+ aOutputSize ) );
+
+ // bitmasks are much faster than alphamasks on some platforms
+ // so convert to bitmask if useful
+#ifndef QUARTZ
+ if( aMask.GetBitCount() != 1 )
+ {
+ OSL_ENSURE(false,
+ "CanvasCustomSprite::redraw(): Mask bitmap is not "
+ "monochrome (performance!)");
+ aMask.MakeMono(255);
+ }
+#endif
+
+ // Note: since we retrieved aBmp and aMask
+ // directly from an OutDev, it's already a
+ // 'display bitmap' on windows.
+ maContent = BitmapEx( aBmp, aMask );
+ }
+ }
+
+ ::basegfx::B2DHomMatrix aTransform( getTransformation() );
+
+ // check whether matrix is "easy" to handle - pure
+ // translations or scales are handled by OutputDevice
+ // alone
+ const bool bIdentityTransform( aTransform.isIdentity() );
+
+ // make transformation absolute (put sprite to final
+ // output position). Need to happen here, as we also have
+ // to translate the clip polygon
+ aTransform.translate( aOutPos.X(),
+ aOutPos.Y() );
+
+ if( !bIdentityTransform )
+ {
+ if( !::basegfx::fTools::equalZero( aTransform.get(0,1) ) ||
+ !::basegfx::fTools::equalZero( aTransform.get(1,0) ) )
+ {
+ // "complex" transformation, employ affine
+ // transformator
+
+ // modify output position, to account for the fact
+ // that transformBitmap() always normalizes its output
+ // bitmap into the smallest enclosing box.
+ ::basegfx::B2DRectangle aDestRect;
+ ::canvas::tools::calcTransformedRectBounds( aDestRect,
+ ::basegfx::B2DRectangle(0,
+ 0,
+ rOrigOutputSize.getX(),
+ rOrigOutputSize.getY()),
+ aTransform );
+
+ aOutPos.X() = ::basegfx::fround( aDestRect.getMinX() );
+ aOutPos.Y() = ::basegfx::fround( aDestRect.getMinY() );
+
+ // TODO(P3): Use optimized bitmap transformation here.
+
+ // actually re-create the bitmap ONLY if necessary
+ if( bNeedBitmapUpdate )
+ maContent = tools::transformBitmap( *maContent,
+ aTransform,
+ uno::Sequence<double>(),
+ tools::MODULATE_NONE );
+
+ aOutputSize = maContent->GetSizePixel();
+ }
+ else
+ {
+ // relatively 'simplistic' transformation -
+ // retrieve scale and translational offset
+ aOutputSize.setWidth (
+ ::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) );
+ aOutputSize.setHeight(
+ ::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) );
+
+ aOutPos.X() = ::basegfx::fround( aTransform.get(0,2) );
+ aOutPos.Y() = ::basegfx::fround( aTransform.get(1,2) );
+ }
+ }
+
+ // transformBitmap() might return empty bitmaps, for tiny
+ // scales.
+ if( !!(*maContent) )
+ {
+ // when true, fast path for slide transition has
+ // already redrawn the sprite.
+ bool bSpriteRedrawn( false );
+
+ rTargetSurface.Push( PUSH_CLIPREGION );
+
+ // apply clip (if any)
+ if( getClip().is() )
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(
+ ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
+ getClip() ));
+
+ if( aClipPoly.count() )
+ {
+ // aTransform already contains the
+ // translational component, moving the clip to
+ // the final sprite output position.
+ aClipPoly.transform( aTransform );
+
+#if ! defined WNT && ! defined QUARTZ
+ // non-Windows only - bAtLeastOnePolygon is
+ // only used in non-WNT code below
+
+ // check whether maybe the clip consists
+ // solely out of rectangular polygons. If this
+ // is the case, enforce using the triangle
+ // clip region setup - non-optimized X11
+ // drivers tend to perform abyssmally on
+ // XPolygonRegion, which is used internally,
+ // when filling complex polypolygons.
+ bool bAtLeastOnePolygon( false );
+ const sal_Int32 nPolygons( aClipPoly.count() );
+
+ for( sal_Int32 i=0; i<nPolygons; ++i )
+ {
+ if( !::basegfx::tools::isRectangle(
+ aClipPoly.getB2DPolygon(i)) )
+ {
+ bAtLeastOnePolygon = true;
+ break;
+ }
+ }
+#endif
+
+ if( mbShowSpriteBounds )
+ {
+ // Paint green sprite clip area
+ rTargetSurface.SetLineColor( Color( 0,255,0 ) );
+ rTargetSurface.SetFillColor();
+
+ rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
+ }
+
+#if ! defined WNT && ! defined QUARTZ
+ // as a matter of fact, this fast path only
+ // performs well for X11 - under Windows, the
+ // clip via SetTriangleClipRegion is faster.
+ if( bAtLeastOnePolygon &&
+ bBufferedUpdate &&
+ ::rtl::math::approxEqual(fAlpha, 1.0) &&
+ !maContent->IsTransparent() )
+ {
+ // fast path for slide transitions
+ // (buffered, no alpha, no mask (because
+ // full slide is contained in the sprite))
+
+ // XOR bitmap onto backbuffer, clear area
+ // that should be _visible_ with black,
+ // XOR bitmap again on top of that -
+ // result: XOR cancels out where no black
+ // has been rendered, and yields the
+ // original bitmap, where black is
+ // underneath.
+ rTargetSurface.Push( PUSH_RASTEROP );
+ rTargetSurface.SetRasterOp( ROP_XOR );
+ rTargetSurface.DrawBitmap( aOutPos,
+ aOutputSize,
+ maContent->GetBitmap() );
+
+ rTargetSurface.SetLineColor();
+ rTargetSurface.SetFillColor( COL_BLACK );
+ rTargetSurface.SetRasterOp( ROP_0 );
+ rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
+
+ rTargetSurface.SetRasterOp( ROP_XOR );
+ rTargetSurface.DrawBitmap( aOutPos,
+ aOutputSize,
+ maContent->GetBitmap() );
+
+ rTargetSurface.Pop();
+
+ bSpriteRedrawn = true;
+ }
+ else
+#endif
+ {
+ // redraw is direcly on the front buffer,
+ // or using alpha blending - cannot use
+ // XOR, thus, employing the still somewhat
+ // speedier triangle clip method
+ ::basegfx::B2DPolygon aTriangulatedClip(::basegfx::triangulator::triangulate(aClipPoly));
+
+ // restrict the clipping area to the visible portion of the output device.
+ Size aSize(rTargetSurface.GetOutputSizePixel());
+ ::basegfx::B2DRange aOutputRect(::basegfx::B2DPoint(0,0),::basegfx::B2DPoint(aSize.Width(),aSize.Height()));
+ ::basegfx::B2DPolygon aClippedClip(::basegfx::tools::clipTriangleListOnRange(aTriangulatedClip,aOutputRect));
+
+ // #i76339#
+ const Polygon aPoly(aClippedClip);
+ const PolyPolygon aPolyPoly(aPoly);
+ rTargetSurface.SetTriangleClipRegion(aPolyPoly);
+ }
+ }
+ }
+
+ if( !bSpriteRedrawn )
+ {
+ if( ::rtl::math::approxEqual(fAlpha, 1.0) )
+ {
+ // no alpha modulation -> just copy to output
+ if( maContent->IsTransparent() )
+ rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent );
+ else
+ rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() );
+ }
+ else
+ {
+ // TODO(P3): Switch to OutputDevice::DrawTransparent()
+ // here
+
+ // draw semi-transparent
+ BYTE nColor( static_cast<UINT8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
+ AlphaMask aAlpha( maContent->GetSizePixel(),
+ &nColor );
+
+ // mask out fully transparent areas
+ if( maContent->IsTransparent() )
+ aAlpha.Replace( maContent->GetMask(), 255 );
+
+ // alpha-blend to output
+ rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize,
+ BitmapEx( maContent->GetBitmap(),
+ aAlpha ) );
+ }
+ }
+
+ rTargetSurface.Pop();
+
+ if( mbShowSpriteBounds )
+ {
+ ::PolyPolygon aMarkerPoly(
+ ::canvas::tools::getBoundMarksPolyPolygon(
+ ::basegfx::B2DRectangle(aOutPos.X(),
+ aOutPos.Y(),
+ aOutPos.X() + aOutputSize.Width()-1,
+ aOutPos.Y() + aOutputSize.Height()-1) ) );
+
+ // Paint little red sprite area markers
+ rTargetSurface.SetLineColor( COL_RED );
+ rTargetSurface.SetFillColor();
+
+ for( int i=0; i<aMarkerPoly.Count(); ++i )
+ {
+ rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject((USHORT)i) );
+ }
+
+ // paint sprite prio
+ Font aVCLFont;
+ aVCLFont.SetHeight( std::min(long(20),aOutputSize.Height()) );
+ aVCLFont.SetColor( COL_RED );
+
+ rTargetSurface.SetTextAlign(ALIGN_TOP);
+ rTargetSurface.SetTextColor( COL_RED );
+ rTargetSurface.SetFont( aVCLFont );
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( getPriority(),
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ rTargetSurface.DrawText( aOutPos+Point(2,2), text );
+
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ OSL_TRACE( "SpriteHelper::redraw(): sprite %X has prio %f\n",
+ this, getPriority() );
+#endif
+ }
+ }
+ }
+ }
+
+ ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
+ {
+ return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/spritehelper.hxx b/canvas/source/vcl/spritehelper.hxx
new file mode 100644
index 000000000000..bc33ecd7b97b
--- /dev/null
+++ b/canvas/source/vcl/spritehelper.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_SPRITEHELPER_HXX
+#define _VCLCANVAS_SPRITEHELPER_HXX
+
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+
+#include <vcl/virdev.hxx>
+
+#include <canvas/base/canvascustomspritehelper.hxx>
+#include <canvas/base/spritesurface.hxx>
+#include <canvas/vclwrapper.hxx>
+
+#include "backbuffer.hxx"
+#include "impltools.hxx"
+#include "spritecanvas.hxx"
+
+
+namespace vclcanvas
+{
+ /* 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:
+ SpriteHelper();
+
+ // make CanvasCustomSpriteHelper::init visible for name lookup
+ using ::canvas::CanvasCustomSpriteHelper::init;
+
+ /** 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 rBackBuffer
+ Buffer of the sprite content (non-alpha part)
+
+ @param rBackBufferMask
+ Buffer of the sprite content (alpha part)
+ */
+ void init( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
+ const BackBufferSharedPtr& rBackBuffer,
+ const BackBufferSharedPtr& rBackBufferMask,
+ bool bShowSpriteBounds );
+
+ void disposing();
+
+ /** 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( OutputDevice& rOutDev,
+ 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;
+
+ // for the redraw
+ BackBufferSharedPtr mpBackBuffer;
+ BackBufferSharedPtr mpBackBufferMask;
+
+ /// Cached bitmap for the current sprite content
+ mutable ::canvas::vcltools::VCLObject<BitmapEx> maContent;
+
+ /// When true, line sprite corners in red
+ bool mbShowSpriteBounds;
+
+ };
+}
+
+#endif /* _VCLCANVAS_SPRITEHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/textlayout.cxx b/canvas/source/vcl/textlayout.cxx
new file mode 100644
index 000000000000..1bf6ff99dc9b
--- /dev/null
+++ b/canvas/source/vcl/textlayout.cxx
@@ -0,0 +1,499 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <canvas/canvastools.hxx>
+
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/TextDirection.hpp>
+
+#include <vcl/metric.hxx>
+#include <vcl/virdev.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include "impltools.hxx"
+#include "textlayout.hxx"
+
+#include <boost/scoped_array.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ 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 uno::Reference<rendering::XGraphicDevice>& xDevice,
+ const OutDevProviderSharedPtr& rOutDev ) :
+ TextLayout_Base( m_aMutex ),
+ maText( aText ),
+ maLogicalAdvancements(),
+ mpFont( rFont ),
+ mxDevice( xDevice ),
+ mpOutDevProvider( rOutDev ),
+ mnTextDirection( nDirection )
+ {
+ (void)nRandomSeed;
+ }
+
+ void SAL_CALL TextLayout::disposing()
+ {
+ SolarMutexGuard aGuard;
+
+ mpOutDevProvider.reset();
+ mxDevice.clear();
+ mpFont.reset();
+ }
+
+ // XTextLayout
+ uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
+ VirtualDevice aVDev( rOutDev );
+ aVDev.SetFont( mpFont->getVCLFont() );
+
+ setupLayoutMode( aVDev, mnTextDirection );
+
+ const rendering::ViewState aViewState(
+ geometry::AffineMatrix2D(1,0,0, 0,1,0),
+ NULL);
+
+ rendering::RenderState aRenderState (
+ geometry::AffineMatrix2D(1,0,0,0,1,0),
+ NULL,
+ uno::Sequence<double>(4),
+ rendering::CompositeOperation::SOURCE);
+
+ ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
+ setupTextOffsets(aOffsets.get(), maLogicalAdvancements, aViewState, aRenderState);
+
+ uno::Sequence< uno::Reference< rendering::XPolyPolygon2D> > aOutlineSequence;
+ ::basegfx::B2DPolyPolygonVector aOutlines;
+ if (aVDev.GetTextOutlines(
+ aOutlines,
+ maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length),
+ FALSE,
+ 0,
+ aOffsets.get()))
+ {
+ aOutlineSequence.realloc(aOutlines.size());
+ sal_Int32 nIndex (0);
+ for (::basegfx::B2DPolyPolygonVector::const_iterator
+ iOutline(aOutlines.begin()),
+ iEnd(aOutlines.end());
+ iOutline!=iEnd;
+ ++iOutline)
+ {
+ aOutlineSequence[nIndex++] = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxDevice,
+ *iOutline);
+ }
+ }
+
+ return aOutlineSequence;
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+
+ OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
+ VirtualDevice aVDev( rOutDev );
+ aVDev.SetFont( mpFont->getVCLFont() );
+
+ setupLayoutMode( aVDev, mnTextDirection );
+
+ const rendering::ViewState aViewState(
+ geometry::AffineMatrix2D(1,0,0, 0,1,0),
+ NULL);
+
+ rendering::RenderState aRenderState (
+ geometry::AffineMatrix2D(1,0,0,0,1,0),
+ NULL,
+ uno::Sequence<double>(4),
+ rendering::CompositeOperation::SOURCE);
+
+ ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
+ setupTextOffsets(aOffsets.get(), maLogicalAdvancements, aViewState, aRenderState);
+
+ MetricVector aMetricVector;
+ uno::Sequence<geometry::RealRectangle2D> aBoundingBoxes;
+ if (aVDev.GetGlyphBoundRects(
+ Point(0,0),
+ maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length),
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ aMetricVector))
+ {
+ aBoundingBoxes.realloc(aMetricVector.size());
+ sal_Int32 nIndex (0);
+ for (MetricVector::const_iterator
+ iMetric(aMetricVector.begin()),
+ iEnd(aMetricVector.end());
+ iMetric!=iEnd;
+ ++iMetric)
+ {
+ aBoundingBoxes[nIndex++] = geometry::RealRectangle2D(
+ iMetric->getX(),
+ iMetric->getY(),
+ iMetric->getX() + iMetric->getWidth(),
+ iMetric->getY() + iMetric->getHeight());
+ }
+ }
+ return aBoundingBoxes;
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return uno::Sequence< geometry::RealRectangle2D >();
+ }
+
+ uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ return maLogicalAdvancements;
+ }
+
+ void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ ENSURE_ARG_OR_THROW( aAdvancements.getLength() == maText.Length,
+ "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
+
+ maLogicalAdvancements = aAdvancements;
+ }
+
+ geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ if( !mpOutDevProvider )
+ return geometry::RealRectangle2D();
+
+ OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
+
+ VirtualDevice aVDev( rOutDev );
+ 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)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)nSize;
+
+ // TODO(F1)
+ return 0.0;
+ }
+
+ double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& aNextLayouts,
+ double nSize ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)aNextLayouts;
+ (void)nSize;
+
+ // TODO(F1)
+ return 0.0;
+ }
+
+ rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& aHitPoint ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)aHitPoint;
+
+ // TODO(F1)
+ return rendering::TextHit();
+ }
+
+ rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)nInsertionIndex;
+ (void)bExcludeLigatures;
+
+ // TODO(F1)
+ return rendering::Caret();
+ }
+
+ sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)nStartIndex;
+ (void)nCaretAdvancement;
+ (void)bExcludeLigatures;
+
+ // TODO(F1)
+ return 0;
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)nStartIndex;
+ (void)nEndIndex;
+
+ // TODO(F1)
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ (void)nStartIndex;
+ (void)nEndIndex;
+
+ // TODO(F1)
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ double SAL_CALL TextLayout::getBaselineOffset( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ // TODO(F1)
+ return 0.0;
+ }
+
+ sal_Int8 SAL_CALL TextLayout::getMainTextDirection( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ return mnTextDirection;
+ }
+
+ uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ return mpFont.getRef();
+ }
+
+ rendering::StringContext SAL_CALL TextLayout::getText( ) throw (uno::RuntimeException)
+ {
+ SolarMutexGuard aGuard;
+
+ return maText;
+ }
+
+ bool TextLayout::draw( OutputDevice& rOutDev,
+ const Point& rOutpos,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState ) const
+ {
+ SolarMutexGuard aGuard;
+
+ setupLayoutMode( rOutDev, mnTextDirection );
+
+ if( maLogicalAdvancements.getLength() )
+ {
+ // TODO(P2): cache that
+ ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[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)
+
+ rOutDev.DrawTextArray( rOutpos,
+ maText.Text,
+ aOffsets.get(),
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
+ }
+ else
+ {
+ rOutDev.DrawText( rOutpos,
+ maText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
+ }
+
+ 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 IMPLEMENTATION_NAME "VCLCanvas::TextLayout"
+#define SERVICE_NAME "com.sun.star.rendering.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;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/textlayout.hxx b/canvas/source/vcl/textlayout.hxx
new file mode 100644
index 000000000000..a052fdff6960
--- /dev/null
+++ b/canvas/source/vcl/textlayout.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_TEXTLAYOUT_HXX
+#define _VCLCANVAS_TEXTLAYOUT_HXX
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <com/sun/star/rendering/XTextLayout.hpp>
+
+#include <canvas/vclwrapper.hxx>
+
+#include "canvasfont.hxx"
+#include "impltools.hxx"
+
+#include <boost/utility.hpp>
+
+
+/* Definition of TextLayout class */
+
+namespace vclcanvas
+{
+ 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 ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice>& xDevice,
+ const OutDevProviderSharedPtr& rOutDev );
+
+ /// 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( OutputDevice& rOutDev,
+ const Point& rOutpos,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState ) const;
+
+ private:
+ 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;
+
+ ::com::sun::star::rendering::StringContext maText;
+ ::com::sun::star::uno::Sequence< double > maLogicalAdvancements;
+ CanvasFont::Reference mpFont;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice> mxDevice;
+ OutDevProviderSharedPtr mpOutDevProvider;
+ sal_Int8 mnTextDirection;
+ };
+
+}
+
+#endif /* _VCLCANVAS_TEXTLAYOUT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/windowoutdevholder.cxx b/canvas/source/vcl/windowoutdevholder.cxx
new file mode 100644
index 000000000000..ed2508761139
--- /dev/null
+++ b/canvas/source/vcl/windowoutdevholder.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <com/sun/star/lang/NoSupportException.hpp>
+
+#include "windowoutdevholder.hxx"
+#include <toolkit/helper/vclunohelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace vclcanvas
+{
+ namespace
+ {
+ Window& windowFromXWin( const uno::Reference<awt::XWindow>& xWin )
+ {
+ Window* pWindow = VCLUnoHelper::GetWindow(xWin);
+ if( !pWindow )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Parent window not VCL window, or canvas out-of-process!")),
+ NULL);
+ return *pWindow;
+ }
+ }
+
+ WindowOutDevHolder::WindowOutDevHolder( const uno::Reference<awt::XWindow>& xWin ) :
+ mrOutputWindow( windowFromXWin(xWin) )
+ {}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/source/vcl/windowoutdevholder.hxx b/canvas/source/vcl/windowoutdevholder.hxx
new file mode 100644
index 000000000000..40f979252807
--- /dev/null
+++ b/canvas/source/vcl/windowoutdevholder.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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_WINDOWOUTDEVHOLDER_HXX
+#define _VCLCANVAS_WINDOWOUTDEVHOLDER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <vcl/window.hxx>
+
+#include "outdevprovider.hxx"
+
+#include <boost/utility.hpp>
+
+namespace vclcanvas
+{
+ class WindowOutDevHolder : public OutDevProvider,
+ private ::boost::noncopyable
+ {
+ public:
+ explicit WindowOutDevHolder( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::awt::XWindow>& xWin );
+
+ private:
+ virtual OutputDevice& getOutDev() { return mrOutputWindow; }
+ virtual const OutputDevice& getOutDev() const { return mrOutputWindow; }
+
+ // TODO(Q2): Lifetime issue. Though WindowGraphicDeviceBase
+ // now listenes to the window component, I still consider
+ // holding a naked reference unsafe here (especially as we
+ // pass it around via getOutDev). This _only_ works reliably,
+ // if disposing the SpriteCanvas correctly disposes all
+ // entities which hold this pointer.
+ // So: as soon as the protocol inside
+ // vcl/source/window/window.cxx is broken, that disposes the
+ // canvas during window deletion, we're riding a dead horse
+ // here
+ Window& mrOutputWindow;
+ };
+}
+
+#endif /* _VCLCANVAS_WINDOWOUTDEVHOLDER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/workben/canvasdemo.cxx b/canvas/workben/canvasdemo.cxx
new file mode 100644
index 000000000000..510cd43cab21
--- /dev/null
+++ b/canvas/workben/canvasdemo.cxx
@@ -0,0 +1,715 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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"
+// This code strongly inspired by Miguel / Federico's Gnome Canvas demo code.
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/regpathhelper.hxx>
+#include <cppuhelper/servicefactory.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/configurationkeys.hxx>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <vcl/window.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/unowrap.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <rtl/bootstrap.hxx>
+#include <sal/macros.h>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/FillRule.hpp>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+// never import whole leaf namespaces, since this will result in
+// absolutely weird effects during (Koenig) name lookup
+using namespace ::com::sun::star;
+
+
+class DemoApp : public Application
+{
+public:
+ virtual void Main();
+ virtual USHORT Exception( USHORT nError );
+};
+
+static void PrintHelp()
+{
+ fprintf( stdout, "canvasdemo - Exercise the new canvas impl\n" );
+}
+
+class TestWindow : public Dialog
+{
+ public:
+ TestWindow() : Dialog( (Window *) NULL )
+ {
+ SetText( rtl::OUString::createFromAscii( "Canvas test" ) );
+ SetSizePixel( Size( 600, 450 ) );
+ EnablePaint( true );
+ Show();
+ }
+ virtual ~TestWindow() {}
+ virtual void MouseButtonUp( const MouseEvent& /*rMEvt*/ )
+ {
+ //TODO: do something cool
+ EndDialog();
+ }
+ virtual void Paint( const Rectangle& rRect );
+};
+
+class DemoRenderer
+{
+ public:
+ Size maSize;
+ Size maBox;
+ rendering::ViewState maViewState;
+ rendering::RenderState maRenderState;
+ uno::Sequence< double > maColorBlack;
+ uno::Sequence< double > maColorWhite;
+ uno::Sequence< double > maColorRed;
+ uno::Reference< rendering::XCanvas > mxCanvas;
+ uno::Reference< rendering::XCanvasFont > mxDefaultFont;
+ uno::Reference< rendering::XGraphicDevice > mxDevice;
+
+ DemoRenderer( uno::Reference< rendering::XGraphicDevice > xDevice,
+ uno::Reference< rendering::XCanvas > xCanvas,
+ Size aSize ) :
+ maSize(aSize),
+ maBox(),
+ maViewState(),
+ maRenderState(),
+ maColorBlack( vcl::unotools::colorToStdColorSpaceSequence( Color(COL_BLACK)) ),
+ maColorWhite( vcl::unotools::colorToStdColorSpaceSequence( Color(COL_WHITE)) ),
+ maColorRed( vcl::unotools::colorToStdColorSpaceSequence( Color(COL_RED)) ),
+ mxCanvas(xCanvas),
+ mxDefaultFont(),
+ mxDevice( xDevice )
+ {
+ // Geometry init
+ geometry::AffineMatrix2D aUnit( 1,0, 0,
+ 0,1, 0 );
+ maViewState.AffineTransform = aUnit;
+ maRenderState.AffineTransform = aUnit;
+ maRenderState.DeviceColor = maColorBlack;
+
+ //I can't figure out what the compsiteoperation stuff does
+ //it doesn't seem to do anything in either VCL or cairocanvas
+ //I was hoping that CLEAR would clear the canvas before we paint,
+ //but nothing changes
+ maRenderState.CompositeOperation = rendering::CompositeOperation::OVER;
+
+ maBox.Width() = aSize.Width() / 3;
+ maBox.Height() = aSize.Height() / 3;
+
+ lang::Locale aLocale;
+ rendering::FontInfo aFontInfo;
+ aFontInfo.FamilyName = ::rtl::OUString::createFromAscii( "Swiss" );
+ aFontInfo.StyleName = ::rtl::OUString::createFromAscii( "SansSerif" );
+ geometry::Matrix2D aFontMatrix( 1, 0,
+ 0, 1 );
+ rendering::FontRequest aFontRequest( aFontInfo, 12.0, 0.0, aLocale );
+ uno::Sequence< beans::PropertyValue > aExtraFontProperties;
+ mxDefaultFont = xCanvas->createFont( aFontRequest, aExtraFontProperties, aFontMatrix );
+ if( !mxDefaultFont.is() )
+ fprintf( stderr, "Failed to create font\n" );
+ }
+
+ void drawGrid()
+ {
+ double d, dIncr = maSize.Width() / 3;
+ for ( d = 0; d <= maSize.Width(); d += dIncr )
+ mxCanvas->drawLine( geometry::RealPoint2D( d, 0 ),
+ geometry::RealPoint2D( d, maSize.Height() ),
+ maViewState, maRenderState );
+ dIncr = maSize.Height() / 3;
+ for ( d = 0; d <= maSize.Height(); d += dIncr )
+ mxCanvas->drawLine( geometry::RealPoint2D( 0, d ),
+ geometry::RealPoint2D( maSize.Width(), d ),
+ maViewState, maRenderState );
+ }
+
+ void drawStringAt( ::rtl::OString aString, double x, double y )
+ {
+ rendering::StringContext aText;
+ aText.Text = ::rtl::OStringToOUString( aString, RTL_TEXTENCODING_UTF8 );
+ aText.StartPosition = 0;
+ aText.Length = aString.getLength();
+ rendering::RenderState aRenderState( maRenderState );
+ aRenderState.AffineTransform.m02 += x;
+ aRenderState.AffineTransform.m12 += y;
+
+ mxCanvas->drawText( aText, mxDefaultFont, maViewState, aRenderState, 0);
+ }
+
+ void drawRect( Rectangle rRect, uno::Sequence< double > &aColor, int /*nWidth*/ )
+ {
+ uno::Sequence< geometry::RealPoint2D > aPoints(4);
+ uno::Reference< rendering::XLinePolyPolygon2D > xPoly;
+
+ aPoints[0] = geometry::RealPoint2D( rRect.Left(), rRect.Top() );
+ aPoints[1] = geometry::RealPoint2D( rRect.Left(), rRect.Bottom() );
+ aPoints[2] = geometry::RealPoint2D( rRect.Right(), rRect.Bottom() );
+ aPoints[3] = geometry::RealPoint2D( rRect.Right(), rRect.Top() );
+
+ uno::Sequence< uno::Sequence< geometry::RealPoint2D > > aPolys(1);
+ aPolys[0] = aPoints;
+ xPoly = mxDevice->createCompatibleLinePolyPolygon( aPolys );
+ xPoly->setClosed( 0, true );
+ uno::Reference< rendering::XPolyPolygon2D> xPP( xPoly, uno::UNO_QUERY );
+
+ rendering::RenderState aRenderState( maRenderState );
+ aRenderState.DeviceColor = aColor;
+ mxCanvas->drawPolyPolygon( xPP, maViewState, aRenderState );
+ }
+
+ void translate( double x, double y)
+ {
+ maRenderState.AffineTransform.m02 += x;
+ maRenderState.AffineTransform.m12 += y;
+ }
+
+ void drawPolishDiamond( double center_x, double center_y)
+ {
+ const int VERTICES = 10;
+ const double RADIUS = 60.0;
+ int i, j;
+ double a;
+
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( center_x, center_y );
+
+ for (i = 0; i < VERTICES; i++)
+ {
+ a = 2.0 * M_PI * i / VERTICES;
+ geometry::RealPoint2D aSrc( RADIUS * cos (a), RADIUS * sin (a) );
+
+ for (j = i + 1; j < VERTICES; j++)
+ {
+ a = 2.0 * M_PI * j / VERTICES;
+
+// FIXME: set cap_style to 'ROUND'
+ mxCanvas->drawLine( aSrc,
+ geometry::RealPoint2D( RADIUS * cos (a),
+ RADIUS * sin (a) ),
+ maViewState, maRenderState );
+ }
+ }
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawHilbert( double anchor_x, double anchor_y )
+ {
+ const double SCALE=7.0;
+ const char hilbert[] = "urdrrulurulldluuruluurdrurddldrrruluurdrurddldrddlulldrdldrrurd";
+ int nLength = SAL_N_ELEMENTS( hilbert );
+
+ uno::Sequence< geometry::RealPoint2D > aPoints( nLength );
+ uno::Reference< rendering::XLinePolyPolygon2D > xPoly;
+
+ aPoints[0] = geometry::RealPoint2D( anchor_x, anchor_y );
+ for (int i = 0; i < nLength; i++ )
+ {
+ switch( hilbert[i] )
+ {
+ case 'u':
+ aPoints[i+1] = geometry::RealPoint2D( aPoints[i].X,
+ aPoints[i].Y - SCALE );
+ break;
+ case 'd':
+ aPoints[i+1] = geometry::RealPoint2D( aPoints[i].X,
+ aPoints[i].Y + SCALE );
+ break;
+ case 'l':
+ aPoints[i+1] = geometry::RealPoint2D( aPoints[i].X - SCALE,
+ aPoints[i].Y );
+ break;
+ case 'r':
+ aPoints[i+1] = geometry::RealPoint2D( aPoints[i].X + SCALE,
+ aPoints[i].Y );
+ break;
+ }
+ }
+
+ uno::Sequence< uno::Sequence< geometry::RealPoint2D > > aPolys(1);
+ aPolys[0] = aPoints;
+
+ xPoly = mxDevice->createCompatibleLinePolyPolygon( aPolys );
+ xPoly->setClosed( 0, false );
+ uno::Reference< rendering::XPolyPolygon2D> xPP( xPoly, uno::UNO_QUERY );
+
+ rendering::RenderState aRenderState( maRenderState );
+ aRenderState.DeviceColor = maColorRed;
+// aRenderState.DeviceColor[3] = 0.5;
+ rendering::StrokeAttributes aStrokeAttrs;
+ aStrokeAttrs.StrokeWidth = 4.0;
+ aStrokeAttrs.MiterLimit = 2.0; // ?
+ aStrokeAttrs.StartCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.EndCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.JoinType = rendering::PathJoinType::MITER;
+ //fprintf( stderr, "FIXME: stroking a PolyPolygon doesn't show up\n" );
+ //yes it does
+ mxCanvas->strokePolyPolygon( xPP, maViewState, aRenderState, aStrokeAttrs );
+ // FIXME: do this instead:
+ //mxCanvas->drawPolyPolygon( xPP, maViewState, aRenderState );
+ }
+
+ void drawTitle( rtl::OString aTitle )
+ {
+ // FIXME: text anchoring to be done
+ double nStringWidth = aTitle.getLength() * 8.0;
+ drawStringAt ( aTitle, (maBox.Width() - nStringWidth) / 2, 15 );
+ }
+
+ void drawRectangles()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+
+ drawTitle( ::rtl::OString( "Rectangles" ) );
+
+ drawRect( Rectangle( 20, 30, 70, 60 ), maColorRed, 8 );
+ // color mediumseagreen, stipple fill, outline black
+ drawRect( Rectangle( 90, 40, 180, 100 ), maColorBlack, 4 );
+ // color steelblue, filled, no outline
+ drawRect( Rectangle( 10, 80, 80, 140 ), maColorBlack, 1 );
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawEllipses()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width(), 0.0 );
+
+ drawTitle( ::rtl::OString( "Ellipses" ) );
+
+ const basegfx::B2DPoint aCenter( maBox.Width()*.5,
+ maBox.Height()*.5 );
+ const basegfx::B2DPoint aRadii( maBox.Width()*.3,
+ maBox.Height()*.3 );
+ const basegfx::B2DPolygon& rEllipse(
+ basegfx::tools::createPolygonFromEllipse( aCenter,
+ aRadii.getX(),
+ aRadii.getY() ));
+
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(mxDevice,
+ rEllipse) );
+
+ rendering::StrokeAttributes aStrokeAttrs;
+ aStrokeAttrs.StrokeWidth = 4.0;
+ aStrokeAttrs.MiterLimit = 2.0; // ?
+ aStrokeAttrs.StartCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.EndCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.JoinType = rendering::PathJoinType::MITER;
+ mxCanvas->strokePolyPolygon( xPoly, maViewState, maRenderState, aStrokeAttrs );
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawText()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width() * 2.0, 0.0 );
+
+ drawTitle( ::rtl::OString( "Text" ) );
+
+ translate( 0.0,
+ maBox.Height() * .5 );
+ drawTitle( ::rtl::OString( "This is lame" ) );
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawImages()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( 0.0, maBox.Height() );
+
+ drawTitle( ::rtl::OString( "Images" ) );
+
+ uno::Reference< rendering::XBitmap > xBitmap(mxCanvas, uno::UNO_QUERY);
+
+ if( !xBitmap.is() )
+ return;
+
+ translate( maBox.Width()*0.1, maBox.Height()*0.2 );
+ maRenderState.AffineTransform.m00 *= 4.0/15;
+ maRenderState.AffineTransform.m11 *= 3.0/15;
+
+ mxCanvas->drawBitmap(xBitmap, maViewState, maRenderState);
+
+ // uno::Reference< rendering::XBitmap > xBitmap2( xBitmap->getScaledBitmap(geometry::RealSize2D(48, 48), false) );
+ // mxCanvas->drawBitmap(xBitmap2, maViewState, maRenderState); //yes, but where?
+ //cairo-canvas says:
+ //called CanvasHelper::getScaledBitmap, we return NULL, TODO
+ //Exception 'BitmapEx vclcanvas::tools::bitmapExFromXBitmap(const com::sun::star::uno::Reference<com::sun::star::rendering::XBitmap>&),
+ //bitmapExFromXBitmap(): could not extract BitmapEx' thrown
+ //
+ //vcl-canvas says:
+ //Exception 'BitmapEx vclcanvas::tools::bitmapExFromXBitmap(const com::sun::star::uno::Reference<com::sun::star::rendering::XBitmap>&),
+ //bitmapExFromXBitmap(): could not extract bitmap' thrown
+ // Thorsten says that this is a bug, and Thorsten never lies.
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawLines()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width(), maBox.Height() );
+
+ drawTitle( ::rtl::OString( "Lines" ) );
+
+ drawPolishDiamond( 70.0, 80.0 );
+ drawHilbert( 140.0, 140.0 );
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawCurves()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width() * 2.0, maBox.Height() );
+
+ drawTitle( ::rtl::OString( "Curves" ) );
+
+ translate( maBox.Width() * .5, maBox.Height() * .5 );
+
+ const double r= 30.0;
+ const int num_curves = 3;
+
+ //hacky hack hack
+ uno::Sequence< geometry::RealBezierSegment2D > aBeziers (num_curves);
+ uno::Reference< rendering::XBezierPolyPolygon2D > xPoly;
+
+ for (int i= 0; i < num_curves; i++)
+ aBeziers[i]= geometry::RealBezierSegment2D( r * cos(i*2*M_PI/num_curves), //Px
+ r * sin(i*2*M_PI/num_curves), //py
+ r * 2 * cos((i*2*M_PI + 2*M_PI)/num_curves), //C1x
+ r * 2 * sin((i*2*M_PI + 2*M_PI)/num_curves), //C1y
+ r * 2 * cos((i*2*M_PI + 2*M_PI)/num_curves), //C2x
+ r * 2 * sin((i*2*M_PI + 2*M_PI)/num_curves)); //C2y
+ uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > aPolys(1);
+ aPolys[0] = aBeziers;
+ xPoly = mxDevice->createCompatibleBezierPolyPolygon(aPolys);
+ xPoly->setClosed( 0, true );
+ //uno::Reference< rendering::XBezierPolyPolygon2D> xPP( xPoly, uno::UNO_QUERY );
+ //compiles, but totally screws up. I think it is interpretting the bezier as a line
+ uno::Reference< rendering::XPolyPolygon2D> xPP( xPoly, uno::UNO_QUERY );
+
+ rendering::StrokeAttributes aStrokeAttrs;
+ aStrokeAttrs.StrokeWidth = 4.0;
+ aStrokeAttrs.MiterLimit = 2.0; // ?
+ aStrokeAttrs.StartCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.EndCapType = rendering::PathCapType::BUTT;
+ aStrokeAttrs.JoinType = rendering::PathJoinType::MITER;
+ mxCanvas->strokePolyPolygon( xPP, maViewState, maRenderState, aStrokeAttrs );
+ //you can't draw a BezierPolyPolygon2D with this, even though it is derived from it
+ //mxCanvas->drawPolyPolygon( xPP, maViewState, maRenderState );
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ double gimmerand()
+ {
+ return (double)(rand()) / RAND_MAX * 100 + 50;
+ }
+
+ void drawArcs()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( 0.0, maBox.Height() * 2.0 );
+
+ drawTitle( ::rtl::OString( "Arcs" ) );
+
+
+ //begin hacks
+ //This stuff doesn't belong here, but probably in curves
+ //This stuff doesn't work in VCL b/c vcl doesn't do beziers
+ //Hah! Everytime the window redraws, we do this
+ double ax;
+ double ay;
+ double bx;
+ double by;
+ bx= gimmerand();
+ by= gimmerand();
+
+ for (int i= 0; i < 1; i++)
+ {
+ //point a= point b;
+ ax= bx;
+ ay= by;
+ //point b= rand;
+ bx= gimmerand();
+ by= gimmerand();
+ double c1x= gimmerand();
+ double c1y= gimmerand();
+ double c2x= gimmerand();
+ double c2y= gimmerand();
+ maRenderState.DeviceColor = maColorRed;
+ mxCanvas->drawLine(geometry::RealPoint2D(ax, ay), geometry::RealPoint2D(c1x, c1y), maViewState, maRenderState);
+ mxCanvas->drawLine(geometry::RealPoint2D(c1x, c1y), geometry::RealPoint2D(c2x, c2y), maViewState, maRenderState);
+ mxCanvas->drawLine(geometry::RealPoint2D(bx, by), geometry::RealPoint2D(c2x, c2y), maViewState, maRenderState);
+ //draw from a to b
+ geometry::RealBezierSegment2D aBezierSegment(
+ ax, //Px
+ ay, //Py
+ c1x,
+ c1x,
+ c2x,
+ c2y
+ );
+ geometry::RealPoint2D aEndPoint(bx, by);
+ maRenderState.DeviceColor = maColorBlack;
+ mxCanvas->drawBezier(
+ aBezierSegment,
+ aEndPoint,
+ maViewState, maRenderState );
+ }
+ maRenderState = maOldRenderState; // pop
+ }
+
+
+ void drawRegularPolygon(double centerx, double centery, int sides, double r)
+ {
+ //hacky hack hack
+ uno::Sequence< geometry::RealPoint2D > aPoints (sides);
+ uno::Reference< rendering::XLinePolyPolygon2D > xPoly;
+
+ for (int i= 0; i < sides; i++)
+ {
+ aPoints[i]= geometry::RealPoint2D( centerx + r * cos(i*2 * M_PI/sides),
+ centery + r * sin(i*2 * M_PI/sides));
+ }
+ uno::Sequence< uno::Sequence< geometry::RealPoint2D > > aPolys(1);
+ aPolys[0] = aPoints;
+ xPoly = mxDevice->createCompatibleLinePolyPolygon( aPolys );
+ xPoly->setClosed( 0, true );
+ rendering::RenderState aRenderState( maRenderState );
+ aRenderState.DeviceColor = maColorRed;
+ uno::Reference< rendering::XPolyPolygon2D> xPP( xPoly, uno::UNO_QUERY );
+ mxCanvas->drawPolyPolygon( xPP, maViewState, aRenderState);
+ mxCanvas->fillPolyPolygon( xPP,
+ maViewState,
+ aRenderState );
+ }
+
+ void drawPolygons()
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width() * 1.0, maBox.Height() * 2.0 );
+
+ drawTitle( ::rtl::OString( "Polgyons" ) );
+
+ int sides= 3;
+ for (int i= 1; i <= 4; i++)
+ {
+ drawRegularPolygon(35*i, 35, sides, 15);
+ sides++;
+ }
+
+ maRenderState = maOldRenderState; // pop
+ }
+
+ void drawWidgets() // FIXME: prolly makes no sense
+ {
+ rendering::RenderState maOldRenderState = maRenderState; // push
+ translate( maBox.Width() * 2.0, maBox.Height() * 2.0 );
+
+ drawTitle( ::rtl::OString( "Widgets" ) );
+
+ maRenderState = maOldRenderState; // pop
+ }
+};
+
+
+void TestWindow::Paint( const Rectangle& /*rRect*/ )
+{
+ try
+ {
+ const Size aVDevSize(300,300);
+ VirtualDevice aVDev(*this);
+ aVDev.SetOutputSizePixel(aVDevSize);
+ uno::Reference< rendering::XCanvas > xVDevCanvas( aVDev.GetCanvas(),
+ uno::UNO_QUERY_THROW );
+ uno::Reference< rendering::XGraphicDevice > xVDevDevice( xVDevCanvas->getDevice(),
+ uno::UNO_QUERY_THROW );
+ DemoRenderer aVDevRenderer( xVDevDevice, xVDevCanvas, aVDevSize);
+ xVDevCanvas->clear();
+ aVDevRenderer.drawGrid();
+ aVDevRenderer.drawRectangles();
+ aVDevRenderer.drawEllipses();
+ aVDevRenderer.drawText();
+ aVDevRenderer.drawLines();
+ aVDevRenderer.drawCurves();
+ aVDevRenderer.drawArcs();
+ aVDevRenderer.drawPolygons();
+
+ uno::Reference< rendering::XCanvas > xCanvas( GetSpriteCanvas(),
+ uno::UNO_QUERY_THROW );
+ uno::Reference< rendering::XGraphicDevice > xDevice( xCanvas->getDevice(),
+ uno::UNO_QUERY_THROW );
+
+ DemoRenderer aRenderer( xDevice, xCanvas, GetSizePixel() );
+ xCanvas->clear();
+ aRenderer.drawGrid();
+ aRenderer.drawRectangles();
+ aRenderer.drawEllipses();
+ aRenderer.drawText();
+ aRenderer.drawLines();
+ aRenderer.drawCurves();
+ aRenderer.drawArcs();
+ aRenderer.drawPolygons();
+ aRenderer.drawWidgets();
+ aRenderer.drawImages();
+
+ // check whether virdev actually contained something
+ uno::Reference< rendering::XBitmap > xBitmap(xVDevCanvas, uno::UNO_QUERY);
+ if( !xBitmap.is() )
+ return;
+
+ aRenderer.maRenderState.AffineTransform.m02 += 100;
+ aRenderer.maRenderState.AffineTransform.m12 += 100;
+ xCanvas->drawBitmap(xBitmap, aRenderer.maViewState, aRenderer.maRenderState);
+
+ uno::Reference< rendering::XSpriteCanvas > xSpriteCanvas( xCanvas,
+ uno::UNO_QUERY );
+ if( xSpriteCanvas.is() )
+ xSpriteCanvas->updateScreen( sal_True ); // without
+ // updateScreen(),
+ // nothing is
+ // visible
+ }
+ catch (const uno::Exception &e)
+ {
+ fprintf( stderr, "Exception '%s' thrown\n" ,
+ (const sal_Char *) ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ) );
+ }
+}
+
+USHORT DemoApp::Exception( USHORT nError )
+{
+ switch( nError & EXC_MAJORTYPE )
+ {
+ case EXC_RSCNOTLOADED:
+ Abort( String::CreateFromAscii( "Error: could not load language resources.\nPlease check your installation.\n" ) );
+ break;
+ }
+ return 0;
+}
+
+void DemoApp::Main()
+{
+ bool bHelp = false;
+
+ for( USHORT i = 0; i < GetCommandLineParamCount(); i++ )
+ {
+ ::rtl::OUString aParam = GetCommandLineParam( i );
+
+ if( aParam.equalsAscii( "--help" ) ||
+ aParam.equalsAscii( "-h" ) )
+ bHelp = true;
+ }
+
+ if( bHelp )
+ {
+ PrintHelp();
+ return;
+ }
+
+ //-------------------------------------------------
+ // create the global service-manager
+ //-------------------------------------------------
+ uno::Reference< lang::XMultiServiceFactory > xFactory;
+ try
+ {
+ uno::Reference< uno::XComponentContext > xCtx = ::cppu::defaultBootstrap_InitialComponentContext();
+ xFactory = uno::Reference< lang::XMultiServiceFactory >( xCtx->getServiceManager(),
+ uno::UNO_QUERY );
+ if( xFactory.is() )
+ ::comphelper::setProcessServiceFactory( xFactory );
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ if( !xFactory.is() )
+ {
+ fprintf( stderr, "Could not bootstrap UNO, installation must be in disorder. Exiting.\n" );
+ exit( 1 );
+ }
+
+ // Create UCB.
+ uno::Sequence< uno::Any > aArgs( 2 );
+ aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
+ aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );
+ ::ucbhelper::ContentBroker::initialize( xFactory, aArgs );
+
+ InitVCL( xFactory );
+ TestWindow pWindow;
+ pWindow.Execute();
+ DeInitVCL();
+
+ // clean up UCB
+ ::ucbhelper::ContentBroker::deinitialize();
+}
+
+DemoApp aDemoApp;
+
+// TODO
+// - bouncing clip-rectangle mode - bounce a clip-rect around the window ...
+// - complete all of pre-existing canvas bits
+// - affine transform tweakage ...
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/canvas/workben/makefile.mk b/canvas/workben/makefile.mk
new file mode 100644
index 000000000000..be98c10c0e3c
--- /dev/null
+++ b/canvas/workben/makefile.mk
@@ -0,0 +1,37 @@
+PRJ=..
+
+PRJNAME=canvas
+TARGET=canvasdemo
+TARGETTYPE=GUI
+LIBTARGET=NO
+
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+APP1TARGET= $(TARGET)
+
+APP1OBJS= \
+ $(OBJ)$/canvasdemo.obj
+
+APP1STDLIBS=$(TOOLSLIB) \
+ $(COMPHELPERLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB) \
+ $(UCBHELPERLIB) \
+ $(SALLIB) \
+ $(VCLLIB) \
+ $(BASEGFXLIB)
+
+.IF "$(GUI)"!="UNX"
+APP1DEF= $(MISC)$/$(TARGET).def
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk