summaryrefslogtreecommitdiff
path: root/canvas/source/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/vcl')
-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
41 files changed, 9785 insertions, 0 deletions
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: */