summaryrefslogtreecommitdiff
path: root/cppcanvas
diff options
context:
space:
mode:
Diffstat (limited to 'cppcanvas')
-rw-r--r--cppcanvas/inc/cppcanvas/basegfxfactory.hxx107
-rw-r--r--cppcanvas/inc/cppcanvas/bitmap.hxx83
-rw-r--r--cppcanvas/inc/cppcanvas/bitmapcanvas.hxx69
-rw-r--r--cppcanvas/inc/cppcanvas/canvas.hxx119
-rw-r--r--cppcanvas/inc/cppcanvas/canvasgraphic.hxx173
-rw-r--r--cppcanvas/inc/cppcanvas/color.hxx98
-rw-r--r--cppcanvas/inc/cppcanvas/customsprite.hxx56
-rw-r--r--cppcanvas/inc/cppcanvas/font.hxx68
-rw-r--r--cppcanvas/inc/cppcanvas/polypolygon.hxx96
-rw-r--r--cppcanvas/inc/cppcanvas/renderer.hxx153
-rw-r--r--cppcanvas/inc/cppcanvas/sprite.hxx119
-rw-r--r--cppcanvas/inc/cppcanvas/spritecanvas.hxx84
-rw-r--r--cppcanvas/inc/cppcanvas/text.hxx58
-rw-r--r--cppcanvas/inc/cppcanvas/vclfactory.hxx150
-rw-r--r--cppcanvas/inc/makefile.mk47
-rw-r--r--cppcanvas/inc/pch/precompiled_cppcanvas.cxx31
-rw-r--r--cppcanvas/inc/pch/precompiled_cppcanvas.hxx34
-rw-r--r--cppcanvas/prj/build.lst8
-rw-r--r--cppcanvas/prj/d.lst21
-rw-r--r--cppcanvas/source/inc/action.hxx165
-rw-r--r--cppcanvas/source/inc/canvasgraphichelper.hxx89
-rw-r--r--cppcanvas/source/inc/implrenderer.hxx327
-rw-r--r--cppcanvas/source/inc/tools.hxx59
-rw-r--r--cppcanvas/source/mtfrenderer/bitmapaction.cxx241
-rw-r--r--cppcanvas/source/mtfrenderer/bitmapaction.hxx84
-rw-r--r--cppcanvas/source/mtfrenderer/cachedprimitivebase.cxx96
-rw-r--r--cppcanvas/source/mtfrenderer/cachedprimitivebase.hxx98
-rw-r--r--cppcanvas/source/mtfrenderer/emfplus.cxx1617
-rw-r--r--cppcanvas/source/mtfrenderer/implrenderer.cxx3209
-rw-r--r--cppcanvas/source/mtfrenderer/lineaction.cxx170
-rw-r--r--cppcanvas/source/mtfrenderer/lineaction.hxx76
-rw-r--r--cppcanvas/source/mtfrenderer/makefile.mk58
-rw-r--r--cppcanvas/source/mtfrenderer/mtftools.cxx696
-rw-r--r--cppcanvas/source/mtfrenderer/mtftools.hxx273
-rw-r--r--cppcanvas/source/mtfrenderer/outdevstate.hxx136
-rw-r--r--cppcanvas/source/mtfrenderer/pointaction.cxx190
-rw-r--r--cppcanvas/source/mtfrenderer/pointaction.hxx81
-rw-r--r--cppcanvas/source/mtfrenderer/polypolyaction.cxx527
-rw-r--r--cppcanvas/source/mtfrenderer/polypolyaction.hxx104
-rw-r--r--cppcanvas/source/mtfrenderer/textaction.cxx2299
-rw-r--r--cppcanvas/source/mtfrenderer/textaction.hxx105
-rw-r--r--cppcanvas/source/mtfrenderer/transparencygroupaction.cxx578
-rw-r--r--cppcanvas/source/mtfrenderer/transparencygroupaction.hxx143
-rw-r--r--cppcanvas/source/tools/canvasgraphichelper.cxx154
-rw-r--r--cppcanvas/source/tools/makefile.mk50
-rw-r--r--cppcanvas/source/tools/tools.cxx65
-rw-r--r--cppcanvas/source/uno/exports.dxp2
-rw-r--r--cppcanvas/source/uno/exports.map8
-rw-r--r--cppcanvas/source/uno/makefile.mk70
-rw-r--r--cppcanvas/source/uno/mtfrenderer.component7
-rw-r--r--cppcanvas/source/uno/uno_mtfrenderer.cxx83
-rw-r--r--cppcanvas/source/uno/uno_mtfrenderer.hxx63
-rw-r--r--cppcanvas/source/wrapper/basegfxfactory.cxx167
-rw-r--r--cppcanvas/source/wrapper/implbitmap.cxx129
-rw-r--r--cppcanvas/source/wrapper/implbitmap.hxx81
-rw-r--r--cppcanvas/source/wrapper/implbitmapcanvas.cxx76
-rw-r--r--cppcanvas/source/wrapper/implbitmapcanvas.hxx73
-rw-r--r--cppcanvas/source/wrapper/implcanvas.cxx144
-rw-r--r--cppcanvas/source/wrapper/implcanvas.hxx107
-rw-r--r--cppcanvas/source/wrapper/implcolor.cxx71
-rw-r--r--cppcanvas/source/wrapper/implcolor.hxx65
-rw-r--r--cppcanvas/source/wrapper/implcustomsprite.cxx85
-rw-r--r--cppcanvas/source/wrapper/implcustomsprite.hxx72
-rw-r--r--cppcanvas/source/wrapper/implfont.cxx94
-rw-r--r--cppcanvas/source/wrapper/implfont.hxx82
-rw-r--r--cppcanvas/source/wrapper/implpolypolygon.cxx204
-rw-r--r--cppcanvas/source/wrapper/implpolypolygon.hxx96
-rw-r--r--cppcanvas/source/wrapper/implsprite.cxx239
-rw-r--r--cppcanvas/source/wrapper/implsprite.hxx96
-rw-r--r--cppcanvas/source/wrapper/implspritecanvas.cxx162
-rw-r--r--cppcanvas/source/wrapper/implspritecanvas.hxx109
-rw-r--r--cppcanvas/source/wrapper/impltext.cxx98
-rw-r--r--cppcanvas/source/wrapper/impltext.hxx73
-rw-r--r--cppcanvas/source/wrapper/makefile.mk60
-rw-r--r--cppcanvas/source/wrapper/vclfactory.cxx366
-rw-r--r--cppcanvas/util/cppcanvas.flt4
-rw-r--r--cppcanvas/util/makefile.mk70
77 files changed, 16320 insertions, 0 deletions
diff --git a/cppcanvas/inc/cppcanvas/basegfxfactory.hxx b/cppcanvas/inc/cppcanvas/basegfxfactory.hxx
new file mode 100644
index 000000000000..10be95fc8eb5
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/basegfxfactory.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_BASEGFXFACTORY_HXX
+#define _CPPCANVAS_BASEGFXFACTORY_HXX
+
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/bitmapcanvas.hxx>
+#include <cppcanvas/spritecanvas.hxx>
+#include <cppcanvas/polypolygon.hxx>
+#include <cppcanvas/bitmap.hxx>
+#include <cppcanvas/renderer.hxx>
+#include <cppcanvas/text.hxx>
+#include <cppcanvas/sprite.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+
+namespace basegfx
+{
+ class B2DPolygon;
+ class B2DPolyPolygon;
+}
+
+namespace rtl
+{
+ class OUString;
+}
+
+/* Definition of BaseGfxFactory class */
+
+namespace cppcanvas
+{
+ /** The BaseGfxFactory creates Canvas objects for various basegfx
+ primitives, such as polygons and bitmaps (not yet
+ implemented).
+
+ Please note that the objects created for a specific Canvas can
+ only be drawn on exactly that canvas. You have to regenerate
+ them for different canvases.
+ */
+ class BaseGfxFactory
+ {
+ public:
+ static BaseGfxFactory& getInstance();
+
+ /** Create a polygon from a ::basegfx::B2DPolygon
+
+ The created polygon initially has the same size in user
+ coordinate space as the source polygon
+ */
+ PolyPolygonSharedPtr createPolyPolygon( const CanvasSharedPtr&, const ::basegfx::B2DPolygon& rPoly ) const;
+ PolyPolygonSharedPtr createPolyPolygon( const CanvasSharedPtr&, const ::basegfx::B2DPolyPolygon& rPoly ) const;
+
+ /** Create an uninitialized bitmap with the given size
+ */
+ BitmapSharedPtr createBitmap( const CanvasSharedPtr&, const ::basegfx::B2ISize& rSize ) const;
+
+ /** Create an uninitialized alpha bitmap with the given size
+ */
+ BitmapSharedPtr createAlphaBitmap( const CanvasSharedPtr&, const ::basegfx::B2ISize& rSize ) const;
+
+ /** Create a text portion with the given content string
+ */
+ TextSharedPtr createText( const CanvasSharedPtr&, const ::rtl::OUString& ) const;
+
+ private:
+ friend struct InitInstance2;
+
+ // singleton
+ BaseGfxFactory();
+ ~BaseGfxFactory();
+
+ // default: disabled copy/assignment
+ BaseGfxFactory(const BaseGfxFactory&);
+ BaseGfxFactory& operator=( const BaseGfxFactory& );
+ };
+
+}
+
+#endif /* _CPPCANVAS_BASEGFXFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/bitmap.hxx b/cppcanvas/inc/cppcanvas/bitmap.hxx
new file mode 100644
index 000000000000..425428b24ab5
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/bitmap.hxx
@@ -0,0 +1,83 @@
+/* -*- 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 _CPPCANVAS_BITMAP_HXX
+#define _CPPCANVAS_BITMAP_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/canvasgraphic.hxx>
+#include <cppcanvas/bitmapcanvas.hxx>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XBitmap;
+} } } }
+
+
+/* Definition of Bitmap interface */
+
+namespace cppcanvas
+{
+
+ /** This interface defines a Bitmap canvas object
+
+ Consider this object part of the view, and not of the model
+ data, as this bitmap can only be painted on its parent canvas
+ */
+ class Bitmap : public virtual CanvasGraphic
+ {
+ public:
+ /** Render to parent canvas, with global alpha.
+
+ This method renders the content to the parent canvas,
+ i.e. the canvas this object was constructed for.
+
+ @param nAlphaModulation
+ Global alpha value, with which each pixel alpha value gets
+ multiplied. For a normal, opaque bitmap, this will make
+ the bitmap appear transparent with the given alpha value
+ (value must be in the range [0,1]).
+
+ @return whether the rendering finished successfully.
+ */
+ virtual bool drawAlphaModulated( double nAlphaModulation ) const = 0;
+
+ virtual BitmapCanvasSharedPtr getBitmapCanvas() const = 0;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > getUNOBitmap() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Bitmap > BitmapSharedPtr;
+}
+
+#endif /* _CPPCANVAS_BITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/bitmapcanvas.hxx b/cppcanvas/inc/cppcanvas/bitmapcanvas.hxx
new file mode 100644
index 000000000000..4221833bc29e
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/bitmapcanvas.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 _CPPCANVAS_BITMAPCANVAS_HXX
+#define _CPPCANVAS_BITMAPCANVAS_HXX
+
+#include <sal/types.h>
+#include <osl/diagnose.h>
+
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2isize.hxx>
+#include <cppcanvas/canvas.hxx>
+
+
+/* Definition of BitmapCanvas */
+
+namespace cppcanvas
+{
+ class BitmapCanvas;
+
+ // forward declaration, since cloneBitmapCanvas() also references BitmapCanvas
+ typedef ::boost::shared_ptr< BitmapCanvas > BitmapCanvasSharedPtr;
+
+ /** BitmapCanvas interface
+ */
+ class BitmapCanvas : public virtual Canvas
+ {
+ public:
+ virtual ::basegfx::B2ISize getSize() const = 0;
+
+ // shared_ptr does not allow for covariant return types
+ BitmapCanvasSharedPtr cloneBitmapCanvas() const
+ {
+ BitmapCanvasSharedPtr p( ::boost::dynamic_pointer_cast< BitmapCanvas >(this->clone()) );
+ OSL_ENSURE(p.get(), "BitmapCanvas::cloneBitmapCanvas(): dynamic cast failed");
+ return p;
+ }
+ };
+
+}
+
+#endif /* _CPPCANVAS_BITMAPCANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/canvas.hxx b/cppcanvas/inc/cppcanvas/canvas.hxx
new file mode 100644
index 000000000000..385006fdba46
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/canvas.hxx
@@ -0,0 +1,119 @@
+/* -*- 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 _CPPCANVAS_CANVAS_HXX
+#define _CPPCANVAS_CANVAS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/font.hxx>
+#include <cppcanvas/color.hxx>
+
+namespace rtl
+{
+ class OUString;
+}
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvas;
+ struct ViewState;
+} } } }
+
+
+/* Definition of BitmapCanvas */
+
+namespace cppcanvas
+{
+ class PolyPolygon;
+ class Canvas;
+
+ // forward declaration, since PolyPolygon also references Canvas
+ typedef ::boost::shared_ptr< PolyPolygon > PolyPolygonSharedPtr;
+
+ // forward declaration, since cloneCanvas() also references Canvas
+ typedef ::boost::shared_ptr< Canvas > CanvasSharedPtr;
+
+ /** Canvas interface
+ */
+ class Canvas
+ {
+ public:
+ enum
+ {
+ /** Extra pixel used when canvas anti-aliases.
+
+ Enlarge the bounding box of drawing primitives by this
+ amount in both dimensions, and on both sides of the
+ bounds, to account for extra pixel touched outside the
+ actual primitive bounding box, when the canvas
+ performs anti-aliasing.
+ */
+ ANTIALIASING_EXTRA_SIZE=2
+ };
+
+ virtual ~Canvas() {}
+
+ virtual void setTransformation( const ::basegfx::B2DHomMatrix& rMatrix ) = 0;
+ virtual ::basegfx::B2DHomMatrix getTransformation() const = 0;
+
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly ) = 0;
+ virtual void setClip() = 0;
+
+ /** Get current clip
+
+ @return NULL, if no clip is set, otherwise the current clip poly-polygon
+ */
+ virtual ::basegfx::B2DPolyPolygon const* getClip() const = 0;
+
+ virtual FontSharedPtr createFont( const ::rtl::OUString& rFontName, const double& rCellSize ) const = 0;
+
+ virtual ColorSharedPtr createColor() const = 0;
+
+ virtual CanvasSharedPtr clone() const = 0;
+ virtual void clear() const = 0;
+
+ // this should be considered private. if RTTI gets enabled
+ // someday, remove that to a separate interface
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas > getUNOCanvas() const = 0;
+ virtual ::com::sun::star::rendering::ViewState getViewState() const = 0;
+ };
+
+}
+
+#endif /* _CPPCANVAS_CANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/canvasgraphic.hxx b/cppcanvas/inc/cppcanvas/canvasgraphic.hxx
new file mode 100644
index 000000000000..4ae43fb4334c
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/canvasgraphic.hxx
@@ -0,0 +1,173 @@
+/* -*- 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 _CPPCANVAS_CANVASGRAPHIC_HXX
+#define _CPPCANVAS_CANVASGRAPHIC_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/color.hxx>
+#include <cppcanvas/canvas.hxx>
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+}
+
+
+/* Definition of CanvasGraphic interface */
+
+namespace cppcanvas
+{
+ // forward declaration, since PolyPolygon also derives from CanvasGraphic
+ typedef ::boost::shared_ptr< class PolyPolygon > PolyPolygonSharedPtr;
+
+
+ /** This interface defines basic properties of
+ objects that can be painted on a Canvas
+ */
+ class CanvasGraphic
+ {
+ public:
+
+ /** These enums determine how the primitive color is combined
+ with the background. When performing this calculations, it
+ is assumed that all color values are premultiplied with
+ the corresponding alpha values (if no alpha is specified,
+ 1.0 is assumed). Then, the following general compositing
+ operation is performed:
+
+ C = Ca * Fa + Cb * Fb
+
+ where C is the result color, Ca and Cb are the input
+ colors, premultiplied with alpha, and Fa and Fb are
+ described for the different composite modes (wherein Aa
+ and Ab denote source and destination alpha, respectively).
+ */
+ enum CompositeOp
+ {
+ /// Clear destination. Fa = Fb = 0.
+ CLEAR,
+
+ /// Copy source as-is to destination. Fa = 1, Fb = 0.
+ SOURCE,
+
+ /// Leave destination as-is. Fa = 0, Fb = 1.
+ DESTINATION,
+
+ /// Copy source over destination. Fa = 1, Fb = 1-Aa.
+ OVER,
+
+ /// Copy source under destination. Fa = 1-Ab, Fb = 1.
+ UNDER,
+
+ /// Copy source to destination, but limited to where the destination is. Fa = Ab, Fb = 0.
+ INSIDE,
+
+ /// Leave destination as is, but only where source was. Fa = 0, Fb = Aa.
+ INSIDE_REVERSE,
+
+ /// Copy source to destination, but limited to where destination is not. Fa = 1-Ab, Fb = 0.
+ OUTSIDE,
+
+ /// Leave destination as is, but only where source has not been. Fa = 0, Fb = 1-Aa.
+ OUTSIDE_REVERSE,
+
+ /// Copy source over destination, but only where destination is. Keep destination. Fa = Ab, Fb = 1-Aa.
+ ATOP,
+
+ /// Copy destination over source, but only where source is. Keep source. Fa = 1-Ab, Fb = Aa.
+ ATOP_REVERSE,
+
+ /// Take only parts where either source or destination, but not both are. Fa = 1-Ab, Fb = 1-Aa.
+ XOR,
+
+ /** simply add contributions of both source and destination. The
+ resulting color values are limited to the permissible color
+ range, and clipped to the maximal value, if exceeded. Fa = 1, Fb = 1.
+ */
+ ADD,
+
+ /// Fa = min(1,(1-Ab)/Aa), Fb = 1
+ SATURATE
+ };
+
+ virtual ~CanvasGraphic() {}
+
+ /** Set object transformation matrix
+ */
+ virtual void setTransformation( const ::basegfx::B2DHomMatrix& rMatrix ) = 0;
+ /** Get object transformation matrix
+ */
+ virtual ::basegfx::B2DHomMatrix getTransformation() const = 0;
+
+ /** Set object clipping polygon
+ */
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly ) = 0;
+ /** Clear object clipping polygon
+ */
+ virtual void setClip() = 0;
+ /** Get object clipping polygon
+
+ @return NULL, if no clip is set; otherwise, the current clip poly-polygon is returned
+ */
+ virtual ::basegfx::B2DPolyPolygon const* getClip() const = 0;
+
+ /** Set object color
+ */
+ virtual void setRGBAColor( Color::IntSRGBA ) = 0;
+ /** Get object color
+ */
+ virtual Color::IntSRGBA getRGBAColor() const = 0;
+
+ /** Set object composite mode
+ */
+ virtual void setCompositeOp( CompositeOp aOp ) = 0;
+ /** Get object composite mode
+ */
+ virtual CompositeOp getCompositeOp() const = 0;
+
+ /** Render to parent canvas
+
+ This method renders the content to the parent canvas,
+ i.e. the canvas this object was constructed for.
+
+ @return whether the rendering finished successfully.
+ */
+ virtual bool draw() const = 0;
+
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::CanvasGraphic > CanvasGraphicSharedPtr;
+}
+
+#endif /* _CPPCANVAS_CANVASGRAPHIC_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/color.hxx b/cppcanvas/inc/cppcanvas/color.hxx
new file mode 100644
index 000000000000..6a8e872f328d
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/color.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_COLOR_HXX
+#define _CPPCANVAS_COLOR_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of Color class */
+
+namespace cppcanvas
+{
+ class Color
+ {
+ public:
+ /** Color in the sRGB color space, plus alpha channel
+
+ The four bytes of the sal_uInt32 are allocated as follows
+ to the color channels and alpha: 0xRRGGBBAA.
+ */
+ typedef sal_uInt32 IntSRGBA;
+
+ virtual ~Color() {}
+
+ virtual IntSRGBA getIntSRGBA( ::com::sun::star::uno::Sequence< double >& rDeviceColor ) const = 0;
+ virtual ::com::sun::star::uno::Sequence< double > getDeviceColor( IntSRGBA aSRGBA ) const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Color > ColorSharedPtr;
+
+ inline sal_uInt8 getRed( Color::IntSRGBA nCol )
+ {
+ return static_cast<sal_uInt8>( (nCol&0xFF000000U) >> 24U );
+ }
+
+ inline sal_uInt8 getGreen( Color::IntSRGBA nCol )
+ {
+ return static_cast<sal_uInt8>( (nCol&0x00FF0000U) >> 16U );
+ }
+
+ inline sal_uInt8 getBlue( Color::IntSRGBA nCol )
+ {
+ return static_cast<sal_uInt8>( (nCol&0x0000FF00U) >> 8U );
+ }
+
+ inline sal_uInt8 getAlpha( Color::IntSRGBA nCol )
+ {
+ return static_cast<sal_uInt8>( nCol&0x000000FFU );
+ }
+
+ inline Color::IntSRGBA makeColor( sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue, sal_uInt8 nAlpha )
+ {
+ return (nRed << 24U)|(nGreen << 16U)|(nBlue << 8U)|(nAlpha);
+ }
+
+ inline sal_Int32 unMakeColor( sal_uInt8 nAlpha, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
+ {
+ return (nAlpha << 24U)|(nRed << 16U)|(nGreen << 8U)|(nBlue);
+ }
+
+ inline sal_Int32 makeColorARGB( sal_uInt8 nAlpha, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
+ {
+ return (nAlpha << 24U)|(nRed << 16U)|(nGreen << 8U)|(nBlue);
+ }
+
+}
+
+#endif /* _CPPCANVAS_COLOR_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/customsprite.hxx b/cppcanvas/inc/cppcanvas/customsprite.hxx
new file mode 100644
index 000000000000..bd92fbd6f76a
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/customsprite.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_CUSTOMSPRITE_HXX
+#define _CPPCANVAS_CUSTOMSPRITE_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/sprite.hxx>
+#include <cppcanvas/canvas.hxx>
+
+
+/* Definition of CustomSprite class */
+
+namespace cppcanvas
+{
+
+ class CustomSprite : public virtual Sprite
+ {
+ public:
+
+ virtual CanvasSharedPtr getContentCanvas() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::CustomSprite > CustomSpriteSharedPtr;
+}
+
+#endif /* _CPPCANVAS_CUSTOMSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/font.hxx b/cppcanvas/inc/cppcanvas/font.hxx
new file mode 100644
index 000000000000..b8d864321fd8
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/font.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_FONT_HXX
+#define _CPPCANVAS_FONT_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+namespace rtl
+{
+ class OUString;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvasFont;
+} } } }
+
+/* Definition of Font class */
+
+namespace cppcanvas
+{
+
+ class Font
+ {
+ public:
+ virtual ~Font() {}
+
+ virtual ::rtl::OUString getName() const = 0;
+ virtual double getCellSize() const = 0;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont > getUNOFont() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Font > FontSharedPtr;
+}
+
+#endif /* _CPPCANVAS_FONT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/polypolygon.hxx b/cppcanvas/inc/cppcanvas/polypolygon.hxx
new file mode 100644
index 000000000000..0adc9426b692
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/polypolygon.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_POLYPOLYGON_HXX
+#define _CPPCANVAS_POLYPOLYGON_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/canvasgraphic.hxx>
+
+namespace basegfx
+{
+ class B2DPolygon;
+ class B2DPolyPolygon;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XPolyPolygon2D;
+} } } }
+
+
+/* Definition of PolyPolygon interface */
+
+namespace cppcanvas
+{
+
+ /** This interface defines a PolyPolygon canvas object
+
+ Consider this object part of the view, and not of the model
+ data. Although the given polygon is typically copied and held
+ internally (to facilitate migration to incompatible canvases),
+ ::basegfx::B2DPolygon et al. are ref-counted copy-on-write
+ classes, i.e. memory shouldn't be wasted. On the other hand,
+ the API polygon created internally _does_ necessarily
+ duplicate the data held, but can be easily flushed away via
+ flush().
+ */
+ class PolyPolygon : public virtual CanvasGraphic
+ {
+ public:
+ virtual void addPolygon( const ::basegfx::B2DPolygon& rPoly ) = 0;
+ virtual void addPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly ) = 0;
+
+ /** Set polygon fill color
+ */
+ virtual void setRGBAFillColor( Color::IntSRGBA ) = 0;
+ /** Set polygon line color
+ */
+ virtual void setRGBALineColor( Color::IntSRGBA ) = 0;
+ /** Get polygon fill color
+ */
+ virtual Color::IntSRGBA getRGBAFillColor() const = 0;
+ /** Get polygon line color
+ */
+ virtual Color::IntSRGBA getRGBALineColor() const = 0;
+
+ virtual void setStrokeWidth( const double& rStrokeWidth ) = 0;
+ virtual double getStrokeWidth() const = 0;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D > getUNOPolyPolygon() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::PolyPolygon > PolyPolygonSharedPtr;
+}
+
+#endif /* _CPPCANVAS_POLYPOLYGON_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/renderer.hxx b/cppcanvas/inc/cppcanvas/renderer.hxx
new file mode 100644
index 000000000000..a01b438670a8
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/renderer.hxx
@@ -0,0 +1,153 @@
+/* -*- 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 _CPPCANVAS_RENDERER_HXX
+#define _CPPCANVAS_RENDERER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <cppcanvas/canvasgraphic.hxx>
+#include <cppcanvas/color.hxx>
+
+namespace basegfx
+{
+ class B2DRange;
+}
+
+/* Definition of Renderer interface */
+
+namespace cppcanvas
+{
+
+ class Renderer : public virtual CanvasGraphic
+ {
+ public:
+ /** Render subset of metafile to given canvas
+
+ This method renders the given subset of the content to the
+ associated canvas.
+
+ @param nStartIndex
+ The index of the first action to be rendered (the indices
+ correspond roughly to the action indices of the
+ originating GDIMetaFile. Note, although, that certain
+ actions, e.g. text, accounts for more than one index: a
+ text produces as many addressable indices as it has
+ characters).
+
+ @param nEndIndex
+ The index of the first action _not_ painted anymore,
+ i.e. the action after the last action rendered (the
+ indices correspond roughly to the action indices of the
+ originating GDIMetaFile. Note, although, that certain
+ actions, e.g. text, accounts for more than one index: a
+ text produces as many addressable indices as it has
+ characters).
+
+ @return whether the rendering finished successfully.
+ */
+ virtual bool drawSubset( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const = 0;
+
+ /** Query bounding box of metafile subset
+
+ This method queries the actual bounding box of the given
+ subset, when rendered on the associated canvas.
+
+ @param nStartIndex
+ The index of the first action to be rendered (the indices
+ correspond roughly to the action indices of the
+ originating GDIMetaFile. Note, although, that certain
+ actions, e.g. text, accounts for more than one index: a
+ text produces as many addressable indices as it has
+ characters).
+
+ @param nEndIndex
+ The index of the first action _not_ painted anymore,
+ i.e. the action after the last action rendered (the
+ indices correspond roughly to the action indices of the
+ originating GDIMetaFile. Note, although, that certain
+ actions, e.g. text, accounts for more than one index: a
+ text produces as many addressable indices as it has
+ characters).
+
+ @return the bounding box of the specified subset
+ */
+ virtual ::basegfx::B2DRange getSubsetArea( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const = 0;
+
+ /** Parameters for the Renderer
+ */
+ struct Parameters
+ {
+ /// Optionally forces the fill color attribute for all actions
+ ::boost::optional< Color::IntSRGBA > maFillColor;
+
+ /// Optionally forces the line color attribute for all actions
+ ::boost::optional< Color::IntSRGBA > maLineColor;
+
+ /// Optionally forces the text color attribute for all actions
+ ::boost::optional< Color::IntSRGBA > maTextColor;
+
+ /// Optionally forces the given fontname for all text actions
+ ::boost::optional< ::rtl::OUString > maFontName;
+
+ /** Optionally transforms all text output actions with the
+ given matrix (in addition to the overall canvas
+ transformation).
+
+ Note that the matrix given here is applied to the unit
+ rect coordinate system, i.e. the metafile is assumed
+ to be contained in the unit rect.
+ */
+ ::boost::optional< ::basegfx::B2DHomMatrix > maTextTransformation;
+
+ /// Optionally forces the given font weight for all text actions
+ ::boost::optional< sal_Int8 > maFontWeight;
+
+ /// Optionally forces the given font letter form (italics etc.) for all text actions
+ ::boost::optional< sal_Int8 > maFontLetterForm;
+
+ /// Optionally forces the given font proportion (condensed, monospaced etc.) for all text actions
+ ::boost::optional< sal_Int8 > maFontProportion;
+
+ /// Optionally forces underlining for all text actions
+ ::boost::optional< bool > maFontUnderline;
+ };
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Renderer > RendererSharedPtr;
+}
+
+#endif /* _CPPCANVAS_RENDERER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/sprite.hxx b/cppcanvas/inc/cppcanvas/sprite.hxx
new file mode 100644
index 000000000000..08c2beb2286a
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/sprite.hxx
@@ -0,0 +1,119 @@
+/* -*- 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 _CPPCANVAS_SPRITE_HXX
+#define _CPPCANVAS_SPRITE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+ class B2DPoint;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XSprite;
+} } } }
+
+
+/* Definition of Sprite class */
+
+namespace cppcanvas
+{
+
+ class Sprite
+ {
+ public:
+ virtual ~Sprite() {}
+
+ virtual void setAlpha( const double& rAlpha ) = 0;
+
+ /** Set the sprite position on screen
+
+ This method differs from the XSprite::move() insofar, as
+ no viewstate/renderstate transformations are applied to
+ the specified position. The given position is interpreted
+ in device coordinates (i.e. screen pixel)
+ */
+ virtual void movePixel( const ::basegfx::B2DPoint& rNewPos ) = 0;
+
+ /** Set the sprite position on screen
+
+ This method sets the sprite position in the view
+ coordinate system of the parent canvas
+ */
+ virtual void move( const ::basegfx::B2DPoint& rNewPos ) = 0;
+
+ virtual void transform( const ::basegfx::B2DHomMatrix& rMatrix ) = 0;
+
+ /** Set output clipping
+
+ This method differs from the XSprite::clip() insofar, as
+ no viewstate/renderstate transformations are applied to
+ the specified clip polygon. The given polygon is
+ interpreted in device coordinates (i.e. screen pixel)
+ */
+ virtual void setClipPixel( const ::basegfx::B2DPolyPolygon& rClipPoly ) = 0;
+
+ /** Set output clipping
+
+ This method applies the clip poly-polygon interpreted in
+ the view coordinate system of the parent canvas.
+ */
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly ) = 0;
+
+ virtual void setClip() = 0;
+
+ virtual void show() = 0;
+ virtual void hide() = 0;
+
+ /** Change the sprite priority
+
+ @param fPriority
+ New sprite priority. The higher the priority, the further
+ towards the viewer the sprite appears. That is, sprites
+ with higher priority appear before ones with lower
+ priority.
+ */
+ virtual void setPriority( double fPriority ) = 0;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSprite > getUNOSprite() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Sprite > SpriteSharedPtr;
+}
+
+#endif /* _CPPCANVAS_SPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/spritecanvas.hxx b/cppcanvas/inc/cppcanvas/spritecanvas.hxx
new file mode 100644
index 000000000000..df29d4345a85
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/spritecanvas.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_SPRITECANVAS_HXX
+#define _CPPCANVAS_SPRITECANVAS_HXX
+
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+#include <cppcanvas/bitmapcanvas.hxx>
+#include <cppcanvas/sprite.hxx>
+#include <cppcanvas/customsprite.hxx>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XSpriteCanvas;
+} } } }
+
+
+/* Definition of SpriteCanvas */
+
+namespace cppcanvas
+{
+ class SpriteCanvas;
+
+ // forward declaration, since cloneSpriteCanvas() also references SpriteCanvas
+ typedef ::boost::shared_ptr< ::cppcanvas::SpriteCanvas > SpriteCanvasSharedPtr;
+
+ /** SpriteCanvas interface
+ */
+ class SpriteCanvas : public virtual BitmapCanvas
+ {
+ public:
+ virtual bool updateScreen( bool bUpdateAll ) const = 0;
+
+ virtual CustomSpriteSharedPtr createCustomSprite( const ::basegfx::B2DSize& ) const = 0;
+ virtual SpriteSharedPtr createClonedSprite( const SpriteSharedPtr& ) const = 0;
+
+ // shared_ptr does not allow for covariant return types
+ SpriteCanvasSharedPtr cloneSpriteCanvas() const
+ {
+ SpriteCanvasSharedPtr p( ::boost::dynamic_pointer_cast< SpriteCanvas >(this->clone()) );
+ OSL_ENSURE(p.get(), "SpriteCanvas::cloneSpriteCanvas(): dynamic cast failed");
+ return p;
+ }
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas > getUNOSpriteCanvas() const = 0;
+ };
+
+}
+
+#endif /* _CPPCANVAS_SPRITECANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/text.hxx b/cppcanvas/inc/cppcanvas/text.hxx
new file mode 100644
index 000000000000..1787103141ae
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/text.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_TEXT_HXX
+#define _CPPCANVAS_TEXT_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/canvasgraphic.hxx>
+
+
+namespace rtl
+{
+ class OUString;
+}
+
+
+/* Definition of Text interface */
+
+namespace cppcanvas
+{
+ class Text : public virtual CanvasGraphic
+ {
+ public:
+ virtual void setFont( const FontSharedPtr& ) = 0;
+ virtual FontSharedPtr getFont() = 0;
+ };
+
+ typedef ::boost::shared_ptr< ::cppcanvas::Text > TextSharedPtr;
+}
+
+#endif /* _CPPCANVAS_TEXT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/cppcanvas/vclfactory.hxx b/cppcanvas/inc/cppcanvas/vclfactory.hxx
new file mode 100644
index 000000000000..acd51dfd8a81
--- /dev/null
+++ b/cppcanvas/inc/cppcanvas/vclfactory.hxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_VCLFACTORY_HXX
+#define _CPPCANVAS_VCLFACTORY_HXX
+
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/bitmapcanvas.hxx>
+#include <cppcanvas/spritecanvas.hxx>
+#include <cppcanvas/polypolygon.hxx>
+#include <cppcanvas/bitmap.hxx>
+#include <cppcanvas/renderer.hxx>
+#include <cppcanvas/text.hxx>
+#include <cppcanvas/sprite.hxx>
+
+
+class Window;
+class Bitmap;
+class BitmapEx;
+class Polygon;
+class PolyPolygon;
+class Size;
+class Graphic;
+class GDIMetaFile;
+class Animation;
+
+namespace rtl
+{
+ class OUString;
+}
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XBitmapCanvas;
+ class XSpriteCanvas;
+} } } }
+
+/* Definition of VCLFactory class */
+
+namespace cppcanvas
+{
+ /** The VCLFactory creates Canvas objects for various VCL
+ OutputDevice primitives, such as windows, polygons, bitmaps
+ and metafiles.
+
+ Please note that the objects created for a specific Canvas can
+ only be drawn on exactly that canvas. You have to regenerate
+ them for different canvases.
+ */
+ class VCLFactory
+ {
+ public:
+ static VCLFactory& getInstance();
+
+ BitmapCanvasSharedPtr createCanvas( const ::Window& rVCLWindow );
+ BitmapCanvasSharedPtr createCanvas( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmapCanvas >& xCanvas );
+
+ SpriteCanvasSharedPtr createSpriteCanvas( const ::Window& rVCLWindow ) const;
+ SpriteCanvasSharedPtr createSpriteCanvas( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas >& xCanvas ) const;
+ SpriteCanvasSharedPtr createFullscreenSpriteCanvas( const ::Window& rVCLWindow, const Size& rFullscreenSize ) const;
+
+ /** Create a polygon from a tools::Polygon
+
+ The created polygon initially has the same size in user
+ coordinate space as the source polygon
+ */
+ PolyPolygonSharedPtr createPolyPolygon( const CanvasSharedPtr&, const ::Polygon& rPoly ) const;
+ PolyPolygonSharedPtr createPolyPolygon( const CanvasSharedPtr&, const ::PolyPolygon& rPoly ) const;
+
+ /** Create an uninitialized bitmap with the given size
+ */
+ BitmapSharedPtr createBitmap( const CanvasSharedPtr&, const ::Size& rSize ) const;
+
+ /** Create an uninitialized alpha bitmap with the given size
+ */
+ BitmapSharedPtr createAlphaBitmap( const CanvasSharedPtr&, const ::Size& rSize ) const;
+
+ /** Create a bitmap from a VCL Bitmap
+ */
+ BitmapSharedPtr createBitmap( const CanvasSharedPtr&, const ::Bitmap& rBitmap ) const;
+ BitmapSharedPtr createBitmap( const CanvasSharedPtr&, const ::BitmapEx& rBmpEx ) const;
+
+ /** Create a renderer object from a Graphic
+
+ The created renderer initially draws the graphic
+ one-by-one units large, in user coordinate space
+ */
+ RendererSharedPtr createRenderer( const CanvasSharedPtr& rCanvas,
+ const ::Graphic& rGraphic,
+ const Renderer::Parameters& rParms ) const;
+ /** Create a renderer object from a Metafile
+
+ The created renderer initially draws the metafile
+ one-by-one units large, in user coordinate space
+ */
+ RendererSharedPtr createRenderer( const CanvasSharedPtr& rCanvas,
+ const ::GDIMetaFile& rMtf,
+ const Renderer::Parameters& rParms ) const;
+
+ /** Create an animated sprite from a VCL animation
+ */
+ SpriteSharedPtr createAnimatedSprite( const SpriteCanvasSharedPtr&, const ::Animation& rAnim ) const;
+
+ /** Create a text portion with the given content string
+ */
+ TextSharedPtr createText( const CanvasSharedPtr&, const ::rtl::OUString& ) const;
+
+ private:
+ friend struct InitInstance;
+
+ // singleton
+ VCLFactory();
+ ~VCLFactory();
+
+ // default: disabled copy/assignment
+ VCLFactory(const VCLFactory&);
+ VCLFactory& operator=( const VCLFactory& );
+ };
+
+}
+
+#endif /* _CPPCANVAS_VCLFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/makefile.mk b/cppcanvas/inc/makefile.mk
new file mode 100644
index 000000000000..ccf2d3a92425
--- /dev/null
+++ b/cppcanvas/inc/makefile.mk
@@ -0,0 +1,47 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..
+
+PRJNAME=cppcanvas
+TARGET=inc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.IF "$(ENABLE_PCH)"!=""
+ALLTAR : \
+ $(SLO)$/precompiled.pch \
+ $(SLO)$/precompiled_ex.pch
+
+.ENDIF # "$(ENABLE_PCH)"!=""
+
diff --git a/cppcanvas/inc/pch/precompiled_cppcanvas.cxx b/cppcanvas/inc/pch/precompiled_cppcanvas.cxx
new file mode 100644
index 000000000000..04b6f76e6ab5
--- /dev/null
+++ b/cppcanvas/inc/pch/precompiled_cppcanvas.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_cppcanvas.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/inc/pch/precompiled_cppcanvas.hxx b/cppcanvas/inc/pch/precompiled_cppcanvas.hxx
new file mode 100644
index 000000000000..87c94a92a0ff
--- /dev/null
+++ b/cppcanvas/inc/pch/precompiled_cppcanvas.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:36.717845
+
+#ifdef PRECOMPILED_HEADERS
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/prj/build.lst b/cppcanvas/prj/build.lst
new file mode 100644
index 000000000000..317e3276c249
--- /dev/null
+++ b/cppcanvas/prj/build.lst
@@ -0,0 +1,8 @@
+cx cppcanvas : comphelper cppuhelper offuh tools vcl basegfx canvas NULL
+cx cppcanvas usr1 - all cx_mkout NULL
+cx cppcanvas\inc nmake - all cx_inc NULL
+cx cppcanvas\source\tools nmake - all cx_tools cx_inc NULL
+cx cppcanvas\source\wrapper nmake - all cx_wrapper cx_inc NULL
+cx cppcanvas\source\mtfrenderer nmake - all cx_mtfrenderer cx_inc NULL
+cx cppcanvas\util nmake - all cx_util cx_tools cx_wrapper cx_mtfrenderer NULL
+cx cppcanvas\source\uno nmake - all cx_uno cx_tools cx_wrapper cx_mtfrenderer cx_util NULL
diff --git a/cppcanvas/prj/d.lst b/cppcanvas/prj/d.lst
new file mode 100644
index 000000000000..c05b2f4102d3
--- /dev/null
+++ b/cppcanvas/prj/d.lst
@@ -0,0 +1,21 @@
+..\%__SRC%\bin\cppcanv*.dll %_DEST%\bin%_EXT%\cppcanv*.dll
+..\%__SRC%\bin\mtfrenderer*.dll %_DEST%\bin%_EXT%\mtfrenderer*.dll
+..\%__SRC%\lib\icppcanvas.lib %_DEST%\lib%_EXT%\icppcanvas.lib
+..\%__SRC%\lib\lib*.* %_DEST%\lib%_EXT%\lib*.*
+..\%__SRC%\misc\mtfrenderer.component %_DEST%\xml\mtfrenderer.component
+
+mkdir: %_DEST%\inc%_EXT%\cppcanvas
+..\inc\cppcanvas\bitmap.hxx %_DEST%\inc%_EXT%\cppcanvas\bitmap.hxx
+..\inc\cppcanvas\bitmapcanvas.hxx %_DEST%\inc%_EXT%\cppcanvas\bitmapcanvas.hxx
+..\inc\cppcanvas\canvas.hxx %_DEST%\inc%_EXT%\cppcanvas\canvas.hxx
+..\inc\cppcanvas\canvasgraphic.hxx %_DEST%\inc%_EXT%\cppcanvas\canvasgraphic.hxx
+..\inc\cppcanvas\color.hxx %_DEST%\inc%_EXT%\cppcanvas\color.hxx
+..\inc\cppcanvas\customsprite.hxx %_DEST%\inc%_EXT%\cppcanvas\customsprite.hxx
+..\inc\cppcanvas\font.hxx %_DEST%\inc%_EXT%\cppcanvas\font.hxx
+..\inc\cppcanvas\polypolygon.hxx %_DEST%\inc%_EXT%\cppcanvas\polypolygon.hxx
+..\inc\cppcanvas\renderer.hxx %_DEST%\inc%_EXT%\cppcanvas\renderer.hxx
+..\inc\cppcanvas\sprite.hxx %_DEST%\inc%_EXT%\cppcanvas\sprite.hxx
+..\inc\cppcanvas\spritecanvas.hxx %_DEST%\inc%_EXT%\cppcanvas\spritecanvas.hxx
+..\inc\cppcanvas\text.hxx %_DEST%\inc%_EXT%\cppcanvas\text.hxx
+..\inc\cppcanvas\vclfactory.hxx %_DEST%\inc%_EXT%\cppcanvas\vclfactory.hxx
+..\inc\cppcanvas\basegfxfactory.hxx %_DEST%\inc%_EXT%\cppcanvas\basegfxfactory.hxx
diff --git a/cppcanvas/source/inc/action.hxx b/cppcanvas/source/inc/action.hxx
new file mode 100644
index 000000000000..971cfcb4609f
--- /dev/null
+++ b/cppcanvas/source/inc/action.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_ACTION_HXX
+#define _CPPCANVAS_ACTION_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DRange;
+}
+
+
+/* Definition of Action interface */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ /** Interface for internal render actions
+
+ This interface is implemented by all objects generated
+ from the metafile renderer, and corresponds roughly to the
+ VCL meta action.
+ */
+ class Action
+ {
+ public:
+ /** Used for rendering action subsets
+
+ There are several cases where an Action might have
+ subsettable content, e.g. text, or referenced
+ metafiles, like the transparent action.
+
+ Generally, at the metafile renderer, all actions are
+ 'flattened' out, i.e. a meta action rendering the
+ string "Hello" counts five indices, and a transparent
+ action containing a metafile with 100 actions counts
+ at least 100 indices (contained transparency or text
+ actions recursively add to this value). From the
+ outside, the subset to render is referenced via this
+ flat index range
+ */
+ struct Subset
+ {
+ /** Denotes start of the subset.
+
+ The index given here specifies the first subaction
+ to render.
+ */
+ sal_Int32 mnSubsetBegin;
+
+ /** Denotes end of the subset
+
+ The index given here specifies the first subaction
+ <em>not<em> to render, i.e. one action behind the
+ subset to be rendered
+ */
+ sal_Int32 mnSubsetEnd;
+ };
+
+ virtual ~Action() {}
+
+ /** Render this action to the associated canvas
+
+ @param rTransformation
+ Transformation matrix to apply before rendering
+
+ @return true, if rendering was successful. If
+ rendering failed, false is returned.
+ */
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const = 0;
+
+ /** Render the given part of the action to the associated
+ canvas.
+
+ @param rTransformation
+ Transformation matrix to apply before rendering
+
+ @param rSubset
+ Subset of the action to render. See Subset description
+ for index semantics.
+
+ @return true, if rendering was successful. If the
+ specified subset is invalid for this action, or if
+ rendering failed for other reasons, false is returned.
+ */
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const = 0;
+
+ /** Query bounds of this action on the associated canvas
+
+ @param rTransformation
+ Transformation matrix to apply
+
+ @return the bounds for this action in device
+ coordinate space.
+ */
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const = 0;
+
+ /** Query bounds for the given part of the action on the
+ associated canvas.
+
+ @param rTransformation
+ Transformation matrix to apply.
+
+ @param rSubset
+ Subset of the action to query. See Subset description
+ for index semantics.
+
+ @return the bounds for the given subset in device
+ coordinate space.
+ */
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const = 0;
+
+ /** Query action count.
+
+ This method returns the number of subset actions
+ contained in this action. The render( Subset ) method
+ must accept subset ranges up to the value returned
+ here.
+
+ @return the number of subset actions
+ */
+ virtual sal_Int32 getActionCount() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< Action > ActionSharedPtr;
+
+ }
+}
+
+#endif /* _CPPCANVAS_ACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/inc/canvasgraphichelper.hxx b/cppcanvas/source/inc/canvasgraphichelper.hxx
new file mode 100644
index 000000000000..6d49939be1b7
--- /dev/null
+++ b/cppcanvas/source/inc/canvasgraphichelper.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_CANVASGRAPHICHELPER_HXX
+#define _CPPCANVAS_CANVASGRAPHICHELPER_HXX
+
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <cppcanvas/canvasgraphic.hxx>
+
+#include <boost/optional.hpp>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XGraphicDevice;
+} } } }
+
+
+/* Definition of CanvasGraphicHelper class */
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+
+ class CanvasGraphicHelper : public virtual CanvasGraphic
+ {
+ public:
+ CanvasGraphicHelper( const CanvasSharedPtr& rParentCanvas );
+
+ // CanvasGraphic implementation
+ virtual void setTransformation( const ::basegfx::B2DHomMatrix& rMatrix );
+ virtual ::basegfx::B2DHomMatrix getTransformation() const;
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly );
+ virtual void setClip();
+ virtual ::basegfx::B2DPolyPolygon const* getClip() const;
+ virtual void setRGBAColor( Color::IntSRGBA );
+ virtual Color::IntSRGBA getRGBAColor() const;
+ virtual void setCompositeOp( CompositeOp aOp );
+ virtual CompositeOp getCompositeOp() const;
+
+ protected:
+ // for our clients
+ // ===============
+ CanvasSharedPtr getCanvas() const;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice > getGraphicDevice() const;
+ const ::com::sun::star::rendering::RenderState& getRenderState() const;
+
+ private:
+ mutable ::com::sun::star::rendering::RenderState maRenderState;
+
+ boost::optional<basegfx::B2DPolyPolygon> maClipPolyPolygon;
+ CanvasSharedPtr mpCanvas;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice > mxGraphicDevice;
+ };
+
+ }
+}
+
+#endif /* _CPPCANVAS_CANVASGRAPHICHELPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx
new file mode 100644
index 000000000000..3c1ec6de127f
--- /dev/null
+++ b/cppcanvas/source/inc/implrenderer.hxx
@@ -0,0 +1,327 @@
+/* -*- 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 _CPPCANVAS_IMPLRENDERER_HXX
+#define _CPPCANVAS_IMPLRENDERER_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/renderer.hxx>
+#include <cppcanvas/canvas.hxx>
+
+#include <canvasgraphichelper.hxx>
+#include <action.hxx>
+
+#include <vector>
+
+class GDIMetaFile;
+class VirtualDevice;
+class Gradient;
+class BitmapEx;
+class MapMode;
+class Size;
+class Rectangle;
+class Font;
+class PolyPolygon;
+class Point;
+class MetaCommentAction;
+
+namespace basegfx {
+ class B2DPolyPolygon;
+ class B2DPolygon;
+}
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+ struct OutDevState;
+ struct ActionFactoryParameters;
+ struct EMFPObject;
+ struct XForm;
+
+ // state stack of OutputDevice, to correctly handle
+ // push/pop actions
+ typedef ::std::vector< OutDevState > VectorOfOutDevStates;
+
+ // EMF+
+ // TODO: replace?
+ struct XForm
+ {
+ float eM11;
+ float eM12;
+ float eM21;
+ float eM22;
+ float eDx;
+ float eDy;
+ XForm()
+ {
+ SetIdentity ();
+ };
+
+ void SetIdentity ()
+ {
+ eM11 = eM22 = 1.0f;
+ eDx = eDy = eM12 = eM21 = 0.0f;
+ }
+
+ void Set (float m11, float m12, float dx, float m21, float m22, float dy)
+ {
+ eM11 = m11;
+ eM12 = m12;
+ eDx = dx;
+ eM21 = m21;
+ eM22 = m22;
+ eDy = dy;
+ }
+
+ void Set (XForm f)
+ {
+ eM11 = f.eM11;
+ eM12 = f.eM12;
+ eM21 = f.eM21;
+ eM22 = f.eM22;
+ eDx = f.eDx;
+ eDy = f.eDy;
+ }
+
+ void Multiply (float m11, float m12, float dx, float m21, float m22, float dy)
+ {
+ eM11 = eM11*m11 + eM12*m21;
+ eM12 = eM11*m12 + eM12*m22;
+ eM21 = eM21*m11 + eM22*m21;
+ eM22 = eM21*m12 + eM22*m22;
+ eDx *= eDx*m11 + eDy*m21 + dx;
+ eDy *= eDx*m12 + eDy*m22 + dy;
+ }
+
+ void Multiply (XForm f)
+ {
+ eM11 = eM11*f.eM11 + eM12*f.eM21;
+ eM12 = eM11*f.eM12 + eM12*f.eM22;
+ eM21 = eM21*f.eM11 + eM22*f.eM21;
+ eM22 = eM21*f.eM12 + eM22*f.eM22;
+ eDx *= eDx*f.eM11 + eDy*f.eM21 + f.eDx;
+ eDy *= eDx*f.eM12 + eDy*f.eM22 + f.eDy;
+ }
+
+#ifdef OSL_BIGENDIAN
+// currently unused
+static float GetSwapFloat( SvStream& rSt )
+{
+ float fTmp;
+ sal_Int8* pPtr = (sal_Int8*)&fTmp;
+ rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
+ return fTmp;
+}
+#endif
+
+ friend SvStream& operator>>( SvStream& rIn, XForm& rXForm )
+ {
+ if ( sizeof( float ) != 4 )
+ {
+ OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
+ rXForm = XForm();
+ }
+ else
+ {
+#ifdef OSL_BIGENDIAN
+ rXForm.eM11 = GetSwapFloat( rIn );
+ rXForm.eM12 = GetSwapFloat( rIn );
+ rXForm.eM21 = GetSwapFloat( rIn );
+ rXForm.eM22 = GetSwapFloat( rIn );
+ rXForm.eDx = GetSwapFloat( rIn );
+ rXForm.eDy = GetSwapFloat( rIn );
+#else
+ rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
+ >> rXForm.eDx >> rXForm.eDy;
+#endif
+ }
+ return rIn;
+ }
+ };
+
+ class ImplRenderer : public virtual Renderer, protected CanvasGraphicHelper
+ {
+ public:
+ ImplRenderer( const CanvasSharedPtr& rCanvas,
+ const GDIMetaFile& rMtf,
+ const Parameters& rParms );
+ ImplRenderer( const CanvasSharedPtr& rCanvas,
+ const BitmapEx& rBmpEx,
+ const Parameters& rParms );
+
+ virtual ~ImplRenderer();
+
+ virtual bool draw() const;
+ virtual bool drawSubset( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const;
+ virtual ::basegfx::B2DRange getSubsetArea( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const;
+
+
+ // element of the Renderer's action vector. Need to be
+ // public, since some functors need it, too.
+ struct MtfAction
+ {
+ MtfAction( const ActionSharedPtr& rAction,
+ sal_Int32 nOrigIndex ) :
+ mpAction( rAction ),
+ mnOrigIndex( nOrigIndex )
+ {
+ }
+
+ ActionSharedPtr mpAction;
+ sal_Int32 mnOrigIndex;
+ };
+
+ // prefetched and prepared canvas actions
+ // (externally not visible)
+ typedef ::std::vector< MtfAction > ActionVector;
+
+ /* EMF+ */
+ void ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, sal_uInt32 flags = 0);
+ void ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags = 0);
+ void MapToDevice (double &x, double &y);
+ ::basegfx::B2DPoint Map (::basegfx::B2DPoint& p);
+ ::basegfx::B2DPoint Map (double ix, double iy);
+ ::basegfx::B2DSize MapSize (double iwidth, double iheight);
+ ::basegfx::B2DRange MapRectangle (double ix, double iy, double iwidth, double iheight);
+
+ private:
+ // default: disabled copy/assignment
+ ImplRenderer(const ImplRenderer&);
+ ImplRenderer& operator=( const ImplRenderer& );
+
+ void updateClipping( const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ActionFactoryParameters& rParms,
+ bool bIntersect );
+
+ void updateClipping( const ::Rectangle& rClipRect,
+ const ActionFactoryParameters& rParms,
+ bool bIntersect );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont > createFont( double& o_rFontRotation,
+ const ::Font& rFont,
+ const ActionFactoryParameters& rParms ) const;
+ bool createActions( GDIMetaFile& rMtf,
+ const ActionFactoryParameters& rParms,
+ bool bSubsettableActions );
+ bool createFillAndStroke( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const ActionFactoryParameters& rParms );
+ bool createFillAndStroke( const ::basegfx::B2DPolygon& rPoly,
+ const ActionFactoryParameters& rParms );
+ void skipContent( GDIMetaFile& rMtf,
+ const char* pCommentString,
+ sal_Int32& io_rCurrActionIndex ) const;
+
+ bool isActionContained( GDIMetaFile& rMtf,
+ const char* pCommentString,
+ sal_uInt16 nType ) const;
+
+ void createGradientAction( const ::PolyPolygon& rPoly,
+ const ::Gradient& rGradient,
+ const ActionFactoryParameters& rParms,
+ bool bIsPolygonRectangle,
+ bool bSubsettableActions );
+
+ void createTextAction( const ::Point& rStartPoint,
+ const String rString,
+ int nIndex,
+ int nLength,
+ const sal_Int32* pCharWidths,
+ const ActionFactoryParameters& rParms,
+ bool bSubsettable );
+
+ bool getSubsetIndices( sal_Int32& io_rStartIndex,
+ sal_Int32& io_rEndIndex,
+ ActionVector::const_iterator& o_rRangeBegin,
+ ActionVector::const_iterator& o_rRangeEnd ) const;
+
+ void processObjectRecord(SvMemoryStream& rObjectStream, sal_uInt16 flags);
+ void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
+ void EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor);
+
+ ActionVector maActions;
+
+ /* EMF+ */
+ XForm aBaseTransform;
+ XForm aWorldTransform;
+ EMFPObject* aObjects [256];
+ float fPageScale;
+ sal_Int32 nOriginX;
+ sal_Int32 nOriginY;
+ sal_Int32 nHDPI;
+ sal_Int32 nVDPI;
+ ::PolyPolygon aClippingPolygon;
+ /* EMF+ emf header info */
+ sal_Int32 nFrameLeft;
+ sal_Int32 nFrameTop;
+ sal_Int32 nFrameRight;
+ sal_Int32 nFrameBottom;
+ sal_Int32 nPixX;
+ sal_Int32 nPixY;
+ sal_Int32 nMmX;
+ sal_Int32 nMmY;
+ /* multipart object data */
+ bool mbMultipart;
+ sal_uInt16 mMFlags;
+ SvMemoryStream mMStream;
+ };
+
+
+ /// Common parameters when creating actions
+ struct ActionFactoryParameters
+ {
+ ActionFactoryParameters( VectorOfOutDevStates& rStates,
+ const CanvasSharedPtr& rCanvas,
+ ::VirtualDevice& rVDev,
+ const Renderer::Parameters& rParms,
+ sal_Int32& io_rCurrActionIndex ) :
+ mrStates(rStates),
+ mrCanvas(rCanvas),
+ mrVDev(rVDev),
+ mrParms(rParms),
+ mrCurrActionIndex(io_rCurrActionIndex)
+ {}
+
+ VectorOfOutDevStates& mrStates;
+ const CanvasSharedPtr& mrCanvas;
+ ::VirtualDevice& mrVDev;
+ const Renderer::Parameters& mrParms;
+ sal_Int32& mrCurrActionIndex;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLRENDERER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/inc/tools.hxx b/cppcanvas/source/inc/tools.hxx
new file mode 100644
index 000000000000..bdd9848822fa
--- /dev/null
+++ b/cppcanvas/source/inc/tools.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_TOOLS_HXX
+#define _CPPCANVAS_TOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <cppcanvas/color.hxx>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XGraphicDevice;
+} } } }
+
+
+namespace cppcanvas
+{
+ namespace tools
+ {
+ ::com::sun::star::uno::Sequence< double >
+ intSRGBAToDoubleSequence( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >&,
+ Color::IntSRGBA );
+
+ Color::IntSRGBA doubleSequenceToIntSRGBA( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< double >& rColor );
+ }
+}
+
+#endif /* _CPPCANVAS_TOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/bitmapaction.cxx b/cppcanvas/source/mtfrenderer/bitmapaction.cxx
new file mode 100644
index 000000000000..cbbd817cc0ec
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/bitmapaction.cxx
@@ -0,0 +1,241 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <rtl/logfile.hxx>
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <com/sun/star/rendering/RepaintResult.hpp>
+#include <com/sun/star/rendering/XCachedPrimitive.hpp>
+#include <vcl/bitmapex.hxx>
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <boost/utility.hpp>
+#include "cachedprimitivebase.hxx"
+#include "bitmapaction.hxx"
+#include "outdevstate.hxx"
+#include "mtftools.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ namespace
+ {
+
+ class BitmapAction : public CachedPrimitiveBase
+ {
+ public:
+ BitmapAction( const ::BitmapEx&,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+ BitmapAction( const ::BitmapEx&,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ using Action::render;
+ virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const;
+
+ uno::Reference< rendering::XBitmap > mxBitmap;
+ CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ };
+
+
+ BitmapAction::BitmapAction( const ::BitmapEx& rBmpEx,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ CachedPrimitiveBase( rCanvas, true ),
+ mxBitmap( ::vcl::unotools::xBitmapFromBitmapEx( rCanvas->getUNOCanvas()->getDevice(),
+ rBmpEx ) ),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ tools::initRenderState(maState,rState);
+
+ // Setup transformation such that the next render call is
+ // moved rPoint away.
+ const basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createTranslateB2DHomMatrix(rDstPoint));
+ ::canvas::tools::appendToRenderState( maState,
+ aLocalTransformation );
+
+ // correct clip (which is relative to original transform)
+ tools::modifyClip( maState,
+ rState,
+ rCanvas,
+ rDstPoint,
+ NULL,
+ NULL );
+ }
+
+ BitmapAction::BitmapAction( const ::BitmapEx& rBmpEx,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ CachedPrimitiveBase( rCanvas, true ),
+ mxBitmap( ::vcl::unotools::xBitmapFromBitmapEx( rCanvas->getUNOCanvas()->getDevice(),
+ rBmpEx ) ),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ tools::initRenderState(maState,rState);
+
+ // Setup transformation such that the next render call is
+ // moved rPoint away, and scaled according to the ratio
+ // given by src and dst size.
+ const ::Size aBmpSize( rBmpEx.GetSizePixel() );
+
+ const ::basegfx::B2DVector aScale( rDstSize.getX() / aBmpSize.Width(),
+ rDstSize.getY() / aBmpSize.Height() );
+ const basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aScale, rDstPoint));
+ ::canvas::tools::appendToRenderState( maState, aLocalTransformation );
+
+ // correct clip (which is relative to original transform)
+ tools::modifyClip( maState,
+ rState,
+ rCanvas,
+ rDstPoint,
+ &aScale,
+ NULL );
+ }
+
+ bool BitmapAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::BitmapAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::BitmapAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ rCachedPrimitive = mpCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ bool BitmapAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // bitmap only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return CachedPrimitiveBase::render( rTransformation );
+ }
+
+ ::basegfx::B2DRange BitmapAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ const geometry::IntegerSize2D aSize( mxBitmap->getSize() );
+
+ return tools::calcDevicePixelBounds( ::basegfx::B2DRange( 0,0,
+ aSize.Width,
+ aSize.Height ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange BitmapAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // bitmap only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 BitmapAction::getActionCount() const
+ {
+ return 1;
+ }
+ }
+
+ ActionSharedPtr BitmapActionFactory::createBitmapAction( const ::BitmapEx& rBmpEx,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new BitmapAction(rBmpEx,
+ rDstPoint,
+ rCanvas,
+ rState ) );
+ }
+
+ ActionSharedPtr BitmapActionFactory::createBitmapAction( const ::BitmapEx& rBmpEx,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new BitmapAction(rBmpEx,
+ rDstPoint,
+ rDstSize,
+ rCanvas,
+ rState ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/bitmapaction.hxx b/cppcanvas/source/mtfrenderer/bitmapaction.hxx
new file mode 100644
index 000000000000..e6c7b83ee626
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/bitmapaction.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_BITMAPACTION_HXX
+#define _CPPCANVAS_BITMAPACTION_HXX
+
+#include <cppcanvas/canvas.hxx>
+#include <action.hxx>
+
+namespace basegfx {
+ class B2DPoint;
+ class B2DVector;
+}
+class BitmapEx;
+
+/* Definition of internal::BitmapActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ /** Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class BitmapActionFactory
+ {
+ public:
+ /// Unscaled bitmap action, only references destination point
+ static ActionSharedPtr createBitmapAction( const ::BitmapEx&,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ /// Scaled bitmap action, dest point and dest size
+ static ActionSharedPtr createBitmapAction( const ::BitmapEx&,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ private:
+ // static factory, disable big four
+ BitmapActionFactory();
+ ~BitmapActionFactory();
+ BitmapActionFactory(const BitmapActionFactory&);
+ BitmapActionFactory& operator=( const BitmapActionFactory& );
+ };
+ }
+}
+
+#endif /*_CPPCANVAS_BITMAPACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/cachedprimitivebase.cxx b/cppcanvas/source/mtfrenderer/cachedprimitivebase.cxx
new file mode 100644
index 000000000000..9cd01fc42a03
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/cachedprimitivebase.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <rtl/logfile.hxx>
+
+#include <com/sun/star/rendering/RepaintResult.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/canvas.hxx>
+
+#include "cachedprimitivebase.hxx"
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ CachedPrimitiveBase::CachedPrimitiveBase( const CanvasSharedPtr& rCanvas,
+ bool bOnlyRedrawWithSameTransform ) :
+ mpCanvas( rCanvas ),
+ mxCachedPrimitive(),
+ maLastTransformation(),
+ mbOnlyRedrawWithSameTransform( bOnlyRedrawWithSameTransform )
+ {
+ // TODO(F2): also store last view transform, and refuse to
+ // redraw if changed.
+ }
+
+ bool CachedPrimitiveBase::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::CachedPrimitiveBase::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::CachedPrimitiveBase: 0x%X", this );
+
+ const rendering::ViewState& rViewState( mpCanvas->getViewState() );
+ ::basegfx::B2DHomMatrix aTotalTransform;
+
+ ::canvas::tools::getViewStateTransform( aTotalTransform,
+ rViewState );
+ aTotalTransform *= rTransformation;
+
+ // can we use the cached primitive? For that, it must be
+ // present in the first place, and, if
+ // mbOnlyRedrawWithSameTransform is true, the overall
+ // transformation must be the same.
+ if( mxCachedPrimitive.is() &&
+ (!mbOnlyRedrawWithSameTransform ||
+ maLastTransformation == aTotalTransform) )
+ {
+ if( mxCachedPrimitive->redraw( rViewState ) ==
+ rendering::RepaintResult::REDRAWN )
+ {
+ // cached repaint succeeded, done.
+ return true;
+ }
+ }
+
+ maLastTransformation = aTotalTransform;
+
+ // delegate rendering to derived classes
+ return render( mxCachedPrimitive,
+ rTransformation );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/cachedprimitivebase.hxx b/cppcanvas/source/mtfrenderer/cachedprimitivebase.hxx
new file mode 100644
index 000000000000..8cef77f1dd26
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/cachedprimitivebase.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_CACHEDPRIMITIVEBASE_HXX
+#define _CPPCANVAS_CACHEDPRIMITIVEBASE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <cppcanvas/canvas.hxx>
+#include <boost/utility.hpp>
+
+#include "action.hxx"
+
+namespace basegfx { class B2DHomMatrix; }
+
+
+/* Definition of internal::CachedPrimitiveBase class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ /** Base class providing cached re-rendering, if XCanvas
+ returns XCachedPrimitive
+
+ Derive from this class and implement private render()
+ method to perform the actual primitive rendering. Return
+ cached primitive into given reference. Next time this
+ class' public render() method gets called, the cached
+ representation is taken.
+ */
+ class CachedPrimitiveBase : public Action,
+ private ::boost::noncopyable
+ {
+ public:
+ /** Constructor
+
+ @param rCanvas
+ Canvas on which this primitive is to appear
+
+ @param bOnlyRedrawWithSameTransform
+ When true, this class only reuses the cached
+ primitive, if the overall transformation stays the
+ same. Otherwise, repaints are always performed via the
+ cached primitive.
+ */
+ CachedPrimitiveBase( const CanvasSharedPtr& rCanvas,
+ bool bOnlyRedrawWithSameTransform );
+ virtual ~CachedPrimitiveBase() {}
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+
+ protected:
+ using Action::render;
+
+ private:
+ virtual bool render( ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const = 0;
+
+ CanvasSharedPtr mpCanvas;
+ mutable ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCachedPrimitive > mxCachedPrimitive;
+ mutable ::basegfx::B2DHomMatrix maLastTransformation;
+ const bool mbOnlyRedrawWithSameTransform;
+ };
+ }
+}
+
+#endif /*_CPPCANVAS_CACHEDPRIMITIVEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
new file mode 100644
index 000000000000..e90db4032bf6
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -0,0 +1,1617 @@
+/* -*- 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 2010 Novell, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <tools/stream.hxx>
+#include <vcl/metaact.hxx>
+#include <svtools/filter.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/alloca.h>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+
+#include <bitmapaction.hxx>
+#include <implrenderer.hxx>
+#include <outdevstate.hxx>
+#include <polypolyaction.hxx>
+#include <textaction.hxx>
+
+#define EmfPlusRecordTypeHeader 16385
+#define EmfPlusRecordTypeEndOfFile 16386
+#define EmfPlusRecordTypeGetDC 16388
+#define EmfPlusRecordTypeObject 16392
+#define EmfPlusRecordTypeFillRects 16394
+#define EmfPlusRecordTypeFillPolygon 16396
+#define EmfPlusRecordTypeDrawLines 16397
+#define EmfPlusRecordTypeFillPath 16404
+#define EmfPlusRecordTypeDrawPath 16405
+#define EmfPlusRecordTypeDrawImagePoints 16411
+#define EmfPlusRecordTypeDrawString 16412
+#define EmfPlusRecordTypeSetRenderingOrigin 16413
+#define EmfPlusRecordTypeSetAntiAliasMode 16414
+#define EmfPlusRecordTypeSetTextRenderingHint 16415
+#define EmfPlusRecordTypeSetInterpolationMode 16417
+#define EmfPlusRecordTypeSetPixelOffsetMode 16418
+#define EmfPlusRecordTypeSetCompositingQuality 16420
+#define EmfPlusRecordTypeSave 16421
+#define EmfPlusRecordTypeSetWorldTransform 16426
+#define EmfPlusRecordTypeResetWorldTransform 16427
+#define EmfPlusRecordTypeSetPageTransform 16432
+#define EmfPlusRecordTypeSetClipPath 16435
+#define EmfPlusRecordTypeSetClipRegion 16436
+#define EmfPlusRecordTypeDrawDriverString 16438
+
+#define EmfPlusObjectTypeBrush 0x100
+#define EmfPlusObjectTypePen 0x200
+#define EmfPlusObjectTypePath 0x300
+#define EmfPlusObjectTypeRegion 0x400
+#define EmfPlusObjectTypeImage 0x500
+#define EmfPlusObjectTypeFont 0x600
+#define EmfPlusObjectTypeStringFormat 0x700
+#define EmfPlusObjectTypeImageAttributes 0x800
+
+#define EmfPlusRegionInitialStateRectangle 0x10000000
+#define EmfPlusRegionInitialStatePath 0x10000001
+#define EmfPlusRegionInitialStateEmpty 0x10000002
+#define EmfPlusRegionInitialStateInfinite 0x10000003
+
+#define EMFP_DEBUG(x)
+//#define EMFP_DEBUG(x) x
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ EMFP_DEBUG (void dumpWords (SvStream& s, int i)
+ {
+ sal_uInt32 pos = s.Tell ();
+ sal_Int16 data;
+ for (; i > 0; i --) {
+ s >> data;
+ printf ("EMF+\tdata: %04hX\n", data);
+ }
+ s.Seek (pos);
+ });
+
+ struct EMFPObject
+ {
+ };
+
+ struct EMFPPath : public EMFPObject
+ {
+ ::basegfx::B2DPolyPolygon aPolygon;
+ sal_Int32 nPoints;
+ float* pPoints;
+ sal_uInt8* pPointTypes;
+
+ public:
+ EMFPPath (sal_Int32 _nPoints, bool bLines = false)
+ {
+ if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
+ _nPoints = SAL_MAX_INT32/(2*sizeof(float));
+ nPoints = _nPoints;
+ pPoints = new float [nPoints*2];
+ if (!bLines)
+ pPointTypes = new sal_uInt8 [_nPoints];
+ else
+ pPointTypes = NULL;
+ }
+
+ ~EMFPPath ()
+ {
+ delete [] pPoints;
+ delete [] pPointTypes;
+ }
+
+ // TODO: remove rR argument when debug code is not longer needed
+ void Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
+ {
+ for (int i = 0; i < nPoints; i ++) {
+ if (pathFlags & 0x4000) {
+ // points are stored in short 16bit integer format
+ sal_uInt16 x, y;
+
+ s >> x >> y;
+ EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %hd,%hd\n", x, y));
+ pPoints [i*2] = x;
+ pPoints [i*2 + 1] = y;
+ } else {
+ // points are stored in Single (float) format
+ s >> pPoints [i*2] >> pPoints [i*2 + 1];
+ EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1]));
+ }
+ }
+
+ if (pPointTypes)
+ for (int i = 0; i < nPoints; i ++) {
+ s >> pPointTypes [i];
+ EMFP_DEBUG (printf ("EMF+\tpoint type: %x\n", pPointTypes [i]));
+ }
+
+ aPolygon.clear ();
+
+ // debug code
+ const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
+ EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f (mapped)\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
+ }
+
+ ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
+ {
+ ::basegfx::B2DPolygon polygon;
+
+ aPolygon.clear ();
+
+ int last_normal = 0, p = 0;
+ ::basegfx::B2DPoint prev, mapped;
+ bool hasPrev = false;
+ for (int i = 0; i < nPoints; i ++) {
+ if (p && pPointTypes && (pPointTypes [i] == 0)) {
+ aPolygon.append (polygon);
+ last_normal = i;
+ p = 0;
+ polygon.clear ();
+ }
+
+ if (bMapIt)
+ mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
+ else
+ mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
+ //EMFP_DEBUG (printf ("polygon point: %f,%f mapped: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1], mapped.getX (), mapped.getY ()));
+ if (pPointTypes) {
+ if ((pPointTypes [i] & 0x07) == 3) {
+ if (((i - last_normal )% 3) == 1) {
+ polygon.setNextControlPoint (p - 1, mapped);
+ continue;
+ } else if (((i - last_normal) % 3) == 2) {
+ prev = mapped;
+ hasPrev = true;
+ continue;
+ }
+ } else
+ last_normal = i;
+ }
+ polygon.append (mapped);
+ if (hasPrev) {
+ polygon.setPrevControlPoint (p, prev);
+ hasPrev = false;
+ }
+ p ++;
+ if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
+ polygon.setClosed (true);
+ aPolygon.append (polygon);
+ last_normal = i + 1;
+ p = 0;
+ polygon.clear ();
+ }
+ }
+
+ if (polygon.count ())
+ aPolygon.append (polygon);
+
+ return aPolygon;
+ }
+ };
+
+ struct EMFPRegion : public EMFPObject
+ {
+ sal_Int32 parts;
+ sal_Int32 *combineMode;
+ sal_Int32 initialState;
+ EMFPPath *initialPath;
+ float ix, iy, iw, ih;
+
+ EMFPRegion ()
+ {
+ combineMode = NULL;
+ initialPath = NULL;
+ }
+
+ ~EMFPRegion ()
+ {
+ if (combineMode) {
+ delete [] combineMode;
+ combineMode = NULL;
+ }
+ if (initialPath) {
+ delete initialPath;
+ initialPath = NULL;
+ }
+ }
+
+ void Read (SvStream& s)
+ {
+ sal_uInt32 header;
+
+ s >> header >> parts;
+
+ EMFP_DEBUG (printf ("EMF+\tregion\n"));
+ EMFP_DEBUG (printf ("EMF+\theader: 0x%08x parts: %d\n", header, parts));
+
+ if (parts) {
+ if( parts<0 || sal_uInt32(parts)>SAL_MAX_INT32/sizeof(sal_Int32) )
+ parts = SAL_MAX_INT32/sizeof(sal_Int32);
+
+ combineMode = new sal_Int32 [parts];
+
+ for (int i = 0; i < parts; i ++) {
+ s >> combineMode [i];
+ EMFP_DEBUG (printf ("EMF+\tcombine mode [%d]: 0x%08x\n", i, combineMode [i]));
+ }
+ }
+
+ s >> initialState;
+ EMFP_DEBUG (printf ("EMF+\tinitial state: 0x%08x\n", initialState));
+ }
+ };
+
+ struct EMFPBrush : public EMFPObject
+ {
+ ::Color solidColor;
+ sal_uInt32 type;
+ sal_uInt32 additionalFlags;
+
+ /* linear gradient */
+ sal_Int32 wrapMode;
+ float areaX, areaY, areaWidth, areaHeight;
+ ::Color secondColor; // first color is stored in solidColor;
+ XForm transformation;
+ bool hasTransformation;
+ sal_Int32 blendPoints;
+ float* blendPositions;
+ float* blendFactors;
+ sal_Int32 colorblendPoints;
+ float* colorblendPositions;
+ ::Color* colorblendColors;
+ sal_Int32 surroundColorsNumber;
+ ::Color* surroundColors;
+ EMFPPath *path;
+
+ public:
+ EMFPBrush ()
+ {
+ blendPositions = NULL;
+ colorblendPositions = NULL;
+ colorblendColors = NULL;
+ surroundColors = NULL;
+ path = NULL;
+ hasTransformation = false;
+ }
+
+ ~EMFPBrush ()
+ {
+ if (blendPositions != NULL) {
+ delete[] blendPositions;
+ blendPositions = NULL;
+ }
+ if (colorblendPositions != NULL) {
+ delete[] colorblendPositions;
+ colorblendPositions = NULL;
+ }
+ if (colorblendColors != NULL) {
+ delete[] colorblendColors;
+ colorblendColors = NULL;
+ }
+ if (surroundColors != NULL) {
+ delete[] surroundColors;
+ surroundColors = NULL;
+ }
+ if (path) {
+ delete path;
+ path = NULL;
+ }
+ }
+
+ sal_uInt32 GetType() const { return type; }
+ const ::Color& GetColor() const { return solidColor; }
+
+ void Read (SvStream& s, ImplRenderer& rR)
+ {
+ sal_uInt32 header;
+
+ s >> header >> type;
+
+ EMFP_DEBUG (printf ("EMF+\tbrush\nEMF+\theader: 0x%08x type: %d\n", header, type));
+
+ switch (type) {
+ case 0:
+ {
+ sal_uInt32 color;
+
+ s >> color;
+ solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tsolid color: 0x%08x\n", color));
+
+ break;
+ }
+ // path gradient
+ case 3:
+ {
+ s >> additionalFlags >> wrapMode;
+
+ EMFP_DEBUG (printf ("EMF+\tpath gradient, additional flags: 0x%02x\n", additionalFlags));
+
+ sal_uInt32 color;
+
+ s >> color;
+ solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tcenter color: 0x%08x\n", color));
+
+ s >> areaX >> areaY;
+ EMFP_DEBUG (printf ("EMF+\tcenter point: %f,%f\n", areaX, areaY));
+
+ s >> surroundColorsNumber;
+ EMFP_DEBUG (printf ("EMF+\tsurround colors: %d\n", surroundColorsNumber));
+
+ if( surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32/sizeof(::Color) )
+ surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
+
+ surroundColors = new ::Color [surroundColorsNumber];
+ for (int i = 0; i < surroundColorsNumber; i++) {
+ s >> color;
+ surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ if (i == 0)
+ secondColor = surroundColors [0];
+ EMFP_DEBUG (printf ("EMF+\tsurround color[%d]: 0x%08x\n", i, color));
+ }
+
+ if (additionalFlags & 0x01) {
+ sal_Int32 pathLength;
+
+ s >> pathLength;
+ EMFP_DEBUG (printf ("EMF+\tpath length: %d\n", pathLength));
+
+ sal_uInt32 pos = s.Tell ();
+ EMFP_DEBUG (dumpWords (s, 32));
+
+ sal_uInt32 pathHeader;
+ sal_Int32 pathPoints, pathFlags;
+ s >> pathHeader >> pathPoints >> pathFlags;
+
+ EMFP_DEBUG (printf ("EMF+\tpath (brush path gradient)\n"));
+ EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", pathHeader, pathPoints, pathFlags));
+
+ path = new EMFPPath (pathPoints);
+ path->Read (s, pathFlags, rR);
+
+ s.Seek (pos + pathLength);
+
+ const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
+ areaWidth = aBounds.getWidth ();
+ areaHeight = aBounds.getHeight ();
+
+ EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
+
+
+ if (additionalFlags & 0x02) {
+ EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
+ s >> transformation;
+ hasTransformation = true;
+ EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
+ transformation.eM11, transformation.eM12,
+ transformation.eM21, transformation.eM22,
+ transformation.eDx, transformation.eDy));
+ }
+ if (additionalFlags & 0x08) {
+ s >> blendPoints;
+ EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
+ if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
+ blendPoints = SAL_MAX_INT32/(2*sizeof(float));
+ blendPositions = new float [2*blendPoints];
+ blendFactors = blendPositions + blendPoints;
+ for (int i=0; i < blendPoints; i ++) {
+ s >> blendPositions [i];
+ EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
+ }
+ for (int i=0; i < blendPoints; i ++) {
+ s >> blendFactors [i];
+ EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
+ }
+ }
+
+ if (additionalFlags & 0x04) {
+ s >> colorblendPoints;
+ EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
+ if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
+ colorblendPoints = SAL_MAX_INT32/sizeof(float);
+ if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
+ colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
+ colorblendPositions = new float [colorblendPoints];
+ colorblendColors = new ::Color [colorblendPoints];
+ for (int i=0; i < colorblendPoints; i ++) {
+ s >> colorblendPositions [i];
+ EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
+ }
+ for (int i=0; i < colorblendPoints; i ++) {
+ s >> color;
+ colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
+ }
+ }
+ } else {
+ EMFP_DEBUG (dumpWords (s, 1024));
+ }
+ break;
+ }
+ // linear gradient
+ case 4:
+ {
+ s >> additionalFlags >> wrapMode;
+
+ EMFP_DEBUG (printf ("EMF+\tlinear gradient, additional flags: 0x%02x\n", additionalFlags));
+
+ s >> areaX >> areaY >> areaWidth >> areaHeight;
+
+ EMFP_DEBUG (printf ("EMF+\tarea: %f,%f - %fx%f\n", areaX, areaY, areaWidth, areaHeight));
+
+ sal_uInt32 color;
+
+ s >> color;
+ solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tfirst color: 0x%08x\n", color));
+
+ s >> color;
+ secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tsecond color: 0x%08x\n", color));
+
+ // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
+ s >> color;
+ s >> color;
+
+ if (additionalFlags & 0x02) {
+ EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
+ s >> transformation;
+ hasTransformation = true;
+ EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
+ transformation.eM11, transformation.eM12,
+ transformation.eM21, transformation.eM22,
+ transformation.eDx, transformation.eDy));
+ }
+ if (additionalFlags & 0x08) {
+ s >> blendPoints;
+ EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
+ if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
+ blendPoints = SAL_MAX_INT32/(2*sizeof(float));
+ blendPositions = new float [2*blendPoints];
+ blendFactors = blendPositions + blendPoints;
+ for (int i=0; i < blendPoints; i ++) {
+ s >> blendPositions [i];
+ EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
+ }
+ for (int i=0; i < blendPoints; i ++) {
+ s >> blendFactors [i];
+ EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
+ }
+ }
+
+ if (additionalFlags & 0x04) {
+ s >> colorblendPoints;
+ EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
+ if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
+ colorblendPoints = SAL_MAX_INT32/sizeof(float);
+ if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
+ colorblendPoints = sal_uInt32(SAL_MAX_INT32)/sizeof(::Color);
+ colorblendPositions = new float [colorblendPoints];
+ colorblendColors = new ::Color [colorblendPoints];
+ for (int i=0; i < colorblendPoints; i ++) {
+ s >> colorblendPositions [i];
+ EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
+ }
+ for (int i=0; i < colorblendPoints; i ++) {
+ s >> color;
+ colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+ EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
+ }
+ }
+
+ break;
+ }
+ default:
+ EMFP_DEBUG (printf ("EMF+\tunhandled brush type: %d\n", type));
+ }
+ }
+ };
+
+ struct EMFPPen : public EMFPBrush
+ {
+ XForm transformation;
+ float width;
+ sal_Int32 startCap;
+ sal_Int32 endCap;
+ sal_Int32 lineJoin;
+ float mitterLimit;
+ sal_Int32 dashStyle;
+ sal_Int32 dashCap;
+ float dashOffset;
+ sal_Int32 dashPatternLen;
+ float *dashPattern;
+ sal_Int32 alignment;
+ sal_Int32 compoundArrayLen;
+ float *compoundArray;
+ sal_Int32 customStartCapLen;
+ sal_uInt8 *customStartCap;
+ sal_Int32 customEndCapLen;
+ sal_uInt8 *customEndCap;
+
+ public:
+ EMFPPen () : EMFPBrush ()
+ {
+ }
+
+ void SetStrokeAttributes (rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
+ {
+ rStrokeAttributes.StrokeWidth = (rState.mapModeTransform * rR.MapSize (width, 0)).getX ();
+ }
+
+ void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
+ {
+ sal_uInt32 header, unknown, penFlags, unknown2;
+ int i;
+
+ s >> header >> unknown >> penFlags >> unknown2 >> width;
+
+ EMFP_DEBUG (printf ("EMF+\tpen\nEMF+\theader: 0x%08x unknown: 0x%08x additional flags: 0x%08x unknown: 0x%08x width: %f\n", header, unknown, penFlags, unknown2, width));
+
+ if (penFlags & 1)
+ s >> transformation;
+
+ if (penFlags & 2)
+ s >> startCap;
+ else
+ startCap = 0;
+
+ if (penFlags & 4)
+ s >> endCap;
+ else
+ endCap = 0;
+
+ if (penFlags & 8)
+ s >> lineJoin;
+ else
+ lineJoin = 0;
+
+ if (penFlags & 16)
+ s >> mitterLimit;
+ else
+ mitterLimit = 0;
+
+ if (penFlags & 32)
+ s >> dashStyle;
+ else
+ dashStyle = 0;
+
+ if (penFlags & 64)
+ s >> dashCap;
+ else
+ dashCap = 0;
+
+ if (penFlags & 128)
+ s >> dashOffset;
+ else
+ dashOffset = 0;
+
+ if (penFlags & 256) {
+ s >> dashPatternLen;
+ if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
+ dashPatternLen = SAL_MAX_INT32/sizeof(float);
+ dashPattern = new float [dashPatternLen];
+ for (i = 0; i < dashPatternLen; i++)
+ s >> dashPattern [i];
+ } else
+ dashPatternLen = 0;
+
+ if (penFlags & 512)
+ s >> alignment;
+ else
+ alignment = 0;
+
+ if (penFlags & 1024) {
+ s >> compoundArrayLen;
+ if( compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32/sizeof(float) )
+ compoundArrayLen = SAL_MAX_INT32/sizeof(float);
+ compoundArray = new float [compoundArrayLen];
+ for (i = 0; i < compoundArrayLen; i++)
+ s >> compoundArray [i];
+ } else
+ compoundArrayLen = 0;
+
+ if (penFlags & 2048) {
+ s >> customStartCapLen;
+ if( customStartCapLen<0 )
+ customStartCapLen=0;
+ customStartCap = new sal_uInt8 [customStartCapLen];
+ for (i = 0; i < customStartCapLen; i++)
+ s >> customStartCap [i];
+ } else
+ customStartCapLen = 0;
+
+ if (penFlags & 4096) {
+ s >> customEndCapLen;
+ if( customEndCapLen<0 )
+ customEndCapLen=0;
+ customEndCap = new sal_uInt8 [customEndCapLen];
+ for (i = 0; i < customEndCapLen; i++)
+ s >> customEndCap [i];
+ } else
+ customEndCapLen = 0;
+
+ EMFPBrush::Read (s, rR);
+ }
+ };
+
+ struct EMFPImage : public EMFPObject
+ {
+ sal_uInt32 type;
+ sal_Int32 width;
+ sal_Int32 height;
+ sal_Int32 stride;
+ sal_Int32 pixelFormat;
+ Graphic graphic;
+
+
+ void Read (SvMemoryStream &s)
+ {
+ sal_uInt32 header, unknown;
+
+ s >> header >> type;
+
+ EMFP_DEBUG (printf ("EMF+\timage\nEMF+\theader: 0x%08x type: 0x%08x\n", header, type));
+
+ if (type == 1) { // bitmap
+ s >> width >> height >> stride >> pixelFormat >> unknown;
+ EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d stride: %d pixelFormat: 0x%08x\n", width, height, stride, pixelFormat));
+ if (width == 0) { // non native formats
+ GraphicFilter filter;
+
+ filter.ImportGraphic (graphic, String (), s);
+ EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d\n", graphic.GetBitmap ().GetSizePixel ().Width (), graphic.GetBitmap ().GetSizePixel ().Height ()));
+ }
+
+ } else if (type == 2) {
+ sal_Int32 mfType, mfSize;
+
+ s >> mfType >> mfSize;
+ EMFP_DEBUG (printf ("EMF+\tmetafile type: %d dataSize: %d\n", mfType, mfSize));
+
+ GraphicFilter filter;
+ SvMemoryStream mfStream (((char *)s.GetData()) + s.Tell(), mfSize, STREAM_READ);
+
+ filter.ImportGraphic (graphic, String (), mfStream);
+
+ // debug code - write the stream to debug file /tmp/emf-stream.emf
+ EMFP_DEBUG(mfStream.Seek(0);
+ SvFileStream file( UniString::CreateFromAscii( "/tmp/emf-embedded-stream.emf" ), STREAM_WRITE | STREAM_TRUNC );
+
+ mfStream >> file;
+ file.Flush();
+ file.Close());
+ }
+ }
+ };
+
+ struct EMFPFont : public EMFPObject
+ {
+ sal_uInt32 version;
+ float emSize;
+ sal_uInt32 sizeUnit;
+ sal_Int32 fontFlags;
+ rtl::OUString family;
+
+ void Read (SvMemoryStream &s)
+ {
+ sal_uInt32 header;
+ sal_uInt32 reserved;
+ sal_uInt32 length;
+
+ s >> header >> emSize >> sizeUnit >> fontFlags >> reserved >> length;
+
+ OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
+
+ EMFP_DEBUG (printf ("EMF+\tfont\nEMF+\theader: 0x%08x version: 0x%08x size: %f unit: 0x%08x\n", header >> 12, header & 0x1fff, emSize, sizeUnit));
+ EMFP_DEBUG (printf ("EMF+\tflags: 0x%08x reserved: 0x%08x length: 0x%08x\n", fontFlags, reserved, length));
+
+ if( length > 0 && length < 0x4000 ) {
+ sal_Unicode *chars = (sal_Unicode *) alloca( sizeof( sal_Unicode ) * length );
+
+ for( sal_uInt32 i = 0; i < length; i++ )
+ s >> chars[ i ];
+
+ family = ::rtl::OUString( chars, length );
+ EMFP_DEBUG (printf ("EMF+\tfamily: %s\n", rtl::OUStringToOString( family, RTL_TEXTENCODING_UTF8).getStr()));
+ }
+ }
+ };
+
+ void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, sal_uInt32 flags)
+ {
+ if (flags & 0x4000) {
+ sal_Int16 ix, iy, iw, ih;
+
+ s >> ix >> iy >> iw >> ih;
+
+ x = ix;
+ y = iy;
+ width = iw;
+ height = ih;
+ } else
+ s >> x >> y >> width >> height;
+ }
+
+ void ImplRenderer::ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags)
+ {
+ if (flags & 0x4000) {
+ sal_Int16 ix, iy;
+
+ s >> ix >> iy;
+
+ x = ix;
+ y = iy;
+ } else
+ s >> x >> y;
+ }
+
+ void ImplRenderer::MapToDevice (double& x, double& y)
+ {
+ // TODO: other untis
+ x = 100*nMmX*x/nPixX;
+ y = 100*nMmY*y/nPixY;
+ }
+
+ ::basegfx::B2DPoint ImplRenderer::Map (::basegfx::B2DPoint& p)
+ {
+ return Map (p.getX (), p.getY ());
+ }
+
+ ::basegfx::B2DPoint ImplRenderer::Map (double ix, double iy)
+ {
+ double x, y;
+
+ x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
+ y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
+
+ MapToDevice (x, y);
+
+ x -= nFrameLeft;
+ y -= nFrameTop;
+
+ x *= aBaseTransform.eM11;
+ y *= aBaseTransform.eM22;
+
+ return ::basegfx::B2DPoint (x, y);
+ }
+
+ ::basegfx::B2DSize ImplRenderer::MapSize (double iwidth, double iheight)
+ {
+ double w, h;
+
+ w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
+ h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
+
+ MapToDevice (w, h);
+
+ w *= aBaseTransform.eM11;
+ h *= aBaseTransform.eM22;
+
+ return ::basegfx::B2DSize (w, h);
+ }
+
+ ::basegfx::B2DRange ImplRenderer::MapRectangle (double ix, double iy, double iwidth, double iheight)
+ {
+ double x, y, w, h;
+
+ x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
+ y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
+ w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
+ h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
+
+ MapToDevice (x, y);
+ MapToDevice (w, h);
+
+ x -= nFrameLeft;
+ y -= nFrameTop;
+
+ x *= aBaseTransform.eM11;
+ y *= aBaseTransform.eM22;
+ w *= aBaseTransform.eM11;
+ h *= aBaseTransform.eM22;
+
+ return ::basegfx::B2DRange (x, y, x + w, y + h);
+ }
+
+#define COLOR(x) \
+ ::vcl::unotools::colorToDoubleSequence( ::Color (0xff - (x >> 24), \
+ (x >> 16) & 0xff, \
+ (x >> 8) & 0xff, \
+ x & 0xff), \
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
+#define SET_FILL_COLOR(x) \
+ rState.fillColor = COLOR(x);
+#define SET_LINE_COLOR(x) \
+ rState.lineColor = COLOR(x);
+#define SET_TEXT_COLOR(x) \
+ rState.textColor = COLOR(x);
+
+ void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
+ OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor)
+ {
+ ::basegfx::B2DPolyPolygon localPolygon (polygon);
+
+ EMFP_DEBUG (printf ("EMF+\tfill polygon\n"));
+
+ localPolygon.transform( rState.mapModeTransform );
+
+ ActionSharedPtr pPolyAction;
+
+ if (isColor) {
+ EMFP_DEBUG (printf ("EMF+\t\tcolor fill\n"));
+
+ rState.isFillColorSet = true;
+ rState.isLineColorSet = false;
+ SET_FILL_COLOR(brushIndexOrColor);
+
+ pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
+
+ } else {
+ rState.isFillColorSet = true;
+ // extract UseBrush
+ EMFPBrush* brush = (EMFPBrush*) aObjects [brushIndexOrColor];
+ EMFP_DEBUG (printf ("EMF+\tbrush fill slot: %d (type: %d)\n", brushIndexOrColor, brush->GetType ()));
+
+ // give up in case something wrong happened
+ if( !brush )
+ return;
+
+ rState.isFillColorSet = false;
+ rState.isLineColorSet = false;
+
+ if (brush->type == 3 || brush->type == 4) {
+
+ if (brush->type == 3 && !(brush->additionalFlags & 0x1))
+ return; // we are unable to parse these brushes yet
+
+ ::basegfx::B2DHomMatrix aTextureTransformation;
+ ::basegfx::B2DHomMatrix aWorldTransformation;
+ ::basegfx::B2DHomMatrix aBaseTransformation;
+ rendering::Texture aTexture;
+
+ aWorldTransformation.set (0, 0, aWorldTransform.eM11);
+ aWorldTransformation.set (0, 1, aWorldTransform.eM21);
+ aWorldTransformation.set (0, 2, aWorldTransform.eDx);
+ aWorldTransformation.set (1, 0, aWorldTransform.eM12);
+ aWorldTransformation.set (1, 1, aWorldTransform.eM22);
+ aWorldTransformation.set (1, 2, aWorldTransform.eDy);
+
+ aBaseTransformation.set (0, 0, aBaseTransform.eM11);
+ aBaseTransformation.set (0, 1, aBaseTransform.eM21);
+ aBaseTransformation.set (0, 2, aBaseTransform.eDx);
+ aBaseTransformation.set (1, 0, aBaseTransform.eM12);
+ aBaseTransformation.set (1, 1, aBaseTransform.eM22);
+ aBaseTransformation.set (1, 2, aBaseTransform.eDy);
+
+ if (brush->type == 4) {
+ aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
+ aTextureTransformation.translate (brush->areaX, brush->areaY);
+ } else {
+ aTextureTransformation.translate (-0.5, -0.5);
+ aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
+ aTextureTransformation.translate (brush->areaX,brush->areaY);
+ }
+
+ if (brush->hasTransformation) {
+ ::basegfx::B2DHomMatrix aTransformation;
+
+ aTransformation.set (0, 0, brush->transformation.eM11);
+ aTransformation.set (0, 1, brush->transformation.eM21);
+ aTransformation.set (0, 2, brush->transformation.eDx);
+ aTransformation.set (1, 0, brush->transformation.eM12);
+ aTransformation.set (1, 1, brush->transformation.eM22);
+ aTransformation.set (1, 2, brush->transformation.eDy);
+
+ aTextureTransformation *= aTransformation;
+ }
+
+ aTextureTransformation *= aWorldTransformation;
+ aTextureTransformation.scale (100.0*nMmX/nPixX, 100.0*nMmY/nPixY);
+ aTextureTransformation.translate (-nFrameLeft, -nFrameTop);
+ aTextureTransformation *= rState.mapModeTransform;
+ aTextureTransformation *= aBaseTransformation;
+
+ aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
+ aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
+ aTexture.Alpha = 1.0;
+
+ basegfx::ODFGradientInfo aGradInfo;
+ rtl::OUString aGradientService;
+
+ const uno::Sequence< double > aStartColor(
+ ::vcl::unotools::colorToDoubleSequence( brush->solidColor,
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
+ const uno::Sequence< double > aEndColor(
+ ::vcl::unotools::colorToDoubleSequence( brush->secondColor,
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
+ uno::Sequence< uno::Sequence < double > > aColors (2);
+ uno::Sequence< double > aStops (2);
+
+ if (brush->blendPositions) {
+ EMFP_DEBUG (printf ("EMF+\t\tuse blend\n"));
+ aColors.realloc (brush->blendPoints);
+ aStops.realloc (brush->blendPoints);
+ int length = aStartColor.getLength ();
+ uno::Sequence< double > aColor (length);
+
+ OSL_ASSERT (length == aEndColor.getLength());
+
+ for (int i = 0; i < brush->blendPoints; i++) {
+ aStops[i] = brush->blendPositions [i];
+
+ for (int j = 0; j < length; j++) {
+ if (brush->type == 4) {
+// // gamma correction
+// if (brush->additionalFlags & 0x80)
+// aColor [j] = pow (aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i], 1/2.2);
+// else
+ aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
+ } else
+ aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
+ }
+
+ aColors[i] = aColor;
+ }
+ } else if (brush->colorblendPositions) {
+ EMFP_DEBUG (printf ("EMF+\t\tuse color blend\n"));
+ aColors.realloc (brush->colorblendPoints);
+ aStops.realloc (brush->colorblendPoints);
+
+ for (int i = 0; i < brush->colorblendPoints; i++) {
+ aStops[i] = brush->colorblendPositions [i];
+ aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = ::vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
+ }
+ } else {
+ aStops[0] = 0.0;
+ aStops[1] = 1.0;
+
+ if (brush->type == 4) {
+ aColors[0] = aStartColor;
+ aColors[1] = aEndColor;
+ } else {
+ aColors[1] = aStartColor;
+ aColors[0] = aEndColor;
+ }
+ }
+
+ EMFP_DEBUG (printf ("EMF+\t\tset gradient\n"));
+ basegfx::B2DRange aBoundsRectangle (0, 0, 1, 1);
+ if (brush->type == 4) {
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LinearGradient"));
+ basegfx::tools::createLinearODFGradientInfo( aGradInfo,
+ aBoundsRectangle,
+ aStops.getLength(),
+ 0,
+ 0 );
+
+ } else {
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EllipticalGradient"));
+ basegfx::tools::createEllipticalODFGradientInfo( aGradInfo,
+ aBoundsRectangle,
+ ::basegfx::B2DVector( 0, 0 ),
+ aStops.getLength(),
+ 0,
+ 0 );
+ }
+
+ uno::Reference< lang::XMultiServiceFactory > xFactory(
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
+
+ if( xFactory.is() ) {
+ uno::Sequence<uno::Any> args( 3 );
+ beans::PropertyValue aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Colors"));
+ aProp.Value <<= aColors;
+ args[0] <<= aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Stops"));
+ aProp.Value <<= aStops;
+ args[1] <<= aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AspectRatio"));
+ aProp.Value <<= static_cast<sal_Int32>(1);
+ args[2] <<= aProp;
+
+ aTexture.Gradient.set(
+ xFactory->createInstanceWithArguments( aGradientService,
+ args ),
+ uno::UNO_QUERY);
+ }
+
+ ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
+ aTextureTransformation );
+
+ if( aTexture.Gradient.is() )
+ pPolyAction =
+ ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon,
+ rParms.mrCanvas,
+ rState,
+ aTexture ) );
+ }
+ }
+
+ if( pPolyAction )
+ {
+ EMFP_DEBUG (printf ("EMF+\t\tadd poly action\n"));
+
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ rParms.mrCurrActionIndex ) );
+
+ rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+ }
+
+ void ImplRenderer::processObjectRecord(SvMemoryStream& rObjectStream, sal_uInt16 flags)
+ {
+ EMFP_DEBUG (sal_uInt32 objectLen);
+ sal_uInt32 index;
+
+ EMFP_DEBUG (printf ("EMF+ Object slot: %hd flags: %hx\n", flags & 0xff, flags & 0xff00));
+
+ index = flags & 0xff;
+ if (aObjects [index] != NULL) {
+ delete aObjects [index];
+ aObjects [index] = NULL;
+ }
+
+ switch (flags & 0x7f00) {
+ case EmfPlusObjectTypeBrush:
+ {
+ EMFPBrush *brush;
+ aObjects [index] = brush = new EMFPBrush ();
+ brush->Read (rObjectStream, *this);
+
+ break;
+ }
+ case EmfPlusObjectTypePen:
+ {
+ EMFPPen *pen;
+ aObjects [index] = pen = new EMFPPen ();
+ pen->Read (rObjectStream, *this, nHDPI, nVDPI);
+
+ break;
+ }
+ case EmfPlusObjectTypePath:
+ sal_uInt32 header, pathFlags;
+ sal_Int32 points;
+
+ rObjectStream >> header >> points >> pathFlags;
+
+ EMFP_DEBUG (printf ("EMF+\tpath\n"));
+ EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", header, points, pathFlags));
+
+ EMFPPath *path;
+ aObjects [index] = path = new EMFPPath (points);
+ path->Read (rObjectStream, pathFlags, *this);
+
+ break;
+ case EmfPlusObjectTypeRegion: {
+ EMFPRegion *region;
+
+ aObjects [index] = region = new EMFPRegion ();
+ region->Read (rObjectStream);
+
+ break;
+ }
+ case EmfPlusObjectTypeImage:
+ {
+ EMFPImage *image;
+ aObjects [index] = image = new EMFPImage ();
+ image->Read (rObjectStream);
+
+ break;
+ }
+ case EmfPlusObjectTypeFont:
+ {
+ EMFPFont *font;
+ aObjects [index] = font = new EMFPFont ();
+ font->Read (rObjectStream);
+
+ break;
+ }
+ default:
+ EMFP_DEBUG (printf ("EMF+\tObject unhandled flags: 0x%04x\n", flags & 0xff00));
+ break;
+ }
+ }
+
+ void ImplRenderer::processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms,
+ OutDevState& rState, const CanvasSharedPtr& rCanvas )
+ {
+ sal_uInt32 length = pAct->GetDataSize ();
+ SvMemoryStream rMF ((void*) pAct->GetData (), length, STREAM_READ);
+
+ length -= 4;
+
+ while (length > 0) {
+ sal_uInt16 type, flags;
+ sal_uInt32 size, dataSize;
+ sal_uInt32 next;
+
+ rMF >> type >> flags >> size >> dataSize;
+
+ next = rMF.Tell() + ( size - 12 );
+
+ EMFP_DEBUG (printf ("EMF+ record size: %d type: %04hx flags: %04hx data size: %d\n", size, type, flags, dataSize));
+
+ if (type == EmfPlusRecordTypeObject && ((mbMultipart && (flags & 0x7fff) == (mMFlags & 0x7fff)) || (flags & 0x8000))) {
+ if (!mbMultipart) {
+ mbMultipart = true;
+ mMFlags = flags;
+ mMStream.Seek(0);
+ }
+
+ // 1st 4 bytes are unknown
+ mMStream.Write (((const char *)rMF.GetData()) + rMF.Tell() + 4, dataSize - 4);
+ EMFP_DEBUG (printf ("EMF+ read next object part size: %d type: %04hx flags: %04hx data size: %d\n", size, type, flags, dataSize));
+ } else {
+ if (mbMultipart) {
+ EMFP_DEBUG (printf ("EMF+ multipart record flags: %04hx\n", mMFlags));
+ mMStream.Seek (0);
+ processObjectRecord (mMStream, mMFlags);
+ }
+ mbMultipart = false;
+ }
+
+ if (type != EmfPlusRecordTypeObject || !(flags & 0x8000))
+ switch (type) {
+ case EmfPlusRecordTypeHeader:
+ sal_uInt32 header, version;
+
+ rMF >> header >> version >> nHDPI >> nVDPI;
+
+ EMFP_DEBUG (printf ("EMF+ Header\n"));
+ EMFP_DEBUG (printf ("EMF+\theader: 0x%08x version: %d horizontal DPI: %d vertical DPI: %d dual: %d\n", header, version, nHDPI, nVDPI, flags & 1));
+
+ break;
+ case EmfPlusRecordTypeEndOfFile:
+ EMFP_DEBUG (printf ("EMF+ EndOfFile\n"));
+ break;
+ case EmfPlusRecordTypeGetDC:
+ EMFP_DEBUG (printf ("EMF+ GetDC\n"));
+ EMFP_DEBUG (printf ("EMF+\talready used in svtools wmf/emf filter parser\n"));
+ break;
+ case EmfPlusRecordTypeObject:
+ processObjectRecord (rMF, flags);
+ break;
+ case EmfPlusRecordTypeFillPath:
+ {
+ sal_uInt32 index = flags & 0xff;
+ sal_uInt32 brushIndexOrColor;
+
+ rMF >> brushIndexOrColor;
+
+ EMFP_DEBUG (printf ("EMF+ FillPath slot: %d\n", index));
+
+ EMFPPlusFillPolygon (((EMFPPath*) aObjects [index])->GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
+ }
+ break;
+ case EmfPlusRecordTypeFillRects:
+ {
+ EMFP_DEBUG (printf ("EMF+ FillRects\n"));
+
+ sal_uInt32 brushIndexOrColor;
+ sal_Int32 rectangles;
+ ::basegfx::B2DPolygon polygon;
+
+ rMF >> brushIndexOrColor >> rectangles;
+
+ EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags & 0x8000) ? "color" : "brush index", brushIndexOrColor));
+
+ for (int i=0; i < rectangles; i++) {
+ if (flags & 0x4000) {
+ /* 16bit integers */
+ sal_Int16 x, y, width, height;
+
+ rMF >> x >> y >> width >> height;
+
+ polygon.append (Map (x, y));
+ polygon.append (Map (x + width, y));
+ polygon.append (Map (x + width, y + height));
+ polygon.append (Map (x, y + height));
+
+ EMFP_DEBUG (printf ("EMF+\trectangle: %d,%d %dx%d\n", x, y, width, height));
+ } else {
+ /* Single's */
+ float x, y, width, height;
+
+ rMF >> x >> y >> width >> height;
+
+ polygon.append (Map (x, y));
+ polygon.append (Map (x + width, y));
+ polygon.append (Map (x + width, y + height));
+ polygon.append (Map (x, y + height));
+
+ EMFP_DEBUG (printf ("EMF+\trectangle: %f,%f %fx%f\n", x, y, width, height));
+ }
+
+ ::basegfx::B2DPolyPolygon polyPolygon (polygon);
+
+ EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
+ }
+ break;
+ }
+ case EmfPlusRecordTypeFillPolygon:
+ {
+ EMFP_DEBUG (sal_uInt8 index = flags & 0xff);
+ sal_uInt32 brushIndexOrColor;
+ EMFP_DEBUG (sal_Int32 brushIndex);
+ sal_Int32 points;
+ EMFP_DEBUG (sal_uInt32 color);
+ EMFP_DEBUG (sal_uInt16 transparency = 0);
+
+ rMF >> brushIndexOrColor;
+ rMF >> points;
+
+ EMFP_DEBUG (printf ("EMF+ FillPolygon in slot: %d points: %d\n", index, points));
+ EMFP_DEBUG (printf ("EMF+\twith solid color (ARGB): 0x%08X\n", color));
+
+ EMFPPath path (points, true);
+ path.Read (rMF, flags, *this);
+
+
+ EMFPPlusFillPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
+
+ break;
+ }
+ case EmfPlusRecordTypeDrawLines:
+ {
+ sal_uInt32 index = flags & 0xff;
+ sal_uInt32 points;
+
+ rMF >> points;
+
+ EMFP_DEBUG (printf ("EMF+ DrawLines in slot: %d points: %d\n", index, points));
+
+ EMFPPath path (points, true);
+ path.Read (rMF, flags, *this);
+
+ EMFPPen* pen = (EMFPPen*) aObjects [index];
+
+ rState.isFillColorSet = false;
+ rState.isLineColorSet = true;
+ rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
+ rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace() );
+ ::basegfx::B2DPolyPolygon& polygon (path.GetPolygon (*this));
+
+ polygon.transform( rState.mapModeTransform );
+
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
+
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ rFactoryParms.mrCurrActionIndex ) );
+
+ rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+
+ break;
+ }
+ case EmfPlusRecordTypeDrawPath:
+ {
+ sal_uInt32 penIndex;
+
+ rMF >> penIndex;
+
+ EMFP_DEBUG (printf ("EMF+ DrawPath\n"));
+ EMFP_DEBUG (printf ("EMF+\tpen: %d\n", penIndex));
+
+ EMFPPath* path = (EMFPPath*) aObjects [flags & 0xff];
+ EMFPPen* pen = (EMFPPen*) aObjects [penIndex];
+
+ rState.isFillColorSet = false;
+ rState.isLineColorSet = true;
+ rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
+ rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
+ ::basegfx::B2DPolyPolygon& polygon (path->GetPolygon (*this));
+
+ polygon.transform( rState.mapModeTransform );
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
+
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ rFactoryParms.mrCurrActionIndex ) );
+
+ rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+ break;
+ }
+ case EmfPlusRecordTypeDrawImagePoints:
+ {
+ sal_uInt32 attrIndex;
+ sal_Int32 sourceUnit;
+
+ rMF >> attrIndex >> sourceUnit;
+
+ EMFP_DEBUG (printf ("EMF+ DrawImagePoints attributes index: %d source unit: %d\n", attrIndex, sourceUnit));
+ EMFP_DEBUG (printf ("EMF+\tTODO: use image attributes\n"));
+
+ if (sourceUnit == 2 && aObjects [flags & 0xff]) { // we handle only GraphicsUnit.Pixel now
+ EMFPImage& image = *(EMFPImage *) aObjects [flags & 0xff];
+ float sx, sy, sw, sh;
+ sal_Int32 unknown;
+
+ ReadRectangle (rMF, sx, sy, sw, sh);
+
+ rMF >> unknown;
+
+ EMFP_DEBUG (printf ("EMF+ DrawImagePoints source rectangle: %f,%f %fx%f unknown: 0x%08x\n", sx, sy, sw, sh, unknown));
+
+ if (unknown == 3) { // it probably means number of points defining destination rectangle
+ float x1, y1, x2, y2, x3, y3;
+
+ ReadPoint (rMF, x1, y1);
+ ReadPoint (rMF, x2, y2);
+ ReadPoint (rMF, x3, y3);
+
+ BitmapEx aBmp( image.graphic.GetBitmapEx () );
+ const Rectangle aCropRect (::vcl::unotools::pointFromB2DPoint (Map (sx, sy)),
+ ::vcl::unotools::sizeFromB2DSize (MapSize(sw, sh)));
+ aBmp.Crop( aCropRect );
+
+
+ ActionSharedPtr pBmpAction (
+ internal::BitmapActionFactory::createBitmapAction (
+ aBmp,
+ rState.mapModeTransform * Map (x1, y1),
+ rState.mapModeTransform * MapSize(x2 - x1, y3 - y1),
+ rCanvas,
+ rState));
+
+ if( pBmpAction ) {
+ maActions.push_back( MtfAction( pBmpAction,
+ rFactoryParms.mrCurrActionIndex ) );
+
+ rFactoryParms.mrCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ } else {
+ EMFP_DEBUG (printf ("EMF+ DrawImagePoints TODO (fixme)\n"));
+ }
+ }
+ break;
+ }
+ case EmfPlusRecordTypeDrawString:
+ EMFP_DEBUG (printf ("EMF+ DrawString\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetPageTransform:
+ rMF >> fPageScale;
+
+ EMFP_DEBUG (printf ("EMF+ SetPageTransform\n"));
+ EMFP_DEBUG (printf ("EMF+\tscale: %f unit: %d\n", fPageScale, flags));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetRenderingOrigin:
+ rMF >> nOriginX >> nOriginY;
+ EMFP_DEBUG (printf ("EMF+ SetRenderingOrigin\n"));
+ EMFP_DEBUG (printf ("EMF+\torigin [x,y]: %d,%d\n", nOriginX, nOriginY));
+ break;
+ case EmfPlusRecordTypeSetTextRenderingHint:
+ EMFP_DEBUG (printf ("EMF+ SetTextRenderingHint\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetAntiAliasMode:
+ EMFP_DEBUG (printf ("EMF+ SetAntiAliasMode\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetInterpolationMode:
+ EMFP_DEBUG (printf ("EMF+ InterpolationMode\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetPixelOffsetMode:
+ EMFP_DEBUG (printf ("EMF+ SetPixelOffsetMode\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetCompositingQuality:
+ EMFP_DEBUG (printf ("EMF+ SetCompositingQuality\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSave:
+ EMFP_DEBUG (printf ("EMF+ Save\n"));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ break;
+ case EmfPlusRecordTypeSetWorldTransform: {
+ EMFP_DEBUG (printf ("EMF+ SetWorldTransform\n"));
+ XForm transform;
+ rMF >> transform;
+ aWorldTransform.Set (transform);
+ EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
+ aWorldTransform.eM11, aWorldTransform.eM12,
+ aWorldTransform.eM21, aWorldTransform.eM22,
+ aWorldTransform.eDx, aWorldTransform.eDy));
+ break;
+ }
+ case EmfPlusRecordTypeResetWorldTransform:
+ EMFP_DEBUG (printf ("EMF+ ResetWorldTransform\n"));
+ aWorldTransform.SetIdentity ();
+ break;
+ case EmfPlusRecordTypeSetClipPath:
+ {
+ EMFP_DEBUG (printf ("EMF+ SetClipPath\n"));
+ EMFP_DEBUG (printf ("EMF+\tpath in slot: %d\n", flags & 0xff));
+
+ EMFPPath& path = *(EMFPPath*) aObjects [flags & 0xff];
+ ::basegfx::B2DPolyPolygon& clipPoly (path.GetPolygon (*this));
+
+ clipPoly.transform (rState.mapModeTransform);
+ updateClipping (clipPoly, rFactoryParms, false);
+
+ break;
+ }
+ case EmfPlusRecordTypeSetClipRegion: {
+ EMFP_DEBUG (printf ("EMF+ SetClipRegion\n"));
+ EMFP_DEBUG (printf ("EMF+\tregion in slot: %d combine mode: %d\n", flags & 0xff, (flags & 0xff00) >> 8));
+ EMFPRegion& region = *(EMFPRegion*) aObjects [flags & 0xff];
+
+ // reset clip
+ if (region.parts == 0 && region.initialState == EmfPlusRegionInitialStateInfinite) {
+ updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, false);
+ } else {
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ }
+ break;
+ }
+ case EmfPlusRecordTypeDrawDriverString: {
+ EMFP_DEBUG (printf ("EMF+ DrawDriverString, flags: 0x%04x\n", flags));
+ sal_uInt32 brushIndexOrColor;
+ sal_uInt32 optionFlags;
+ sal_uInt32 hasMatrix;
+ sal_uInt32 glyphsCount;
+
+ rMF >> brushIndexOrColor >> optionFlags >> hasMatrix >> glyphsCount;
+
+ EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags & 0x8000) ? "color" : "brush index", brushIndexOrColor));
+ EMFP_DEBUG (printf ("EMF+\toption flags: 0x%08x\n", optionFlags));
+ EMFP_DEBUG (printf ("EMF+\thas matrix: %d\n", hasMatrix));
+ EMFP_DEBUG (printf ("EMF+\tglyphs: %d\n", glyphsCount));
+
+ if( ( optionFlags & 1 ) && glyphsCount > 0 ) {
+ sal_uInt16 *chars = new sal_uInt16[glyphsCount];
+ float *charsPosX = new float[glyphsCount];
+ float *charsPosY = new float[glyphsCount];
+
+ for( sal_uInt32 i=0; i<glyphsCount; i++) {
+ rMF >> chars[i];
+ EMFP_DEBUG (printf ("EMF+\tglyph[%d]: 0x%04x\n",
+ i, chars[i]));
+ }
+ for( sal_uInt32 i=0; i<glyphsCount; i++) {
+ rMF >> charsPosX[i] >> charsPosY[i];
+ EMFP_DEBUG (printf ("EMF+\tglyphPosition[%d]: %f, %f\n", i, charsPosX[i], charsPosY[i]));
+ }
+
+ XForm transform;
+ if( hasMatrix ) {
+ rMF >> transform;
+ EMFP_DEBUG (printf ("EMF+\tmatrix:: %f, %f, %f, %f, %f, %f\n", transform.eM11, transform.eM12, transform.eM21, transform.eM22, transform.eDx, transform.eDy));
+ }
+
+ // create and add the text action
+ XubString text( chars, glyphsCount );
+
+ EMFPFont *font = (EMFPFont*) aObjects[ flags & 0xff ];
+
+ rendering::FontRequest aFontRequest;
+ aFontRequest.FontDescription.FamilyName = font->family;
+ aFontRequest.CellSize = (rState.mapModeTransform*MapSize( font->emSize, 0 )).getX();
+ rState.xFont = rFactoryParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ geometry::Matrix2D() );
+ if( flags & 0x8000 )
+ SET_TEXT_COLOR(brushIndexOrColor);
+
+ ActionSharedPtr pTextAction(
+ TextActionFactory::createTextAction(
+ ::vcl::unotools::pointFromB2DPoint ( Map( charsPosX[0], charsPosY[0] ) ),
+ ::Size(),
+ ::Color(),
+ ::Size(),
+ ::Color(),
+ text,
+ 0,
+ glyphsCount,
+ NULL,
+ rFactoryParms.mrVDev,
+ rFactoryParms.mrCanvas,
+ rState,
+ rFactoryParms.mrParms,
+ false ) );
+
+ if( pTextAction )
+ {
+ EMFP_DEBUG (printf ("EMF+\t\tadd text action\n"));
+
+ maActions.push_back(
+ MtfAction(
+ pTextAction,
+ rFactoryParms.mrCurrActionIndex ) );
+
+ rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
+ }
+
+ delete[] chars;
+ delete[] charsPosX;
+ delete[] charsPosY;
+ } else {
+ EMFP_DEBUG (printf ("EMF+\tTODO: fonts (non-unicode glyphs chars)\n"));
+ }
+
+ break;
+ }
+ default:
+ EMFP_DEBUG (printf ("EMF+ unhandled record type: %d\n", type));
+ EMFP_DEBUG (printf ("EMF+\tTODO\n"));
+ }
+
+ rMF.Seek (next);
+
+ length -= size;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx
new file mode 100644
index 000000000000..c71c09863234
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx
@@ -0,0 +1,3209 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+#include <osl/mutex.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <rtl/logfile.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppcanvas/canvas.hxx>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/rendering/PanoseProportion.hpp>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <canvas/canvastools.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/salbtype.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/graphictools.hxx>
+#include <tools/poly.hxx>
+#include <i18npool/mslangid.hxx>
+#include <implrenderer.hxx>
+#include <tools.hxx>
+#include <outdevstate.hxx>
+#include <action.hxx>
+#include <bitmapaction.hxx>
+#include <lineaction.hxx>
+#include <pointaction.hxx>
+#include <polypolyaction.hxx>
+#include <textaction.hxx>
+#include <transparencygroupaction.hxx>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <boost/scoped_array.hpp>
+#include "mtftools.hxx"
+#include "outdevstate.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#define EMFP_DEBUG(x)
+//#define EMFP_DEBUG(x) x
+
+using namespace ::com::sun::star;
+
+
+// free support functions
+// ======================
+namespace
+{
+ template < class MetaActionType > void setStateColor( MetaActionType* pAct,
+ bool& rIsColorSet,
+ uno::Sequence< double >& rColorSequence,
+ const cppcanvas::CanvasSharedPtr& rCanvas )
+ {
+ // set rIsColorSet and check for true at the same time
+ if( (rIsColorSet=pAct->IsSetting()) != false )
+ {
+ ::Color aColor( pAct->GetColor() );
+
+ // force alpha part of color to
+ // opaque. transparent painting is done
+ // explicitely via META_TRANSPARENT_ACTION
+ aColor.SetTransparency(0);
+ //aColor.SetTransparency(128);
+
+ rColorSequence = ::vcl::unotools::colorToDoubleSequence(
+ aColor,
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
+ }
+ }
+
+
+ // state stack manipulators
+ // ------------------------
+ void clearStateStack( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
+ {
+ rStates.clear();
+ const ::cppcanvas::internal::OutDevState aDefaultState;
+ rStates.push_back( aDefaultState );
+ }
+
+ ::cppcanvas::internal::OutDevState& getState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
+ {
+ return rStates.back();
+ }
+
+ const ::cppcanvas::internal::OutDevState& getState( const ::cppcanvas::internal::VectorOfOutDevStates& rStates )
+ {
+ return rStates.back();
+ }
+
+ void pushState( ::cppcanvas::internal::VectorOfOutDevStates& rStates,
+ sal_uInt16 nFlags )
+ {
+ rStates.push_back( getState( rStates ) );
+ getState( rStates ).pushFlags = nFlags;
+ }
+
+ void popState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
+ {
+ if( getState( rStates ).pushFlags != PUSH_ALL )
+ {
+ // a state is pushed which is incomplete, i.e. does not
+ // restore everything to the previous stack level when
+ // popped.
+ // That means, we take the old state, and restore every
+ // OutDevState member whose flag is set, from the new to the
+ // old state. Then the new state gets overwritten by the
+ // calculated state
+
+ // preset to-be-calculated new state with old state
+ ::cppcanvas::internal::OutDevState aCalculatedNewState( getState( rStates ) );
+
+ // selectively copy to-be-restored content over saved old
+ // state
+ rStates.pop_back();
+
+ const ::cppcanvas::internal::OutDevState& rNewState( getState( rStates ) );
+
+ if( (aCalculatedNewState.pushFlags & PUSH_LINECOLOR) )
+ {
+ aCalculatedNewState.lineColor = rNewState.lineColor;
+ aCalculatedNewState.isLineColorSet = rNewState.isLineColorSet;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_FILLCOLOR) )
+ {
+ aCalculatedNewState.fillColor = rNewState.fillColor;
+ aCalculatedNewState.isFillColorSet = rNewState.isFillColorSet;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_FONT) )
+ {
+ aCalculatedNewState.xFont = rNewState.xFont;
+ aCalculatedNewState.fontRotation = rNewState.fontRotation;
+ aCalculatedNewState.textReliefStyle = rNewState.textReliefStyle;
+ aCalculatedNewState.textOverlineStyle = rNewState.textOverlineStyle;
+ aCalculatedNewState.textUnderlineStyle = rNewState.textUnderlineStyle;
+ aCalculatedNewState.textStrikeoutStyle = rNewState.textStrikeoutStyle;
+ aCalculatedNewState.textEmphasisMarkStyle = rNewState.textEmphasisMarkStyle;
+ aCalculatedNewState.isTextEffectShadowSet = rNewState.isTextEffectShadowSet;
+ aCalculatedNewState.isTextWordUnderlineSet = rNewState.isTextWordUnderlineSet;
+ aCalculatedNewState.isTextOutlineModeSet = rNewState.isTextOutlineModeSet;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_TEXTCOLOR) )
+ {
+ aCalculatedNewState.textColor = rNewState.textColor;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_MAPMODE) )
+ {
+ aCalculatedNewState.mapModeTransform = rNewState.mapModeTransform;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_CLIPREGION) )
+ {
+ aCalculatedNewState.clip = rNewState.clip;
+ aCalculatedNewState.clipRect = rNewState.clipRect;
+ aCalculatedNewState.xClipPoly = rNewState.xClipPoly;
+ }
+
+ // TODO(F2): Raster ops NYI
+ // if( (aCalculatedNewState.pushFlags & PUSH_RASTEROP) )
+ // {
+ // }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_TEXTFILLCOLOR) )
+ {
+ aCalculatedNewState.textFillColor = rNewState.textFillColor;
+ aCalculatedNewState.isTextFillColorSet = rNewState.isTextFillColorSet;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_TEXTALIGN) )
+ {
+ aCalculatedNewState.textReferencePoint = rNewState.textReferencePoint;
+ }
+
+ // TODO(F1): Refpoint handling NYI
+ // if( (aCalculatedNewState.pushFlags & PUSH_REFPOINT) )
+ // {
+ // }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_TEXTLINECOLOR) )
+ {
+ aCalculatedNewState.textLineColor = rNewState.textLineColor;
+ aCalculatedNewState.isTextLineColorSet = rNewState.isTextLineColorSet;
+ }
+
+ if( (aCalculatedNewState.pushFlags & PUSH_TEXTLAYOUTMODE) )
+ {
+ aCalculatedNewState.textAlignment = rNewState.textAlignment;
+ aCalculatedNewState.textDirection = rNewState.textDirection;
+ }
+
+ // TODO(F2): Text language handling NYI
+ // if( (aCalculatedNewState.pushFlags & PUSH_TEXTLANGUAGE) )
+ // {
+ // }
+
+ // always copy push mode
+ aCalculatedNewState.pushFlags = rNewState.pushFlags;
+
+ // flush to stack
+ getState( rStates ) = aCalculatedNewState;
+ }
+ else
+ {
+ rStates.pop_back();
+ }
+ }
+
+ void setupStrokeAttributes( rendering::StrokeAttributes& o_rStrokeAttributes,
+ const ::cppcanvas::internal::ActionFactoryParameters& rParms,
+ const LineInfo& rLineInfo )
+ {
+ const ::basegfx::B2DSize aWidth( rLineInfo.GetWidth(), 0 );
+ o_rStrokeAttributes.StrokeWidth =
+ (getState( rParms.mrStates ).mapModeTransform * aWidth).getX();
+
+ // setup reasonable defaults
+ o_rStrokeAttributes.MiterLimit = 15.0; // 1.0 was no good default; GDI+'s limit is 10.0, our's is 15.0
+ o_rStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
+ o_rStrokeAttributes.EndCapType = rendering::PathCapType::BUTT;
+
+ switch(rLineInfo.GetLineJoin())
+ {
+ default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::NONE;
+ break;
+ case basegfx::B2DLINEJOIN_BEVEL:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::BEVEL;
+ break;
+ case basegfx::B2DLINEJOIN_MITER:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
+ break;
+ case basegfx::B2DLINEJOIN_ROUND:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::ROUND;
+ break;
+ }
+
+ if( LINE_DASH == rLineInfo.GetStyle() )
+ {
+ const ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
+
+ // TODO(F1): Interpret OutDev::GetRefPoint() for the start of the dashing.
+
+ // interpret dash info only if explicitely enabled as
+ // style
+ const ::basegfx::B2DSize aDistance( rLineInfo.GetDistance(), 0 );
+ const double nDistance( (rState.mapModeTransform * aDistance).getX() );
+
+ const ::basegfx::B2DSize aDashLen( rLineInfo.GetDashLen(), 0 );
+ const double nDashLen( (rState.mapModeTransform * aDashLen).getX() );
+
+ const ::basegfx::B2DSize aDotLen( rLineInfo.GetDotLen(), 0 );
+ const double nDotLen( (rState.mapModeTransform * aDotLen).getX() );
+
+ const sal_Int32 nNumArryEntries( 2*rLineInfo.GetDashCount() +
+ 2*rLineInfo.GetDotCount() );
+
+ o_rStrokeAttributes.DashArray.realloc( nNumArryEntries );
+ double* pDashArray = o_rStrokeAttributes.DashArray.getArray();
+
+
+ // iteratively fill dash array, first with dashs, then
+ // with dots.
+ // ===================================================
+
+ sal_Int32 nCurrEntry=0;
+
+ for( sal_Int32 i=0; i<rLineInfo.GetDashCount(); ++i )
+ {
+ pDashArray[nCurrEntry++] = nDashLen;
+ pDashArray[nCurrEntry++] = nDistance;
+ }
+ for( sal_Int32 i=0; i<rLineInfo.GetDotCount(); ++i )
+ {
+ pDashArray[nCurrEntry++] = nDotLen;
+ pDashArray[nCurrEntry++] = nDistance;
+ }
+ }
+ }
+
+
+ /** Create masked BitmapEx, where the white areas of rBitmap are
+ transparent, and the other appear in rMaskColor.
+ */
+ BitmapEx createMaskBmpEx( const Bitmap& rBitmap,
+ const ::Color& rMaskColor )
+ {
+ const ::Color aWhite( COL_WHITE );
+ BitmapPalette aBiLevelPalette(2);
+ aBiLevelPalette[0] = aWhite;
+ aBiLevelPalette[1] = rMaskColor;
+
+ Bitmap aMask( rBitmap.CreateMask( aWhite ));
+ Bitmap aSolid( rBitmap.GetSizePixel(),
+ 1,
+ &aBiLevelPalette );
+ aSolid.Erase( rMaskColor );
+
+ return BitmapEx( aSolid, aMask );
+ }
+
+ /** Shameless rip from vcl/source/gdi/outdev3.cxx
+
+ Should consolidate, into something like basetxt...
+ */
+ sal_Unicode getLocalizedChar( sal_Unicode nChar, LanguageType eLang )
+ {
+ // currently only conversion from ASCII digits is interesting
+ if( (nChar < '0') || ('9' < nChar) )
+ return nChar;
+
+ sal_Unicode nOffset(0);
+ // eLang & LANGUAGE_MASK_PRIMARY catches language independent of region.
+ // CAVEAT! To some like Mongolian MS assigned the same primary language
+ // although the script type is different!
+ switch( eLang & LANGUAGE_MASK_PRIMARY )
+ {
+ default:
+ break;
+
+ case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY:
+ case LANGUAGE_URDU & LANGUAGE_MASK_PRIMARY:
+ case LANGUAGE_PUNJABI & LANGUAGE_MASK_PRIMARY: //???
+ nOffset = 0x0660 - '0'; // arabic/persian/urdu
+ break;
+ case LANGUAGE_BENGALI & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x09E6 - '0'; // bengali
+ break;
+ case LANGUAGE_BURMESE & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x1040 - '0'; // burmese
+ break;
+ case LANGUAGE_HINDI & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0966 - '0'; // devanagari
+ break;
+ case LANGUAGE_GUJARATI & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0AE6 - '0'; // gujarati
+ break;
+ case LANGUAGE_KANNADA & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0CE6 - '0'; // kannada
+ break;
+ case LANGUAGE_KHMER & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x17E0 - '0'; // khmer
+ break;
+ case LANGUAGE_LAO & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0ED0 - '0'; // lao
+ break;
+ case LANGUAGE_MALAYALAM & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0D66 - '0'; // malayalam
+ break;
+ case LANGUAGE_MONGOLIAN & LANGUAGE_MASK_PRIMARY:
+ if (eLang == LANGUAGE_MONGOLIAN_MONGOLIAN)
+ nOffset = 0x1810 - '0'; // mongolian
+ else
+ nOffset = 0; // mongolian cyrillic
+ break;
+ case LANGUAGE_ORIYA & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0B66 - '0'; // oriya
+ break;
+ case LANGUAGE_TAMIL & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0BE7 - '0'; // tamil
+ break;
+ case LANGUAGE_TELUGU & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0C66 - '0'; // telugu
+ break;
+ case LANGUAGE_THAI & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0E50 - '0'; // thai
+ break;
+ case LANGUAGE_TIBETAN & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0F20 - '0'; // tibetan
+ break;
+ }
+
+ nChar = sal::static_int_cast<sal_Unicode>(nChar + nOffset);
+ return nChar;
+ }
+
+ void convertToLocalizedNumerals( XubString& rStr,
+ LanguageType eTextLanguage )
+ {
+ const sal_Unicode* pBase = rStr.GetBuffer();
+ const sal_Unicode* pBegin = pBase + 0;
+ const xub_StrLen nEndIndex = rStr.Len();
+ const sal_Unicode* pEnd = pBase + nEndIndex;
+
+ for( ; pBegin < pEnd; ++pBegin )
+ {
+ // TODO: are there non-digit localizations?
+ if( (*pBegin >= '0') && (*pBegin <= '9') )
+ {
+ // translate characters to local preference
+ sal_Unicode cChar = getLocalizedChar( *pBegin, eTextLanguage );
+ if( cChar != *pBegin )
+ rStr.SetChar( sal::static_int_cast<sal_uInt16>(pBegin - pBase), cChar );
+ }
+ }
+ }
+}
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const ActionFactoryParameters& rParms )
+ {
+ const OutDevState& rState( getState( rParms.mrStates ) );
+ if( (!rState.isLineColorSet &&
+ !rState.isFillColorSet) ||
+ (rState.lineColor.getLength() == 0 &&
+ rState.fillColor.getLength() == 0) )
+ {
+ return false;
+ }
+
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ rPolyPoly, rParms.mrCanvas, rState ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ rParms.mrCurrActionIndex ) );
+
+ rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+
+ return true;
+ }
+
+ bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolygon& rPoly,
+ const ActionFactoryParameters& rParms )
+ {
+ return createFillAndStroke( ::basegfx::B2DPolyPolygon( rPoly ),
+ rParms );
+ }
+
+ void ImplRenderer::skipContent( GDIMetaFile& rMtf,
+ const char* pCommentString,
+ sal_Int32& io_rCurrActionIndex ) const
+ {
+ ENSURE_OR_THROW( pCommentString,
+ "ImplRenderer::skipContent(): NULL string given" );
+
+ MetaAction* pCurrAct;
+ while( (pCurrAct=rMtf.NextAction()) != NULL )
+ {
+ // increment action index, we've skipped an action.
+ ++io_rCurrActionIndex;
+
+ if( pCurrAct->GetType() == META_COMMENT_ACTION &&
+ static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
+ pCommentString ) == COMPARE_EQUAL )
+ {
+ // requested comment found, done
+ return;
+ }
+ }
+
+ // EOF
+ return;
+ }
+
+ bool ImplRenderer::isActionContained( GDIMetaFile& rMtf,
+ const char* pCommentString,
+ sal_uInt16 nType ) const
+ {
+ ENSURE_OR_THROW( pCommentString,
+ "ImplRenderer::isActionContained(): NULL string given" );
+
+ bool bRet( false );
+
+ // at least _one_ call to GDIMetaFile::NextAction() is
+ // executed
+ sal_uIntPtr nPos( 1 );
+
+ MetaAction* pCurrAct;
+ while( (pCurrAct=rMtf.NextAction()) != NULL )
+ {
+ if( pCurrAct->GetType() == nType )
+ {
+ bRet = true; // action type found
+ break;
+ }
+
+ if( pCurrAct->GetType() == META_COMMENT_ACTION &&
+ static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
+ pCommentString ) == COMPARE_EQUAL )
+ {
+ // delimiting end comment found, done
+ bRet = false; // not yet found
+ break;
+ }
+
+ ++nPos;
+ }
+
+ // rewind metafile to previous position (this method must
+ // not change the current metaaction)
+ while( nPos-- )
+ rMtf.WindPrev();
+
+ if( !pCurrAct )
+ {
+ // EOF, and not yet found
+ bRet = false;
+ }
+
+ return bRet;
+ }
+
+ void ImplRenderer::createGradientAction( const ::PolyPolygon& rPoly,
+ const ::Gradient& rGradient,
+ const ActionFactoryParameters& rParms,
+ bool bIsPolygonRectangle,
+ bool bSubsettableActions )
+ {
+ DBG_TESTSOLARMUTEX();
+
+ ::basegfx::B2DPolyPolygon aDevicePoly( rPoly.getB2DPolyPolygon() );
+ aDevicePoly.transform( getState( rParms.mrStates ).mapModeTransform );
+
+ // decide, whether this gradient can be rendered natively
+ // by the canvas, or must be emulated via VCL gradient
+ // action extraction.
+ const sal_uInt16 nSteps( rGradient.GetSteps() );
+
+ if( // step count is infinite, can use native canvas
+ // gradients here
+ nSteps == 0 ||
+ // step count is sufficiently high, such that no
+ // discernible difference should be visible.
+ nSteps > 64 )
+ {
+ uno::Reference< lang::XMultiServiceFactory> xFactory(
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
+
+ if( xFactory.is() )
+ {
+ rendering::Texture aTexture;
+
+ aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
+ aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
+ aTexture.Alpha = 1.0;
+
+
+ // setup start/end color values
+ // ----------------------------
+
+ // scale color coefficients with gradient intensities
+ const sal_uInt16 nStartIntensity( rGradient.GetStartIntensity() );
+ ::Color aVCLStartColor( rGradient.GetStartColor() );
+ aVCLStartColor.SetRed( (sal_uInt8)(aVCLStartColor.GetRed() * nStartIntensity / 100) );
+ aVCLStartColor.SetGreen( (sal_uInt8)(aVCLStartColor.GetGreen() * nStartIntensity / 100) );
+ aVCLStartColor.SetBlue( (sal_uInt8)(aVCLStartColor.GetBlue() * nStartIntensity / 100) );
+
+ const sal_uInt16 nEndIntensity( rGradient.GetEndIntensity() );
+ ::Color aVCLEndColor( rGradient.GetEndColor() );
+ aVCLEndColor.SetRed( (sal_uInt8)(aVCLEndColor.GetRed() * nEndIntensity / 100) );
+ aVCLEndColor.SetGreen( (sal_uInt8)(aVCLEndColor.GetGreen() * nEndIntensity / 100) );
+ aVCLEndColor.SetBlue( (sal_uInt8)(aVCLEndColor.GetBlue() * nEndIntensity / 100) );
+
+ uno::Reference<rendering::XColorSpace> xColorSpace(
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
+ const uno::Sequence< double > aStartColor(
+ ::vcl::unotools::colorToDoubleSequence( aVCLStartColor,
+ xColorSpace ));
+ const uno::Sequence< double > aEndColor(
+ ::vcl::unotools::colorToDoubleSequence( aVCLEndColor,
+ xColorSpace ));
+
+ uno::Sequence< uno::Sequence < double > > aColors(2);
+ uno::Sequence< double > aStops(2);
+
+ if( rGradient.GetStyle() == GRADIENT_AXIAL )
+ {
+ aStops.realloc(3);
+ aColors.realloc(3);
+
+ aStops[0] = 0.0;
+ aStops[1] = 0.5;
+ aStops[2] = 1.0;
+
+ aColors[0] = aEndColor;
+ aColors[1] = aStartColor;
+ aColors[2] = aEndColor;
+ }
+ else
+ {
+ aStops[0] = 0.0;
+ aStops[1] = 1.0;
+
+ aColors[0] = aStartColor;
+ aColors[1] = aEndColor;
+ }
+
+ const ::basegfx::B2DRectangle aBounds(
+ ::basegfx::tools::getRange(aDevicePoly) );
+ const ::basegfx::B2DVector aOffset(
+ rGradient.GetOfsX() / 100.0,
+ rGradient.GetOfsY() / 100.0);
+ double fRotation( rGradient.GetAngle() * M_PI / 1800.0 );
+ const double fBorder( rGradient.GetBorder() / 100.0 );
+
+ basegfx::B2DHomMatrix aRot90;
+ aRot90.rotate(M_PI_2);
+
+ basegfx::ODFGradientInfo aGradInfo;
+ rtl::OUString aGradientService;
+ switch( rGradient.GetStyle() )
+ {
+ case GRADIENT_LINEAR:
+ basegfx::tools::createLinearODFGradientInfo(aGradInfo,
+ aBounds,
+ nSteps,
+ fBorder,
+ fRotation);
+ // map odf to svg gradient orientation - x
+ // instead of y direction
+ aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LinearGradient"));
+ break;
+
+ case GRADIENT_AXIAL:
+ {
+ // Adapt the border so that it is suitable
+ // for the axial gradient. An axial
+ // gradient consists of two linear
+ // gradients. Each of those covers half
+ // of the total size. In order to
+ // compensate for the condensed display of
+ // the linear gradients, we have to
+ // enlarge the area taken up by the actual
+ // gradient (1-fBorder). After that we
+ // have to turn the result back into a
+ // border value, hence the second (left
+ // most 1-...
+ const double fAxialBorder (1-2*(1-fBorder));
+ basegfx::tools::createAxialODFGradientInfo(aGradInfo,
+ aBounds,
+ nSteps,
+ fAxialBorder,
+ fRotation);
+ // map odf to svg gradient orientation - x
+ // instead of y direction
+ aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
+
+ // map odf axial gradient to 3-stop linear
+ // gradient - shift left by 0.5
+ basegfx::B2DHomMatrix aShift;
+ aShift.translate(-0.5,0);
+ aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aShift;
+
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LinearGradient"));
+ break;
+ }
+
+ case GRADIENT_RADIAL:
+ basegfx::tools::createRadialODFGradientInfo(aGradInfo,
+ aBounds,
+ aOffset,
+ nSteps,
+ fBorder);
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EllipticalGradient"));
+ break;
+
+ case GRADIENT_ELLIPTICAL:
+ basegfx::tools::createEllipticalODFGradientInfo(aGradInfo,
+ aBounds,
+ aOffset,
+ nSteps,
+ fBorder,
+ fRotation);
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EllipticalGradient"));
+ break;
+
+ case GRADIENT_SQUARE:
+ basegfx::tools::createSquareODFGradientInfo(aGradInfo,
+ aBounds,
+ aOffset,
+ nSteps,
+ fBorder,
+ fRotation);
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RectangularGradient"));
+ break;
+
+ case GRADIENT_RECT:
+ basegfx::tools::createRectangularODFGradientInfo(aGradInfo,
+ aBounds,
+ aOffset,
+ nSteps,
+ fBorder,
+ fRotation);
+ aGradientService = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RectangularGradient"));
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "ImplRenderer::createGradientAction(): Unexpected gradient type" );
+ break;
+ }
+
+ // As the texture coordinate space is relative to
+ // the polygon coordinate space (NOT to the
+ // polygon itself), move gradient to the start of
+ // the actual polygon. If we skip this, the
+ // gradient will always display at the origin, and
+ // not within the polygon bound (which might be
+ // miles away from the origin).
+ aGradInfo.maTextureTransform.translate( aBounds.getMinX(),
+ aBounds.getMinY() );
+ ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
+ aGradInfo.maTextureTransform );
+
+ uno::Sequence<uno::Any> args(3);
+ beans::PropertyValue aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Colors"));
+ aProp.Value <<= aColors;
+ args[0] <<= aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Stops"));
+ aProp.Value <<= aStops;
+ args[1] <<= aProp;
+ aProp.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AspectRatio"));
+ aProp.Value <<= aGradInfo.mfAspectRatio;
+ args[2] <<= aProp;
+
+ aTexture.Gradient.set(
+ xFactory->createInstanceWithArguments(aGradientService,
+ args),
+ uno::UNO_QUERY);
+ if( aTexture.Gradient.is() )
+ {
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ aDevicePoly,
+ rParms.mrCanvas,
+ getState( rParms.mrStates ),
+ aTexture ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ rParms.mrCurrActionIndex ) );
+
+ rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+
+ // done, using native gradients
+ return;
+ }
+ }
+ }
+
+ // cannot currently use native canvas gradients, as a
+ // finite step size is given (this funny feature is not
+ // supported by the XCanvas API)
+ pushState( rParms.mrStates, PUSH_ALL );
+
+ if( !bIsPolygonRectangle )
+ {
+ // only clip, if given polygon is not a rectangle in
+ // the first place (the gradient is always limited to
+ // the given bound rect)
+ updateClipping(
+ aDevicePoly,
+ rParms,
+ true );
+ }
+
+ GDIMetaFile aTmpMtf;
+ rParms.mrVDev.AddGradientActions( rPoly.GetBoundRect(),
+ rGradient,
+ aTmpMtf );
+
+ createActions( aTmpMtf, rParms, bSubsettableActions );
+
+ popState( rParms.mrStates );
+ }
+
+ uno::Reference< rendering::XCanvasFont > ImplRenderer::createFont( double& o_rFontRotation,
+ const ::Font& rFont,
+ const ActionFactoryParameters& rParms ) const
+ {
+ rendering::FontRequest aFontRequest;
+
+ if( rParms.mrParms.maFontName.is_initialized() )
+ aFontRequest.FontDescription.FamilyName = *rParms.mrParms.maFontName;
+ else
+ aFontRequest.FontDescription.FamilyName = rFont.GetName();
+
+ aFontRequest.FontDescription.StyleName = rFont.GetStyleName();
+
+ aFontRequest.FontDescription.IsSymbolFont = (rFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL) ? util::TriState_YES : util::TriState_NO;
+ aFontRequest.FontDescription.IsVertical = rFont.IsVertical() ? util::TriState_YES : util::TriState_NO;
+
+ // TODO(F2): improve vclenum->panose conversion
+ aFontRequest.FontDescription.FontDescription.Weight =
+ rParms.mrParms.maFontWeight.is_initialized() ?
+ *rParms.mrParms.maFontWeight :
+ ::canvas::tools::numeric_cast<sal_Int8>( ::basegfx::fround( rFont.GetWeight() ) );
+ aFontRequest.FontDescription.FontDescription.Letterform =
+ rParms.mrParms.maFontLetterForm.is_initialized() ?
+ *rParms.mrParms.maFontLetterForm :
+ (rFont.GetItalic() == ITALIC_NONE) ? 0 : 9;
+ aFontRequest.FontDescription.FontDescription.Proportion =
+ rParms.mrParms.maFontProportion.is_initialized() ?
+ *rParms.mrParms.maFontProportion :
+ (rFont.GetPitch() == PITCH_FIXED)
+ ? rendering::PanoseProportion::MONO_SPACED
+ : rendering::PanoseProportion::ANYTHING;
+
+ LanguageType aLang = rFont.GetLanguage();
+ aFontRequest.Locale = MsLangId::convertLanguageToLocale(aLang, false);
+
+ // setup state-local text transformation,
+ // if the font be rotated
+ const short nFontAngle( rFont.GetOrientation() );
+ if( nFontAngle != 0 )
+ {
+ // set to unity transform rotated by font angle
+ const double nAngle( nFontAngle * (F_PI / 1800.0) );
+ o_rFontRotation = -nAngle;
+ }
+ else
+ {
+ o_rFontRotation = 0.0;
+ }
+
+ geometry::Matrix2D aFontMatrix;
+ ::canvas::tools::setIdentityMatrix2D( aFontMatrix );
+
+ // TODO(F2): use correct scale direction, font
+ // height might be width or anything else
+
+ // TODO(Q3): This code smells of programming by
+ // coincidence (the next two if statements)
+ const ::Size rFontSizeLog( rFont.GetSize() );
+ const sal_Int32 nFontWidthLog = rFontSizeLog.Width();
+ if( nFontWidthLog != 0 )
+ {
+ ::Font aTestFont = rFont;
+ aTestFont.SetWidth( 0 );
+ sal_Int32 nNormalWidth = rParms.mrVDev.GetFontMetric( aTestFont ).GetWidth();
+ if( nNormalWidth != nFontWidthLog )
+ if( nNormalWidth )
+ aFontMatrix.m00 = (double)nFontWidthLog / nNormalWidth;
+ }
+
+ // #i52608# apply map mode scale also to font matrix - an
+ // anisotrophic mapmode must be reflected in an
+ // anisotrophic font matrix scale.
+ const OutDevState& rState( getState( rParms.mrStates ) );
+ if( !::basegfx::fTools::equal(
+ rState.mapModeTransform.get(0,0),
+ rState.mapModeTransform.get(1,1)) )
+ {
+ const double nScaleX( rState.mapModeTransform.get(0,0) );
+ const double nScaleY( rState.mapModeTransform.get(1,1) );
+
+ // note: no reason to check for division by zero, we
+ // always have the value closer (or equal) to zero as
+ // the nominator.
+ if( fabs(nScaleX) < fabs(nScaleY) )
+ aFontMatrix.m00 *= nScaleX / nScaleY;
+ else
+ aFontMatrix.m11 *= nScaleY / nScaleX;
+ }
+ aFontRequest.CellSize = (rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize(rFontSizeLog)).getY();
+
+ return rParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ aFontMatrix );
+ }
+
+ // create text effects such as shadow/relief/embossed
+ void ImplRenderer::createTextAction( const ::Point& rStartPoint,
+ const String rString,
+ int nIndex,
+ int nLength,
+ const sal_Int32* pCharWidths,
+ const ActionFactoryParameters& rParms,
+ bool bSubsettableActions )
+ {
+ ENSURE_OR_THROW( nIndex >= 0 && nLength <= rString.Len() + nIndex,
+ "ImplRenderer::createTextWithEffectsAction(): Invalid text index" );
+
+ if( !nLength )
+ return; // zero-length text, no visible output
+
+ const OutDevState& rState( getState( rParms.mrStates ) );
+
+ // TODO(F2): implement all text effects
+ // if( rState.textAlignment ); // TODO(F2): NYI
+
+ ::Color aShadowColor( COL_AUTO );
+ ::Color aReliefColor( COL_AUTO );
+ ::Size aShadowOffset;
+ ::Size aReliefOffset;
+
+ uno::Reference<rendering::XColorSpace> xColorSpace(
+ rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
+
+ if( rState.isTextEffectShadowSet )
+ {
+ // calculate shadow offset (similar to outdev3.cxx)
+ // TODO(F3): better match with outdev3.cxx
+ sal_Int32 nShadowOffset = static_cast<sal_Int32>(1.5 + ((rParms.mrVDev.GetFont().GetHeight()-24.0)/24.0));
+ if( nShadowOffset < 1 )
+ nShadowOffset = 1;
+
+ aShadowOffset.setWidth( nShadowOffset );
+ aShadowOffset.setHeight( nShadowOffset );
+
+ // determine shadow color (from outdev3.cxx)
+ ::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
+ rState.textColor, xColorSpace );
+ bool bIsDark = (aTextColor.GetColor() == COL_BLACK)
+ || (aTextColor.GetLuminance() < 8);
+
+ aShadowColor = bIsDark ? COL_LIGHTGRAY : COL_BLACK;
+ aShadowColor.SetTransparency( aTextColor.GetTransparency() );
+ }
+
+ if( rState.textReliefStyle )
+ {
+ // calculate relief offset (similar to outdev3.cxx)
+ sal_Int32 nReliefOffset = rParms.mrVDev.PixelToLogic( Size( 1, 1 ) ).Height();
+ nReliefOffset += nReliefOffset/2;
+ if( nReliefOffset < 1 )
+ nReliefOffset = 1;
+
+ if( rState.textReliefStyle == RELIEF_ENGRAVED )
+ nReliefOffset = -nReliefOffset;
+
+ aReliefOffset.setWidth( nReliefOffset );
+ aReliefOffset.setHeight( nReliefOffset );
+
+ // determine relief color (from outdev3.cxx)
+ ::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
+ rState.textColor, xColorSpace );
+
+ aReliefColor = ::Color( COL_LIGHTGRAY );
+
+ // we don't have a automatic color, so black is always
+ // drawn on white (literally copied from
+ // vcl/source/gdi/outdev3.cxx)
+ if( aTextColor.GetColor() == COL_BLACK )
+ {
+ aTextColor = ::Color( COL_WHITE );
+ getState( rParms.mrStates ).textColor =
+ ::vcl::unotools::colorToDoubleSequence(
+ aTextColor, xColorSpace );
+ }
+
+ if( aTextColor.GetColor() == COL_WHITE )
+ aReliefColor = ::Color( COL_BLACK );
+ aReliefColor.SetTransparency( aTextColor.GetTransparency() );
+ }
+
+ // create the actual text action
+ ActionSharedPtr pTextAction(
+ TextActionFactory::createTextAction(
+ rStartPoint,
+ aReliefOffset,
+ aReliefColor,
+ aShadowOffset,
+ aShadowColor,
+ rString,
+ nIndex,
+ nLength,
+ pCharWidths,
+ rParms.mrVDev,
+ rParms.mrCanvas,
+ rState,
+ rParms.mrParms,
+ bSubsettableActions ) );
+
+ ActionSharedPtr pStrikeoutTextAction;
+
+ if ( rState.textStrikeoutStyle == STRIKEOUT_X || rState.textStrikeoutStyle == STRIKEOUT_SLASH )
+ {
+ long nWidth = rParms.mrVDev.GetTextWidth( rString,nIndex,nLength );
+
+ xub_Unicode pChars[5];
+ if ( rState.textStrikeoutStyle == STRIKEOUT_X )
+ pChars[0] = 'X';
+ else
+ pChars[0] = '/';
+ pChars[3]=pChars[2]=pChars[1]=pChars[0];
+
+ long nStrikeoutWidth = nWidth;
+ String aStrikeoutTest( pChars, 4 );
+
+ if( aStrikeoutTest.Len() )
+ {
+ nStrikeoutWidth = ( rParms.mrVDev.GetTextWidth( aStrikeoutTest ) + 2 ) / 4;
+ aStrikeoutTest.Erase();
+
+ if( nStrikeoutWidth <= 0 )
+ nStrikeoutWidth = 1;
+ }
+
+ long nMaxWidth = nStrikeoutWidth/2;
+ if ( nMaxWidth < 2 )
+ nMaxWidth = 2;
+ nMaxWidth += nWidth + 1;
+
+ long nFullStrikeoutWidth = 0;
+ String aStrikeoutText( pChars, 0 );
+ while( (nFullStrikeoutWidth+=nStrikeoutWidth ) < nMaxWidth+1 )
+ aStrikeoutText += pChars[0];
+
+
+ sal_Int32 nStartPos = 0;
+ xub_StrLen nLen = aStrikeoutText.Len();
+
+ if( nLen )
+ {
+ long nInterval = ( nWidth - nStrikeoutWidth * nLen ) / nLen;
+ nStrikeoutWidth += nInterval;
+ sal_Int32* pStrikeoutCharWidths = new sal_Int32[nLen];
+
+ for ( int i = 0;i<nLen; i++)
+ {
+ pStrikeoutCharWidths[i] = nStrikeoutWidth;
+ }
+
+ for ( int i = 1;i< nLen; i++ )
+ {
+ pStrikeoutCharWidths[ i ] += pStrikeoutCharWidths[ i-1 ];
+ }
+
+ pStrikeoutTextAction =
+ TextActionFactory::createTextAction(
+ rStartPoint,
+ aReliefOffset,
+ aReliefColor,
+ aShadowOffset,
+ aShadowColor,
+ aStrikeoutText,
+ nStartPos,
+ aStrikeoutText.Len(),
+ pStrikeoutCharWidths,
+ rParms.mrVDev,
+ rParms.mrCanvas,
+ rState,
+ rParms.mrParms,
+ bSubsettableActions ) ;
+ }
+ }
+
+ if( pTextAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pTextAction,
+ rParms.mrCurrActionIndex ) );
+
+ if ( pStrikeoutTextAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pStrikeoutTextAction,
+ rParms.mrCurrActionIndex ) );
+ }
+
+ rParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
+ }
+ }
+
+ void ImplRenderer::updateClipping( const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ActionFactoryParameters& rParms,
+ bool bIntersect )
+ {
+ ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
+ ::basegfx::B2DPolyPolygon aClipPoly( rClipPoly );
+
+ const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
+ const bool bEmptyClipPoly( rState.clip.count() == 0 );
+
+ ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
+ "ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
+
+ if( !bIntersect ||
+ (bEmptyClipRect && bEmptyClipPoly) )
+ {
+ rState.clip = rClipPoly;
+ }
+ else
+ {
+ if( !bEmptyClipRect )
+ {
+ // TODO(P3): Use Liang-Barsky polygon clip here,
+ // after all, one object is just a rectangle!
+
+ // convert rect to polygon beforehand, must revert
+ // to general polygon clipping here.
+ rState.clip = ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ // #121100# VCL rectangular clips always
+ // include one more pixel to the right
+ // and the bottom
+ ::basegfx::B2DRectangle( rState.clipRect.Left(),
+ rState.clipRect.Top(),
+ rState.clipRect.Right()+1,
+ rState.clipRect.Bottom()+1 ) ) );
+ }
+
+ // AW: Simplified
+ rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+ aClipPoly, rState.clip, true, false);
+ }
+
+ // by now, our clip resides in the OutDevState::clip
+ // poly-polygon.
+ rState.clipRect.SetEmpty();
+
+ if( rState.clip.count() == 0 )
+ {
+ if( rState.clipRect.IsEmpty() )
+ {
+ rState.xClipPoly.clear();
+ }
+ else
+ {
+ rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rParms.mrCanvas->getUNOCanvas()->getDevice(),
+ ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ // #121100# VCL rectangular clips
+ // always include one more pixel to
+ // the right and the bottom
+ ::basegfx::B2DRectangle( rState.clipRect.Left(),
+ rState.clipRect.Top(),
+ rState.clipRect.Right()+1,
+ rState.clipRect.Bottom()+1 ) ) ) );
+ }
+ }
+ else
+ {
+ rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rParms.mrCanvas->getUNOCanvas()->getDevice(),
+ rState.clip );
+ }
+ }
+
+ void ImplRenderer::updateClipping( const ::Rectangle& rClipRect,
+ const ActionFactoryParameters& rParms,
+ bool bIntersect )
+ {
+ ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
+
+ const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
+ const bool bEmptyClipPoly( rState.clip.count() == 0 );
+
+ ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
+ "ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
+
+ if( !bIntersect ||
+ (bEmptyClipRect && bEmptyClipPoly) )
+ {
+ rState.clipRect = rClipRect;
+ rState.clip.clear();
+ }
+ else if( bEmptyClipPoly )
+ {
+ rState.clipRect.Intersection( rClipRect );
+ rState.clip.clear();
+ }
+ else
+ {
+ // TODO(P3): Handle a fourth case here, when all clip
+ // polygons are rectangular, once B2DMultiRange's
+ // sweep line implementation is done.
+
+ // general case: convert to polygon and clip
+ // -----------------------------------------
+
+ // convert rect to polygon beforehand, must revert
+ // to general polygon clipping here.
+ ::basegfx::B2DPolyPolygon aClipPoly(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( rClipRect.Left(),
+ rClipRect.Top(),
+ rClipRect.Right(),
+ rClipRect.Bottom() ) ) );
+
+ rState.clipRect.SetEmpty();
+
+ // AW: Simplified
+ rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+ aClipPoly, rState.clip, true, false);
+ }
+
+ if( rState.clip.count() == 0 )
+ {
+ if( rState.clipRect.IsEmpty() )
+ {
+ rState.xClipPoly.clear();
+ }
+ else
+ {
+ rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rParms.mrCanvas->getUNOCanvas()->getDevice(),
+ ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ // #121100# VCL rectangular clips
+ // always include one more pixel to
+ // the right and the bottom
+ ::basegfx::B2DRectangle( rState.clipRect.Left(),
+ rState.clipRect.Top(),
+ rState.clipRect.Right()+1,
+ rState.clipRect.Bottom()+1 ) ) ) );
+ }
+ }
+ else
+ {
+ rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rParms.mrCanvas->getUNOCanvas()->getDevice(),
+ rState.clip );
+ }
+ }
+
+ bool ImplRenderer::createActions( GDIMetaFile& rMtf,
+ const ActionFactoryParameters& rFactoryParms,
+ bool bSubsettableActions )
+ {
+ /* TODO(P2): interpret mtf-comments
+ ================================
+
+ - gradient fillings (do that via comments)
+
+ - think about mapping. _If_ we do everything in logical
+ coordinates (which would solve the probs for stroke
+ widths and text offsets), then we would have to
+ recalc scaling for every drawing operation. This is
+ because the outdev map mode might change at any time.
+ Also keep in mind, that, although we've double precision
+ float arithmetic now, different offsets might still
+ generate different roundings (aka
+ 'OutputDevice::SetPixelOffset())
+
+ */
+
+ // alias common parameters
+ VectorOfOutDevStates& rStates(rFactoryParms.mrStates);
+ const CanvasSharedPtr& rCanvas(rFactoryParms.mrCanvas);
+ ::VirtualDevice& rVDev(rFactoryParms.mrVDev);
+ const Parameters& rParms(rFactoryParms.mrParms);
+ sal_Int32& io_rCurrActionIndex(rFactoryParms.mrCurrActionIndex);
+
+
+ // Loop over every metaaction
+ // ==========================
+ MetaAction* pCurrAct;
+
+ // TODO(P1): think about caching
+ for( pCurrAct=rMtf.FirstAction();
+ pCurrAct;
+ pCurrAct = rMtf.NextAction() )
+ {
+ // execute every action, to keep VDev state up-to-date
+ // currently used only for
+ // - the map mode
+ // - the line/fill color when processing a META_TRANSPARENT_ACTION
+ // - SetFont to process font metric specific actions
+ pCurrAct->Execute( &rVDev );
+
+ switch( pCurrAct->GetType() )
+ {
+ // ------------------------------------------------------------
+
+ // In the first part of this monster-switch, we
+ // handle all state-changing meta actions. These
+ // are all handled locally.
+
+ // ------------------------------------------------------------
+
+ case META_PUSH_ACTION:
+ {
+ MetaPushAction* pPushAction = static_cast<MetaPushAction*>(pCurrAct);
+ pushState( rStates,
+ pPushAction->GetFlags() );
+ }
+ break;
+
+ case META_POP_ACTION:
+ popState( rStates );
+ break;
+
+ case META_TEXTLANGUAGE_ACTION:
+ // FALLTHROUGH intended
+ case META_REFPOINT_ACTION:
+ // handled via pCurrAct->Execute( &rVDev )
+ break;
+
+ case META_MAPMODE_ACTION:
+ // modify current mapModeTransformation
+ // transformation, such that subsequent
+ // coordinates map correctly
+ tools::calcLogic2PixelAffineTransform( getState( rStates ).mapModeTransform,
+ rVDev );
+ break;
+
+ // monitor clip regions, to assemble clip polygon on our own
+ case META_CLIPREGION_ACTION:
+ {
+ MetaClipRegionAction* pClipAction = static_cast<MetaClipRegionAction*>(pCurrAct);
+
+ if( !pClipAction->IsClipping() )
+ {
+ // clear clipping
+ getState( rStates ).clip.clear();
+ }
+ else
+ {
+ if( !pClipAction->GetRegion().HasPolyPolygon() )
+ {
+ VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
+ "region encountered, falling back to bounding box!" );
+
+ // #121806# explicitely kept integer
+ Rectangle aClipRect(
+ rVDev.LogicToPixel(
+ pClipAction->GetRegion().GetBoundRect() ) );
+
+ // intersect current clip with given rect
+ updateClipping(
+ aClipRect,
+ rFactoryParms,
+ false );
+ }
+ else
+ {
+ // set new clip polygon (don't intersect
+ // with old one, just set it)
+
+ // #121806# explicitely kept integer
+ updateClipping(
+ rVDev.LogicToPixel(
+ pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
+ rFactoryParms,
+ false );
+ }
+ }
+
+ break;
+ }
+
+ case META_ISECTRECTCLIPREGION_ACTION:
+ {
+ MetaISectRectClipRegionAction* pClipAction = static_cast<MetaISectRectClipRegionAction*>(pCurrAct);
+
+ // #121806# explicitely kept integer
+ Rectangle aClipRect(
+ rVDev.LogicToPixel( pClipAction->GetRect() ) );
+
+ // intersect current clip with given rect
+ updateClipping(
+ aClipRect,
+ rFactoryParms,
+ true );
+
+ break;
+ }
+
+ case META_ISECTREGIONCLIPREGION_ACTION:
+ {
+ MetaISectRegionClipRegionAction* pClipAction = static_cast<MetaISectRegionClipRegionAction*>(pCurrAct);
+
+ if( !pClipAction->GetRegion().HasPolyPolygon() )
+ {
+ VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
+ "region encountered, falling back to bounding box!" );
+
+ // #121806# explicitely kept integer
+ Rectangle aClipRect(
+ rVDev.LogicToPixel( pClipAction->GetRegion().GetBoundRect() ) );
+
+ // intersect current clip with given rect
+ updateClipping(
+ aClipRect,
+ rFactoryParms,
+ true );
+ }
+ else
+ {
+ // intersect current clip with given clip polygon
+
+ // #121806# explicitely kept integer
+ updateClipping(
+ rVDev.LogicToPixel(
+ pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
+ rFactoryParms,
+ true );
+ }
+
+ break;
+ }
+
+ case META_MOVECLIPREGION_ACTION:
+ // TODO(F2): NYI
+ break;
+
+ case META_LINECOLOR_ACTION:
+ if( !rParms.maLineColor.is_initialized() )
+ {
+ setStateColor( static_cast<MetaLineColorAction*>(pCurrAct),
+ getState( rStates ).isLineColorSet,
+ getState( rStates ).lineColor,
+ rCanvas );
+ }
+ break;
+
+ case META_FILLCOLOR_ACTION:
+ if( !rParms.maFillColor.is_initialized() )
+ {
+ setStateColor( static_cast<MetaFillColorAction*>(pCurrAct),
+ getState( rStates ).isFillColorSet,
+ getState( rStates ).fillColor,
+ rCanvas );
+ }
+ break;
+
+ case META_TEXTCOLOR_ACTION:
+ {
+ if( !rParms.maTextColor.is_initialized() )
+ {
+ // Text color is set unconditionally, thus, no
+ // use of setStateColor here
+ ::Color aColor( static_cast<MetaTextColorAction*>(pCurrAct)->GetColor() );
+
+ // force alpha part of color to
+ // opaque. transparent painting is done
+ // explicitely via META_TRANSPARENT_ACTION
+ aColor.SetTransparency(0);
+
+ getState( rStates ).textColor =
+ ::vcl::unotools::colorToDoubleSequence(
+ aColor,
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
+ }
+ }
+ break;
+
+ case META_TEXTFILLCOLOR_ACTION:
+ if( !rParms.maTextColor.is_initialized() )
+ {
+ setStateColor( static_cast<MetaTextFillColorAction*>(pCurrAct),
+ getState( rStates ).isTextFillColorSet,
+ getState( rStates ).textFillColor,
+ rCanvas );
+ }
+ break;
+
+ case META_TEXTLINECOLOR_ACTION:
+ if( !rParms.maTextColor.is_initialized() )
+ {
+ setStateColor( static_cast<MetaTextLineColorAction*>(pCurrAct),
+ getState( rStates ).isTextLineColorSet,
+ getState( rStates ).textLineColor,
+ rCanvas );
+ }
+ break;
+
+ case META_TEXTALIGN_ACTION:
+ {
+ ::cppcanvas::internal::OutDevState& rState = getState( rStates );
+ const TextAlign eTextAlign( static_cast<MetaTextAlignAction*>(pCurrAct)->GetTextAlign() );
+
+ rState.textReferencePoint = eTextAlign;
+ }
+ break;
+
+ case META_FONT_ACTION:
+ {
+ ::cppcanvas::internal::OutDevState& rState = getState( rStates );
+ const ::Font& rFont( static_cast<MetaFontAction*>(pCurrAct)->GetFont() );
+
+ rState.xFont = createFont( rState.fontRotation,
+ rFont,
+ rFactoryParms );
+
+ // TODO(Q2): define and use appropriate enumeration types
+ rState.textReliefStyle = (sal_Int8)rFont.GetRelief();
+ rState.textOverlineStyle = (sal_Int8)rFont.GetOverline();
+ rState.textUnderlineStyle = rParms.maFontUnderline.is_initialized() ?
+ (*rParms.maFontUnderline ? (sal_Int8)UNDERLINE_SINGLE : (sal_Int8)UNDERLINE_NONE) :
+ (sal_Int8)rFont.GetUnderline();
+ rState.textStrikeoutStyle = (sal_Int8)rFont.GetStrikeout();
+ rState.textEmphasisMarkStyle = (sal_Int8)rFont.GetEmphasisMark();
+ rState.isTextEffectShadowSet = (rFont.IsShadow() != sal_False);
+ rState.isTextWordUnderlineSet = (rFont.IsWordLineMode() != sal_False);
+ rState.isTextOutlineModeSet = (rFont.IsOutline() != sal_False);
+ }
+ break;
+
+ case META_RASTEROP_ACTION:
+ // TODO(F2): NYI
+ break;
+
+ case META_LAYOUTMODE_ACTION:
+ {
+ // TODO(F2): A lot is missing here
+ int nLayoutMode = static_cast<MetaLayoutModeAction*>(pCurrAct)->GetLayoutMode();
+ ::cppcanvas::internal::OutDevState& rState = getState( rStates );
+ switch( nLayoutMode & (TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_BIDI_STRONG) )
+ {
+ case TEXT_LAYOUT_BIDI_LTR:
+ rState.textDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
+ break;
+
+ case (TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG):
+ rState.textDirection = rendering::TextDirection::STRONG_LEFT_TO_RIGHT;
+ break;
+
+ case TEXT_LAYOUT_BIDI_RTL:
+ rState.textDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
+ break;
+
+ case (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG):
+ rState.textDirection = rendering::TextDirection::STRONG_RIGHT_TO_LEFT;
+ break;
+ }
+
+ rState.textAlignment = 0; // TODO(F2): rendering::TextAlignment::LEFT_ALIGNED;
+ if( (nLayoutMode & (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_RIGHT) )
+ && !(nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT ) )
+ {
+ rState.textAlignment = 1; // TODO(F2): rendering::TextAlignment::RIGHT_ALIGNED;
+ }
+ }
+ break;
+
+ // ------------------------------------------------------------
+
+ // In the second part of this monster-switch, we
+ // handle all recursing meta actions. These are the
+ // ones generating a metafile by themselves, which is
+ // then processed by recursively calling this method.
+
+ // ------------------------------------------------------------
+
+ case META_GRADIENT_ACTION:
+ {
+ MetaGradientAction* pGradAct = static_cast<MetaGradientAction*>(pCurrAct);
+ createGradientAction( ::Polygon( pGradAct->GetRect() ),
+ pGradAct->GetGradient(),
+ rFactoryParms,
+ true,
+ bSubsettableActions );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ // TODO(F2): use native Canvas hatches here
+ GDIMetaFile aTmpMtf;
+
+ rVDev.AddHatchActions( static_cast<MetaHatchAction*>(pCurrAct)->GetPolyPolygon(),
+ static_cast<MetaHatchAction*>(pCurrAct)->GetHatch(),
+ aTmpMtf );
+ createActions( aTmpMtf, rFactoryParms,
+ bSubsettableActions );
+ }
+ break;
+
+ case META_EPS_ACTION:
+ {
+ MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pCurrAct);
+ const GDIMetaFile& rSubstitute = pAct->GetSubstitute();
+
+ // #121806# explicitely kept integer
+ const Size aMtfSize( rSubstitute.GetPrefSize() );
+ const Size aMtfSizePixPre( rVDev.LogicToPixel( aMtfSize,
+ rSubstitute.GetPrefMapMode() ) );
+
+ // #i44110# correct null-sized output - there
+ // are metafiles which have zero size in at
+ // least one dimension
+ const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
+ ::std::max( aMtfSizePixPre.Height(), 1L ) );
+
+ // Setup local transform, such that the
+ // metafile renders itself into the given
+ // output rectangle
+ pushState( rStates, PUSH_ALL );
+
+ rVDev.Push();
+ rVDev.SetMapMode( rSubstitute.GetPrefMapMode() );
+
+ const ::Point& rPos( rVDev.LogicToPixel( pAct->GetPoint() ) );
+ const ::Size& rSize( rVDev.LogicToPixel( pAct->GetSize() ) );
+
+ getState( rStates ).transform.translate( rPos.X(),
+ rPos.Y() );
+ getState( rStates ).transform.scale( (double)rSize.Width() / aMtfSizePix.Width(),
+ (double)rSize.Height() / aMtfSizePix.Height() );
+
+ createActions( const_cast<GDIMetaFile&>(pAct->GetSubstitute()),
+ rFactoryParms,
+ bSubsettableActions );
+
+ rVDev.Pop();
+ popState( rStates );
+ }
+ break;
+
+ // handle metafile comments, to retrieve
+ // meta-information for gradients, fills and
+ // strokes. May skip actions, and may recurse.
+ case META_COMMENT_ACTION:
+ {
+ MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pCurrAct);
+
+ // Handle gradients
+ if ( pAct->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
+ {
+ MetaGradientExAction* pGradAction = NULL;
+ bool bDone( false );
+ while( !bDone &&
+ (pCurrAct=rMtf.NextAction()) != NULL )
+ {
+ switch( pCurrAct->GetType() )
+ {
+ // extract gradient info
+ case META_GRADIENTEX_ACTION:
+ pGradAction = static_cast<MetaGradientExAction*>(pCurrAct);
+ break;
+
+ // skip broken-down rendering, output gradient when sequence is ended
+ case META_COMMENT_ACTION:
+ if( static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL )
+ {
+ bDone = true;
+
+ if( pGradAction )
+ {
+ createGradientAction( pGradAction->GetPolyPolygon(),
+ pGradAction->GetGradient(),
+ rFactoryParms,
+ false,
+ bSubsettableActions );
+ }
+ }
+ break;
+ }
+ }
+ }
+ // TODO(P2): Handle drawing layer strokes, via
+ // XPATHSTROKE_SEQ_BEGIN comment
+
+ // Handle drawing layer fills
+ else if( pAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
+ {
+ const sal_uInt8* pData = pAct->GetData();
+ if ( pData )
+ {
+ SvMemoryStream aMemStm( (void*)pData, pAct->GetDataSize(), STREAM_READ );
+
+ SvtGraphicFill aFill;
+ aMemStm >> aFill;
+
+ // TODO(P2): Also handle gradients and
+ // hatches like this
+
+ // only evaluate comment for pure
+ // bitmap fills. If a transparency
+ // gradient is involved (denoted by
+ // the FloatTransparent action), take
+ // the normal meta actions.
+ if( aFill.getFillType() == SvtGraphicFill::fillTexture &&
+ !isActionContained( rMtf,
+ "XPATHFILL_SEQ_END",
+ META_FLOATTRANSPARENT_ACTION ) )
+ {
+ rendering::Texture aTexture;
+
+ // TODO(F1): the SvtGraphicFill
+ // can also transport metafiles
+ // here, handle that case, too
+ Graphic aGraphic;
+ aFill.getGraphic( aGraphic );
+
+ BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
+ const ::Size aBmpSize( aBmpEx.GetSizePixel() );
+
+ ::SvtGraphicFill::Transform aTransform;
+ aFill.getTransform( aTransform );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ // convert to basegfx matrix
+ aMatrix.set(0,0, aTransform.matrix[ 0 ] );
+ aMatrix.set(0,1, aTransform.matrix[ 1 ] );
+ aMatrix.set(0,2, aTransform.matrix[ 2 ] );
+ aMatrix.set(1,0, aTransform.matrix[ 3 ] );
+ aMatrix.set(1,1, aTransform.matrix[ 4 ] );
+ aMatrix.set(1,2, aTransform.matrix[ 5 ] );
+
+ ::basegfx::B2DHomMatrix aScale;
+ aScale.scale( aBmpSize.Width(),
+ aBmpSize.Height() );
+
+ // post-multiply with the bitmap
+ // size (XCanvas' texture assumes
+ // the given bitmap to be
+ // normalized to [0,1]x[0,1]
+ // rectangle)
+ aMatrix = aMatrix * aScale;
+
+ // pre-multiply with the
+ // logic-to-pixel scale factor
+ // (the metafile comment works in
+ // logical coordinates).
+ ::basegfx::B2DHomMatrix aLogic2PixelTransform;
+ aMatrix *= tools::calcLogic2PixelLinearTransform( aLogic2PixelTransform,
+ rVDev );
+
+ ::basegfx::unotools::affineMatrixFromHomMatrix(
+ aTexture.AffineTransform,
+ aMatrix );
+
+ aTexture.Alpha = 1.0 - aFill.getTransparency();
+ aTexture.Bitmap =
+ ::vcl::unotools::xBitmapFromBitmapEx(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aBmpEx );
+ if( aFill.isTiling() )
+ {
+ aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
+ aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
+ }
+ else
+ {
+ aTexture.RepeatModeX = rendering::TexturingMode::NONE;
+ aTexture.RepeatModeY = rendering::TexturingMode::NONE;
+ }
+
+ ::PolyPolygon aPath;
+ aFill.getPath( aPath );
+
+ ::basegfx::B2DPolyPolygon aPoly( aPath.getB2DPolyPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ aPoly,
+ rCanvas,
+ getState( rStates ),
+ aTexture ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+
+ // skip broken-down render output
+ skipContent( rMtf,
+ "XPATHFILL_SEQ_END",
+ io_rCurrActionIndex );
+ }
+ }
+ }
+ // Handle drawing layer fills
+ else if( pAct->GetComment().Equals( "EMF_PLUS" ) ) {
+ static int count = -1, limit = 0x7fffffff;
+ if (count == -1) {
+ count = 0;
+ if (char *env = getenv ("EMF_PLUS_LIMIT")) {
+ limit = atoi (env);
+ EMFP_DEBUG (printf ("EMF+ records limit: %d\n", limit));
+ }
+ }
+ EMFP_DEBUG (printf ("EMF+ passed to canvas mtf renderer, size: %d\n", pAct->GetDataSize ()));
+ if (count < limit)
+ processEMFPlus( pAct, rFactoryParms, getState( rStates ), rCanvas );
+ count ++;
+ } else if( pAct->GetComment().Equals( "EMF_PLUS_HEADER_INFO" ) ) {
+ EMFP_DEBUG (printf ("EMF+ passed to canvas mtf renderer - header info, size: %d\n", pAct->GetDataSize ()));
+
+ SvMemoryStream rMF ((void*) pAct->GetData (), pAct->GetDataSize (), STREAM_READ);
+
+ rMF >> nFrameLeft >> nFrameTop >> nFrameRight >> nFrameBottom;
+ EMFP_DEBUG (printf ("EMF+ picture frame: %d,%d - %d,%d\n", nFrameLeft, nFrameTop, nFrameRight, nFrameBottom));
+ rMF >> nPixX >> nPixY >> nMmX >> nMmY;
+ EMFP_DEBUG (printf ("EMF+ ref device pixel size: %dx%d mm size: %dx%d\n", nPixX, nPixY, nMmX, nMmY));
+
+ rMF >> aBaseTransform;
+ //aWorldTransform.Set (aBaseTransform);
+ }
+ }
+ break;
+
+ // ------------------------------------------------------------
+
+ // In the third part of this monster-switch, we
+ // handle all 'acting' meta actions. These are all
+ // processed by constructing function objects for
+ // them, which will later ease caching.
+
+ // ------------------------------------------------------------
+
+ case META_POINT_ACTION:
+ {
+ const OutDevState& rState( getState( rStates ) );
+ if( rState.lineColor.getLength() )
+ {
+ ActionSharedPtr pPointAction(
+ internal::PointActionFactory::createPointAction(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
+ static_cast<MetaPointAction*>(pCurrAct)->GetPoint() ),
+ rCanvas,
+ rState ) );
+
+ if( pPointAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPointAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pPointAction->getActionCount()-1;
+ }
+ }
+ }
+ break;
+
+ case META_PIXEL_ACTION:
+ {
+ const OutDevState& rState( getState( rStates ) );
+ if( rState.lineColor.getLength() )
+ {
+ ActionSharedPtr pPointAction(
+ internal::PointActionFactory::createPointAction(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
+ static_cast<MetaPixelAction*>(pCurrAct)->GetPoint() ),
+ rCanvas,
+ rState,
+ static_cast<MetaPixelAction*>(pCurrAct)->GetColor() ) );
+
+ if( pPointAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPointAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pPointAction->getActionCount()-1;
+ }
+ }
+ }
+ break;
+
+ case META_LINE_ACTION:
+ {
+ const OutDevState& rState( getState( rStates ) );
+ if( rState.lineColor.getLength() )
+ {
+ MetaLineAction* pLineAct = static_cast<MetaLineAction*>(pCurrAct);
+
+ const LineInfo& rLineInfo( pLineAct->GetLineInfo() );
+
+ const ::basegfx::B2DPoint aStartPoint(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetStartPoint() ));
+ const ::basegfx::B2DPoint aEndPoint(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetEndPoint() ));
+
+ ActionSharedPtr pLineAction;
+
+ if( rLineInfo.IsDefault() )
+ {
+ // plain hair line
+ pLineAction =
+ internal::LineActionFactory::createLineAction(
+ aStartPoint,
+ aEndPoint,
+ rCanvas,
+ rState );
+
+ if( pLineAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pLineAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pLineAction->getActionCount()-1;
+ }
+ }
+ else if( LINE_NONE != rLineInfo.GetStyle() )
+ {
+ // 'thick' line
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ setupStrokeAttributes( aStrokeAttributes,
+ rFactoryParms,
+ rLineInfo );
+
+ // XCanvas can only stroke polygons,
+ // not simple lines - thus, handle
+ // this case via the polypolygon
+ // action
+ ::basegfx::B2DPolygon aPoly;
+ aPoly.append( aStartPoint );
+ aPoly.append( aEndPoint );
+ pLineAction =
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ ::basegfx::B2DPolyPolygon( aPoly ),
+ rCanvas, rState, aStrokeAttributes );
+
+ if( pLineAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pLineAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pLineAction->getActionCount()-1;
+ }
+ }
+ // else: line style is default
+ // (i.e. invisible), don't generate action
+ }
+ }
+ break;
+
+ case META_RECT_ACTION:
+ {
+ const Rectangle& rRect(
+ static_cast<MetaRectAction*>(pCurrAct)->GetRect() );
+
+ if( rRect.IsEmpty() )
+ break;
+
+ const OutDevState& rState( getState( rStates ) );
+ const ::basegfx::B2DPoint aTopLeftPixel(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ) );
+ const ::basegfx::B2DPoint aBottomRightPixel(
+ rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
+ // #121100# OutputDevice::DrawRect() fills
+ // rectangles Apple-like, i.e. with one
+ // additional pixel to the right and bottom.
+ ::basegfx::B2DPoint(1,1) );
+
+ createFillAndStroke( ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRange( aTopLeftPixel,
+ aBottomRightPixel )),
+ rFactoryParms );
+ break;
+ }
+
+ case META_ROUNDRECT_ACTION:
+ {
+ const Rectangle& rRect(
+ static_cast<MetaRoundRectAction*>(pCurrAct)->GetRect());
+
+ if( rRect.IsEmpty() )
+ break;
+
+ ::basegfx::B2DPolygon aPoly(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRange(
+ ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
+ ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
+ ::basegfx::B2DPoint(1,1) ),
+ ( (double) static_cast<MetaRoundRectAction*>(pCurrAct)->GetHorzRound() ) / rRect.GetWidth(),
+ ( (double) static_cast<MetaRoundRectAction*>(pCurrAct)->GetVertRound() ) / rRect.GetHeight() ) );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_ELLIPSE_ACTION:
+ {
+ const Rectangle& rRect(
+ static_cast<MetaEllipseAction*>(pCurrAct)->GetRect() );
+
+ if( rRect.IsEmpty() )
+ break;
+
+ const ::basegfx::B2DRange aRange(
+ ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
+ ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
+ ::basegfx::B2DPoint(1,1) );
+
+ ::basegfx::B2DPolygon aPoly(
+ ::basegfx::tools::createPolygonFromEllipse(
+ aRange.getCenter(),
+ aRange.getWidth(),
+ aRange.getHeight() ));
+ aPoly.transform( getState( rStates ).mapModeTransform );
+
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_ARC_ACTION:
+ {
+ // TODO(F1): Missing basegfx functionality. Mind empty rects!
+ const Polygon aToolsPoly( static_cast<MetaArcAction*>(pCurrAct)->GetRect(),
+ static_cast<MetaArcAction*>(pCurrAct)->GetStartPoint(),
+ static_cast<MetaArcAction*>(pCurrAct)->GetEndPoint(), POLY_ARC );
+ ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_PIE_ACTION:
+ {
+ // TODO(F1): Missing basegfx functionality. Mind empty rects!
+ const Polygon aToolsPoly( static_cast<MetaPieAction*>(pCurrAct)->GetRect(),
+ static_cast<MetaPieAction*>(pCurrAct)->GetStartPoint(),
+ static_cast<MetaPieAction*>(pCurrAct)->GetEndPoint(), POLY_PIE );
+ ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_CHORD_ACTION:
+ {
+ // TODO(F1): Missing basegfx functionality. Mind empty rects!
+ const Polygon aToolsPoly( static_cast<MetaChordAction*>(pCurrAct)->GetRect(),
+ static_cast<MetaChordAction*>(pCurrAct)->GetStartPoint(),
+ static_cast<MetaChordAction*>(pCurrAct)->GetEndPoint(), POLY_CHORD );
+ ::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_POLYLINE_ACTION:
+ {
+ const OutDevState& rState( getState( rStates ) );
+ if( rState.lineColor.getLength() ||
+ rState.fillColor.getLength() )
+ {
+ MetaPolyLineAction* pPolyLineAct = static_cast<MetaPolyLineAction*>(pCurrAct);
+
+ const LineInfo& rLineInfo( pPolyLineAct->GetLineInfo() );
+ ::basegfx::B2DPolygon aPoly( pPolyLineAct->GetPolygon().getB2DPolygon() );
+ aPoly.transform( rState.mapModeTransform );
+
+ ActionSharedPtr pLineAction;
+
+ if( rLineInfo.IsDefault() )
+ {
+ // plain hair line polygon
+ pLineAction =
+ internal::PolyPolyActionFactory::createLinePolyPolyAction(
+ ::basegfx::B2DPolyPolygon(aPoly),
+ rCanvas,
+ rState );
+
+ if( pLineAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pLineAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pLineAction->getActionCount()-1;
+ }
+ }
+ else if( LINE_NONE != rLineInfo.GetStyle() )
+ {
+ // 'thick' line polygon
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ setupStrokeAttributes( aStrokeAttributes,
+ rFactoryParms,
+ rLineInfo );
+
+ pLineAction =
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ ::basegfx::B2DPolyPolygon(aPoly),
+ rCanvas,
+ rState,
+ aStrokeAttributes ) ;
+
+ if( pLineAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pLineAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pLineAction->getActionCount()-1;
+ }
+ }
+ // else: line style is default
+ // (i.e. invisible), don't generate action
+ }
+ }
+ break;
+
+ case META_POLYGON_ACTION:
+ {
+ ::basegfx::B2DPolygon aPoly( static_cast<MetaPolygonAction*>(pCurrAct)->GetPolygon().getB2DPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_POLYPOLYGON_ACTION:
+ {
+ ::basegfx::B2DPolyPolygon aPoly( static_cast<MetaPolyPolygonAction*>(pCurrAct)->GetPolyPolygon().getB2DPolyPolygon() );
+ aPoly.transform( getState( rStates ).mapModeTransform );
+ createFillAndStroke( aPoly,
+ rFactoryParms );
+ }
+ break;
+
+ case META_BMP_ACTION:
+ {
+ MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pCurrAct);
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ pAct->GetBitmap(),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_BMPSCALE_ACTION:
+ {
+ MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pCurrAct);
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ pAct->GetBitmap(),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_BMPSCALEPART_ACTION:
+ {
+ MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pCurrAct);
+
+ // crop bitmap to given source rectangle (no
+ // need to copy and convert the whole bitmap)
+ Bitmap aBmp( pAct->GetBitmap() );
+ const Rectangle aCropRect( pAct->GetSrcPoint(),
+ pAct->GetSrcSize() );
+ aBmp.Crop( aCropRect );
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ aBmp,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_BMPEX_ACTION:
+ {
+ MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pCurrAct);
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ pAct->GetBitmapEx(),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_BMPEXSCALE_ACTION:
+ {
+ MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pCurrAct);
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ pAct->GetBitmapEx(),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_BMPEXSCALEPART_ACTION:
+ {
+ MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pCurrAct);
+
+ // crop bitmap to given source rectangle (no
+ // need to copy and convert the whole bitmap)
+ BitmapEx aBmp( pAct->GetBitmapEx() );
+ const Rectangle aCropRect( pAct->GetSrcPoint(),
+ pAct->GetSrcSize() );
+ aBmp.Crop( aCropRect );
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ aBmp,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_MASK_ACTION:
+ {
+ MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pCurrAct);
+
+ // create masked BitmapEx right here, as the
+ // canvas does not provide equivalent
+ // functionality
+ BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
+ pAct->GetColor() ));
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ aBmp,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_MASKSCALE_ACTION:
+ {
+ MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pCurrAct);
+
+ // create masked BitmapEx right here, as the
+ // canvas does not provide equivalent
+ // functionality
+ BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
+ pAct->GetColor() ));
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ aBmp,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_MASKSCALEPART_ACTION:
+ {
+ MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pCurrAct);
+
+ // create masked BitmapEx right here, as the
+ // canvas does not provide equivalent
+ // functionality
+ BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
+ pAct->GetColor() ));
+
+ // crop bitmap to given source rectangle (no
+ // need to copy and convert the whole bitmap)
+ const Rectangle aCropRect( pAct->GetSrcPoint(),
+ pAct->GetSrcSize() );
+ aBmp.Crop( aCropRect );
+
+ ActionSharedPtr pBmpAction(
+ internal::BitmapActionFactory::createBitmapAction(
+ aBmp,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pBmpAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pBmpAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pBmpAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_GRADIENTEX_ACTION:
+ // TODO(F1): use native Canvas gradients here
+ // action is ignored here, because redundant to META_GRADIENT_ACTION
+ break;
+
+ case META_WALLPAPER_ACTION:
+ // TODO(F2): NYI
+ break;
+
+ case META_TRANSPARENT_ACTION:
+ {
+ const OutDevState& rState( getState( rStates ) );
+ if( rState.lineColor.getLength() ||
+ rState.fillColor.getLength() )
+ {
+ MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pCurrAct);
+ ::basegfx::B2DPolyPolygon aPoly( pAct->GetPolyPolygon().getB2DPolyPolygon() );
+ aPoly.transform( rState.mapModeTransform );
+
+ ActionSharedPtr pPolyAction(
+ internal::PolyPolyActionFactory::createPolyPolyAction(
+ aPoly,
+ rCanvas,
+ rState,
+ pAct->GetTransparence() ) );
+
+ if( pPolyAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+ }
+ }
+ break;
+
+ case META_FLOATTRANSPARENT_ACTION:
+ {
+ MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pCurrAct);
+
+ internal::MtfAutoPtr pMtf(
+ new ::GDIMetaFile( pAct->GetGDIMetaFile() ) );
+
+ // TODO(P2): Use native canvas gradients here (saves a lot of UNO calls)
+ internal::GradientAutoPtr pGradient(
+ new Gradient( pAct->GetGradient() ) );
+
+ DBG_TESTSOLARMUTEX();
+
+ ActionSharedPtr pFloatTransAction(
+ internal::TransparencyGroupActionFactory::createTransparencyGroupAction(
+ pMtf,
+ pGradient,
+ rParms,
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
+ getState( rStates ).mapModeTransform *
+ ::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
+ rCanvas,
+ getState( rStates ) ) );
+
+ if( pFloatTransAction )
+ {
+ maActions.push_back(
+ MtfAction(
+ pFloatTransAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pFloatTransAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_TEXT_ACTION:
+ {
+ MetaTextAction* pAct = static_cast<MetaTextAction*>(pCurrAct);
+ XubString sText = XubString( pAct->GetText() );
+
+ if( rVDev.GetDigitLanguage())
+ convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
+
+ createTextAction(
+ pAct->GetPoint(),
+ sText,
+ pAct->GetIndex(),
+ pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
+ NULL,
+ rFactoryParms,
+ bSubsettableActions );
+ }
+ break;
+
+ case META_TEXTARRAY_ACTION:
+ {
+ MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pCurrAct);
+ XubString sText = XubString( pAct->GetText() );
+
+ if( rVDev.GetDigitLanguage())
+ convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
+
+ createTextAction(
+ pAct->GetPoint(),
+ sText,
+ pAct->GetIndex(),
+ pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
+ pAct->GetDXArray(),
+ rFactoryParms,
+ bSubsettableActions );
+ }
+ break;
+
+ case META_TEXTLINE_ACTION:
+ {
+ MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pCurrAct);
+
+ const OutDevState& rState( getState( rStates ) );
+ const ::Size aBaselineOffset( tools::getBaselineOffset( rState,
+ rVDev ) );
+ const ::Point aStartPoint( pAct->GetStartPoint() );
+ const ::basegfx::B2DSize aSize( rState.mapModeTransform *
+ ::basegfx::B2DSize(pAct->GetWidth(),
+ 0 ));
+
+ ActionSharedPtr pPolyAction(
+ PolyPolyActionFactory::createPolyPolyAction(
+ tools::createTextLinesPolyPolygon(
+ rState.mapModeTransform *
+ ::basegfx::B2DPoint(
+ ::vcl::unotools::b2DPointFromPoint(pAct->GetStartPoint()) +
+ ::vcl::unotools::b2DSizeFromSize(aBaselineOffset)),
+ aSize.getX(),
+ tools::createTextLineInfo( rVDev,
+ rState )),
+ rCanvas,
+ rState ) );
+
+ if( pPolyAction.get() )
+ {
+ maActions.push_back(
+ MtfAction(
+ pPolyAction,
+ io_rCurrActionIndex ) );
+
+ io_rCurrActionIndex += pPolyAction->getActionCount()-1;
+ }
+ }
+ break;
+
+ case META_TEXTRECT_ACTION:
+ {
+ MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pCurrAct);
+
+ pushState( rStates, PUSH_ALL );
+
+ // use the VDev to break up the text rect
+ // action into readily formatted lines
+ GDIMetaFile aTmpMtf;
+ rVDev.AddTextRectActions( pAct->GetRect(),
+ pAct->GetText(),
+ pAct->GetStyle(),
+ aTmpMtf );
+
+ createActions( aTmpMtf,
+ rFactoryParms,
+ bSubsettableActions );
+
+ popState( rStates );
+
+ break;
+ }
+
+ case META_STRETCHTEXT_ACTION:
+ {
+ MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pCurrAct);
+ XubString sText = XubString( pAct->GetText() );
+
+ if( rVDev.GetDigitLanguage())
+ convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
+
+ const sal_uInt16 nLen( pAct->GetLen() == (sal_uInt16)STRING_LEN ?
+ pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen() );
+
+ // #i70897# Nothing to do, actually...
+ if( nLen == 0 )
+ break;
+
+ // have to fit the text into the given
+ // width. This is achieved by internally
+ // generating a DX array, and uniformly
+ // distributing the excess/insufficient width
+ // to every logical character.
+ ::boost::scoped_array< sal_Int32 > pDXArray( new sal_Int32[nLen] );
+
+ rVDev.GetTextArray( pAct->GetText(), pDXArray.get(),
+ pAct->GetIndex(), pAct->GetLen() );
+
+ const sal_Int32 nWidthDifference( pAct->GetWidth() - pDXArray[ nLen-1 ] );
+
+ // Last entry of pDXArray contains total width of the text
+ sal_Int32* p=pDXArray.get();
+ for( sal_uInt16 i=1; i<=nLen; ++i )
+ {
+ // calc ratio for every array entry, to
+ // distribute rounding errors 'evenly'
+ // across the characters. Note that each
+ // entry represents the 'end' position of
+ // the corresponding character, thus, we
+ // let i run from 1 to nLen.
+ *p++ += (sal_Int32)i*nWidthDifference/nLen;
+ }
+
+ createTextAction(
+ pAct->GetPoint(),
+ sText,
+ pAct->GetIndex(),
+ pAct->GetLen() == (sal_uInt16)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
+ pDXArray.get(),
+ rFactoryParms,
+ bSubsettableActions );
+ }
+ break;
+
+ default:
+ OSL_FAIL( "Unknown meta action type encountered" );
+ break;
+ }
+
+ // increment action index (each mtf action counts _at
+ // least_ one. Some count for more, therefore,
+ // io_rCurrActionIndex is sometimes incremented by
+ // pAct->getActionCount()-1 above, the -1 being the
+ // correction for the unconditional increment here).
+ ++io_rCurrActionIndex;
+ }
+
+ return true;
+ }
+
+
+ namespace
+ {
+ class ActionRenderer
+ {
+ public:
+ ActionRenderer( const ::basegfx::B2DHomMatrix& rTransformation ) :
+ maTransformation( rTransformation ),
+ mbRet( true )
+ {
+ }
+
+ bool result() const
+ {
+ return mbRet;
+ }
+
+ void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
+ {
+ // ANDing the result. We want to fail if at least
+ // one action failed.
+ mbRet &= rAction.mpAction->render( maTransformation );
+ }
+
+ void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction,
+ const Action::Subset& rSubset )
+ {
+ // ANDing the result. We want to fail if at least
+ // one action failed.
+ mbRet &= rAction.mpAction->render( maTransformation,
+ rSubset );
+ }
+
+ private:
+ ::basegfx::B2DHomMatrix maTransformation;
+ bool mbRet;
+ };
+
+ class AreaQuery
+ {
+ public:
+ AreaQuery( const ::basegfx::B2DHomMatrix& rTransformation ) :
+ maTransformation( rTransformation ),
+ maBounds()
+ {
+ }
+
+ bool result() const
+ {
+ return true; // nothing can fail here
+ }
+
+ void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
+ {
+ maBounds.expand( rAction.mpAction->getBounds( maTransformation ) );
+ }
+
+ void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction,
+ const Action::Subset& rSubset )
+ {
+ maBounds.expand( rAction.mpAction->getBounds( maTransformation,
+ rSubset ) );
+ }
+
+ ::basegfx::B2DRange getBounds() const
+ {
+ return maBounds;
+ }
+
+ private:
+ ::basegfx::B2DHomMatrix maTransformation;
+ ::basegfx::B2DRange maBounds;
+ };
+
+ // Doing that via inline class. Compilers tend to not inline free
+ // functions.
+ struct UpperBoundActionIndexComparator
+ {
+ bool operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rLHS,
+ const ::cppcanvas::internal::ImplRenderer::MtfAction& rRHS )
+ {
+ const sal_Int32 nLHSCount( rLHS.mpAction ?
+ rLHS.mpAction->getActionCount() : 0 );
+ const sal_Int32 nRHSCount( rRHS.mpAction ?
+ rRHS.mpAction->getActionCount() : 0 );
+
+ // compare end of action range, to have an action selected
+ // by lower_bound even if the requested index points in
+ // the middle of the action's range
+ return rLHS.mnOrigIndex + nLHSCount < rRHS.mnOrigIndex + nRHSCount;
+ }
+ };
+
+ /** Algorithm to apply given functor to a subset range
+
+ @tpl Functor
+
+ Functor to call for each element of the subset
+ range. Must provide the following method signatures:
+ bool result() (returning false if operation failed)
+
+ */
+ template< typename Functor > bool
+ forSubsetRange( Functor& rFunctor,
+ ImplRenderer::ActionVector::const_iterator aRangeBegin,
+ ImplRenderer::ActionVector::const_iterator aRangeEnd,
+ sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex,
+ const ImplRenderer::ActionVector::const_iterator& rEnd )
+ {
+ if( aRangeBegin == aRangeEnd )
+ {
+ // only a single action. Setup subset, and call functor
+ Action::Subset aSubset;
+ aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
+ nStartIndex - aRangeBegin->mnOrigIndex );
+ aSubset.mnSubsetEnd = ::std::min( aRangeBegin->mpAction->getActionCount(),
+ nEndIndex - aRangeBegin->mnOrigIndex );
+
+ ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
+ "ImplRenderer::forSubsetRange(): Invalid indices" );
+
+ rFunctor( *aRangeBegin, aSubset );
+ }
+ else
+ {
+ // more than one action.
+
+ // render partial first, full intermediate, and
+ // partial last action
+ Action::Subset aSubset;
+ aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
+ nStartIndex - aRangeBegin->mnOrigIndex );
+ aSubset.mnSubsetEnd = aRangeBegin->mpAction->getActionCount();
+
+ ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
+ "ImplRenderer::forSubsetRange(): Invalid indices" );
+
+ rFunctor( *aRangeBegin, aSubset );
+
+ // first action rendered, skip to next
+ ++aRangeBegin;
+
+ // render full middle actions
+ while( aRangeBegin != aRangeEnd )
+ rFunctor( *aRangeBegin++ );
+
+ if( aRangeEnd == rEnd ||
+ aRangeEnd->mnOrigIndex > nEndIndex )
+ {
+ // aRangeEnd denotes end of action vector,
+ //
+ // or
+ //
+ // nEndIndex references something _after_
+ // aRangeBegin, but _before_ aRangeEnd
+ //
+ // either way: no partial action left
+ return rFunctor.result();
+ }
+
+ aSubset.mnSubsetBegin = 0;
+ aSubset.mnSubsetEnd = nEndIndex - aRangeEnd->mnOrigIndex;
+
+ ENSURE_OR_RETURN_FALSE( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
+ "ImplRenderer::forSubsetRange(): Invalid indices" );
+
+ rFunctor( *aRangeEnd, aSubset );
+ }
+
+ return rFunctor.result();
+ }
+ }
+
+ bool ImplRenderer::getSubsetIndices( sal_Int32& io_rStartIndex,
+ sal_Int32& io_rEndIndex,
+ ActionVector::const_iterator& o_rRangeBegin,
+ ActionVector::const_iterator& o_rRangeEnd ) const
+ {
+ ENSURE_OR_RETURN_FALSE( io_rStartIndex<=io_rEndIndex,
+ "ImplRenderer::getSubsetIndices(): invalid action range" );
+
+ ENSURE_OR_RETURN_FALSE( !maActions.empty(),
+ "ImplRenderer::getSubsetIndices(): no actions to render" );
+
+ const sal_Int32 nMinActionIndex( maActions.front().mnOrigIndex );
+ const sal_Int32 nMaxActionIndex( maActions.back().mnOrigIndex +
+ maActions.back().mpAction->getActionCount() );
+
+ // clip given range to permissible values (there might be
+ // ranges before and behind the valid indices)
+ io_rStartIndex = ::std::max( nMinActionIndex,
+ io_rStartIndex );
+ io_rEndIndex = ::std::min( nMaxActionIndex,
+ io_rEndIndex );
+
+ if( io_rStartIndex == io_rEndIndex ||
+ io_rStartIndex > io_rEndIndex )
+ {
+ // empty range, don't render anything. The second
+ // condition e.g. happens if the requested range lies
+ // fully before or behind the valid action indices.
+ return false;
+ }
+
+
+ const ActionVector::const_iterator aBegin( maActions.begin() );
+ const ActionVector::const_iterator aEnd( maActions.end() );
+
+
+ // find start and end action
+ // =========================
+ o_rRangeBegin = ::std::lower_bound( aBegin, aEnd,
+ MtfAction( ActionSharedPtr(), io_rStartIndex ),
+ UpperBoundActionIndexComparator() );
+ o_rRangeEnd = ::std::lower_bound( aBegin, aEnd,
+ MtfAction( ActionSharedPtr(), io_rEndIndex ),
+ UpperBoundActionIndexComparator() );
+ return true;
+ }
+
+
+ // Public methods
+ // ====================================================================
+
+ ImplRenderer::ImplRenderer( const CanvasSharedPtr& rCanvas,
+ const GDIMetaFile& rMtf,
+ const Parameters& rParams ) :
+ CanvasGraphicHelper( rCanvas ),
+ maActions()
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(mtf)" );
+
+ OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
+ "ImplRenderer::ImplRenderer(): Invalid canvas" );
+ OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
+ "ImplRenderer::ImplRenderer(): Invalid graphic device" );
+
+ // make sure canvas and graphic device are valid; action
+ // creation don't check that every time
+ if( rCanvas.get() == NULL ||
+ !rCanvas->getUNOCanvas().is() ||
+ !rCanvas->getUNOCanvas()->getDevice().is() )
+ {
+ // leave actions empty
+ return;
+ }
+
+ VectorOfOutDevStates aStateStack;
+
+ VirtualDevice aVDev;
+ aVDev.EnableOutput( sal_False );
+
+ // Setup VDev for state tracking and mapping
+ // =========================================
+
+ aVDev.SetMapMode( rMtf.GetPrefMapMode() );
+
+ const Size aMtfSize( rMtf.GetPrefSize() );
+ const Size aMtfSizePixPre( aVDev.LogicToPixel( aMtfSize,
+ rMtf.GetPrefMapMode() ) );
+ const Point aEmptyPt;
+ const Point aMtfOriginPix( aVDev.LogicToPixel( aEmptyPt ) );
+
+ // #i44110# correct null-sized output - there are shapes
+ // which have zero size in at least one dimension
+ const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
+ ::std::max( aMtfSizePixPre.Height(), 1L ) );
+
+ sal_Int32 nCurrActions(0);
+ ActionFactoryParameters aParms(aStateStack,
+ rCanvas,
+ aVDev,
+ rParams,
+ nCurrActions );
+
+ // init state stack
+ clearStateStack( aStateStack );
+
+ // Setup local state, such that the metafile renders
+ // itself into a one-by-one square at the origin for
+ // identity view and render transformations
+ getState( aStateStack ).transform.scale( 1.0 / aMtfSizePix.Width(),
+ 1.0 / aMtfSizePix.Height() );
+
+ tools::calcLogic2PixelAffineTransform( getState( aStateStack ).mapModeTransform,
+ aVDev );
+
+ ColorSharedPtr pColor( getCanvas()->createColor() );
+
+ // setup default text color to black
+ getState( aStateStack ).textColor =
+ getState( aStateStack ).textFillColor =
+ getState( aStateStack ).textLineColor = pColor->getDeviceColor( 0x000000FF );
+
+ // apply overrides from the Parameters struct
+ if( rParams.maFillColor.is_initialized() )
+ {
+ getState( aStateStack ).isFillColorSet = true;
+ getState( aStateStack ).fillColor = pColor->getDeviceColor( *rParams.maFillColor );
+ }
+ if( rParams.maLineColor.is_initialized() )
+ {
+ getState( aStateStack ).isLineColorSet = true;
+ getState( aStateStack ).lineColor = pColor->getDeviceColor( *rParams.maLineColor );
+ }
+ if( rParams.maTextColor.is_initialized() )
+ {
+ getState( aStateStack ).isTextFillColorSet = true;
+ getState( aStateStack ).isTextLineColorSet = true;
+ getState( aStateStack ).textColor =
+ getState( aStateStack ).textFillColor =
+ getState( aStateStack ).textLineColor = pColor->getDeviceColor( *rParams.maTextColor );
+ }
+ if( rParams.maFontName.is_initialized() ||
+ rParams.maFontWeight.is_initialized() ||
+ rParams.maFontLetterForm.is_initialized() ||
+ rParams.maFontUnderline.is_initialized() ||
+ rParams.maFontProportion.is_initialized() )
+ {
+ ::cppcanvas::internal::OutDevState& rState = getState( aStateStack );
+
+ rState.xFont = createFont( rState.fontRotation,
+ ::Font(), // default font
+ aParms );
+ }
+
+ /* EMF+ */
+ memset (aObjects, 0, sizeof (aObjects));
+ mbMultipart = false;
+
+ createActions( const_cast<GDIMetaFile&>(rMtf), // HACK(Q2):
+ // we're
+ // changing
+ // the
+ // current
+ // action
+ // in
+ // createActions!
+ aParms,
+ true // TODO(P1): make subsettability configurable
+ );
+ }
+
+ ImplRenderer::ImplRenderer( const CanvasSharedPtr& rCanvas,
+ const BitmapEx& rBmpEx,
+ const Parameters& rParams ) :
+ CanvasGraphicHelper( rCanvas ),
+ maActions()
+ {
+ // TODO(F3): property modification parameters are
+ // currently ignored for Bitmaps
+ (void)rParams;
+
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(bitmap)" );
+
+ OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
+ "ImplRenderer::ImplRenderer(): Invalid canvas" );
+ OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
+ "ImplRenderer::ImplRenderer(): Invalid graphic device" );
+
+ // make sure canvas and graphic device are valid; action
+ // creation don't check that every time
+ if( rCanvas.get() == NULL ||
+ !rCanvas->getUNOCanvas().is() ||
+ !rCanvas->getUNOCanvas()->getDevice().is() )
+ {
+ // leave actions empty
+ return;
+ }
+
+ OutDevState aState;
+
+ const Size aBmpSize( rBmpEx.GetSizePixel() );
+
+ // Setup local state, such that the bitmap renders itself
+ // into a one-by-one square for identity view and render
+ // transformations
+ aState.transform.scale( 1.0 / aBmpSize.Width(),
+ 1.0 / aBmpSize.Height() );
+
+ // create a single action for the provided BitmapEx
+ maActions.push_back(
+ MtfAction(
+ BitmapActionFactory::createBitmapAction(
+ rBmpEx,
+ ::basegfx::B2DPoint(),
+ rCanvas,
+ aState),
+ 0 ) );
+ }
+
+ ImplRenderer::~ImplRenderer()
+ {
+ }
+
+ bool ImplRenderer::drawSubset( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::drawSubset()" );
+
+ ActionVector::const_iterator aRangeBegin;
+ ActionVector::const_iterator aRangeEnd;
+
+ try
+ {
+ if( !getSubsetIndices( nStartIndex, nEndIndex,
+ aRangeBegin, aRangeEnd ) )
+ return true; // nothing to render (but _that_ was successful)
+
+ // now, aRangeBegin references the action in which the
+ // subset rendering must start, and aRangeEnd references
+ // the action in which the subset rendering must end (it
+ // might also end right at the start of the referenced
+ // action, such that zero of that action needs to be
+ // rendered).
+
+
+ // render subset of actions
+ // ========================
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::getRenderStateTransform( aMatrix,
+ getRenderState() );
+
+ ActionRenderer aRenderer( aMatrix );
+
+ return forSubsetRange( aRenderer,
+ aRangeBegin,
+ aRangeEnd,
+ nStartIndex,
+ nEndIndex,
+ maActions.end() );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ // convert error to return value
+ return false;
+ }
+ }
+
+ ::basegfx::B2DRange ImplRenderer::getSubsetArea( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::getSubsetArea()" );
+
+ ActionVector::const_iterator aRangeBegin;
+ ActionVector::const_iterator aRangeEnd;
+
+ if( !getSubsetIndices( nStartIndex, nEndIndex,
+ aRangeBegin, aRangeEnd ) )
+ return ::basegfx::B2DRange(); // nothing to render -> empty range
+
+ // now, aRangeBegin references the action in which the
+ // subset querying must start, and aRangeEnd references
+ // the action in which the subset querying must end (it
+ // might also end right at the start of the referenced
+ // action, such that zero of that action needs to be
+ // queried).
+
+
+ // query bounds for subset of actions
+ // ==================================
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::getRenderStateTransform( aMatrix,
+ getRenderState() );
+
+ AreaQuery aQuery( aMatrix );
+ forSubsetRange( aQuery,
+ aRangeBegin,
+ aRangeEnd,
+ nStartIndex,
+ nEndIndex,
+ maActions.end() );
+
+ return aQuery.getBounds();
+ }
+
+ bool ImplRenderer::draw() const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::draw()" );
+
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::canvas::tools::getRenderStateTransform( aMatrix,
+ getRenderState() );
+
+ try
+ {
+ return ::std::for_each( maActions.begin(), maActions.end(), ActionRenderer( aMatrix ) ).result();
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/lineaction.cxx b/cppcanvas/source/mtfrenderer/lineaction.cxx
new file mode 100644
index 000000000000..7639fe352511
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/lineaction.cxx
@@ -0,0 +1,170 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <lineaction.hxx>
+#include <outdevstate.hxx>
+
+#include <rtl/logfile.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <boost/utility.hpp>
+
+#include <cppcanvas/canvas.hxx>
+
+#include <mtftools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ namespace
+ {
+ class LineAction : public Action, private ::boost::noncopyable
+ {
+ public:
+ LineAction( const ::basegfx::B2DPoint&,
+ const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ ::basegfx::B2DPoint maStartPoint;
+ ::basegfx::B2DPoint maEndPoint;
+ CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ };
+
+ LineAction::LineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DPoint& rEndPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ maStartPoint( rStartPoint ),
+ maEndPoint( rEndPoint ),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ tools::initRenderState(maState,rState);
+ maState.DeviceColor = rState.lineColor;
+ }
+
+ bool LineAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::LineAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::LineAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ mpCanvas->getUNOCanvas()->drawLine( ::basegfx::unotools::point2DFromB2DPoint(maStartPoint),
+ ::basegfx::unotools::point2DFromB2DPoint(maEndPoint),
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ bool LineAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // line only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return render( rTransformation );
+ }
+
+ ::basegfx::B2DRange LineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds( ::basegfx::B2DRange( maStartPoint,
+ maEndPoint ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange LineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // line only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 LineAction::getActionCount() const
+ {
+ return 1;
+ }
+ }
+
+ ActionSharedPtr LineActionFactory::createLineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DPoint& rEndPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new LineAction( rStartPoint,
+ rEndPoint,
+ rCanvas,
+ rState) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/lineaction.hxx b/cppcanvas/source/mtfrenderer/lineaction.hxx
new file mode 100644
index 000000000000..810c8cb4fe03
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/lineaction.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_LINEACTION_HXX
+#define _CPPCANVAS_LINEACTION_HXX
+
+#include <action.hxx>
+#include <cppcanvas/canvas.hxx>
+
+namespace basegfx {
+ class B2DPoint;
+}
+
+
+/* Definition of internal::LineActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ /** Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class LineActionFactory
+ {
+ public:
+ /// Plain hair line from point 1 to point 2
+ static ActionSharedPtr createLineAction( const ::basegfx::B2DPoint&,
+ const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ private:
+ // static factory, disable big four
+ LineActionFactory();
+ ~LineActionFactory();
+ LineActionFactory(const LineActionFactory&);
+ LineActionFactory& operator=( const LineActionFactory& );
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_LINEACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/makefile.mk b/cppcanvas/source/mtfrenderer/makefile.mk
new file mode 100644
index 000000000000..1109ce2a3950
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/makefile.mk
@@ -0,0 +1,58 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General 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=cppcanvas
+TARGET=metafilerenderer
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+SLOFILES = $(SLO)$/cachedprimitivebase.obj \
+ $(SLO)$/bitmapaction.obj \
+ $(SLO)$/emfplus.obj \
+ $(SLO)$/implrenderer.obj \
+ $(SLO)$/lineaction.obj \
+ $(SLO)$/pointaction.obj \
+ $(SLO)$/polypolyaction.obj \
+ $(SLO)$/textaction.obj \
+ $(SLO)$/transparencygroupaction.obj \
+ $(SLO)$/mtftools.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/cppcanvas/source/mtfrenderer/mtftools.cxx b/cppcanvas/source/mtfrenderer/mtftools.cxx
new file mode 100644
index 000000000000..4810268b7ca7
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/mtftools.cxx
@@ -0,0 +1,696 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <canvas/canvastools.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <tools/poly.hxx>
+#include "mtftools.hxx"
+#include "outdevstate.hxx"
+#include "polypolyaction.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace tools
+ {
+ void initRenderState( rendering::RenderState& renderState,
+ const ::cppcanvas::internal::OutDevState& outdevState )
+ {
+ ::canvas::tools::initRenderState( renderState );
+ ::canvas::tools::setRenderStateTransform( renderState,
+ outdevState.transform );
+ renderState.Clip = outdevState.xClipPoly;
+ }
+
+ ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState& outdevState,
+ const VirtualDevice& rVDev )
+ {
+ const ::FontMetric& aMetric = rVDev.GetFontMetric();
+
+ // calc offset for text output, the XCanvas always renders
+ // baseline offset.
+ switch( outdevState.textReferencePoint )
+ {
+ case ALIGN_TOP:
+ return ::Size( 0,
+ aMetric.GetIntLeading() + aMetric.GetAscent() );
+
+ default:
+ ENSURE_OR_THROW( false,
+ "tools::getBaselineOffset(): Unexpected TextAlign value" );
+ // FALLTHROUGH intended (to calm compiler warning - case won't happen)
+ case ALIGN_BASELINE:
+ return ::Size( 0, 0 );
+
+ case ALIGN_BOTTOM:
+ return ::Size( 0,
+ -aMetric.GetDescent() );
+
+ }
+ }
+
+ ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
+ const VirtualDevice& rVDev )
+ {
+ // select size value in the middle of the available range,
+ // to have headroom both when map mode scales up, and when
+ // it scales down.
+ const ::Size aSizeLogic( 0x00010000L,
+ 0x00010000L );
+
+ const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) );
+
+ o_rMatrix = basegfx::tools::createScaleB2DHomMatrix(
+ aSizePixel.Width() / (double)aSizeLogic.Width(),
+ aSizePixel.Height() / (double)aSizeLogic.Height() );
+
+ return o_rMatrix;
+ }
+
+ ::basegfx::B2DHomMatrix& calcLogic2PixelAffineTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
+ const VirtualDevice& rVDev )
+ {
+ // retrieves scale
+ calcLogic2PixelLinearTransform(o_rMatrix, rVDev);
+
+ // translate according to curr map mode/pref map mode offset
+ const ::Point aEmptyPoint;
+ const ::Point& rTranslatedPoint(
+ rVDev.LogicToPixel( aEmptyPoint ));
+
+ o_rMatrix.translate(rTranslatedPoint.X(),
+ rTranslatedPoint.Y());
+
+ return o_rMatrix;
+ }
+
+ bool modifyClip( rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DPoint& rOffset,
+ const ::basegfx::B2DVector* pScaling,
+ const double* pRotation )
+ {
+ const ::Point aEmptyPoint;
+
+ const bool bOffsetting( !rOffset.equalZero() );
+ const bool bScaling( pScaling &&
+ pScaling->getX() != 1.0 &&
+ pScaling->getY() != 1.0 );
+ const bool bRotation( pRotation &&
+ *pRotation != 0.0 );
+
+ if( !bOffsetting && !bScaling && !bRotation )
+ return false; // nothing to do
+
+ if( rOutdevState.clip.count() )
+ {
+ // general polygon case
+
+ ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip );
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if( bOffsetting )
+ aTransform.translate( -rOffset.getX(),
+ -rOffset.getY() );
+ if( bScaling )
+ aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
+
+ if( bRotation )
+ aTransform.rotate( - *pRotation );
+
+ aLocalClip.transform( aTransform );
+
+ o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aLocalClip );
+
+ return true;
+ }
+ else if( !rOutdevState.clipRect.IsEmpty() )
+ {
+ // simple rect case
+
+ const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
+
+ if( bRotation )
+ {
+ // rotation involved - convert to polygon first,
+ // then transform that
+ ::basegfx::B2DPolygon aLocalClip(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(
+ (double)(aLocalClipRect.Left()),
+ (double)(aLocalClipRect.Top()),
+ (double)(aLocalClipRect.Right()),
+ (double)(aLocalClipRect.Bottom()) ) ) );
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if( bOffsetting )
+ aTransform.translate( -rOffset.getX(),
+ -rOffset.getY() );
+ if( bScaling )
+ aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
+
+ aTransform.rotate( - *pRotation );
+
+ aLocalClip.transform( aTransform );
+
+ o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ ::basegfx::B2DPolyPolygon( aLocalClip ) );
+ }
+ else if( bScaling )
+ {
+ // scale and offset - do it on the fly, have to
+ // convert to float anyway.
+ o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(
+ (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(),
+ (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(),
+ (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(),
+ (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) );
+ }
+ else
+ {
+ // offset only - do it on the fly, have to convert
+ // to float anyway.
+ o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(),
+ aLocalClipRect.Top() - rOffset.getY(),
+ aLocalClipRect.Right() - rOffset.getX(),
+ aLocalClipRect.Bottom() - rOffset.getY() ) ) ) );
+ }
+
+ return true;
+ }
+
+ // empty clip, nothing to do
+ return false;
+ }
+
+ bool modifyClip( rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::Point& rOffset,
+ const ::basegfx::B2DVector* pScaling,
+ const double* pRotation )
+ {
+ return modifyClip( o_rRenderState,
+ rOutdevState,
+ rCanvas,
+ ::basegfx::B2DPoint( rOffset.X(),
+ rOffset.Y() ),
+ pScaling,
+ pRotation );
+ }
+
+ bool modifyClip( rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( !rTransform.isIdentity() ||
+ !rTransform.isInvertible() )
+ return false; // nothing to do
+
+ ::basegfx::B2DPolyPolygon aLocalClip;
+
+ if( rOutdevState.clip.count() )
+ {
+ aLocalClip = rOutdevState.clip;
+ }
+ else if( !rOutdevState.clipRect.IsEmpty() )
+ {
+ const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
+
+ aLocalClip = ::basegfx::B2DPolyPolygon(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(
+ aLocalClipRect.Left(),
+ aLocalClipRect.Top(),
+ aLocalClipRect.Right(),
+ aLocalClipRect.Bottom() ) ) );
+ }
+ else
+ {
+ // empty clip, nothing to do
+ return false;
+ }
+
+ // invert transformation and modify
+ ::basegfx::B2DHomMatrix aLocalTransform( rTransform );
+ aLocalTransform.invert();
+
+ aLocalClip.transform( aLocalTransform );
+
+ o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aLocalClip );
+
+ return true;
+ }
+
+ // create overline/underline/strikeout line info struct
+ TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev,
+ const ::cppcanvas::internal::OutDevState& rState )
+ {
+ const sal_Bool bOldMode( rVDev.IsMapModeEnabled() );
+
+ // #i68512# Force metric regeneration with mapmode enabled
+ // (prolly OutDev bug)
+ rVDev.GetFontMetric();
+
+ // will restore map mode below
+ const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( sal_False );
+
+ const ::FontMetric aMetric = rVDev.GetFontMetric();
+
+ TextLineInfo aTextInfo(
+ (aMetric.GetDescent() + 2) / 4.0,
+ ((aMetric.GetIntLeading() + 1.5) / 3.0),
+ (aMetric.GetIntLeading() / 2.0) - aMetric.GetAscent(),
+ aMetric.GetDescent() / 2.0,
+ (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0,
+ rState.textOverlineStyle,
+ rState.textUnderlineStyle,
+ rState.textStrikeoutStyle );
+
+ const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode );
+
+ return aTextInfo;
+ }
+
+ namespace
+ {
+ void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
+ const ::basegfx::B2DPoint& rStartPos,
+ const double nX1,
+ const double nY1,
+ const double nX2,
+ const double nY2 )
+ {
+ const double x( rStartPos.getX() );
+ const double y( rStartPos.getY() );
+
+ o_rPoly.append(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) );
+ }
+
+ void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
+ const double nX1,
+ const double nY1,
+ const double nX2,
+ const double nY2 )
+ {
+ o_rPoly.append(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) );
+ }
+
+ void appendDashes( ::basegfx::B2DPolyPolygon& o_rPoly,
+ const double nX,
+ const double nY,
+ const double nLineWidth,
+ const double nLineHeight,
+ const double nDashWidth,
+ const double nDashSkip )
+ {
+ const sal_Int32 nNumLoops(
+ static_cast< sal_Int32 >(
+ ::std::max( 1.0,
+ nLineWidth / nDashSkip ) + .5) );
+
+ double x = nX;
+ for( sal_Int32 i=0; i<nNumLoops; ++i )
+ {
+ appendRect( o_rPoly,
+ x, nY,
+ x + nDashWidth, nY + nLineHeight );
+
+ x += nDashSkip;
+ }
+ }
+ }
+
+ // create line actions for text such as underline and
+ // strikeout
+ ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos,
+ const double& rLineWidth,
+ const TextLineInfo& rTextLineInfo )
+ {
+ // fill the polypolygon with all text lines
+ ::basegfx::B2DPolyPolygon aTextLinesPolyPoly;
+
+ switch( rTextLineInfo.mnOverlineStyle )
+ {
+ case UNDERLINE_NONE: // nothing to do
+ // FALLTHROUGH intended
+ case UNDERLINE_DONTKNOW:
+ break;
+
+ case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_WAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_SINGLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnOverlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
+ break;
+
+ case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASH: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLD:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight,
+ rLineWidth,
+ rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
+ break;
+
+ case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DOUBLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight * 2.0 ,
+ rLineWidth,
+ rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight );
+
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight,
+ rLineWidth,
+ rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight * 2.0 );
+ break;
+
+ case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DOTTED:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnOverlineHeight,
+ rTextLineInfo.mnOverlineHeight,
+ 2*rTextLineInfo.mnOverlineHeight );
+ break;
+
+ case UNDERLINE_DASHDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DASH:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnOverlineHeight,
+ 3*rTextLineInfo.mnOverlineHeight,
+ 6*rTextLineInfo.mnOverlineHeight );
+ break;
+
+ case UNDERLINE_LONGDASH:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnOverlineHeight,
+ 6*rTextLineInfo.mnOverlineHeight,
+ 12*rTextLineInfo.mnOverlineHeight );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected overline case" );
+ }
+
+ switch( rTextLineInfo.mnUnderlineStyle )
+ {
+ case UNDERLINE_NONE: // nothing to do
+ // FALLTHROUGH intended
+ case UNDERLINE_DONTKNOW:
+ break;
+
+ case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_WAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_SINGLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnUnderlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight );
+ break;
+
+ case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASH: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_BOLD:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnUnderlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight );
+ break;
+
+ case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DOUBLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight,
+ rLineWidth,
+ rTextLineInfo.mnUnderlineOffset );
+
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight,
+ rLineWidth,
+ rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight );
+ break;
+
+ case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DOTTED:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnLineHeight,
+ rTextLineInfo.mnLineHeight,
+ 2*rTextLineInfo.mnLineHeight );
+ break;
+
+ case UNDERLINE_DASHDOT: // TODO(F3): NYI
+ // FALLTHROUGH intended
+ case UNDERLINE_DASH:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnLineHeight,
+ 3*rTextLineInfo.mnLineHeight,
+ 6*rTextLineInfo.mnLineHeight );
+ break;
+
+ case UNDERLINE_LONGDASH:
+ appendDashes(
+ aTextLinesPolyPoly,
+ rStartPos.getX(),
+ rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
+ rLineWidth,
+ rTextLineInfo.mnLineHeight,
+ 6*rTextLineInfo.mnLineHeight,
+ 12*rTextLineInfo.mnLineHeight );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" );
+ }
+
+ switch( rTextLineInfo.mnStrikeoutStyle )
+ {
+ case STRIKEOUT_NONE: // nothing to do
+ // FALLTHROUGH intended
+ case STRIKEOUT_DONTKNOW:
+ break;
+
+ case STRIKEOUT_SLASH: // TODO(Q1): we should handle this in the text layer
+ // FALLTHROUGH intended
+ case STRIKEOUT_X:
+ break;
+
+ case STRIKEOUT_SINGLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnStrikeoutOffset,
+ rLineWidth,
+ rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight );
+ break;
+
+ case STRIKEOUT_BOLD:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnStrikeoutOffset,
+ rLineWidth,
+ rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight );
+ break;
+
+ case STRIKEOUT_DOUBLE:
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight,
+ rLineWidth,
+ rTextLineInfo.mnStrikeoutOffset );
+
+ appendRect(
+ aTextLinesPolyPoly,
+ rStartPos,
+ 0,
+ rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight,
+ rLineWidth,
+ rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" );
+ }
+
+ return aTextLinesPolyPoly;
+ }
+
+ ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& rBounds,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ::basegfx::B2DHomMatrix aTransform;
+ ::canvas::tools::mergeViewAndRenderTransform( aTransform,
+ viewState,
+ renderState );
+
+ ::basegfx::B2DRange aTransformedBounds;
+ return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
+ rBounds,
+ aTransform );
+ }
+
+ // create line actions for text such as underline and
+ // strikeout
+ ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset,
+ const double& rLineWidth,
+ const TextLineInfo& rTextLineInfo )
+ {
+ return createTextLinesPolyPolygon(
+ ::basegfx::B2DPoint( rStartOffset,
+ 0.0 ),
+ rLineWidth,
+ rTextLineInfo );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/mtftools.hxx b/cppcanvas/source/mtfrenderer/mtftools.hxx
new file mode 100644
index 000000000000..8d466f1d9e7e
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/mtftools.hxx
@@ -0,0 +1,273 @@
+/* -*- 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 _CPPCANVAS_RENDERER_MTFTOOLS_HXX
+#define _CPPCANVAS_RENDERER_MTFTOOLS_HXX
+
+#include <action.hxx>
+#include <cppcanvas/canvas.hxx>
+
+
+class VirtualDevice;
+class Point;
+class Size;
+
+namespace basegfx
+{
+ class B2DVector;
+ class B2DPoint;
+}
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct RenderState;
+} } } }
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+ }
+
+ namespace tools
+ {
+ /** Init render state from OutDevState
+
+ This method initializes the given render state object,
+ sets up the transformation and the clip from the
+ OutDevState.
+ */
+ void initRenderState( ::com::sun::star::rendering::RenderState& renderState,
+ const ::cppcanvas::internal::OutDevState& outdevState );
+
+ /** Calc output offset relative to baseline
+
+ The XCanvas API always renders text relative to its
+ baseline. This method calculates an offset in logical
+ coordinates, depending on the OutDevState's
+ textReferencePoint and the font currently set, to offset
+ the text from the baseline.
+
+ @param outdevState
+ State to take textReferencePoint from
+
+ @param rVDev
+ VDev to obtain font metrics from.
+ */
+ ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState& outdevState,
+ const VirtualDevice& rVDev );
+
+ /** Construct a matrix that converts from logical to pixel
+ coordinate system.
+
+ This method calculates a matrix that approximates the
+ VirtualDevice's LogicToPixel conversion (disregarding any
+ offset components, thus the 'linear' in the method name -
+ the returned matrix is guaranteed to be linear).
+
+ @param o_rMatrix
+ This matrix will receive the calculated transform, and is
+ also returned from this method.
+
+ @return the calculated transformation matrix.
+ */
+ ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
+ const VirtualDevice& rVDev );
+
+ /** Construct a matrix that converts from logical to pixel
+ coordinate system.
+
+ This method calculates a matrix that approximates the
+ VirtualDevice's LogicToPixel conversion.
+
+ @param o_rMatrix
+ This matrix will receive the calculated transform, and is
+ also returned from this method.
+
+ @return the calculated transformation matrix.
+ */
+ ::basegfx::B2DHomMatrix& calcLogic2PixelAffineTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
+ const VirtualDevice& rVDev );
+
+ /** This method modifies the clip, to cancel the given
+ transformation.
+
+ As the clip is relative to the render state
+ transformation, offsetting or scaling the render state
+ must modify the clip, to keep it at the same position
+ relative to the primitive at hand
+
+ @param o_rRenderState
+ Render state to change the clip in
+
+ @param rOutdevState
+ Input state. Is used to retrieve the original clip from
+
+ @param rOffset
+ The clip is offsetted by the negative of this value.
+
+ @param pScaling
+ The clip is inversely scaled by this value (if given)
+
+ @param pRotation
+ The clip is inversely rotated by this value (if given)
+
+ @return true, if the clip has changed, false if not
+ */
+ bool modifyClip( ::com::sun::star::rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::Point& rOffset,
+ const ::basegfx::B2DVector* pScaling,
+ const double* pRotation );
+
+ /** This method modifies the clip, to cancel the given
+ transformation.
+
+ As the clip is relative to the render state
+ transformation, offsetting or scaling the render state
+ must modify the clip, to keep it at the same position
+ relative to the primitive at hand
+
+ @param o_rRenderState
+ Render state to change the clip in
+
+ @param rOutdevState
+ Input state. Is used to retrieve the original clip from
+
+ @param rOffset
+ The clip is offsetted by the negative of this value.
+
+ @param pScaling
+ The clip is inversely scaled by this value (if given)
+
+ @param pRotation
+ The clip is inversely rotated by this value (if given)
+
+ @return true, if the clip has changed, false if not
+ */
+ bool modifyClip( ::com::sun::star::rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DPoint& rOffset,
+ const ::basegfx::B2DVector* pScaling,
+ const double* pRotation );
+
+ /** This method modifies the clip, to cancel the given
+ transformation.
+
+ As the clip is relative to the render state
+ transformation, transforming the render state further must
+ modify the clip, to keep it at the same position relative
+ to the primitive at hand
+
+ @param o_rRenderState
+ Render state to change the clip in
+
+ @param rOutdevState
+ Input state. Is used to retrieve the original clip from
+
+ @param rTransform
+ The clip is transformed by the inverse of this value.
+
+ @return true, if the clip has changed, false if not
+ */
+ bool modifyClip( ::com::sun::star::rendering::RenderState& o_rRenderState,
+ const struct ::cppcanvas::internal::OutDevState& rOutdevState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ struct TextLineInfo
+ {
+ TextLineInfo( const double& rLineHeight,
+ const double& rOverlineHeight,
+ const double& rOverlineOffset,
+ const double& rUnderlineOffset,
+ const double& rStrikeoutOffset,
+ sal_Int8 nOverlineStyle,
+ sal_Int8 nUnderlineStyle,
+ sal_Int8 nStrikeoutStyle ) :
+ mnLineHeight( rLineHeight ),
+ mnOverlineHeight( rOverlineHeight ),
+ mnOverlineOffset( rOverlineOffset ),
+ mnUnderlineOffset( rUnderlineOffset ),
+ mnStrikeoutOffset( rStrikeoutOffset ),
+ mnOverlineStyle( nOverlineStyle ),
+ mnUnderlineStyle( nUnderlineStyle ),
+ mnStrikeoutStyle( nStrikeoutStyle )
+ {
+ }
+
+ double mnLineHeight;
+ double mnOverlineHeight;
+ double mnOverlineOffset;
+ double mnUnderlineOffset;
+ double mnStrikeoutOffset;
+ sal_Int8 mnOverlineStyle;
+ sal_Int8 mnUnderlineStyle;
+ sal_Int8 mnStrikeoutStyle;
+ };
+
+ /** Transform given bounds to device coordinate system.
+ */
+ ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& rBounds,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ /** Generate text underline/strikeout info struct from OutDev
+ state.
+ */
+ TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev,
+ const ::cppcanvas::internal::OutDevState& rState );
+
+ /** Create a poly-polygon representing the given combination
+ of overline, strikeout and underline.
+
+ @param rStartOffset
+ Offset in X direction, where the underline starts
+
+ @param rLineWidth
+ Width of the line of text to overline/strikeout/underline
+
+ @param rTextLineInfo
+ Common info needed for overline/strikeout/underline generation
+ */
+ ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset,
+ const double& rLineWidth,
+ const TextLineInfo& rTextLineInfo );
+
+ ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos,
+ const double& rLineWidth,
+ const TextLineInfo& rTextLineInfo );
+ }
+}
+
+#endif /* _CPPCANVAS_RENDERER_MTFTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/outdevstate.hxx b/cppcanvas/source/mtfrenderer/outdevstate.hxx
new file mode 100644
index 000000000000..b0e79d2684dc
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/outdevstate.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 _CPPCANVAS_OUTDEVSTATE_HXX
+#define _CPPCANVAS_OUTDEVSTATE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <vcl/fntstyle.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/outdev.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState
+ {
+ OutDevState() :
+ clip(),
+ clipRect(),
+ xClipPoly(),
+
+ lineColor(),
+ fillColor(),
+ textColor(),
+ textFillColor(),
+ textLineColor(),
+
+ xFont(),
+ transform(),
+ mapModeTransform(),
+ fontRotation(0.0),
+
+ textEmphasisMarkStyle(EMPHASISMARK_NONE),
+ pushFlags(PUSH_ALL),
+ textDirection(::com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT),
+ textAlignment(0), // TODO(Q2): Synchronize with implrenderer
+ // and possibly new rendering::TextAlignment
+ textReliefStyle(RELIEF_NONE),
+ textOverlineStyle(UNDERLINE_NONE),
+ textUnderlineStyle(UNDERLINE_NONE),
+ textStrikeoutStyle(STRIKEOUT_NONE),
+ textReferencePoint(ALIGN_BASELINE),
+
+ isTextOutlineModeSet( false ),
+ isTextEffectShadowSet( false ),
+ isTextWordUnderlineSet( false ),
+
+ isLineColorSet( false ),
+ isFillColorSet( false ),
+ isTextFillColorSet( false ),
+ isTextLineColorSet( false )
+ {
+ }
+
+ ::basegfx::B2DPolyPolygon clip;
+ ::Rectangle clipRect;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > xClipPoly;
+
+ ::com::sun::star::uno::Sequence< double > lineColor;
+ ::com::sun::star::uno::Sequence< double > fillColor;
+ ::com::sun::star::uno::Sequence< double > textColor;
+ ::com::sun::star::uno::Sequence< double > textFillColor;
+ ::com::sun::star::uno::Sequence< double > textLineColor;
+
+ /** Current font.
+
+ @attention Beware, this member can be NULL, and
+ nevertheless text output is generated.
+ */
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > xFont;
+ ::basegfx::B2DHomMatrix transform;
+ ::basegfx::B2DHomMatrix mapModeTransform;
+ double fontRotation;
+
+ sal_uInt16 textEmphasisMarkStyle;
+ sal_uInt16 pushFlags;
+ sal_Int8 textDirection;
+ sal_Int8 textAlignment;
+ sal_Int8 textReliefStyle;
+ sal_Int8 textOverlineStyle;
+ sal_Int8 textUnderlineStyle;
+ sal_Int8 textStrikeoutStyle;
+ TextAlign textReferencePoint;
+
+ bool isTextOutlineModeSet;
+ bool isTextEffectShadowSet;
+ bool isTextWordUnderlineSet;
+
+ bool isLineColorSet;
+ bool isFillColorSet;
+ bool isTextFillColorSet;
+ bool isTextLineColorSet;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_OUTDEVSTATE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/pointaction.cxx b/cppcanvas/source/mtfrenderer/pointaction.cxx
new file mode 100644
index 000000000000..8a2edbdf35ba
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/pointaction.cxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <rtl/logfile.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <boost/utility.hpp>
+
+#include "pointaction.hxx"
+#include "outdevstate.hxx"
+#include "cppcanvas/canvas.hxx"
+#include "mtftools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ namespace
+ {
+ class PointAction : public Action, private ::boost::noncopyable
+ {
+ public:
+ PointAction( const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+ PointAction( const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ const ::Color& );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ // default: disabled copy/assignment
+ PointAction(const PointAction&);
+ PointAction& operator = ( const PointAction& );
+
+ ::basegfx::B2DPoint maPoint;
+ CanvasSharedPtr mpCanvas;
+ ::com::sun::star::rendering::RenderState maState;
+ };
+
+ PointAction::PointAction( const ::basegfx::B2DPoint& rPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ maPoint( rPoint ),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ tools::initRenderState(maState,rState);
+ maState.DeviceColor = rState.lineColor;
+ }
+
+ PointAction::PointAction( const ::basegfx::B2DPoint& rPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::Color& rAltColor ) :
+ maPoint( rPoint ),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ tools::initRenderState(maState,rState);
+ maState.DeviceColor = ::vcl::unotools::colorToDoubleSequence(
+ rAltColor,
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
+ }
+
+ bool PointAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PointAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PointAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ mpCanvas->getUNOCanvas()->drawPoint( ::basegfx::unotools::point2DFromB2DPoint(maPoint),
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ bool PointAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // point only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return render( rTransformation );
+ }
+
+ ::basegfx::B2DRange PointAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds( ::basegfx::B2DRange( maPoint.getX()-1,
+ maPoint.getY()-1,
+ maPoint.getX()+1,
+ maPoint.getY()+1 ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange PointAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // point only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 PointAction::getActionCount() const
+ {
+ return 1;
+ }
+ }
+
+ ActionSharedPtr PointActionFactory::createPointAction( const ::basegfx::B2DPoint& rPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new PointAction( rPoint, rCanvas, rState ) );
+ }
+
+ ActionSharedPtr PointActionFactory::createPointAction( const ::basegfx::B2DPoint& rPoint,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::Color& rColor )
+ {
+ return ActionSharedPtr( new PointAction( rPoint, rCanvas, rState, rColor ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/pointaction.hxx b/cppcanvas/source/mtfrenderer/pointaction.hxx
new file mode 100644
index 000000000000..b17b1eea5a43
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/pointaction.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 _CPPCANVAS_POINTACTION_HXX
+#define _CPPCANVAS_POINTACTION_HXX
+
+#include <action.hxx>
+#include <cppcanvas/canvas.hxx>
+
+class Color;
+namespace basegfx {
+ class B2DPoint;
+}
+
+/* Definition of internal::PointActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ /** Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class PointActionFactory
+ {
+ public:
+ /// Point in current color
+ static ActionSharedPtr createPointAction( const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ /// Point in given color
+ static ActionSharedPtr createPointAction( const ::basegfx::B2DPoint&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ const ::Color& );
+
+ private:
+ // static factory, disable big four
+ PointActionFactory();
+ ~PointActionFactory();
+ PointActionFactory(const PointActionFactory&);
+ PointActionFactory& operator=( const PointActionFactory& );
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_POINTACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/polypolyaction.cxx b/cppcanvas/source/mtfrenderer/polypolyaction.cxx
new file mode 100644
index 000000000000..5b04576d46a8
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/polypolyaction.cxx
@@ -0,0 +1,527 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <rtl/logfile.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <boost/utility.hpp>
+
+#include "cachedprimitivebase.hxx"
+#include "polypolyaction.hxx"
+#include "outdevstate.hxx"
+#include "mtftools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ namespace
+ {
+ class PolyPolyAction : public CachedPrimitiveBase
+ {
+ public:
+ PolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ bool bFill,
+ bool bStroke );
+ PolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ bool bFill,
+ bool bStroke,
+ int nTransparency );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ using Action::render;
+ virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const;
+
+ const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly;
+ const ::basegfx::B2DRange maBounds;
+ const CanvasSharedPtr mpCanvas;
+
+ // stroke color is now implicit: the maState.DeviceColor member
+ rendering::RenderState maState;
+
+ uno::Sequence< double > maFillColor;
+ };
+
+ PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ bool bFill,
+ bool bStroke ) :
+ CachedPrimitiveBase( rCanvas, false ),
+ mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
+ maBounds( ::basegfx::tools::getRange(rPolyPoly) ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maFillColor()
+ {
+ tools::initRenderState(maState,rState);
+
+ if( bFill )
+ maFillColor = rState.fillColor;
+
+ if( bStroke )
+ maState.DeviceColor = rState.lineColor;
+ }
+
+ PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ bool bFill,
+ bool bStroke,
+ int nTransparency ) :
+ CachedPrimitiveBase( rCanvas, false ),
+ mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
+ maBounds( ::basegfx::tools::getRange(rPolyPoly) ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maFillColor()
+ {
+ tools::initRenderState(maState,rState);
+
+ if( bFill )
+ {
+ maFillColor = rState.fillColor;
+
+ if( maFillColor.getLength() < 4 )
+ maFillColor.realloc( 4 );
+
+ // TODO(F1): Color management
+ // adapt fill color transparency
+ maFillColor[3] = 1.0 - nTransparency / 100.0;
+ }
+
+ if( bStroke )
+ {
+ maState.DeviceColor = rState.lineColor;
+
+ if( maState.DeviceColor.getLength() < 4 )
+ maState.DeviceColor.realloc( 4 );
+
+ // TODO(F1): Color management
+ // adapt fill color transparency
+ maState.DeviceColor[3] = 1.0 - nTransparency / 100.0;
+ }
+ }
+
+ bool PolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ if( maFillColor.getLength() )
+ {
+ // TODO(E3): Use DBO's finalizer here,
+ // fillPolyPolygon() might throw
+ const uno::Sequence< double > aTmpColor( aLocalState.DeviceColor );
+ aLocalState.DeviceColor = maFillColor;
+
+ rCachedPrimitive = mpCanvas->getUNOCanvas()->fillPolyPolygon( mxPolyPoly,
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ aLocalState.DeviceColor = aTmpColor;
+ }
+
+ if( aLocalState.DeviceColor.getLength() )
+ {
+ rCachedPrimitive = mpCanvas->getUNOCanvas()->drawPolyPolygon( mxPolyPoly,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ return true;
+ }
+
+ bool PolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return CachedPrimitiveBase::render( rTransformation );
+ }
+
+ ::basegfx::B2DRange PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds(
+ maBounds,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 PolyPolyAction::getActionCount() const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+ return 1;
+ }
+
+
+ // -------------------------------------------------------------------------------
+
+ class TexturedPolyPolyAction : public CachedPrimitiveBase
+ {
+ public:
+ TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::Texture& rTexture );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ using Action::render;
+ virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const;
+
+ const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly;
+ const ::basegfx::B2DRectangle maBounds;
+ const CanvasSharedPtr mpCanvas;
+
+ // stroke color is now implicit: the maState.DeviceColor member
+ rendering::RenderState maState;
+ const rendering::Texture maTexture;
+ };
+
+ TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::Texture& rTexture ) :
+ CachedPrimitiveBase( rCanvas, true ),
+ mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
+ maBounds( ::basegfx::tools::getRange(rPolyPoly) ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTexture( rTexture )
+ {
+ tools::initRenderState(maState,rState);
+ }
+
+ bool TexturedPolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = maTexture;
+
+ rCachedPrimitive = mpCanvas->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly,
+ mpCanvas->getViewState(),
+ aLocalState,
+ aSeq );
+ return true;
+ }
+
+ bool TexturedPolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return CachedPrimitiveBase::render( rTransformation );
+ }
+
+ ::basegfx::B2DRange TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds(
+ maBounds,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 TexturedPolyPolyAction::getActionCount() const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+ return 1;
+ }
+
+ // -------------------------------------------------------------------------------
+
+ class StrokedPolyPolyAction : public CachedPrimitiveBase
+ {
+ public:
+ StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::StrokeAttributes& rStrokeAttributes );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ using Action::render;
+ virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const;
+
+ const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly;
+ const ::basegfx::B2DRectangle maBounds;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ const rendering::StrokeAttributes maStrokeAttributes;
+ };
+
+ StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::StrokeAttributes& rStrokeAttributes ) :
+ CachedPrimitiveBase( rCanvas, false ),
+ mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
+ maBounds( ::basegfx::tools::getRange(rPolyPoly) ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maStrokeAttributes( rStrokeAttributes )
+ {
+ tools::initRenderState(maState,rState);
+ maState.DeviceColor = rState.lineColor;
+ }
+
+ bool StrokedPolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive,
+ const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ rCachedPrimitive = mpCanvas->getUNOCanvas()->strokePolyPolygon( mxPolyPoly,
+ mpCanvas->getViewState(),
+ aLocalState,
+ maStrokeAttributes );
+ return true;
+ }
+
+ bool StrokedPolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, fail if subset
+ // requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return false;
+
+ return CachedPrimitiveBase::render( rTransformation );
+ }
+
+ ::basegfx::B2DRange StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds(
+ maBounds,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+
+ // polygon only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 StrokedPolyPolyAction::getActionCount() const
+ {
+ // TODO(F1): Split up poly-polygon into polygons, or even
+ // line segments, when subsets are requested.
+ return 1;
+ }
+ }
+
+ ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ OSL_ENSURE( rState.isLineColorSet || rState.isFillColorSet,
+ "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
+ return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState,
+ rState.isFillColorSet,
+ rState.isLineColorSet ) );
+ }
+
+ ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::Texture& rTexture )
+ {
+ return ActionSharedPtr( new TexturedPolyPolyAction( rPoly, rCanvas, rState, rTexture ) );
+ }
+
+ ActionSharedPtr PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ OSL_ENSURE( rState.isLineColorSet,
+ "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
+
+ return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState,
+ false,
+ rState.isLineColorSet ) );
+ }
+
+ ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const rendering::StrokeAttributes& rStrokeAttributes )
+ {
+ OSL_ENSURE( rState.isLineColorSet,
+ "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
+ return ActionSharedPtr( new StrokedPolyPolyAction( rPoly, rCanvas, rState, rStrokeAttributes ) );
+ }
+
+ ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ int nTransparency )
+ {
+ OSL_ENSURE( rState.isLineColorSet || rState.isFillColorSet,
+ "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
+ return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState,
+ rState.isFillColorSet,
+ rState.isLineColorSet,
+ nTransparency ) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/polypolyaction.hxx b/cppcanvas/source/mtfrenderer/polypolyaction.hxx
new file mode 100644
index 000000000000..a38ba92a8752
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/polypolyaction.hxx
@@ -0,0 +1,104 @@
+/* -*- 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 _CPPCANVAS_POLYPOLYACTION_HXX
+#define _CPPCANVAS_POLYPOLYACTION_HXX
+
+#include <action.hxx>
+#include <cppcanvas/canvas.hxx>
+
+
+namespace basegfx {
+ class B2DPolyPolygon;
+}
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct Texture;
+ struct StrokeAttributes;
+} } } }
+
+
+/* Definition of internal::PolyPolyActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ /** Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class PolyPolyActionFactory
+ {
+ public:
+ /// Create polygon, fill/stroke according to state
+ static ActionSharedPtr createPolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ /// Create texture-filled polygon
+ static ActionSharedPtr createPolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ const ::com::sun::star::rendering::Texture& );
+
+ /// Create line polygon (always stroked, not filled)
+ static ActionSharedPtr createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState& );
+
+ /// Create stroked polygon
+ static ActionSharedPtr createPolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ const ::com::sun::star::rendering::StrokeAttributes& );
+
+ /// For transparent painting of the given polygon (normally, we take the colors always opaque)
+ static ActionSharedPtr createPolyPolyAction( const ::basegfx::B2DPolyPolygon&,
+ const CanvasSharedPtr&,
+ const OutDevState&,
+ int nTransparency );
+
+ private:
+ // static factory, disable big four
+ PolyPolyActionFactory();
+ ~PolyPolyActionFactory();
+ PolyPolyActionFactory(const PolyPolyActionFactory&);
+ PolyPolyActionFactory& operator=( const PolyPolyActionFactory& );
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_POLYPOLYACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/textaction.cxx b/cppcanvas/source/mtfrenderer/textaction.cxx
new file mode 100644
index 000000000000..a80306df3e05
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/textaction.cxx
@@ -0,0 +1,2299 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <rtl/logfile.hxx>
+
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/virdev.hxx>
+
+#include <basegfx/tools/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <boost/scoped_array.hpp>
+#include <boost/bind.hpp>
+#include <boost/utility.hpp>
+
+#include "textaction.hxx"
+#include "outdevstate.hxx"
+#include "mtftools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ namespace
+ {
+ void init( rendering::RenderState& o_rRenderState,
+ const ::basegfx::B2DPoint& rStartPoint,
+ const OutDevState& rState,
+ const CanvasSharedPtr& rCanvas )
+ {
+ tools::initRenderState(o_rRenderState,rState);
+
+ // #i36950# Offset clip back to origin (as it's also moved
+ // by rStartPoint)
+ // #i53964# Also take VCL font rotation into account,
+ // since this, opposed to the FontMatrix rotation
+ // elsewhere, _does_ get incorporated into the render
+ // state transform.
+ tools::modifyClip( o_rRenderState,
+ rState,
+ rCanvas,
+ rStartPoint,
+ NULL,
+ &rState.fontRotation );
+
+ basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState.fontRotation));
+ aLocalTransformation.translate( rStartPoint.getX(),
+ rStartPoint.getY() );
+ ::canvas::tools::appendToRenderState( o_rRenderState,
+ aLocalTransformation );
+
+ o_rRenderState.DeviceColor = rState.textColor;
+ }
+
+ void init( rendering::RenderState& o_rRenderState,
+ const ::basegfx::B2DPoint& rStartPoint,
+ const OutDevState& rState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DHomMatrix& rTextTransform )
+ {
+ init( o_rRenderState, rStartPoint, rState, rCanvas );
+
+ // TODO(F2): Also inversely-transform clip with
+ // rTextTransform (which is actually rather hard, as the
+ // text transform is _prepended_ to the render state)!
+
+ // prepend extra font transform to render state
+ // (prepend it, because it's interpreted in the unit
+ // rect coordinate space)
+ ::canvas::tools::prependToRenderState( o_rRenderState,
+ rTextTransform );
+ }
+
+ void init( rendering::RenderState& o_rRenderState,
+ uno::Reference< rendering::XCanvasFont >& o_rFont,
+ const ::basegfx::B2DPoint& rStartPoint,
+ const OutDevState& rState,
+ const CanvasSharedPtr& rCanvas )
+ {
+ // ensure that o_rFont is valid. It is possible that
+ // text actions are generated without previously
+ // setting a font. Then, just take a default font
+ if( !o_rFont.is() )
+ {
+ // Use completely default FontRequest
+ const rendering::FontRequest aFontRequest;
+
+ geometry::Matrix2D aFontMatrix;
+ ::canvas::tools::setIdentityMatrix2D( aFontMatrix );
+
+ o_rFont = rCanvas->getUNOCanvas()->createFont(
+ aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ aFontMatrix );
+ }
+
+ init( o_rRenderState,
+ rStartPoint,
+ rState,
+ rCanvas );
+ }
+
+ void init( rendering::RenderState& o_rRenderState,
+ uno::Reference< rendering::XCanvasFont >& o_rFont,
+ const ::basegfx::B2DPoint& rStartPoint,
+ const OutDevState& rState,
+ const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DHomMatrix& rTextTransform )
+ {
+ init( o_rRenderState, o_rFont, rStartPoint, rState, rCanvas );
+
+ // TODO(F2): Also inversely-transform clip with
+ // rTextTransform (which is actually rather hard, as the
+ // text transform is _prepended_ to the render state)!
+
+ // prepend extra font transform to render state
+ // (prepend it, because it's interpreted in the unit
+ // rect coordinate space)
+ ::canvas::tools::prependToRenderState( o_rRenderState,
+ rTextTransform );
+ }
+
+ ::basegfx::B2DPolyPolygon textLinesFromLogicalOffsets( const uno::Sequence< double >& rOffsets,
+ const tools::TextLineInfo& rTextLineInfo )
+ {
+ return tools::createTextLinesPolyPolygon(
+ 0.0,
+ // extract character cell furthest to the right
+ *(::std::max_element(
+ rOffsets.getConstArray(),
+ rOffsets.getConstArray() + rOffsets.getLength() )),
+ rTextLineInfo );
+ }
+
+ uno::Sequence< double > setupDXArray( const sal_Int32* pCharWidths,
+ sal_Int32 nLen,
+ const OutDevState& rState )
+ {
+ // convert character widths from logical units
+ uno::Sequence< double > aCharWidthSeq( nLen );
+ double* pOutputWidths( aCharWidthSeq.getArray() );
+
+ // #143885# maintain (nearly) full precision of DX
+ // array, by circumventing integer-based
+ // OutDev-mapping
+ const double nScale( rState.mapModeTransform.get(0,0) );
+ for( int i = 0; i < nLen; ++i )
+ {
+ // TODO(F2): use correct scale direction
+ *pOutputWidths++ = *pCharWidths++ * nScale;
+ }
+
+ return aCharWidthSeq;
+ }
+
+ uno::Sequence< double > setupDXArray( const ::String& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ VirtualDevice& rVDev,
+ const OutDevState& rState )
+ {
+ // no external DX array given, create one from given
+ // string
+ ::boost::scoped_array< sal_Int32 > pCharWidths( new sal_Int32[nLen] );
+
+ rVDev.GetTextArray( rText, pCharWidths.get(),
+ static_cast<sal_uInt16>(nStartPos),
+ static_cast<sal_uInt16>(nLen) );
+
+ return setupDXArray( pCharWidths.get(), nLen, rState );
+ }
+
+ ::basegfx::B2DPoint adaptStartPoint( const ::basegfx::B2DPoint& rStartPoint,
+ const OutDevState& rState,
+ const uno::Sequence< double >& rOffsets )
+ {
+ ::basegfx::B2DPoint aLocalPoint( rStartPoint );
+
+ if( rState.textAlignment )
+ {
+ // text origin is right, not left. Modify start point
+ // accordingly, because XCanvas::drawTextLayout()
+ // always aligns left!
+
+ const double nOffset( rOffsets[ rOffsets.getLength()-1 ] );
+
+ // correct start point for rotated text: rotate around
+ // former start point
+ aLocalPoint.setX( aLocalPoint.getX() + cos( rState.fontRotation )*nOffset );
+ aLocalPoint.setY( aLocalPoint.getY() + sin( rState.fontRotation )*nOffset );
+ }
+
+ return aLocalPoint;
+ }
+
+ /** Perform common setup for array text actions
+
+ This method creates the XTextLayout object and
+ initializes it, e.g. with the logical advancements.
+ */
+ void initArrayAction( rendering::RenderState& o_rRenderState,
+ uno::Reference< rendering::XTextLayout >& o_rTextLayout,
+ const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix* pTextTransform )
+ {
+ ENSURE_OR_THROW( rOffsets.getLength(),
+ "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
+
+ const ::basegfx::B2DPoint aLocalStartPoint(
+ adaptStartPoint( rStartPoint, rState, rOffsets ) );
+
+ uno::Reference< rendering::XCanvasFont > xFont( rState.xFont );
+
+ if( pTextTransform )
+ init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas, *pTextTransform );
+ else
+ init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas );
+
+ o_rTextLayout = xFont->createTextLayout(
+ rendering::StringContext( rText, nStartPos, nLen ),
+ rState.textDirection,
+ 0 );
+
+ ENSURE_OR_THROW( o_rTextLayout.is(),
+ "::cppcanvas::internal::initArrayAction(): Invalid font" );
+
+ o_rTextLayout->applyLogicalAdvancements( rOffsets );
+ }
+
+ double getLineWidth( ::VirtualDevice& rVDev,
+ const OutDevState& rState,
+ const rendering::StringContext& rStringContext )
+ {
+ // TODO(F2): use correct scale direction
+ const ::basegfx::B2DSize aSize( rVDev.GetTextWidth( rStringContext.Text,
+ static_cast<sal_uInt16>(rStringContext.StartPosition),
+ static_cast<sal_uInt16>(rStringContext.Length) ),
+ 0 );
+
+ return (rState.mapModeTransform * aSize).getX();
+ }
+
+ uno::Sequence< double >
+ calcSubsetOffsets( rendering::RenderState& io_rRenderState,
+ double& o_rMinPos,
+ double& o_rMaxPos,
+ const uno::Reference< rendering::XTextLayout >& rOrigTextLayout,
+ const ::cppcanvas::internal::Action::Subset& rSubset )
+ {
+ ENSURE_OR_THROW( rSubset.mnSubsetEnd > rSubset.mnSubsetBegin,
+ "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
+
+ uno::Sequence< double > aOrigOffsets( rOrigTextLayout->queryLogicalAdvancements() );
+ const double* pOffsets( aOrigOffsets.getConstArray() );
+
+ ENSURE_OR_THROW( aOrigOffsets.getLength() >= rSubset.mnSubsetEnd,
+ "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
+
+ // TODO(F3): It currently seems that for RTL text, the
+ // DX offsets are nevertheless increasing in logical
+ // text order (I'd expect they are decreasing,
+ // mimicking the fact that the text is output
+ // right-to-left). This breaks text effects for ALL
+ // RTL languages.
+
+ // determine leftmost position in given subset range -
+ // as the DX array contains the output positions
+ // starting with the second character (the first is
+ // assumed to have output position 0), correct begin
+ // iterator.
+ const double nMinPos( rSubset.mnSubsetBegin <= 0 ? 0 :
+ *(::std::min_element( pOffsets+rSubset.mnSubsetBegin-1,
+ pOffsets+rSubset.mnSubsetEnd )) );
+
+ // determine rightmost position in given subset range
+ // - as the DX array contains the output positions
+ // starting with the second character (the first is
+ // assumed to have output position 0), correct begin
+ // iterator.
+ const double nMaxPos(
+ *(::std::max_element( pOffsets + (rSubset.mnSubsetBegin <= 0 ?
+ 0 : rSubset.mnSubsetBegin-1),
+ pOffsets + rSubset.mnSubsetEnd )) );
+
+
+ // adapt render state, to move text output to given offset
+ // -------------------------------------------------------
+
+ // TODO(F1): Strictly speaking, we also have to adapt
+ // the clip here, which normally should _not_ move
+ // with the output offset. Neglected for now, as it
+ // does not matter for drawing layer output
+
+ if( rSubset.mnSubsetBegin > 0 )
+ {
+ ::basegfx::B2DHomMatrix aTranslation;
+ if( rOrigTextLayout->getFont()->getFontRequest().FontDescription.IsVertical )
+ {
+ // vertical text -> offset in y direction
+ aTranslation.translate( 0.0, nMinPos );
+ }
+ else
+ {
+ // horizontal text -> offset in x direction
+ aTranslation.translate( nMinPos, 0.0 );
+ }
+
+ ::canvas::tools::appendToRenderState( io_rRenderState,
+ aTranslation );
+ }
+
+
+ // reduce DX array to given substring
+ // ----------------------------------
+
+ const sal_Int32 nNewElements( rSubset.mnSubsetEnd - rSubset.mnSubsetBegin );
+ uno::Sequence< double > aAdaptedOffsets( nNewElements );
+ double* pAdaptedOffsets( aAdaptedOffsets.getArray() );
+
+ // move to new output position (subtract nMinPos,
+ // which is the new '0' position), copy only the range
+ // as given by rSubset.
+ ::std::transform( pOffsets + rSubset.mnSubsetBegin,
+ pOffsets + rSubset.mnSubsetEnd,
+ pAdaptedOffsets,
+ ::boost::bind( ::std::minus<double>(),
+ _1,
+ nMinPos ) );
+
+ o_rMinPos = nMinPos;
+ o_rMaxPos = nMaxPos;
+
+ return aAdaptedOffsets;
+ }
+
+ uno::Reference< rendering::XTextLayout >
+ createSubsetLayout( const rendering::StringContext& rOrigContext,
+ const ::cppcanvas::internal::Action::Subset& rSubset,
+ const uno::Reference< rendering::XTextLayout >& rOrigTextLayout )
+ {
+ // create temporary new text layout with subset string
+ // ---------------------------------------------------
+
+ const sal_Int32 nNewStartPos( rOrigContext.StartPosition + ::std::min(
+ rSubset.mnSubsetBegin, rOrigContext.Length-1 ) );
+ const sal_Int32 nNewLength( ::std::max(
+ ::std::min(
+ rSubset.mnSubsetEnd - rSubset.mnSubsetBegin,
+ rOrigContext.Length ),
+ sal_Int32( 0 ) ) );
+
+ const rendering::StringContext aContext( rOrigContext.Text,
+ nNewStartPos,
+ nNewLength );
+
+ uno::Reference< rendering::XTextLayout > xTextLayout(
+ rOrigTextLayout->getFont()->createTextLayout( aContext,
+ rOrigTextLayout->getMainTextDirection(),
+ 0 ),
+ uno::UNO_QUERY_THROW );
+
+ return xTextLayout;
+ }
+
+ /** Setup subset text layout
+
+ @param io_rTextLayout
+ Must contain original (full set) text layout on input,
+ will contain subsetted text layout (or empty
+ reference, for empty subsets) on output.
+
+ @param io_rRenderState
+ Must contain original render state on input, will
+ contain shifted render state concatenated with
+ rTransformation on output.
+
+ @param rTransformation
+ Additional transformation, to be prepended to render
+ state
+
+ @param rSubset
+ Subset to prepare
+ */
+ void createSubsetLayout( uno::Reference< rendering::XTextLayout >& io_rTextLayout,
+ rendering::RenderState& io_rRenderState,
+ double& o_rMinPos,
+ double& o_rMaxPos,
+ const ::basegfx::B2DHomMatrix& rTransformation,
+ const Action::Subset& rSubset )
+ {
+ ::canvas::tools::prependToRenderState(io_rRenderState, rTransformation);
+
+ if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
+ {
+ // empty range, empty layout
+ io_rTextLayout.clear();
+
+ return;
+ }
+
+ ENSURE_OR_THROW( io_rTextLayout.is(),
+ "createSubsetLayout(): Invalid input layout" );
+
+ const rendering::StringContext& rOrigContext( io_rTextLayout->getText() );
+
+ if( rSubset.mnSubsetBegin == 0 &&
+ rSubset.mnSubsetEnd == rOrigContext.Length )
+ {
+ // full range, no need for subsetting
+ return;
+ }
+
+ uno::Reference< rendering::XTextLayout > xTextLayout(
+ createSubsetLayout( rOrigContext, rSubset, io_rTextLayout ) );
+
+ if( xTextLayout.is() )
+ {
+ xTextLayout->applyLogicalAdvancements(
+ calcSubsetOffsets( io_rRenderState,
+ o_rMinPos,
+ o_rMaxPos,
+ io_rTextLayout,
+ rSubset ) );
+ }
+
+ io_rTextLayout = xTextLayout;
+ }
+
+
+ /** Interface for renderEffectText functor below.
+
+ This is interface is used from the renderEffectText()
+ method below, to call the client implementation.
+ */
+ class TextRenderer
+ {
+ public:
+ virtual ~TextRenderer() {}
+
+ /// Render text with given RenderState
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const = 0;
+ };
+
+ /** Render effect text.
+
+ @param rRenderer
+ Functor object, will be called to render the actual
+ part of the text effect (the text itself and the means
+ to render it are unknown to this method)
+ */
+ bool renderEffectText( const TextRenderer& rRenderer,
+ const rendering::RenderState& rRenderState,
+ const rendering::ViewState& /*rViewState*/,
+ const uno::Reference< rendering::XCanvas >& xCanvas,
+ const ::Color& rShadowColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rReliefOffset )
+ {
+ ::Color aEmptyColor( COL_AUTO );
+ uno::Reference<rendering::XColorSpace> xColorSpace(
+ xCanvas->getDevice()->getDeviceColorSpace() );
+
+ // draw shadow text, if enabled
+ if( rShadowColor != aEmptyColor )
+ {
+ rendering::RenderState aShadowState( rRenderState );
+ ::basegfx::B2DHomMatrix aTranslate;
+
+ aTranslate.translate( rShadowOffset.getX(),
+ rShadowOffset.getY() );
+
+ ::canvas::tools::appendToRenderState(aShadowState, aTranslate);
+
+ aShadowState.DeviceColor =
+ ::vcl::unotools::colorToDoubleSequence( rShadowColor,
+ xColorSpace );
+
+ rRenderer( aShadowState );
+ }
+
+ // draw relief text, if enabled
+ if( rReliefColor != aEmptyColor )
+ {
+ rendering::RenderState aReliefState( rRenderState );
+ ::basegfx::B2DHomMatrix aTranslate;
+
+ aTranslate.translate( rReliefOffset.getX(),
+ rReliefOffset.getY() );
+
+ ::canvas::tools::appendToRenderState(aReliefState, aTranslate);
+
+ aReliefState.DeviceColor =
+ ::vcl::unotools::colorToDoubleSequence( rReliefColor,
+ xColorSpace );
+
+ rRenderer( aReliefState );
+ }
+
+ // draw normal text
+ rRenderer( rRenderState );
+
+ return true;
+ }
+
+
+ ::basegfx::B2DRange calcEffectTextBounds( const ::basegfx::B2DRange& rTextBounds,
+ const ::basegfx::B2DRange& rLineBounds,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const rendering::RenderState& rRenderState,
+ const rendering::ViewState& rViewState )
+ {
+ ::basegfx::B2DRange aBounds( rTextBounds );
+
+ // add extends of text lines
+ aBounds.expand( rLineBounds );
+
+ // TODO(Q3): Provide this functionality at the B2DRange
+ ::basegfx::B2DRange aTotalBounds( aBounds );
+ aTotalBounds.expand(
+ ::basegfx::B2DRange( aBounds.getMinX() + rReliefOffset.getX(),
+ aBounds.getMinY() + rReliefOffset.getY(),
+ aBounds.getMaxX() + rReliefOffset.getX(),
+ aBounds.getMaxY() + rReliefOffset.getY() ) );
+ aTotalBounds.expand(
+ ::basegfx::B2DRange( aBounds.getMinX() + rShadowOffset.getX(),
+ aBounds.getMinY() + rShadowOffset.getY(),
+ aBounds.getMaxX() + rShadowOffset.getX(),
+ aBounds.getMaxY() + rShadowOffset.getY() ) );
+
+ return tools::calcDevicePixelBounds( aTotalBounds,
+ rViewState,
+ rRenderState );
+ }
+
+ void initEffectLinePolyPolygon( ::basegfx::B2DSize& o_rOverallSize,
+ uno::Reference< rendering::XPolyPolygon2D >& o_rTextLines,
+ const CanvasSharedPtr& rCanvas,
+ const uno::Sequence< double >& rOffsets,
+ const tools::TextLineInfo rLineInfo )
+ {
+ const ::basegfx::B2DPolyPolygon aPoly(
+ textLinesFromLogicalOffsets(
+ rOffsets,
+ rLineInfo ) );
+
+ o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();
+
+ o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aPoly );
+ }
+
+ void initEffectLinePolyPolygon( ::basegfx::B2DSize& o_rOverallSize,
+ uno::Reference< rendering::XPolyPolygon2D >& o_rTextLines,
+ const CanvasSharedPtr& rCanvas,
+ double nLineWidth,
+ const tools::TextLineInfo rLineInfo )
+ {
+ const ::basegfx::B2DPolyPolygon aPoly(
+ tools::createTextLinesPolyPolygon( 0.0, nLineWidth,
+ rLineInfo ) );
+
+ o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();
+
+ o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aPoly );
+ }
+
+
+ // -------------------------------------------------------------------------
+
+ class TextAction : public Action, private ::boost::noncopyable
+ {
+ public:
+ TextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ TextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ // TODO(P2): This is potentially a real mass object
+ // (every character might be a separate TextAction),
+ // thus, make it as lightweight as possible. For
+ // example, share common RenderState among several
+ // TextActions, maybe using maOffsets for the
+ // translation.
+
+ uno::Reference< rendering::XCanvasFont > mxFont;
+ const rendering::StringContext maStringContext;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ const sal_Int8 maTextDirection;
+ };
+
+ TextAction::TextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mxFont( rState.xFont ),
+ maStringContext( rString, nStartPos, nLen ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextDirection( rState.textDirection )
+ {
+ init( maState, mxFont,
+ rStartPoint,
+ rState, rCanvas );
+
+ ENSURE_OR_THROW( mxFont.is(),
+ "::cppcanvas::internal::TextAction(): Invalid font" );
+ }
+
+ TextAction::TextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform ) :
+ mxFont( rState.xFont ),
+ maStringContext( rString, nStartPos, nLen ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextDirection( rState.textDirection )
+ {
+ init( maState, mxFont,
+ rStartPoint,
+ rState, rCanvas, rTextTransform );
+
+ ENSURE_OR_THROW( mxFont.is(),
+ "::cppcanvas::internal::TextAction(): Invalid font" );
+ }
+
+ bool TextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ mpCanvas->getUNOCanvas()->drawText( maStringContext, mxFont,
+ mpCanvas->getViewState(), aLocalState, maTextDirection );
+
+ return true;
+ }
+
+ bool TextAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& /*rSubset*/ ) const
+ {
+ OSL_FAIL( "TextAction::render(): Subset not supported by this object" );
+
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // _subsettable_ text
+ return render( rTransformation );
+ }
+
+ ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ // create XTextLayout, to have the
+ // XTextLayout::queryTextBounds() method available
+ uno::Reference< rendering::XTextLayout > xTextLayout(
+ mxFont->createTextLayout(
+ maStringContext,
+ maTextDirection,
+ 0 ) );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ xTextLayout->queryTextBounds() ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& /*rSubset*/ ) const
+ {
+ OSL_FAIL( "TextAction::getBounds(): Subset not supported by this object" );
+
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // _subsettable_ text
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 TextAction::getActionCount() const
+ {
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // _subsettable_ text
+ return 1;
+ }
+
+
+ // -------------------------------------------------------------------------
+
+ class EffectTextAction :
+ public Action,
+ public TextRenderer,
+ private ::boost::noncopyable
+ {
+ public:
+ EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ /// Interface TextRenderer
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const;
+
+ // TODO(P2): This is potentially a real mass object
+ // (every character might be a separate TextAction),
+ // thus, make it as lightweight as possible. For
+ // example, share common RenderState among several
+ // TextActions, maybe using maOffsets for the
+ // translation.
+
+ uno::Reference< rendering::XCanvasFont > mxFont;
+ const rendering::StringContext maStringContext;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ const tools::TextLineInfo maTextLineInfo;
+ ::basegfx::B2DSize maLinesOverallSize;
+ const double mnLineWidth;
+ uno::Reference< rendering::XPolyPolygon2D > mxTextLines;
+ const ::basegfx::B2DSize maReliefOffset;
+ const ::Color maReliefColor;
+ const ::basegfx::B2DSize maShadowOffset;
+ const ::Color maShadowColor;
+ const sal_Int8 maTextDirection;
+ };
+
+ EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mxFont( rState.xFont ),
+ maStringContext( rText, nStartPos, nLen ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor ),
+ maTextDirection( rState.textDirection )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ mnLineWidth,
+ maTextLineInfo );
+
+ init( maState, mxFont,
+ rStartPoint,
+ rState, rCanvas );
+
+ ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
+ "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
+ }
+
+ EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform ) :
+ mxFont( rState.xFont ),
+ maStringContext( rText, nStartPos, nLen ),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor ),
+ maTextDirection( rState.textDirection )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ mnLineWidth,
+ maTextLineInfo );
+
+ init( maState, mxFont,
+ rStartPoint,
+ rState, rCanvas, rTextTransform );
+
+ ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
+ "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
+ }
+
+ bool EffectTextAction::operator()( const rendering::RenderState& rRenderState ) const
+ {
+ const rendering::ViewState& rViewState( mpCanvas->getViewState() );
+ const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
+
+ rCanvas->fillPolyPolygon( mxTextLines,
+ rViewState,
+ rRenderState );
+
+ rCanvas->drawText( maStringContext, mxFont,
+ rViewState,
+ rRenderState,
+ maTextDirection );
+
+ return true;
+ }
+
+ bool EffectTextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return renderEffectText( *this,
+ aLocalState,
+ mpCanvas->getViewState(),
+ mpCanvas->getUNOCanvas(),
+ maShadowColor,
+ maShadowOffset,
+ maReliefColor,
+ maReliefOffset );
+ }
+
+ bool EffectTextAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& /*rSubset*/ ) const
+ {
+ OSL_FAIL( "EffectTextAction::render(): Subset not supported by this object" );
+
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // subsettable text
+ return render( rTransformation );
+ }
+
+ ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ // create XTextLayout, to have the
+ // XTextLayout::queryTextBounds() method available
+ uno::Reference< rendering::XTextLayout > xTextLayout(
+ mxFont->createTextLayout(
+ maStringContext,
+ maTextDirection,
+ 0 ) );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ xTextLayout->queryTextBounds() ),
+ ::basegfx::B2DRange( 0,0,
+ maLinesOverallSize.getX(),
+ maLinesOverallSize.getY() ),
+ maReliefOffset,
+ maShadowOffset,
+ aLocalState,
+ mpCanvas->getViewState() );
+ }
+
+ ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& /*rSubset*/ ) const
+ {
+ OSL_FAIL( "EffectTextAction::getBounds(): Subset not supported by this object" );
+
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // _subsettable_ text
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 EffectTextAction::getActionCount() const
+ {
+ // TODO(P1): Retrieve necessary font metric info for
+ // TextAction from XCanvas. Currently, the
+ // TextActionFactory does not generate this object for
+ // subsettable text
+ return 1;
+ }
+
+
+ // -------------------------------------------------------------------------
+
+ class TextArrayAction : public Action, private ::boost::noncopyable
+ {
+ public:
+ TextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ TextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ // TODO(P2): This is potentially a real mass object
+ // (every character might be a separate TextAction),
+ // thus, make it as lightweight as possible. For
+ // example, share common RenderState among several
+ // TextActions, maybe using maOffsets for the
+ // translation.
+
+ uno::Reference< rendering::XTextLayout > mxTextLayout;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ };
+
+ TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mxTextLayout(),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ initArrayAction( maState,
+ mxTextLayout,
+ rStartPoint,
+ rString,
+ nStartPos,
+ nLen,
+ rOffsets,
+ rCanvas,
+ rState, NULL );
+ }
+
+ TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::rtl::OUString& rString,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform ) :
+ mxTextLayout(),
+ mpCanvas( rCanvas ),
+ maState()
+ {
+ initArrayAction( maState,
+ mxTextLayout,
+ rStartPoint,
+ rString,
+ nStartPos,
+ nLen,
+ rOffsets,
+ rCanvas,
+ rState,
+ &rTextTransform );
+ }
+
+ bool TextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ mpCanvas->getUNOCanvas()->drawTextLayout( mxTextLayout,
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ bool TextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::render( subset )" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
+
+ double nDummy0, nDummy1;
+ createSubsetLayout( xTextLayout,
+ aLocalState,
+ nDummy0,
+ nDummy1,
+ rTransformation,
+ rSubset );
+
+ if( !xTextLayout.is() )
+ return true; // empty layout, render nothing
+
+ mpCanvas->getUNOCanvas()->drawTextLayout( xTextLayout,
+ mpCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ mxTextLayout->queryTextBounds() ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
+
+ double nDummy0, nDummy1;
+ createSubsetLayout( xTextLayout,
+ aLocalState,
+ nDummy0,
+ nDummy1,
+ rTransformation,
+ rSubset );
+
+ if( !xTextLayout.is() )
+ return ::basegfx::B2DRange(); // empty layout, empty bounds
+
+ return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ xTextLayout->queryTextBounds() ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ sal_Int32 TextArrayAction::getActionCount() const
+ {
+ const rendering::StringContext& rOrigContext( mxTextLayout->getText() );
+
+ return rOrigContext.Length;
+ }
+
+
+ // -------------------------------------------------------------------------
+
+ class EffectTextArrayAction :
+ public Action,
+ public TextRenderer,
+ private ::boost::noncopyable
+ {
+ public:
+ EffectTextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+ EffectTextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ // TextRenderer interface
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const;
+
+ // TODO(P2): This is potentially a real mass object
+ // (every character might be a separate TextAction),
+ // thus, make it as lightweight as possible. For
+ // example, share common RenderState among several
+ // TextActions, maybe using maOffsets for the
+ // translation.
+
+ uno::Reference< rendering::XTextLayout > mxTextLayout;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ const tools::TextLineInfo maTextLineInfo;
+ ::basegfx::B2DSize maLinesOverallSize;
+ uno::Reference< rendering::XPolyPolygon2D > mxTextLines;
+ const ::basegfx::B2DSize maReliefOffset;
+ const ::Color maReliefColor;
+ const ::basegfx::B2DSize maShadowOffset;
+ const ::Color maShadowColor;
+ };
+
+ EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mxTextLayout(),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ rOffsets,
+ maTextLineInfo );
+
+ initArrayAction( maState,
+ mxTextLayout,
+ rStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ rOffsets,
+ rCanvas,
+ rState, NULL );
+ }
+
+ EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::rtl::OUString& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform ) :
+ mxTextLayout(),
+ mpCanvas( rCanvas ),
+ maState(),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ rOffsets,
+ maTextLineInfo );
+
+ initArrayAction( maState,
+ mxTextLayout,
+ rStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ rOffsets,
+ rCanvas,
+ rState,
+ &rTextTransform );
+ }
+
+ bool EffectTextArrayAction::operator()( const rendering::RenderState& rRenderState ) const
+ {
+ const rendering::ViewState& rViewState( mpCanvas->getViewState() );
+ const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
+
+ rCanvas->fillPolyPolygon( mxTextLines,
+ rViewState,
+ rRenderState );
+
+ rCanvas->drawTextLayout( mxTextLayout,
+ rViewState,
+ rRenderState );
+
+ return true;
+ }
+
+ bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return renderEffectText( *this,
+ aLocalState,
+ mpCanvas->getViewState(),
+ mpCanvas->getUNOCanvas(),
+ maShadowColor,
+ maShadowOffset,
+ maReliefColor,
+ maReliefOffset );
+ }
+
+ class EffectTextArrayRenderHelper : public TextRenderer
+ {
+ public:
+ EffectTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >& rCanvas,
+ const uno::Reference< rendering::XTextLayout >& rTextLayout,
+ const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
+ const rendering::ViewState& rViewState ) :
+ mrCanvas( rCanvas ),
+ mrTextLayout( rTextLayout ),
+ mrLinePolygon( rLinePolygon ),
+ mrViewState( rViewState )
+ {
+ }
+
+ // TextRenderer interface
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const
+ {
+ mrCanvas->fillPolyPolygon( mrLinePolygon,
+ mrViewState,
+ rRenderState );
+
+ mrCanvas->drawTextLayout( mrTextLayout,
+ mrViewState,
+ rRenderState );
+
+ return true;
+ }
+
+ private:
+ const uno::Reference< rendering::XCanvas >& mrCanvas;
+ const uno::Reference< rendering::XTextLayout >& mrTextLayout;
+ const uno::Reference< rendering::XPolyPolygon2D >& mrLinePolygon;
+ const rendering::ViewState& mrViewState;
+ };
+
+ bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render( subset )" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
+ const geometry::RealRectangle2D aTextBounds( mxTextLayout->queryTextBounds() );
+
+ double nMinPos(0.0);
+ double nMaxPos(aTextBounds.X2 - aTextBounds.X1);
+
+ createSubsetLayout( xTextLayout,
+ aLocalState,
+ nMinPos,
+ nMaxPos,
+ rTransformation,
+ rSubset );
+
+ if( !xTextLayout.is() )
+ return true; // empty layout, render nothing
+
+
+ // create and setup local line polygon
+ // ===================================
+
+ uno::Reference< rendering::XCanvas > xCanvas( mpCanvas->getUNOCanvas() );
+ const rendering::ViewState& rViewState( mpCanvas->getViewState() );
+
+ uno::Reference< rendering::XPolyPolygon2D > xTextLines(
+ ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ xCanvas->getDevice(),
+ tools::createTextLinesPolyPolygon(
+ 0.0, nMaxPos - nMinPos,
+ maTextLineInfo ) ) );
+
+
+ // render everything
+ // =================
+
+ return renderEffectText(
+ EffectTextArrayRenderHelper( xCanvas,
+ xTextLayout,
+ xTextLines,
+ rViewState ),
+ aLocalState,
+ rViewState,
+ xCanvas,
+ maShadowColor,
+ maShadowOffset,
+ maReliefColor,
+ maReliefOffset );
+ }
+
+ ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ mxTextLayout->queryTextBounds() ),
+ ::basegfx::B2DRange( 0,0,
+ maLinesOverallSize.getX(),
+ maLinesOverallSize.getY() ),
+ maReliefOffset,
+ maShadowOffset,
+ aLocalState,
+ mpCanvas->getViewState() );
+ }
+
+ ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
+ const geometry::RealRectangle2D aTextBounds( mxTextLayout->queryTextBounds() );
+
+ double nMinPos(0.0);
+ double nMaxPos(aTextBounds.X2 - aTextBounds.X1);
+
+ createSubsetLayout( xTextLayout,
+ aLocalState,
+ nMinPos,
+ nMaxPos,
+ rTransformation,
+ rSubset );
+
+ if( !xTextLayout.is() )
+ return ::basegfx::B2DRange(); // empty layout, empty bounds
+
+
+ // create and setup local line polygon
+ // ===================================
+
+ const ::basegfx::B2DPolyPolygon aPoly(
+ tools::createTextLinesPolyPolygon(
+ 0.0, nMaxPos - nMinPos,
+ maTextLineInfo ) );
+
+ return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
+ xTextLayout->queryTextBounds() ),
+ ::basegfx::tools::getRange( aPoly ),
+ maReliefOffset,
+ maShadowOffset,
+ aLocalState,
+ mpCanvas->getViewState() );
+ }
+
+ sal_Int32 EffectTextArrayAction::getActionCount() const
+ {
+ const rendering::StringContext& rOrigContext( mxTextLayout->getText() );
+
+ return rOrigContext.Length;
+ }
+
+
+ // -------------------------------------------------------------------------
+
+ class OutlineAction :
+ public Action,
+ public TextRenderer,
+ private ::boost::noncopyable
+ {
+ public:
+ OutlineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::basegfx::B2DRectangle& rOutlineBounds,
+ const uno::Reference< rendering::XPolyPolygon2D >& rTextPoly,
+ const ::std::vector< sal_Int32 >& rPolygonGlyphMap,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+ OutlineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::basegfx::B2DRectangle& rOutlineBounds,
+ const uno::Reference< rendering::XPolyPolygon2D >& rTextPoly,
+ const ::std::vector< sal_Int32 >& rPolygonGlyphMap,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ // TextRenderer interface
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const;
+
+ // TODO(P2): This is potentially a real mass object
+ // (every character might be a separate TextAction),
+ // thus, make it as lightweight as possible. For
+ // example, share common RenderState among several
+ // TextActions, maybe using maOffsets for the
+ // translation.
+
+ uno::Reference< rendering::XPolyPolygon2D > mxTextPoly;
+
+ /** This vector denotes the index of the start polygon
+ for the respective glyph sequence.
+
+ To get a polygon index range for a given character
+ index i, take [ maPolygonGlyphMap[i],
+ maPolygonGlyphMap[i+1] ). Note that this is wrong
+ for BiDi
+ */
+ const ::std::vector< sal_Int32 > maPolygonGlyphMap;
+ const uno::Sequence< double > maOffsets;
+ const CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ double mnOutlineWidth;
+ const uno::Sequence< double > maFillColor;
+ const tools::TextLineInfo maTextLineInfo;
+ ::basegfx::B2DSize maLinesOverallSize;
+ const ::basegfx::B2DRectangle maOutlineBounds;
+ uno::Reference< rendering::XPolyPolygon2D > mxTextLines;
+ const ::basegfx::B2DSize maReliefOffset;
+ const ::Color maReliefColor;
+ const ::basegfx::B2DSize maShadowOffset;
+ const ::Color maShadowColor;
+ };
+
+ double calcOutlineWidth( const OutDevState& rState,
+ VirtualDevice& rVDev )
+ {
+ const ::basegfx::B2DSize aFontSize( 0,
+ rVDev.GetFont().GetHeight() / 64.0 );
+
+ const double nOutlineWidth(
+ (rState.mapModeTransform * aFontSize).getY() );
+
+ return nOutlineWidth < 1.0 ? 1.0 : nOutlineWidth;
+ }
+
+ OutlineAction::OutlineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::basegfx::B2DRectangle& rOutlineBounds,
+ const uno::Reference< rendering::XPolyPolygon2D >& rTextPoly,
+ const ::std::vector< sal_Int32 >& rPolygonGlyphMap,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mxTextPoly( rTextPoly ),
+ maPolygonGlyphMap( rPolygonGlyphMap ),
+ maOffsets( rOffsets ),
+ mpCanvas( rCanvas ),
+ maState(),
+ mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
+ maFillColor(
+ ::vcl::unotools::colorToDoubleSequence(
+ ::Color( COL_WHITE ),
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ maOutlineBounds( rOutlineBounds ),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ rOffsets,
+ maTextLineInfo );
+
+ init( maState,
+ rStartPoint,
+ rState,
+ rCanvas );
+ }
+
+ OutlineAction::OutlineAction( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::basegfx::B2DRectangle& rOutlineBounds,
+ const uno::Reference< rendering::XPolyPolygon2D >& rTextPoly,
+ const ::std::vector< sal_Int32 >& rPolygonGlyphMap,
+ const uno::Sequence< double >& rOffsets,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const ::basegfx::B2DHomMatrix& rTextTransform ) :
+ mxTextPoly( rTextPoly ),
+ maPolygonGlyphMap( rPolygonGlyphMap ),
+ maOffsets( rOffsets ),
+ mpCanvas( rCanvas ),
+ maState(),
+ mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
+ maFillColor(
+ ::vcl::unotools::colorToDoubleSequence(
+ ::Color( COL_WHITE ),
+ rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
+ maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
+ maLinesOverallSize(),
+ maOutlineBounds( rOutlineBounds ),
+ mxTextLines(),
+ maReliefOffset( rReliefOffset ),
+ maReliefColor( rReliefColor ),
+ maShadowOffset( rShadowOffset ),
+ maShadowColor( rShadowColor )
+ {
+ initEffectLinePolyPolygon( maLinesOverallSize,
+ mxTextLines,
+ rCanvas,
+ rOffsets,
+ maTextLineInfo );
+
+ init( maState,
+ rStartPoint,
+ rState,
+ rCanvas,
+ rTextTransform );
+ }
+
+ bool OutlineAction::operator()( const rendering::RenderState& rRenderState ) const
+ {
+ const rendering::ViewState& rViewState( mpCanvas->getViewState() );
+ const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );
+
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ aStrokeAttributes.StrokeWidth = mnOutlineWidth;
+ aStrokeAttributes.MiterLimit = 1.0;
+ aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
+ aStrokeAttributes.EndCapType = rendering::PathCapType::BUTT;
+ aStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
+
+ rendering::RenderState aLocalState( rRenderState );
+ aLocalState.DeviceColor = maFillColor;
+
+ // TODO(P1): implement caching
+
+ // background of text
+ rCanvas->fillPolyPolygon( mxTextPoly,
+ rViewState,
+ aLocalState );
+
+ // border line of text
+ rCanvas->strokePolyPolygon( mxTextPoly,
+ rViewState,
+ rRenderState,
+ aStrokeAttributes );
+
+ // underlines/strikethrough - background
+ rCanvas->fillPolyPolygon( mxTextLines,
+ rViewState,
+ aLocalState );
+ // underlines/strikethrough - border
+ rCanvas->strokePolyPolygon( mxTextLines,
+ rViewState,
+ rRenderState,
+ aStrokeAttributes );
+
+ return true;
+ }
+
+ bool OutlineAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return renderEffectText( *this,
+ aLocalState,
+ mpCanvas->getViewState(),
+ mpCanvas->getUNOCanvas(),
+ maShadowColor,
+ maShadowOffset,
+ maReliefColor,
+ maReliefOffset );
+ }
+
+ class OutlineTextArrayRenderHelper : public TextRenderer
+ {
+ public:
+ OutlineTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >& rCanvas,
+ const uno::Reference< rendering::XPolyPolygon2D >& rTextPolygon,
+ const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
+ const rendering::ViewState& rViewState,
+ double nOutlineWidth ) :
+ maFillColor(
+ ::vcl::unotools::colorToDoubleSequence(
+ ::Color( COL_WHITE ),
+ rCanvas->getDevice()->getDeviceColorSpace() )),
+ mnOutlineWidth( nOutlineWidth ),
+ mrCanvas( rCanvas ),
+ mrTextPolygon( rTextPolygon ),
+ mrLinePolygon( rLinePolygon ),
+ mrViewState( rViewState )
+ {
+ }
+
+ // TextRenderer interface
+ virtual bool operator()( const rendering::RenderState& rRenderState ) const
+ {
+ rendering::StrokeAttributes aStrokeAttributes;
+
+ aStrokeAttributes.StrokeWidth = mnOutlineWidth;
+ aStrokeAttributes.MiterLimit = 1.0;
+ aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
+ aStrokeAttributes.EndCapType = rendering::PathCapType::BUTT;
+ aStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
+
+ rendering::RenderState aLocalState( rRenderState );
+ aLocalState.DeviceColor = maFillColor;
+
+ // TODO(P1): implement caching
+
+ // background of text
+ mrCanvas->fillPolyPolygon( mrTextPolygon,
+ mrViewState,
+ aLocalState );
+
+ // border line of text
+ mrCanvas->strokePolyPolygon( mrTextPolygon,
+ mrViewState,
+ rRenderState,
+ aStrokeAttributes );
+
+ // underlines/strikethrough - background
+ mrCanvas->fillPolyPolygon( mrLinePolygon,
+ mrViewState,
+ aLocalState );
+ // underlines/strikethrough - border
+ mrCanvas->strokePolyPolygon( mrLinePolygon,
+ mrViewState,
+ rRenderState,
+ aStrokeAttributes );
+
+ return true;
+ }
+
+ private:
+ const uno::Sequence< double > maFillColor;
+ double mnOutlineWidth;
+ const uno::Reference< rendering::XCanvas >& mrCanvas;
+ const uno::Reference< rendering::XPolyPolygon2D >& mrTextPolygon;
+ const uno::Reference< rendering::XPolyPolygon2D >& mrLinePolygon;
+ const rendering::ViewState& mrViewState;
+ };
+
+ bool OutlineAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::OutlineAction::render( subset )" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::OutlineAction: 0x%X", this );
+
+ if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
+ return true; // empty range, render nothing
+
+#if 1
+ // TODO(F3): Subsetting NYI for outline text!
+ return render( rTransformation );
+#else
+ const rendering::StringContext rOrigContext( mxTextLayout->getText() );
+
+ if( rSubset.mnSubsetBegin == 0 &&
+ rSubset.mnSubsetEnd == rOrigContext.Length )
+ {
+ // full range, no need for subsetting
+ return render( rTransformation );
+ }
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+
+ // create and setup local Text polygon
+ // ===================================
+
+ uno::Reference< rendering::XPolyPolygon2D > xTextPolygon();
+
+ // TODO(P3): Provide an API method for that!
+
+ if( !xTextLayout.is() )
+ return false;
+
+ // render everything
+ // =================
+
+ return renderEffectText(
+ OutlineTextArrayRenderHelper(
+ xCanvas,
+ mnOutlineWidth,
+ xTextLayout,
+ xTextLines,
+ rViewState ),
+ aLocalState,
+ rViewState,
+ xCanvas,
+ maShadowColor,
+ maShadowOffset,
+ maReliefColor,
+ maReliefOffset );
+#endif
+ }
+
+ ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return calcEffectTextBounds( maOutlineBounds,
+ ::basegfx::B2DRange( 0,0,
+ maLinesOverallSize.getX(),
+ maLinesOverallSize.getY() ),
+ maReliefOffset,
+ maShadowOffset,
+ aLocalState,
+ mpCanvas->getViewState() );
+ }
+
+ ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& /*rSubset*/ ) const
+ {
+ OSL_FAIL( "OutlineAction::getBounds(): Subset not yet supported by this object" );
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 OutlineAction::getActionCount() const
+ {
+ // TODO(F3): Subsetting NYI for outline text!
+ return maOffsets.getLength();
+ }
+
+
+ // ======================================================================
+ //
+ // Action factory methods
+ //
+ // ======================================================================
+
+ /** Create an outline action
+
+ This method extracts the polygonal outline from the
+ text, and creates a properly setup OutlineAction from
+ it.
+ */
+ ActionSharedPtr createOutline( const ::basegfx::B2DPoint& rStartPoint,
+ const ::basegfx::B2DSize& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::basegfx::B2DSize& rShadowOffset,
+ const ::Color& rShadowColor,
+ const String& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const sal_Int32* pDXArray,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const Renderer::Parameters& rParms )
+ {
+ // operate on raw DX array here (in logical coordinate
+ // system), to have a higher resolution
+ // PolyPolygon. That polygon is then converted to
+ // device coordinate system.
+
+ // #i68512# Temporarily switch off font rotation
+ // (which is already contained in the render state
+ // transformation matrix - otherwise, glyph polygons
+ // will be rotated twice)
+ const ::Font aOrigFont( rVDev.GetFont() );
+ ::Font aUnrotatedFont( aOrigFont );
+ aUnrotatedFont.SetOrientation(0);
+ rVDev.SetFont( aUnrotatedFont );
+
+ // TODO(F3): Don't understand parameter semantics of
+ // GetTextOutlines()
+ ::basegfx::B2DPolyPolygon aResultingPolyPolygon;
+ PolyPolyVector aVCLPolyPolyVector;
+ const bool bHaveOutlines( rVDev.GetTextOutlines( aVCLPolyPolyVector, rText,
+ static_cast<sal_uInt16>(nStartPos),
+ static_cast<sal_uInt16>(nStartPos),
+ static_cast<sal_uInt16>(nLen),
+ sal_True, 0, pDXArray ) );
+ rVDev.SetFont(aOrigFont);
+
+ if( !bHaveOutlines )
+ return ActionSharedPtr();
+
+ ::std::vector< sal_Int32 > aPolygonGlyphMap;
+
+ // first glyph starts at polygon index 0
+ aPolygonGlyphMap.push_back( 0 );
+
+ // remove offsetting from mapmode transformation
+ // (outline polygons must stay at origin, only need to
+ // be scaled)
+ ::basegfx::B2DHomMatrix aMapModeTransform(
+ rState.mapModeTransform );
+ aMapModeTransform.set(0,2, 0.0);
+ aMapModeTransform.set(1,2, 0.0);
+
+ PolyPolyVector::const_iterator aIter( aVCLPolyPolyVector.begin() );
+ const PolyPolyVector::const_iterator aEnd( aVCLPolyPolyVector.end() );
+ for( ; aIter!= aEnd; ++aIter )
+ {
+ ::basegfx::B2DPolyPolygon aPolyPolygon;
+
+ aPolyPolygon = aIter->getB2DPolyPolygon();
+ aPolyPolygon.transform( aMapModeTransform );
+
+ // append result to collecting polypoly
+ for( sal_uInt32 i=0; i<aPolyPolygon.count(); ++i )
+ {
+ // #i47795# Ensure closed polygons (since
+ // FreeType returns the glyph outlines
+ // open)
+ const ::basegfx::B2DPolygon& rPoly( aPolyPolygon.getB2DPolygon( i ) );
+ const sal_uInt32 nCount( rPoly.count() );
+ if( nCount<3 ||
+ rPoly.isClosed() )
+ {
+ // polygon either degenerate, or
+ // already closed.
+ aResultingPolyPolygon.append( rPoly );
+ }
+ else
+ {
+ ::basegfx::B2DPolygon aPoly(rPoly);
+ aPoly.setClosed(true);
+
+ aResultingPolyPolygon.append( aPoly );
+ }
+ }
+
+ // TODO(F3): Depending on the semantics of
+ // GetTextOutlines(), this here is wrong!
+
+ // calc next glyph index
+ aPolygonGlyphMap.push_back( aResultingPolyPolygon.count() );
+ }
+
+ const uno::Sequence< double > aCharWidthSeq(
+ pDXArray ?
+ setupDXArray( pDXArray, nLen, rState ) :
+ setupDXArray( rText,
+ nStartPos,
+ nLen,
+ rVDev,
+ rState ));
+ const uno::Reference< rendering::XPolyPolygon2D > xTextPoly(
+ ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ aResultingPolyPolygon ) );
+
+ if( rParms.maTextTransformation.is_initialized() )
+ {
+ return ActionSharedPtr(
+ new OutlineAction(
+ rStartPoint,
+ rReliefOffset,
+ rReliefColor,
+ rShadowOffset,
+ rShadowColor,
+ ::basegfx::tools::getRange(aResultingPolyPolygon),
+ xTextPoly,
+ aPolygonGlyphMap,
+ aCharWidthSeq,
+ rVDev,
+ rCanvas,
+ rState,
+ *rParms.maTextTransformation ) );
+ }
+ else
+ {
+ return ActionSharedPtr(
+ new OutlineAction(
+ rStartPoint,
+ rReliefOffset,
+ rReliefColor,
+ rShadowOffset,
+ rShadowColor,
+ ::basegfx::tools::getRange(aResultingPolyPolygon),
+ xTextPoly,
+ aPolygonGlyphMap,
+ aCharWidthSeq,
+ rVDev,
+ rCanvas,
+ rState ) );
+ }
+ }
+
+ } // namespace
+
+
+ // ---------------------------------------------------------------------------------
+
+ ActionSharedPtr TextActionFactory::createTextAction( const ::Point& rStartPoint,
+ const ::Size& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::Size& rShadowOffset,
+ const ::Color& rShadowColor,
+ const String& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const sal_Int32* pDXArray,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const Renderer::Parameters& rParms,
+ bool bSubsettable )
+ {
+ const ::Size aBaselineOffset( tools::getBaselineOffset( rState,
+ rVDev ) );
+ // #143885# maintain (nearly) full precision positioning,
+ // by circumventing integer-based OutDev-mapping
+ const ::basegfx::B2DPoint aStartPoint(
+ rState.mapModeTransform *
+ ::basegfx::B2DPoint(rStartPoint.X() + aBaselineOffset.Width(),
+ rStartPoint.Y() + aBaselineOffset.Height()) );
+
+ const ::basegfx::B2DSize aReliefOffset(
+ rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rReliefOffset ) );
+ const ::basegfx::B2DSize aShadowOffset(
+ rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rShadowOffset ) );
+
+ if( rState.isTextOutlineModeSet )
+ {
+ return createOutline(
+ aStartPoint,
+ aReliefOffset,
+ rReliefColor,
+ aShadowOffset,
+ rShadowColor,
+ rText,
+ nStartPos,
+ nLen,
+ pDXArray,
+ rVDev,
+ rCanvas,
+ rState,
+ rParms );
+ }
+
+ // convert DX array to device coordinate system (and
+ // create it in the first place, if pDXArray is NULL)
+ const uno::Sequence< double > aCharWidths(
+ pDXArray ?
+ setupDXArray( pDXArray, nLen, rState ) :
+ setupDXArray( rText,
+ nStartPos,
+ nLen,
+ rVDev,
+ rState ));
+
+ // determine type of text action to create
+ // =======================================
+
+ const ::Color aEmptyColor( COL_AUTO );
+
+ // no DX array, and no need to subset - no need to store
+ // DX array, then.
+ if( !pDXArray && !bSubsettable )
+ {
+ // effects, or not?
+ if( !rState.textOverlineStyle &&
+ !rState.textUnderlineStyle &&
+ !rState.textStrikeoutStyle &&
+ rReliefColor == aEmptyColor &&
+ rShadowColor == aEmptyColor )
+ {
+ // nope
+ if( rParms.maTextTransformation.is_initialized() )
+ {
+ return ActionSharedPtr( new TextAction(
+ aStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ rCanvas,
+ rState,
+ *rParms.maTextTransformation ) );
+ }
+ else
+ {
+ return ActionSharedPtr( new TextAction(
+ aStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ rCanvas,
+ rState ) );
+ }
+ }
+ else
+ {
+ // at least one of the effects requested
+ if( rParms.maTextTransformation.is_initialized() )
+ return ActionSharedPtr( new EffectTextAction(
+ aStartPoint,
+ aReliefOffset,
+ rReliefColor,
+ aShadowOffset,
+ rShadowColor,
+ rText,
+ nStartPos,
+ nLen,
+ rVDev,
+ rCanvas,
+ rState,
+ *rParms.maTextTransformation ) );
+ else
+ return ActionSharedPtr( new EffectTextAction(
+ aStartPoint,
+ aReliefOffset,
+ rReliefColor,
+ aShadowOffset,
+ rShadowColor,
+ rText,
+ nStartPos,
+ nLen,
+ rVDev,
+ rCanvas,
+ rState ) );
+ }
+ }
+ else
+ {
+ // DX array necessary - any effects?
+ if( !rState.textOverlineStyle &&
+ !rState.textUnderlineStyle &&
+ !rState.textStrikeoutStyle &&
+ rReliefColor == aEmptyColor &&
+ rShadowColor == aEmptyColor )
+ {
+ // nope
+ if( rParms.maTextTransformation.is_initialized() )
+ return ActionSharedPtr( new TextArrayAction(
+ aStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ aCharWidths,
+ rCanvas,
+ rState,
+ *rParms.maTextTransformation ) );
+ else
+ return ActionSharedPtr( new TextArrayAction(
+ aStartPoint,
+ rText,
+ nStartPos,
+ nLen,
+ aCharWidths,
+ rCanvas,
+ rState ) );
+ }
+ else
+ {
+ // at least one of the effects requested
+ if( rParms.maTextTransformation.is_initialized() )
+ return ActionSharedPtr( new EffectTextArrayAction(
+ aStartPoint,
+ aReliefOffset,
+ rReliefColor,
+ aShadowOffset,
+ rShadowColor,
+ rText,
+ nStartPos,
+ nLen,
+ aCharWidths,
+ rVDev,
+ rCanvas,
+ rState,
+ *rParms.maTextTransformation ) );
+ else
+ return ActionSharedPtr( new EffectTextArrayAction(
+ aStartPoint,
+ aReliefOffset,
+ rReliefColor,
+ aShadowOffset,
+ rShadowColor,
+ rText,
+ nStartPos,
+ nLen,
+ aCharWidths,
+ rVDev,
+ rCanvas,
+ rState ) );
+ }
+ }
+#if defined __GNUC__
+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 1
+ // Unreachable; to avoid bogus warning:
+ return ActionSharedPtr();
+#endif
+#endif
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/textaction.hxx b/cppcanvas/source/mtfrenderer/textaction.hxx
new file mode 100644
index 000000000000..390752d23ce1
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/textaction.hxx
@@ -0,0 +1,105 @@
+/* -*- 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 _CPPCANVAS_TEXTACTION_HXX
+#define _CPPCANVAS_TEXTACTION_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <action.hxx>
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/renderer.hxx>
+#include <tools/poly.hxx>
+#include <tools/gen.hxx>
+
+class VirtualDevice;
+class Point;
+class Color;
+class String;
+
+
+/* Definition of internal::TextActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ /** Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class TextActionFactory
+ {
+ public:
+ /** Create text action, optionally shadow/relief effect
+
+ Note that this method accepts all coordinates in
+ logical coordinates.
+
+ @param pDXArray
+ Pointer to array of logical character offsets (or NULL)
+
+ @param bSubsettable
+ When this parameter is set to true, the generated
+ action might consume slightly more memory, but is
+ subsettable (Action::render( Subset ) works on
+ characters)
+ */
+ static ActionSharedPtr createTextAction( const ::Point& rStartPoint,
+ const ::Size& rReliefOffset,
+ const ::Color& rReliefColor,
+ const ::Size& rShadowOffset,
+ const ::Color& rShadowColor,
+ const ::String& rText,
+ sal_Int32 nStartPos,
+ sal_Int32 nLen,
+ const sal_Int32* pDXArray,
+ VirtualDevice& rVDev,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState,
+ const Renderer::Parameters& rParms,
+ bool bSubsettable );
+
+ private:
+ // static factory, disable big four
+ TextActionFactory();
+ ~TextActionFactory();
+ TextActionFactory(const TextActionFactory&);
+ TextActionFactory& operator=( const TextActionFactory& );
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_TEXTACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx
new file mode 100644
index 000000000000..8c671889280d
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx
@@ -0,0 +1,578 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <tools/gen.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <rtl/logfile.hxx>
+
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <rtl/math.hxx>
+
+#include <vcl/metaact.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/gradient.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/utility.hpp>
+
+#include "transparencygroupaction.hxx"
+#include "outdevstate.hxx"
+#include "mtftools.hxx"
+#include "cppcanvas/vclfactory.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ // free support functions
+ // ======================
+ namespace
+ {
+ class TransparencyGroupAction : public Action, private ::boost::noncopyable
+ {
+ public:
+ /** Create new transparency group action.
+
+ @param rGroupMtf
+ Metafile that groups all actions to be rendered
+ transparent
+
+ @param rParms
+ Render parameters
+
+ @param rDstPoint
+ Left, top edge of destination, in current state
+ coordinate system
+
+ @param rDstSize
+ Size of the transparency group object, in current
+ state coordinate system.
+
+ @param nAlpha
+ Alpha value, must be in the range [0,1]
+ */
+ TransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ double nAlpha,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ /** Create new transparency group action.
+
+ @param rGroupMtf
+ Metafile that groups all actions to be rendered
+ transparent.
+
+ @param rAlphaGradient
+ VCL gradient, to be rendered into the action's alpha
+ channel.
+
+ @param rParms
+ Render parameters
+
+ @param rDstPoint
+ Left, top edge of destination, in current state
+ coordinate system
+
+ @param rDstSize
+ Size of the transparency group object, in current
+ state coordinate system.
+ */
+ TransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ GradientAutoPtr& rAlphaGradient,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
+ virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const;
+
+ virtual sal_Int32 getActionCount() const;
+
+ private:
+ MtfAutoPtr mpGroupMtf;
+ GradientAutoPtr mpAlphaGradient;
+
+ const Renderer::Parameters maParms;
+
+ const ::basegfx::B2DSize maDstSize;
+
+ mutable uno::Reference< rendering::XBitmap > mxBufferBitmap; // contains last rendered version
+ mutable ::basegfx::B2DHomMatrix maLastTransformation; // contains last active transformation
+ mutable Subset maLastSubset; // contains last effective subset
+
+ // transformation for
+ // mxBufferBitmap content
+ CanvasSharedPtr mpCanvas;
+ rendering::RenderState maState;
+ const double mnAlpha;
+ };
+
+
+ /** Setup transformation such that the next render call is
+ moved rPoint away, and scaled according to the ratio
+ given by src and dst size.
+ */
+ void implSetupTransform( rendering::RenderState& rRenderState,
+ const ::basegfx::B2DPoint& rDstPoint )
+ {
+ ::basegfx::B2DHomMatrix aLocalTransformation;
+
+ aLocalTransformation.translate( rDstPoint.getX(),
+ rDstPoint.getY() );
+ ::canvas::tools::appendToRenderState( rRenderState,
+ aLocalTransformation );
+ }
+
+ TransparencyGroupAction::TransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ double nAlpha,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mpGroupMtf( rGroupMtf ),
+ mpAlphaGradient(),
+ maParms( rParms ),
+ maDstSize( rDstSize ),
+ mxBufferBitmap(),
+ maLastTransformation(),
+ mpCanvas( rCanvas ),
+ maState(),
+ mnAlpha( nAlpha )
+ {
+ tools::initRenderState(maState,rState);
+ implSetupTransform( maState, rDstPoint );
+
+ // correct clip (which is relative to original transform)
+ tools::modifyClip( maState,
+ rState,
+ rCanvas,
+ rDstPoint,
+ NULL,
+ NULL );
+
+ maLastSubset.mnSubsetBegin = 0;
+ maLastSubset.mnSubsetEnd = -1;
+ }
+
+ TransparencyGroupAction::TransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ GradientAutoPtr& rAlphaGradient,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState ) :
+ mpGroupMtf( rGroupMtf ),
+ mpAlphaGradient( rAlphaGradient ),
+ maParms( rParms ),
+ maDstSize( rDstSize ),
+ mxBufferBitmap(),
+ maLastTransformation(),
+ mpCanvas( rCanvas ),
+ maState(),
+ mnAlpha( 1.0 )
+ {
+ tools::initRenderState(maState,rState);
+ implSetupTransform( maState, rDstPoint );
+
+ // correct clip (which is relative to original transform)
+ tools::modifyClip( maState,
+ rState,
+ rCanvas,
+ rDstPoint,
+ NULL,
+ NULL );
+
+ maLastSubset.mnSubsetBegin = 0;
+ maLastSubset.mnSubsetEnd = -1;
+ }
+
+ // TODO(P3): The whole float transparency handling is a mess,
+ // this should be refactored. What's more, the old idea of
+ // having only internal 'metaactions', and not the original
+ // GDIMetaFile now looks a lot less attractive. Try to move
+ // into the direction of having a direct GDIMetaFile2XCanvas
+ // renderer, and maybe a separate metafile XCanvas
+ // implementation.
+ bool TransparencyGroupAction::render( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TransparencyGroupAction::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TransparencyGroupAction: 0x%X", this );
+
+ // determine overall transformation matrix (render, view,
+ // and passed transformation)
+ ::basegfx::B2DHomMatrix aTransform;
+ ::canvas::tools::getRenderStateTransform( aTransform, maState );
+ aTransform = rTransformation * aTransform;
+
+ ::basegfx::B2DHomMatrix aTotalTransform;
+ ::canvas::tools::getViewStateTransform( aTotalTransform, mpCanvas->getViewState() );
+ aTotalTransform = aTotalTransform * aTransform;
+
+ // since pure translational changes to the transformation
+ // does not matter, remove them before comparing
+ aTotalTransform.set( 0, 2, 0.0 );
+ aTotalTransform.set( 1, 2, 0.0 );
+
+ // if there's no buffer bitmap, or as soon as the
+ // total transformation changes, we've got to
+ // re-render the bitmap
+ if( !mxBufferBitmap.is() ||
+ aTotalTransform != maLastTransformation ||
+ rSubset.mnSubsetBegin != maLastSubset.mnSubsetBegin ||
+ rSubset.mnSubsetEnd != maLastSubset.mnSubsetEnd )
+ {
+ DBG_TESTSOLARMUTEX();
+
+ // determine total scaling factor of the
+ // transformation matrix - need to make the bitmap
+ // large enough
+ ::basegfx::B2DTuple aScale;
+ ::basegfx::B2DTuple aTranslate;
+ double nRotate;
+ double nShearX;
+ if( !aTotalTransform.decompose( aScale,
+ aTranslate,
+ nRotate,
+ nShearX ) )
+ {
+ OSL_FAIL( "TransparencyGroupAction::render(): non-decomposable transformation" );
+ return false;
+ }
+
+ // output size of metafile
+ ::Size aOutputSizePixel( ::basegfx::fround( aScale.getX() * maDstSize.getX() ),
+ ::basegfx::fround( aScale.getY() * maDstSize.getY() ) );
+
+ // pixel size of cache bitmap: round up to nearest int
+ ::Size aBitmapSizePixel( static_cast<sal_Int32>( aScale.getX() * maDstSize.getX() )+1,
+ static_cast<sal_Int32>( aScale.getY() * maDstSize.getY() )+1 );
+
+ ::Point aEmptyPoint;
+
+ // render our content into an appropriately sized
+ // VirtualDevice with alpha channel
+ VirtualDevice aVDev(
+ *::Application::GetDefaultDevice(), 0, 0 );
+ aVDev.SetOutputSizePixel( aBitmapSizePixel );
+ aVDev.SetMapMode();
+
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != -1 )
+ {
+ // true subset - extract referenced
+ // metaactions from mpGroupMtf
+ GDIMetaFile aMtf;
+ MetaAction* pCurrAct;
+ int nCurrActionIndex;
+
+ // extract subset actions
+ for( nCurrActionIndex=0,
+ pCurrAct=mpGroupMtf->FirstAction();
+ pCurrAct;
+ ++nCurrActionIndex, pCurrAct = mpGroupMtf->NextAction() )
+ {
+ switch( pCurrAct->GetType() )
+ {
+ case META_PUSH_ACTION:
+ case META_POP_ACTION:
+ case META_CLIPREGION_ACTION:
+ case META_ISECTRECTCLIPREGION_ACTION:
+ case META_ISECTREGIONCLIPREGION_ACTION:
+ case META_MOVECLIPREGION_ACTION:
+ case META_LINECOLOR_ACTION:
+ case META_FILLCOLOR_ACTION:
+ case META_TEXTCOLOR_ACTION:
+ case META_TEXTFILLCOLOR_ACTION:
+ case META_TEXTLINECOLOR_ACTION:
+ case META_TEXTALIGN_ACTION:
+ case META_FONT_ACTION:
+ case META_RASTEROP_ACTION:
+ case META_REFPOINT_ACTION:
+ case META_LAYOUTMODE_ACTION:
+ // state-changing action - copy as-is
+ aMtf.AddAction( pCurrAct->Clone() );
+ break;
+
+ case META_GRADIENT_ACTION:
+ case META_HATCH_ACTION:
+ case META_EPS_ACTION:
+ case META_COMMENT_ACTION:
+ case META_POINT_ACTION:
+ case META_PIXEL_ACTION:
+ case META_LINE_ACTION:
+ case META_RECT_ACTION:
+ case META_ROUNDRECT_ACTION:
+ case META_ELLIPSE_ACTION:
+ case META_ARC_ACTION:
+ case META_PIE_ACTION:
+ case META_CHORD_ACTION:
+ case META_POLYLINE_ACTION:
+ case META_POLYGON_ACTION:
+ case META_POLYPOLYGON_ACTION:
+ case META_BMP_ACTION:
+ case META_BMPSCALE_ACTION:
+ case META_BMPSCALEPART_ACTION:
+ case META_BMPEX_ACTION:
+ case META_BMPEXSCALE_ACTION:
+ case META_BMPEXSCALEPART_ACTION:
+ case META_MASK_ACTION:
+ case META_MASKSCALE_ACTION:
+ case META_MASKSCALEPART_ACTION:
+ case META_GRADIENTEX_ACTION:
+ case META_WALLPAPER_ACTION:
+ case META_TRANSPARENT_ACTION:
+ case META_FLOATTRANSPARENT_ACTION:
+ case META_TEXT_ACTION:
+ case META_TEXTARRAY_ACTION:
+ case META_TEXTLINE_ACTION:
+ case META_TEXTRECT_ACTION:
+ case META_STRETCHTEXT_ACTION:
+ // output-generating action - only
+ // copy, if we're within the
+ // requested subset
+ if( rSubset.mnSubsetBegin <= nCurrActionIndex &&
+ rSubset.mnSubsetEnd > nCurrActionIndex )
+ {
+ aMtf.AddAction( pCurrAct->Clone() );
+ }
+ break;
+
+ default:
+ OSL_FAIL( "Unknown meta action type encountered" );
+ break;
+ }
+ }
+
+ aVDev.DrawTransparent( aMtf,
+ aEmptyPoint,
+ aOutputSizePixel,
+ *mpAlphaGradient );
+ }
+ else
+ {
+ // no subsetting - render whole mtf
+ aVDev.DrawTransparent( *mpGroupMtf,
+ aEmptyPoint,
+ aOutputSizePixel,
+ *mpAlphaGradient );
+ }
+
+
+ // update buffered bitmap and transformation
+ BitmapSharedPtr aBmp( VCLFactory::getInstance().createBitmap(
+ mpCanvas,
+ aVDev.GetBitmapEx(
+ aEmptyPoint,
+ aBitmapSizePixel ) ) );
+ mxBufferBitmap = aBmp->getUNOBitmap();
+ maLastTransformation = aTotalTransform;
+ maLastSubset = rSubset;
+ }
+
+ // determine target transformation (we can't simply pass
+ // aTotalTransform as assembled above, since we must take
+ // the canvas' view state as is, it might contain clipping
+ // (which, in turn, is relative to the view
+ // transformation))
+
+ // given that aTotalTransform is the identity
+ // transformation, we could simply render our bitmap
+ // as-is. Now, since the mxBufferBitmap content already
+ // accounts for scale changes in the overall
+ // transformation, we must factor this out
+ // before. Generally, the transformation matrix should be
+ // structured like this:
+ // Translation*Rotation*Shear*Scale. Thus, to neutralize
+ // the contained scaling, we've got to right-multiply with
+ // the inverse.
+ ::basegfx::B2ISize aBmpSize(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBufferBitmap->getSize() ) );
+
+ ::basegfx::B2DHomMatrix aScaleCorrection;
+ aScaleCorrection.scale( (double)maDstSize.getX() / aBmpSize.getX(),
+ (double)maDstSize.getY() / aBmpSize.getY() );
+ aTransform = aTransform * aScaleCorrection;
+
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::setRenderStateTransform(aLocalState, aTransform);
+
+ if( ::rtl::math::approxEqual(mnAlpha, 1.0) )
+ {
+ // no further alpha changes necessary -> draw directly
+ mpCanvas->getUNOCanvas()->drawBitmap( mxBufferBitmap,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+ else
+ {
+ // add alpha modulation value to DeviceColor
+ uno::Sequence<rendering::ARGBColor> aCols(1);
+ aCols[0] = rendering::ARGBColor( mnAlpha, 1.0, 1.0, 1.0);
+ aLocalState.DeviceColor =
+ mpCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace()->convertFromARGB(
+ aCols);
+
+ mpCanvas->getUNOCanvas()->drawBitmapModulated( mxBufferBitmap,
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ return true;
+ }
+
+ // TODO(P3): The whole float transparency handling is a mess,
+ // this should be refactored. What's more, the old idea of
+ // having only internal 'metaactions', and not the original
+ // GDIMetaFile now looks a lot less attractive. Try to move
+ // into the direction of having a direct GDIMetaFile2XCanvas
+ // renderer, and maybe a separate metafile XCanvas
+ // implementation.
+ bool TransparencyGroupAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ Subset aSubset;
+
+ aSubset.mnSubsetBegin = 0;
+ aSubset.mnSubsetEnd = -1;
+
+ return render( rTransformation, aSubset );
+ }
+
+ ::basegfx::B2DRange TransparencyGroupAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
+ {
+ rendering::RenderState aLocalState( maState );
+ ::canvas::tools::prependToRenderState(aLocalState, rTransformation);
+
+ return tools::calcDevicePixelBounds(
+ ::basegfx::B2DRange( 0,0,
+ maDstSize.getX(),
+ maDstSize.getY() ),
+ mpCanvas->getViewState(),
+ aLocalState );
+ }
+
+ ::basegfx::B2DRange TransparencyGroupAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation,
+ const Subset& rSubset ) const
+ {
+ // TODO(F3): Currently, the bounds for
+ // TransparencyGroupAction subsets equal those of the
+ // full set, although this action is able to render
+ // true subsets.
+
+ // polygon only contains a single action, empty bounds
+ // if subset requests different range
+ if( rSubset.mnSubsetBegin != 0 ||
+ rSubset.mnSubsetEnd != 1 )
+ return ::basegfx::B2DRange();
+
+ return getBounds( rTransformation );
+ }
+
+ sal_Int32 TransparencyGroupAction::getActionCount() const
+ {
+ return mpGroupMtf.get() ? mpGroupMtf->GetActionCount() : 0;
+ }
+
+ }
+
+ ActionSharedPtr TransparencyGroupActionFactory::createTransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ double nAlpha,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new TransparencyGroupAction(rGroupMtf,
+ rParms,
+ rDstPoint,
+ rDstSize,
+ nAlpha,
+ rCanvas,
+ rState ) );
+ }
+
+ ActionSharedPtr TransparencyGroupActionFactory::createTransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ GradientAutoPtr& rAlphaGradient,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState )
+ {
+ return ActionSharedPtr( new TransparencyGroupAction(rGroupMtf,
+ rAlphaGradient,
+ rParms,
+ rDstPoint,
+ rDstSize,
+ rCanvas,
+ rState ) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/transparencygroupaction.hxx b/cppcanvas/source/mtfrenderer/transparencygroupaction.hxx
new file mode 100644
index 000000000000..dd629011cfa2
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/transparencygroupaction.hxx
@@ -0,0 +1,143 @@
+/* -*- 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 _CPPCANVAS_TRANSPARENCYGROUPACTION_HXX
+#define _CPPCANVAS_TRANSPARENCYGROUPACTION_HXX
+
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/renderer.hxx>
+#include <action.hxx>
+
+#include <memory> // auto_ptr
+
+namespace basegfx {
+ class B2DPoint;
+ class B2DVector;
+}
+
+class GDIMetaFile;
+class Gradient;
+
+
+/* Definition of internal::TransparencyGroupActionFactory class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ struct OutDevState;
+
+ typedef ::std::auto_ptr< GDIMetaFile > MtfAutoPtr;
+ typedef ::std::auto_ptr< Gradient > GradientAutoPtr;
+
+ /** Transparency group action.
+
+ This action groups a bunch of other actions, to be
+ rendered with the given transparency setting against the
+ background.
+
+ Creates encapsulated converters between GDIMetaFile and
+ XCanvas. The Canvas argument is deliberately placed at the
+ constructor, to force reconstruction of this object for a
+ new canvas. This considerably eases internal state
+ handling, since a lot of the internal state (e.g. fonts,
+ text layout) is Canvas-dependent.
+ */
+ class TransparencyGroupActionFactory
+ {
+ public:
+ /** Create new transparency group action.
+
+ @param rGroupMtf
+ Metafile that groups all actions to be rendered
+ transparent
+
+ @param rParms
+ Render parameters
+
+ @param rDstPoint
+ Left, top edge of destination, in current state
+ coordinate system
+
+ @param rDstSize
+ Size of the transparency group object, in current
+ state coordinate system.
+
+ @param nAlpha
+ Alpha value, must be in the range [0,1]
+ */
+ static ActionSharedPtr createTransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ double nAlpha,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ /** Create new transparency group action.
+
+ @param rGroupMtf
+ Metafile that groups all actions to be rendered
+ transparent.
+
+ @param rAlphaGradient
+ VCL gradient, to be rendered into the action's alpha
+ channel.
+
+ @param rParms
+ Render parameters
+
+ @param rDstPoint
+ Left, top edge of destination, in current state
+ coordinate system
+
+ @param rDstSize
+ Size of the transparency group object, in current
+ state coordinate system.
+ */
+ static ActionSharedPtr createTransparencyGroupAction( MtfAutoPtr& rGroupMtf,
+ GradientAutoPtr& rAlphaGradient,
+ const Renderer::Parameters& rParms,
+ const ::basegfx::B2DPoint& rDstPoint,
+ const ::basegfx::B2DVector& rDstSize,
+ const CanvasSharedPtr& rCanvas,
+ const OutDevState& rState );
+
+ private:
+ // static factory, disable big four
+ TransparencyGroupActionFactory();
+ ~TransparencyGroupActionFactory();
+ TransparencyGroupActionFactory(const TransparencyGroupActionFactory&);
+ TransparencyGroupActionFactory& operator=( const TransparencyGroupActionFactory& );
+ };
+ }
+}
+
+#endif /*_CPPCANVAS_TRANSPARENCYGROUPACTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/tools/canvasgraphichelper.cxx b/cppcanvas/source/tools/canvasgraphichelper.cxx
new file mode 100644
index 000000000000..4888960c0d96
--- /dev/null
+++ b/cppcanvas/source/tools/canvasgraphichelper.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <canvasgraphichelper.hxx>
+
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+
+#include <canvas/canvastools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <cppcanvas/polypolygon.hxx>
+#include "tools.hxx"
+
+
+using namespace ::com::sun::star;
+
+/* Implementation of CanvasGraphicHelper class */
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+ CanvasGraphicHelper::CanvasGraphicHelper( const CanvasSharedPtr& rParentCanvas ) :
+ maClipPolyPolygon(),
+ mpCanvas( rParentCanvas ),
+ mxGraphicDevice()
+ {
+ OSL_ENSURE( mpCanvas.get() != NULL &&
+ mpCanvas->getUNOCanvas().is(),
+ "CanvasGraphicHelper::CanvasGraphicHelper: no valid canvas" );
+
+ if( mpCanvas.get() != NULL &&
+ mpCanvas->getUNOCanvas().is() )
+ {
+ mxGraphicDevice = mpCanvas->getUNOCanvas()->getDevice();
+ }
+
+ ::canvas::tools::initRenderState( maRenderState );
+ }
+
+ void CanvasGraphicHelper::setTransformation( const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ ::canvas::tools::setRenderStateTransform( maRenderState, rMatrix );
+ }
+
+ ::basegfx::B2DHomMatrix CanvasGraphicHelper::getTransformation() const
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+ return ::canvas::tools::getRenderStateTransform( aMatrix,
+ maRenderState );
+ }
+
+ void CanvasGraphicHelper::setClip( const ::basegfx::B2DPolyPolygon& rClipPoly )
+ {
+ // TODO(T3): not thread-safe. B2DPolyPolygon employs copy-on-write
+ maClipPolyPolygon.reset( rClipPoly );
+ maRenderState.Clip.clear();
+ }
+
+ void CanvasGraphicHelper::setClip()
+ {
+ maClipPolyPolygon.reset();
+ maRenderState.Clip.clear();
+ }
+
+ ::basegfx::B2DPolyPolygon const* CanvasGraphicHelper::getClip() const
+ {
+ return !maClipPolyPolygon ? NULL : &(*maClipPolyPolygon);
+ }
+
+ const rendering::RenderState& CanvasGraphicHelper::getRenderState() const
+ {
+ if( maClipPolyPolygon && !maRenderState.Clip.is() )
+ {
+ uno::Reference< rendering::XCanvas > xCanvas( mpCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return maRenderState;
+
+ maRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ xCanvas->getDevice(),
+ *maClipPolyPolygon );
+ }
+
+ return maRenderState;
+ }
+
+ void CanvasGraphicHelper::setRGBAColor( Color::IntSRGBA aColor )
+ {
+ maRenderState.DeviceColor = tools::intSRGBAToDoubleSequence( mxGraphicDevice,
+ aColor );
+ }
+
+ Color::IntSRGBA CanvasGraphicHelper::getRGBAColor() const
+ {
+ return tools::doubleSequenceToIntSRGBA( mxGraphicDevice,
+ maRenderState.DeviceColor );
+ }
+
+ void CanvasGraphicHelper::setCompositeOp( CompositeOp aOp )
+ {
+ maRenderState.CompositeOperation = (sal_Int8)aOp;
+ }
+
+ CanvasGraphic::CompositeOp CanvasGraphicHelper::getCompositeOp() const
+ {
+ return static_cast<CompositeOp>(maRenderState.CompositeOperation);
+ }
+
+ CanvasSharedPtr CanvasGraphicHelper::getCanvas() const
+ {
+ return mpCanvas;
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasGraphicHelper::getGraphicDevice() const
+ {
+ return mxGraphicDevice;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/tools/makefile.mk b/cppcanvas/source/tools/makefile.mk
new file mode 100644
index 000000000000..ee543616f6e0
--- /dev/null
+++ b/cppcanvas/source/tools/makefile.mk
@@ -0,0 +1,50 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General 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=cppcanvas
+TARGET=cppcanvastools
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+SLOFILES = $(SLO)$/canvasgraphichelper.obj \
+ $(SLO)$/tools.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/cppcanvas/source/tools/tools.cxx b/cppcanvas/source/tools/tools.cxx
new file mode 100644
index 000000000000..bea26d8e55e8
--- /dev/null
+++ b/cppcanvas/source/tools/tools.cxx
@@ -0,0 +1,65 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <tools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace tools
+ {
+ uno::Sequence< double > intSRGBAToDoubleSequence( const uno::Reference< rendering::XGraphicDevice >&,
+ Color::IntSRGBA aColor )
+ {
+ uno::Sequence< double > aRes( 4 );
+
+ aRes[0] = getRed(aColor) / 255.0;
+ aRes[1] = getGreen(aColor) / 255.0;
+ aRes[2] = getBlue(aColor) / 255.0;
+ aRes[3] = getAlpha(aColor) / 255.0;
+
+ return aRes;
+ }
+
+ Color::IntSRGBA doubleSequenceToIntSRGBA( const uno::Reference< rendering::XGraphicDevice >&,
+ const uno::Sequence< double >& rColor )
+ {
+ return makeColor( static_cast<sal_uInt8>( 255*rColor[0] + .5 ),
+ static_cast<sal_uInt8>( 255*rColor[1] + .5 ),
+ static_cast<sal_uInt8>( 255*rColor[2] + .5 ),
+ static_cast<sal_uInt8>( 255*rColor[3] + .5 ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/uno/exports.dxp b/cppcanvas/source/uno/exports.dxp
new file mode 100644
index 000000000000..f0e1c69934bc
--- /dev/null
+++ b/cppcanvas/source/uno/exports.dxp
@@ -0,0 +1,2 @@
+component_getImplementationEnvironment
+component_getFactory
diff --git a/cppcanvas/source/uno/exports.map b/cppcanvas/source/uno/exports.map
new file mode 100644
index 000000000000..a488d5d06a43
--- /dev/null
+++ b/cppcanvas/source/uno/exports.map
@@ -0,0 +1,8 @@
+UDK_3_0_0 {
+ global:
+_ZTI*; _ZTS*; # weak RTTI symbols for C++ exceptions
+ component_getImplementationEnvironment;
+ component_getFactory;
+ local:
+ *;
+};
diff --git a/cppcanvas/source/uno/makefile.mk b/cppcanvas/source/uno/makefile.mk
new file mode 100644
index 000000000000..5e06f4f1c839
--- /dev/null
+++ b/cppcanvas/source/uno/makefile.mk
@@ -0,0 +1,70 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2010 Novell, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General 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=cppcanvas
+TARGET=mtfrenderer
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+SLOFILES = $(SLO)$/uno_mtfrenderer.obj
+
+SHL1TARGET=$(TARGET).uno
+
+SHL1STDLIBS= $(SALLIB) $(CPPULIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(CPPCANVASLIB) $(BASEGFXLIB)
+
+SHL1IMPLIB=i$(TARGET)
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1VERSIONMAP=exports.map
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+# ==========================================================================
+
+.INCLUDE : target.mk
+
+$(MISC)/mtfrenderer.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \
+ mtfrenderer.component
+ $(XSLTPROC) --nonet --stringparam uri \
+ '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \
+ $(SOLARENV)/bin/createcomponent.xslt mtfrenderer.component
+
+ALLTAR : $(MISC)/mtfrenderer.component
diff --git a/cppcanvas/source/uno/mtfrenderer.component b/cppcanvas/source/uno/mtfrenderer.component
new file mode 100644
index 000000000000..32284e46cd74
--- /dev/null
+++ b/cppcanvas/source/uno/mtfrenderer.component
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component loader="com.sun.star.loader.SharedLibrary"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.rendering.MtfRenderer">
+ <service name="com.sun.star.rendering.MtfRenderer"/>
+ </implementation>
+</component>
diff --git a/cppcanvas/source/uno/uno_mtfrenderer.cxx b/cppcanvas/source/uno/uno_mtfrenderer.cxx
new file mode 100644
index 000000000000..2c525140c1da
--- /dev/null
+++ b/cppcanvas/source/uno/uno_mtfrenderer.cxx
@@ -0,0 +1,83 @@
+/* -*- 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 2010 Novell, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "uno_mtfrenderer.hxx"
+#include <cppcanvas/vclfactory.hxx>
+#include <comphelper/servicedecl.hxx>
+#include <cppuhelper/factory.hxx>
+
+using namespace ::com::sun::star;
+
+void MtfRenderer::setMetafile (const uno::Sequence< sal_Int8 >& /*rMtf*/) throw (uno::RuntimeException)
+{
+ // printf ("MtfRenderer::setMetafile unimplemented, use fast property set or implement me\n");
+}
+
+void MtfRenderer::draw (double fScaleX, double fScaleY) throw (uno::RuntimeException)
+{
+ if (mpMetafile && mxCanvas.get()) {
+ cppcanvas::VCLFactory& factory = cppcanvas::VCLFactory::getInstance();
+ cppcanvas::BitmapCanvasSharedPtr canvas = factory.createCanvas (mxCanvas);
+ cppcanvas::RendererSharedPtr renderer = factory.createRenderer (canvas, *mpMetafile, cppcanvas::Renderer::Parameters ());
+ ::basegfx::B2DHomMatrix aMatrix;
+ aMatrix.scale( fScaleX, fScaleY );
+ canvas->setTransformation( aMatrix );
+ renderer->draw ();
+ }
+}
+
+void MtfRenderer::setFastPropertyValue( sal_Int32 nHandle, const uno::Any& aAny) throw (uno::RuntimeException)
+{
+ if (nHandle == 0) {
+ mpMetafile = (GDIMetaFile*) *reinterpret_cast<const sal_Int64*>(aAny.getValue());
+ }
+}
+
+MtfRenderer::MtfRenderer (uno::Sequence<uno::Any> const& aArgs, uno::Reference<uno::XComponentContext> const&) : MtfRendererBase (m_aMutex), mpMetafile (NULL)
+{
+ if( aArgs.getLength() == 1 ) {
+ aArgs[0] >>= mxCanvas;
+ }
+}
+
+namespace sdecl = comphelper::service_decl;
+#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+ sdecl::class_<MtfRenderer, sdecl::with_args<true> > serviceImpl;
+ const sdecl::ServiceDecl MtfRendererDecl(
+ serviceImpl,
+#else
+ const sdecl::ServiceDecl MtfRendererDecl(
+ sdecl::class_<MtfRenderer, sdecl::with_args<true> >(),
+#endif
+ "com.sun.star.comp.rendering.MtfRenderer",
+ "com.sun.star.rendering.MtfRenderer" );
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(MtfRendererDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/uno/uno_mtfrenderer.hxx b/cppcanvas/source/uno/uno_mtfrenderer.hxx
new file mode 100644
index 000000000000..e462c6732cc4
--- /dev/null
+++ b/cppcanvas/source/uno/uno_mtfrenderer.hxx
@@ -0,0 +1,63 @@
+/* -*- 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 2010 Novell, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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 _UNO_MTF_RENDERER_HXX_
+#define _UNO_MTF_RENDERER_HXX_
+#include <com/sun/star/rendering/MtfRenderer.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <vcl/gdimtf.hxx>
+
+typedef cppu::WeakComponentImplHelper2<com::sun::star::rendering::XMtfRenderer, com::sun::star::beans::XFastPropertySet> MtfRendererBase;
+
+class MtfRenderer : private cppu::BaseMutex, public MtfRendererBase
+{
+public:
+ MtfRenderer (com::sun::star::uno::Sequence<com::sun::star::uno::Any> const& args,
+ com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&);
+
+ // XMtfRenderer iface
+ void SAL_CALL setMetafile (const ::com::sun::star::uno::Sequence< sal_Int8 >& rMtf) throw (::com::sun::star::uno::RuntimeException);
+ void SAL_CALL draw (double fScaleX, double fScaleY) throw (::com::sun::star::uno::RuntimeException);
+
+ // XFastPropertySet
+ // setFastPropertyValue (0, GDIMetaFile*) is used to speedup the rendering
+ virtual ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 /*nHandle*/) throw (::com::sun::star::uno::RuntimeException) { return ::com::sun::star::uno::Any(); }
+ virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const ::com::sun::star::uno::Any&) throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ GDIMetaFile* mpMetafile;
+ com::sun::star::uno::Reference<com::sun::star::rendering::XBitmapCanvas> mxCanvas;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/basegfxfactory.cxx b/cppcanvas/source/wrapper/basegfxfactory.cxx
new file mode 100644
index 000000000000..c65a4216b522
--- /dev/null
+++ b/cppcanvas/source/wrapper/basegfxfactory.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_cppcanvas.hxx"
+
+#include <rtl/instance.hxx>
+#include <osl/getglobalmutex.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/rendering/InterpolationMode.hpp>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include "implpolypolygon.hxx"
+#include "implbitmap.hxx"
+#include "impltext.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ /* Singleton handling */
+ struct InitInstance2
+ {
+ BaseGfxFactory* operator()()
+ {
+ return new BaseGfxFactory();
+ }
+ };
+
+ BaseGfxFactory& BaseGfxFactory::getInstance()
+ {
+ return *rtl_Instance< BaseGfxFactory, InitInstance2, ::osl::MutexGuard,
+ ::osl::GetGlobalMutex >::create(
+ InitInstance2(), ::osl::GetGlobalMutex());
+ }
+
+ BaseGfxFactory::BaseGfxFactory()
+ {
+ }
+
+ BaseGfxFactory::~BaseGfxFactory()
+ {
+ }
+
+ PolyPolygonSharedPtr BaseGfxFactory::createPolyPolygon( const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DPolygon& rPoly ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "BaseGfxFactory::createPolyPolygon(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return PolyPolygonSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return PolyPolygonSharedPtr();
+
+ return PolyPolygonSharedPtr(
+ new internal::ImplPolyPolygon( rCanvas,
+ ::basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ xCanvas->getDevice(),
+ rPoly) ) );
+ }
+
+ PolyPolygonSharedPtr BaseGfxFactory::createPolyPolygon( const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DPolyPolygon& rPolyPoly ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "BaseGfxFactory::createPolyPolygon(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return PolyPolygonSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return PolyPolygonSharedPtr();
+
+ return PolyPolygonSharedPtr(
+ new internal::ImplPolyPolygon( rCanvas,
+ ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ xCanvas->getDevice(),
+ rPolyPoly) ) );
+ }
+
+ BitmapSharedPtr BaseGfxFactory::createBitmap( const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2ISize& rSize ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "BaseGfxFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr(
+ new internal::ImplBitmap( rCanvas,
+ xCanvas->getDevice()->createCompatibleBitmap(
+ ::basegfx::unotools::integerSize2DFromB2ISize(rSize) ) ) );
+ }
+
+ BitmapSharedPtr BaseGfxFactory::createAlphaBitmap( const CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2ISize& rSize ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "BaseGfxFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr(
+ new internal::ImplBitmap( rCanvas,
+ xCanvas->getDevice()->createCompatibleAlphaBitmap(
+ ::basegfx::unotools::integerSize2DFromB2ISize(rSize) ) ) );
+ }
+
+ TextSharedPtr BaseGfxFactory::createText( const CanvasSharedPtr& rCanvas, const ::rtl::OUString& rText ) const
+ {
+ return TextSharedPtr( new internal::ImplText( rCanvas,
+ rText ) );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implbitmap.cxx b/cppcanvas/source/wrapper/implbitmap.cxx
new file mode 100644
index 000000000000..bf00e0f673c6
--- /dev/null
+++ b/cppcanvas/source/wrapper/implbitmap.cxx
@@ -0,0 +1,129 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include "implbitmap.hxx"
+#include "implbitmapcanvas.hxx"
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <canvas/canvastools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+
+ ImplBitmap::ImplBitmap( const CanvasSharedPtr& rParentCanvas,
+ const uno::Reference< rendering::XBitmap >& rBitmap ) :
+ CanvasGraphicHelper( rParentCanvas ),
+ mxBitmap( rBitmap ),
+ mpBitmapCanvas()
+ {
+ OSL_ENSURE( mxBitmap.is(), "ImplBitmap::ImplBitmap: no valid bitmap" );
+
+ uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( rBitmap,
+ uno::UNO_QUERY );
+ if( xBitmapCanvas.is() )
+ mpBitmapCanvas.reset( new ImplBitmapCanvas(
+ uno::Reference< rendering::XBitmapCanvas >(rBitmap,
+ uno::UNO_QUERY) ) );
+ }
+
+ ImplBitmap::~ImplBitmap()
+ {
+ }
+
+ bool ImplBitmap::draw() const
+ {
+ CanvasSharedPtr pCanvas( getCanvas() );
+
+ OSL_ENSURE( pCanvas.get() != NULL &&
+ pCanvas->getUNOCanvas().is(),
+ "ImplBitmap::draw: invalid canvas" );
+
+ if( pCanvas.get() == NULL ||
+ !pCanvas->getUNOCanvas().is() )
+ {
+ return false;
+ }
+
+ // TODO(P1): implement caching
+ pCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
+ pCanvas->getViewState(),
+ getRenderState() );
+
+ return true;
+ }
+
+ bool ImplBitmap::drawAlphaModulated( double nAlphaModulation ) const
+ {
+ CanvasSharedPtr pCanvas( getCanvas() );
+
+ OSL_ENSURE( pCanvas.get() != NULL &&
+ pCanvas->getUNOCanvas().is(),
+ "ImplBitmap::drawAlphaModulated(): invalid canvas" );
+
+ if( pCanvas.get() == NULL ||
+ !pCanvas->getUNOCanvas().is() )
+ {
+ return false;
+ }
+
+ rendering::RenderState aLocalState( getRenderState() );
+ uno::Sequence<rendering::ARGBColor> aCol(1);
+ aCol[0] = rendering::ARGBColor( nAlphaModulation, 1.0, 1.0, 1.0 );
+ aLocalState.DeviceColor =
+ pCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace()->convertFromARGB(aCol);
+
+ // TODO(P1): implement caching
+ pCanvas->getUNOCanvas()->drawBitmapModulated( mxBitmap,
+ pCanvas->getViewState(),
+ aLocalState );
+
+ return true;
+ }
+
+ BitmapCanvasSharedPtr ImplBitmap::getBitmapCanvas() const
+ {
+ return mpBitmapCanvas;
+ }
+
+ uno::Reference< rendering::XBitmap > ImplBitmap::getUNOBitmap() const
+ {
+ return mxBitmap;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implbitmap.hxx b/cppcanvas/source/wrapper/implbitmap.hxx
new file mode 100644
index 000000000000..c27d095d1888
--- /dev/null
+++ b/cppcanvas/source/wrapper/implbitmap.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 _CPPCANVAS_IMPLBITMAP_HXX
+#define _CPPCANVAS_IMPLBITMAP_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+
+#include <cppcanvas/bitmap.hxx>
+#include <canvasgraphichelper.hxx>
+
+
+/*Definition of ImplBitmap */
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+ // share partial CanvasGraphic implementation from CanvasGraphicHelper
+ class ImplBitmap : public virtual ::cppcanvas::Bitmap, protected CanvasGraphicHelper
+ {
+ public:
+
+ ImplBitmap( const CanvasSharedPtr& rParentCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& rBitmap );
+
+ virtual ~ImplBitmap();
+
+ // CanvasGraphic implementation (that was not already implemented by CanvasGraphicHelper)
+ virtual bool draw() const;
+ virtual bool drawAlphaModulated( double nAlphaModulation ) const;
+
+ virtual BitmapCanvasSharedPtr getBitmapCanvas() const;
+
+ // Bitmap implementation
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > getUNOBitmap() const;
+
+ private:
+ // default: disabled copy/assignment
+ ImplBitmap(const ImplBitmap&);
+ ImplBitmap& operator=( const ImplBitmap& );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > mxBitmap;
+ BitmapCanvasSharedPtr mpBitmapCanvas;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implbitmapcanvas.cxx b/cppcanvas/source/wrapper/implbitmapcanvas.cxx
new file mode 100644
index 000000000000..6aa08a9334d0
--- /dev/null
+++ b/cppcanvas/source/wrapper/implbitmapcanvas.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include "implbitmapcanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ ImplBitmapCanvas::ImplBitmapCanvas( const uno::Reference< rendering::XBitmapCanvas >& rCanvas ) :
+ ImplCanvas( uno::Reference< rendering::XCanvas >(rCanvas,
+ uno::UNO_QUERY) ),
+ mxBitmapCanvas( rCanvas ),
+ mxBitmap( rCanvas,
+ uno::UNO_QUERY )
+ {
+ OSL_ENSURE( mxBitmapCanvas.is(), "ImplBitmapCanvas::ImplBitmapCanvas(): Invalid canvas" );
+ OSL_ENSURE( mxBitmap.is(), "ImplBitmapCanvas::ImplBitmapCanvas(): Invalid bitmap" );
+ }
+
+ ImplBitmapCanvas::~ImplBitmapCanvas()
+ {
+ }
+
+ ::basegfx::B2ISize ImplBitmapCanvas::getSize() const
+ {
+ OSL_ENSURE( mxBitmap.is(), "ImplBitmapCanvas::getSize(): Invalid canvas" );
+ return ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBitmap->getSize() );
+ }
+
+ CanvasSharedPtr ImplBitmapCanvas::clone() const
+ {
+ return BitmapCanvasSharedPtr( new ImplBitmapCanvas( *this ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implbitmapcanvas.hxx b/cppcanvas/source/wrapper/implbitmapcanvas.hxx
new file mode 100644
index 000000000000..5b1b625630a0
--- /dev/null
+++ b/cppcanvas/source/wrapper/implbitmapcanvas.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLBITMAPCANVAS_HXX
+#define _CPPCANVAS_IMPLBITMAPCANVAS_HXX
+
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2dsize.hxx>
+#include <cppcanvas/bitmapcanvas.hxx>
+
+#include <implcanvas.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ // share Canvas implementation from ImplCanvas
+ class ImplBitmapCanvas : public virtual BitmapCanvas, protected virtual ImplCanvas
+ {
+ public:
+ ImplBitmapCanvas( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmapCanvas >& rCanvas );
+ virtual ~ImplBitmapCanvas();
+
+ virtual ::basegfx::B2ISize getSize() const;
+
+ virtual CanvasSharedPtr clone() const;
+
+ // take compiler-provided default copy constructor
+ //ImplBitmapCanvas(const ImplBitmapCanvas&);
+
+ private:
+ // default: disabled assignment
+ ImplBitmapCanvas& operator=( const ImplBitmapCanvas& );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > mxBitmapCanvas;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > mxBitmap;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLBITMAPCANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcanvas.cxx b/cppcanvas/source/wrapper/implcanvas.cxx
new file mode 100644
index 000000000000..2fb6debc0eae
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcanvas.cxx
@@ -0,0 +1,144 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <rtl/ustring.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/polypolygon.hxx>
+
+#include "implfont.hxx"
+#include "implcolor.hxx"
+#include "implcanvas.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ ImplCanvas::ImplCanvas( const uno::Reference< rendering::XCanvas >& xCanvas ) :
+ maViewState(),
+ maClipPolyPolygon(),
+ mxCanvas( xCanvas )
+ {
+ OSL_ENSURE( mxCanvas.is(), "Canvas::Canvas() invalid XCanvas" );
+
+ ::canvas::tools::initViewState( maViewState );
+ }
+
+ ImplCanvas::~ImplCanvas()
+ {
+ }
+
+ void ImplCanvas::setTransformation( const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ ::canvas::tools::setViewStateTransform( maViewState, rMatrix );
+ }
+
+ ::basegfx::B2DHomMatrix ImplCanvas::getTransformation() const
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+ return ::canvas::tools::getViewStateTransform( aMatrix,
+ maViewState );
+ }
+
+ void ImplCanvas::setClip( const ::basegfx::B2DPolyPolygon& rClipPoly )
+ {
+ // TODO(T3): not thread-safe. B2DPolyPolygon employs copy-on-write
+ maClipPolyPolygon.reset( rClipPoly );
+ maViewState.Clip.clear();
+ }
+
+ void ImplCanvas::setClip()
+ {
+ maClipPolyPolygon.reset();
+ maViewState.Clip.clear();
+ }
+
+ ::basegfx::B2DPolyPolygon const* ImplCanvas::getClip() const
+ {
+ return !maClipPolyPolygon ? NULL : &(*maClipPolyPolygon);
+ }
+
+ FontSharedPtr ImplCanvas::createFont( const ::rtl::OUString& rFontName, const double& rCellSize ) const
+ {
+ return FontSharedPtr( new ImplFont( getUNOCanvas(), rFontName, rCellSize ) );
+ }
+
+ ColorSharedPtr ImplCanvas::createColor() const
+ {
+ return ColorSharedPtr( new ImplColor( getUNOCanvas()->getDevice() ) );
+ }
+
+ CanvasSharedPtr ImplCanvas::clone() const
+ {
+ return CanvasSharedPtr( new ImplCanvas( *this ) );
+ }
+
+ void ImplCanvas::clear() const
+ {
+ OSL_ENSURE( mxCanvas.is(), "ImplCanvas::clear(): Invalid XCanvas" );
+ mxCanvas->clear();
+ }
+
+ uno::Reference< rendering::XCanvas > ImplCanvas::getUNOCanvas() const
+ {
+ OSL_ENSURE( mxCanvas.is(), "ImplCanvas::getUNOCanvas(): Invalid XCanvas" );
+
+ return mxCanvas;
+ }
+
+ rendering::ViewState ImplCanvas::getViewState() const
+ {
+ if( maClipPolyPolygon && !maViewState.Clip.is() )
+ {
+ if( !mxCanvas.is() )
+ return maViewState;
+
+ maViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ *maClipPolyPolygon );
+ }
+
+ return maViewState;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcanvas.hxx b/cppcanvas/source/wrapper/implcanvas.hxx
new file mode 100644
index 000000000000..481a5541441c
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcanvas.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLCANVAS_HXX
+#define _CPPCANVAS_IMPLCANVAS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/ViewState.hpp>
+#include <cppcanvas/canvas.hxx>
+
+#include <boost/optional.hpp>
+
+namespace rtl
+{
+ class OUString;
+}
+
+namespace basegfx
+{
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvas;
+} } } }
+
+
+/* Definition of ImplCanvas */
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+
+ class ImplCanvas : public virtual Canvas
+ {
+ public:
+ ImplCanvas( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& rCanvas );
+ virtual ~ImplCanvas();
+
+ virtual void setTransformation( const ::basegfx::B2DHomMatrix& rMatrix );
+ virtual ::basegfx::B2DHomMatrix getTransformation() const;
+
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly );
+ virtual void setClip();
+ virtual ::basegfx::B2DPolyPolygon const* getClip() const;
+
+ virtual FontSharedPtr createFont( const ::rtl::OUString& rFontName, const double& rCellSize ) const;
+
+ virtual ColorSharedPtr createColor() const;
+
+ virtual CanvasSharedPtr clone() const;
+
+ virtual void clear() const;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas > getUNOCanvas() const;
+
+ virtual ::com::sun::star::rendering::ViewState getViewState() const;
+
+ // take compiler-provided default copy constructor
+ //ImplCanvas(const ImplCanvas&);
+
+ private:
+ // default: disabled assignment
+ ImplCanvas& operator=( const ImplCanvas& );
+
+ mutable ::com::sun::star::rendering::ViewState maViewState;
+ boost::optional<basegfx::B2DPolyPolygon> maClipPolyPolygon;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > mxCanvas;
+ };
+
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLCANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcolor.cxx b/cppcanvas/source/wrapper/implcolor.cxx
new file mode 100644
index 000000000000..c474deee2420
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcolor.cxx
@@ -0,0 +1,71 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <implcolor.hxx>
+#include <tools.hxx>
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ ImplColor::ImplColor( const uno::Reference< rendering::XGraphicDevice >& rDevice ) :
+ mxDevice( rDevice )
+ {
+ OSL_ENSURE( mxDevice.is(), "ImplColor::ImplColor(): Invalid graphic device" );
+ }
+
+ ImplColor::~ImplColor()
+ {
+ }
+
+ Color::IntSRGBA ImplColor::getIntSRGBA( uno::Sequence< double >& rDeviceColor ) const
+ {
+ OSL_ENSURE( mxDevice.is(), "ImplColor::getIntSRGBA(): Invalid graphic device" );
+
+ // TODO(F1): Color space handling
+ return tools::doubleSequenceToIntSRGBA( mxDevice, rDeviceColor );
+ }
+
+ uno::Sequence< double > ImplColor::getDeviceColor( Color::IntSRGBA aSRGBA ) const
+ {
+ OSL_ENSURE( mxDevice.is(), "ImplColor::getDeviceColor(): Invalid graphic device" );
+
+ // TODO(F1): Color space handling
+ return tools::intSRGBAToDoubleSequence( mxDevice, aSRGBA );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcolor.hxx b/cppcanvas/source/wrapper/implcolor.hxx
new file mode 100644
index 000000000000..3bc47da73d01
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcolor.hxx
@@ -0,0 +1,65 @@
+/* -*- 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 _CPPCANVAS_IMPLCOLOR_HXX
+#define _CPPCANVAS_IMPLCOLOR_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <cppcanvas/color.hxx>
+
+
+/* Definition of Color class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ class ImplColor : public Color
+ {
+ public:
+ ImplColor( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& rDevice );
+ virtual ~ImplColor();
+
+ virtual IntSRGBA getIntSRGBA( ::com::sun::star::uno::Sequence< double >& rDeviceColor ) const;
+ virtual ::com::sun::star::uno::Sequence< double > getDeviceColor( IntSRGBA aSRGBA ) const;
+
+ private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice > mxDevice;
+ };
+
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLCOLOR_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcustomsprite.cxx b/cppcanvas/source/wrapper/implcustomsprite.cxx
new file mode 100644
index 000000000000..e41e728e40ce
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcustomsprite.cxx
@@ -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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "implcustomsprite.hxx"
+#include "implcanvas.hxx"
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ ImplCustomSprite::ImplCustomSprite( const uno::Reference< rendering::XSpriteCanvas >& rParentCanvas,
+ const uno::Reference< rendering::XCustomSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
+ ImplSprite( rParentCanvas,
+ uno::Reference< rendering::XSprite >(rSprite,
+ uno::UNO_QUERY),
+ rTransformArbiter ),
+ mpLastCanvas(),
+ mxCustomSprite( rSprite )
+ {
+ OSL_ENSURE( rParentCanvas.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid canvas" );
+ OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::ImplCustomSprite(): Invalid sprite" );
+ }
+
+ ImplCustomSprite::~ImplCustomSprite()
+ {
+ }
+
+ CanvasSharedPtr ImplCustomSprite::getContentCanvas() const
+ {
+ OSL_ENSURE( mxCustomSprite.is(), "ImplCustomSprite::getContentCanvas(): Invalid sprite" );
+
+ if( !mxCustomSprite.is() )
+ return CanvasSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( mxCustomSprite->getContentCanvas() );
+
+ if( !xCanvas.is() )
+ return CanvasSharedPtr();
+
+ // cache content canvas C++ wrapper
+ if( mpLastCanvas.get() == NULL ||
+ mpLastCanvas->getUNOCanvas() != xCanvas )
+ {
+ mpLastCanvas = CanvasSharedPtr( new ImplCanvas( xCanvas ) );
+ }
+
+ return mpLastCanvas;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implcustomsprite.hxx b/cppcanvas/source/wrapper/implcustomsprite.hxx
new file mode 100644
index 000000000000..fe40c017b83c
--- /dev/null
+++ b/cppcanvas/source/wrapper/implcustomsprite.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLCUSTOMSPRITE_HXX
+#define _CPPCANVAS_IMPLCUSTOMSPRITE_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/customsprite.hxx>
+
+#include <implsprite.hxx>
+#include <implspritecanvas.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ // share Sprite implementation of ImplSprite
+ class ImplCustomSprite : public virtual CustomSprite, protected virtual ImplSprite
+ {
+ public:
+ ImplCustomSprite( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas >& rParentCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCustomSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter );
+ virtual ~ImplCustomSprite();
+
+ virtual CanvasSharedPtr getContentCanvas() const;
+
+ private:
+ // default: disabled copy/assignment
+ ImplCustomSprite(const ImplCustomSprite&);
+ ImplCustomSprite& operator=( const ImplCustomSprite& );
+
+ mutable CanvasSharedPtr mpLastCanvas;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCustomSprite > mxCustomSprite;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLCUSTOMSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implfont.cxx b/cppcanvas/source/wrapper/implfont.cxx
new file mode 100644
index 000000000000..b466cfabd068
--- /dev/null
+++ b/cppcanvas/source/wrapper/implfont.cxx
@@ -0,0 +1,94 @@
+/* -*- 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_cppcanvas.hxx"
+
+#include <implfont.hxx>
+#include <canvas/canvastools.hxx>
+
+
+using namespace ::com::sun::star;
+
+/* Definition of Font class */
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ ImplFont::ImplFont( const uno::Reference< rendering::XCanvas >& rCanvas,
+ const ::rtl::OUString& rFontName,
+ const double& rCellSize ) :
+ mxCanvas( rCanvas ),
+ mxFont( NULL )
+ {
+ OSL_ENSURE( mxCanvas.is(), "ImplFont::ImplFont(): Invalid Canvas" );
+
+ rendering::FontRequest aFontRequest;
+ aFontRequest.FontDescription.FamilyName = rFontName;
+ aFontRequest.CellSize = rCellSize;
+
+ geometry::Matrix2D aFontMatrix;
+ ::canvas::tools::setIdentityMatrix2D( aFontMatrix );
+
+ mxFont = mxCanvas->createFont( aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ aFontMatrix );
+ }
+
+
+ ImplFont::~ImplFont()
+ {
+ }
+
+ ::rtl::OUString ImplFont::getName() const
+ {
+ OSL_ENSURE( mxFont.is(), "ImplFont::getName(): Invalid Font" );
+
+ return mxFont->getFontRequest().FontDescription.FamilyName;
+ }
+
+ double ImplFont::getCellSize() const
+ {
+ OSL_ENSURE( mxFont.is(), "ImplFont::getCellSize(): Invalid Font" );
+
+ return mxFont->getFontRequest().CellSize;
+ }
+
+ uno::Reference< rendering::XCanvasFont > ImplFont::getUNOFont() const
+ {
+ OSL_ENSURE( mxFont.is(), "ImplFont::getUNOFont(): Invalid Font" );
+
+ return mxFont;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implfont.hxx b/cppcanvas/source/wrapper/implfont.hxx
new file mode 100644
index 000000000000..589bab707e84
--- /dev/null
+++ b/cppcanvas/source/wrapper/implfont.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLFONT_HXX
+#define _CPPCANVAS_IMPLFONT_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <cppcanvas/font.hxx>
+
+namespace rtl
+{
+ class OUString;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvasFont;
+} } } }
+
+/* Definition of Font class */
+
+namespace cppcanvas
+{
+
+ namespace internal
+ {
+
+ class ImplFont : public Font
+ {
+ public:
+ ImplFont( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvas >& rCanvas,
+ const ::rtl::OUString& rFontName,
+ const double& rCellSize );
+
+ virtual ~ImplFont();
+
+ virtual ::rtl::OUString getName() const;
+ virtual double getCellSize() const;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont > getUNOFont() const;
+
+ private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > mxCanvas;
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > mxFont;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLFONT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implpolypolygon.cxx b/cppcanvas/source/wrapper/implpolypolygon.cxx
new file mode 100644
index 000000000000..ac1fa728378c
--- /dev/null
+++ b/cppcanvas/source/wrapper/implpolypolygon.cxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include "implpolypolygon.hxx"
+#include "tools.hxx"
+
+
+using namespace ::com::sun::star;
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ ImplPolyPolygon::ImplPolyPolygon( const CanvasSharedPtr& rParentCanvas,
+ const uno::Reference< rendering::XPolyPolygon2D >& rPolyPoly ) :
+ CanvasGraphicHelper( rParentCanvas ),
+ mxPolyPoly( rPolyPoly ),
+ maStrokeAttributes(1.0,
+ 10.0,
+ uno::Sequence< double >(),
+ uno::Sequence< double >(),
+ rendering::PathCapType::ROUND,
+ rendering::PathCapType::ROUND,
+ rendering::PathJoinType::ROUND ),
+ maFillColor(),
+ maStrokeColor(),
+ mbFillColorSet( false ),
+ mbStrokeColorSet( false )
+ {
+ OSL_ENSURE( mxPolyPoly.is(), "PolyPolygonImpl::PolyPolygonImpl: no valid polygon" );
+ }
+
+ ImplPolyPolygon::~ImplPolyPolygon()
+ {
+ }
+
+ void ImplPolyPolygon::addPolygon( const ::basegfx::B2DPolygon& rPoly )
+ {
+ OSL_ENSURE( mxPolyPoly.is(),
+ "ImplPolyPolygon::addPolygon(): Invalid polygon" );
+
+ if( !mxPolyPoly.is() )
+ return;
+
+ uno::Reference< rendering::XGraphicDevice > xDevice( getGraphicDevice() );
+
+ OSL_ENSURE( xDevice.is(),
+ "ImplPolyPolygon::addPolygon(): Invalid graphic device" );
+
+ if( !xDevice.is() )
+ return;
+
+ mxPolyPoly->addPolyPolygon( geometry::RealPoint2D(0.0, 0.0),
+ ::basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ xDevice,
+ rPoly) );
+ }
+
+ void ImplPolyPolygon::addPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
+ {
+ OSL_ENSURE( mxPolyPoly.is(),
+ "ImplPolyPolygon::addPolyPolygon(): Invalid polygon" );
+
+ if( !mxPolyPoly.is() )
+ return;
+
+ uno::Reference< rendering::XGraphicDevice > xDevice( getGraphicDevice() );
+
+ OSL_ENSURE( xDevice.is(),
+ "ImplPolyPolygon::addPolyPolygon(): Invalid graphic device" );
+
+ if( !xDevice.is() )
+ return;
+
+ mxPolyPoly->addPolyPolygon( geometry::RealPoint2D(0.0, 0.0),
+ ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ xDevice,
+ rPoly) );
+ }
+
+ void ImplPolyPolygon::setRGBAFillColor( Color::IntSRGBA aColor )
+ {
+ maFillColor = tools::intSRGBAToDoubleSequence( getGraphicDevice(),
+ aColor );
+ mbFillColorSet = true;
+ }
+
+ void ImplPolyPolygon::setRGBALineColor( Color::IntSRGBA aColor )
+ {
+ maStrokeColor = tools::intSRGBAToDoubleSequence( getGraphicDevice(),
+ aColor );
+ mbStrokeColorSet = true;
+ }
+
+ Color::IntSRGBA ImplPolyPolygon::getRGBAFillColor() const
+ {
+ return tools::doubleSequenceToIntSRGBA( getGraphicDevice(),
+ maFillColor );
+ }
+
+ Color::IntSRGBA ImplPolyPolygon::getRGBALineColor() const
+ {
+ return tools::doubleSequenceToIntSRGBA( getGraphicDevice(),
+ maStrokeColor );
+ }
+
+ void ImplPolyPolygon::setStrokeWidth( const double& rStrokeWidth )
+ {
+ maStrokeAttributes.StrokeWidth = rStrokeWidth;
+ }
+
+ double ImplPolyPolygon::getStrokeWidth() const
+ {
+ return maStrokeAttributes.StrokeWidth;
+ }
+
+ bool ImplPolyPolygon::draw() const
+ {
+ CanvasSharedPtr pCanvas( getCanvas() );
+
+ OSL_ENSURE( pCanvas.get() != NULL &&
+ pCanvas->getUNOCanvas().is(),
+ "ImplBitmap::draw: invalid canvas" );
+
+ if( pCanvas.get() == NULL ||
+ !pCanvas->getUNOCanvas().is() )
+ return false;
+
+ if( mbFillColorSet )
+ {
+ rendering::RenderState aLocalState( getRenderState() );
+ aLocalState.DeviceColor = maFillColor;
+
+ pCanvas->getUNOCanvas()->fillPolyPolygon( mxPolyPoly,
+ pCanvas->getViewState(),
+ aLocalState );
+ }
+
+ if( mbStrokeColorSet )
+ {
+ rendering::RenderState aLocalState( getRenderState() );
+ aLocalState.DeviceColor = maStrokeColor;
+
+ if( ::rtl::math::approxEqual(maStrokeAttributes.StrokeWidth, 1.0) )
+ pCanvas->getUNOCanvas()->drawPolyPolygon( mxPolyPoly,
+ pCanvas->getViewState(),
+ aLocalState );
+ else
+ pCanvas->getUNOCanvas()->strokePolyPolygon( mxPolyPoly,
+ pCanvas->getViewState(),
+ aLocalState,
+ maStrokeAttributes );
+ }
+
+ return true;
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > ImplPolyPolygon::getUNOPolyPolygon() const
+ {
+ return mxPolyPoly;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implpolypolygon.hxx b/cppcanvas/source/wrapper/implpolypolygon.hxx
new file mode 100644
index 000000000000..7d89039f29c7
--- /dev/null
+++ b/cppcanvas/source/wrapper/implpolypolygon.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CANVAS_IMPLPOLYPOLYGON_HXX
+#define _CANVAS_IMPLPOLYPOLYGON_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/StrokeAttributes.hpp>
+
+#include <cppcanvas/polypolygon.hxx>
+#include <canvasgraphichelper.hxx>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ struct RealPoint2D;
+} } } }
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ class ImplPolyPolygon : public virtual ::cppcanvas::PolyPolygon, protected CanvasGraphicHelper
+ {
+ public:
+ ImplPolyPolygon( const CanvasSharedPtr& rParentCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& rPolyPoly );
+
+ virtual ~ImplPolyPolygon();
+
+ virtual void addPolygon( const ::basegfx::B2DPolygon& rPoly );
+ virtual void addPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly );
+
+ virtual void setRGBAFillColor( Color::IntSRGBA );
+ virtual void setRGBALineColor( Color::IntSRGBA );
+ virtual Color::IntSRGBA getRGBAFillColor() const;
+ virtual Color::IntSRGBA getRGBALineColor() const;
+
+ virtual void setStrokeWidth( const double& rStrokeWidth );
+ virtual double getStrokeWidth() const;
+
+ virtual bool draw() const;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D > getUNOPolyPolygon() const;
+
+ private:
+ // default: disabled copy/assignment
+ ImplPolyPolygon(const ImplPolyPolygon&);
+ ImplPolyPolygon& operator= ( const ImplPolyPolygon& );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > mxPolyPoly;
+
+ ::com::sun::star::rendering::StrokeAttributes maStrokeAttributes;
+
+ ::com::sun::star::uno::Sequence< double > maFillColor;
+ ::com::sun::star::uno::Sequence< double > maStrokeColor;
+ bool mbFillColorSet;
+ bool mbStrokeColorSet;
+ };
+
+ }
+}
+
+#endif /* _CANVAS_IMPLPOLYPOLYGON_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implsprite.cxx b/cppcanvas/source/wrapper/implsprite.cxx
new file mode 100644
index 000000000000..f2f5fba781bd
--- /dev/null
+++ b/cppcanvas/source/wrapper/implsprite.cxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <com/sun/star/rendering/XSprite.hpp>
+#include <com/sun/star/rendering/XAnimatedSprite.hpp>
+
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "implsprite.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ ImplSprite::ImplSprite( const uno::Reference< rendering::XSpriteCanvas >& rParentCanvas,
+ const uno::Reference< rendering::XSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
+ mxGraphicDevice(),
+ mxSprite( rSprite ),
+ mxAnimatedSprite(),
+ mpTransformArbiter( rTransformArbiter )
+ {
+ // Avoiding ternary operator in initializer list (Solaris
+ // compiler bug, when function call and temporary is
+ // involved)
+ if( rParentCanvas.is() )
+ mxGraphicDevice = rParentCanvas->getDevice();
+
+ OSL_ENSURE( rParentCanvas.is() , "ImplSprite::ImplSprite(): Invalid canvas");
+ OSL_ENSURE( mxGraphicDevice.is(), "ImplSprite::ImplSprite(): Invalid graphic device");
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::ImplSprite(): Invalid sprite");
+ OSL_ENSURE( mpTransformArbiter.get(), "ImplSprite::ImplSprite(): Invalid transformation arbiter");
+ }
+
+ ImplSprite::ImplSprite( const uno::Reference< rendering::XSpriteCanvas >& rParentCanvas,
+ const uno::Reference< rendering::XAnimatedSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter ) :
+ mxGraphicDevice(),
+ mxSprite( uno::Reference< rendering::XSprite >(rSprite,
+ uno::UNO_QUERY) ),
+ mxAnimatedSprite( rSprite ),
+ mpTransformArbiter( rTransformArbiter )
+ {
+ // Avoiding ternary operator in initializer list (Solaris
+ // compiler bug, when function call and temporary is
+ // involved)
+ if( rParentCanvas.is() )
+ mxGraphicDevice = rParentCanvas->getDevice();
+
+ OSL_ENSURE( rParentCanvas.is() , "ImplSprite::ImplSprite(): Invalid canvas");
+ OSL_ENSURE( mxGraphicDevice.is(), "ImplSprite::ImplSprite(): Invalid graphic device");
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::ImplSprite(): Invalid sprite");
+ OSL_ENSURE( mpTransformArbiter.get(), "ImplSprite::ImplSprite(): Invalid transformation arbiter");
+ }
+
+ ImplSprite::~ImplSprite()
+ {
+ // hide the sprite on the canvas. If we don't hide the
+ // sprite, it will stay on the canvas forever, since the
+ // canvas naturally keeps a list of visible sprites
+ // (otherwise, it wouldn't be able to paint them
+ // autonomously)
+ if( mxSprite.is() )
+ mxSprite->hide();
+ }
+
+ void ImplSprite::setAlpha( const double& rAlpha )
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::setAlpha(): Invalid sprite");
+
+ if( mxSprite.is() )
+ mxSprite->setAlpha( rAlpha );
+ }
+
+ void ImplSprite::movePixel( const ::basegfx::B2DPoint& rNewPos )
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::movePixel(): Invalid sprite");
+
+ if( mxSprite.is() )
+ {
+ rendering::ViewState aViewState;
+ rendering::RenderState aRenderState;
+
+ ::canvas::tools::initViewState( aViewState );
+ ::canvas::tools::initRenderState( aRenderState );
+
+ mxSprite->move( ::basegfx::unotools::point2DFromB2DPoint( rNewPos ),
+ aViewState,
+ aRenderState );
+ }
+ }
+
+ void ImplSprite::move( const ::basegfx::B2DPoint& rNewPos )
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::move(): Invalid sprite");
+
+ if( mxSprite.is() )
+ {
+ rendering::ViewState aViewState;
+ rendering::RenderState aRenderState;
+
+ ::canvas::tools::initViewState( aViewState );
+ ::canvas::tools::initRenderState( aRenderState );
+
+ ::canvas::tools::setViewStateTransform( aViewState,
+ mpTransformArbiter->getTransformation() );
+
+ mxSprite->move( ::basegfx::unotools::point2DFromB2DPoint( rNewPos ),
+ aViewState,
+ aRenderState );
+ }
+ }
+
+ void ImplSprite::transform( const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::transform(): Invalid sprite");
+
+ if( mxSprite.is() )
+ {
+ geometry::AffineMatrix2D aMatrix;
+
+ mxSprite->transform( ::basegfx::unotools::affineMatrixFromHomMatrix( aMatrix,
+ rMatrix ) );
+ }
+ }
+
+ void ImplSprite::setClipPixel( const ::basegfx::B2DPolyPolygon& rClipPoly )
+ {
+ OSL_ENSURE( mxGraphicDevice.is(), "ImplSprite::setClip(): Invalid canvas");
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::transform(): Invalid sprite");
+
+ if( mxSprite.is() && mxGraphicDevice.is() )
+ mxSprite->clip( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( mxGraphicDevice,
+ rClipPoly ) );
+ }
+
+ void ImplSprite::setClip( const ::basegfx::B2DPolyPolygon& rClipPoly )
+ {
+ OSL_ENSURE( mxGraphicDevice.is(), "ImplSprite::setClip(): Invalid canvas");
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::transform(): Invalid sprite");
+
+ if( mxSprite.is() && mxGraphicDevice.is() )
+ {
+ ::basegfx::B2DPolyPolygon aTransformedClipPoly( rClipPoly );
+
+ // extract linear part of canvas view transformation (linear means:
+ // without translational components)
+ ::basegfx::B2DHomMatrix aViewTransform( mpTransformArbiter->getTransformation() );
+ aViewTransform.set( 0, 2, 0.0 );
+ aViewTransform.set( 1, 2, 0.0 );
+
+ // transform polygon from view to device coordinate space
+ aTransformedClipPoly.transform( aViewTransform );
+
+ mxSprite->clip( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( mxGraphicDevice,
+ aTransformedClipPoly ) );
+ }
+ }
+
+ void ImplSprite::setClip()
+ {
+ OSL_ENSURE( mxGraphicDevice.is(), "ImplSprite::setClip(): Invalid canvas");
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::setClip(): Invalid sprite");
+
+ if( mxSprite.is() && mxGraphicDevice.is() )
+ mxSprite->clip( uno::Reference< rendering::XPolyPolygon2D >() );
+ }
+
+ void ImplSprite::show()
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::show(): Invalid sprite");
+
+ if( mxSprite.is() )
+ mxSprite->show();
+ }
+
+ void ImplSprite::hide()
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::hide(): Invalid sprite");
+
+ if( mxSprite.is() )
+ mxSprite->hide();
+ }
+
+ void ImplSprite::setPriority( double fPriority )
+ {
+ OSL_ENSURE( mxSprite.is(), "ImplSprite::setPriority(): Invalid sprite");
+
+ if( mxSprite.is() )
+ mxSprite->setPriority(fPriority);
+ }
+
+ uno::Reference< rendering::XSprite > ImplSprite::getUNOSprite() const
+ {
+ return mxSprite;
+ }
+
+ uno::Reference< rendering::XGraphicDevice > ImplSprite::getGraphicDevice() const
+ {
+ return mxGraphicDevice;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implsprite.hxx b/cppcanvas/source/wrapper/implsprite.hxx
new file mode 100644
index 000000000000..1397791d1f82
--- /dev/null
+++ b/cppcanvas/source/wrapper/implsprite.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLSPRITE_HXX
+#define _CPPCANVAS_IMPLSPRITE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XSprite.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <cppcanvas/sprite.hxx>
+
+#include <implspritecanvas.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ class ImplSprite : public virtual Sprite
+ {
+ public:
+ ImplSprite( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas >& rParentCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter );
+ ImplSprite( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas >& rParentCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XAnimatedSprite >& rSprite,
+ const ImplSpriteCanvas::TransformationArbiterSharedPtr& rTransformArbiter );
+ virtual ~ImplSprite();
+
+ virtual void setAlpha( const double& rAlpha );
+ virtual void movePixel( const ::basegfx::B2DPoint& rNewPos );
+ virtual void move( const ::basegfx::B2DPoint& rNewPos );
+ virtual void transform( const ::basegfx::B2DHomMatrix& rMatrix );
+ virtual void setClipPixel( const ::basegfx::B2DPolyPolygon& rClipPoly );
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly );
+ virtual void setClip();
+
+ virtual void show();
+ virtual void hide();
+
+ virtual void setPriority( double fPriority );
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSprite > getUNOSprite() const;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >
+ getGraphicDevice() const;
+
+ private:
+ // default: disabled copy/assignment
+ ImplSprite(const ImplSprite&);
+ ImplSprite& operator=( const ImplSprite& );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice > mxGraphicDevice;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite > mxSprite;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimatedSprite > mxAnimatedSprite;
+ ImplSpriteCanvas::TransformationArbiterSharedPtr mpTransformArbiter;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implspritecanvas.cxx b/cppcanvas/source/wrapper/implspritecanvas.cxx
new file mode 100644
index 000000000000..cc8cf5bdefcc
--- /dev/null
+++ b/cppcanvas/source/wrapper/implspritecanvas.cxx
@@ -0,0 +1,162 @@
+/* -*- 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_cppcanvas.hxx"
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <com/sun/star/rendering/InterpolationMode.hpp>
+
+#include <implspritecanvas.hxx>
+#include <implcustomsprite.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ ImplSpriteCanvas::TransformationArbiter::TransformationArbiter() :
+ maTransformation()
+ {
+ }
+
+ void ImplSpriteCanvas::TransformationArbiter::setTransformation( const ::basegfx::B2DHomMatrix& rViewTransform )
+ {
+ maTransformation = rViewTransform;
+ }
+
+ ::basegfx::B2DHomMatrix ImplSpriteCanvas::TransformationArbiter::getTransformation() const
+ {
+ return maTransformation;
+ }
+
+
+ ImplSpriteCanvas::ImplSpriteCanvas( const uno::Reference< rendering::XSpriteCanvas >& rCanvas ) :
+ ImplCanvas( uno::Reference< rendering::XCanvas >(rCanvas,
+ uno::UNO_QUERY) ),
+ ImplBitmapCanvas( uno::Reference< rendering::XBitmapCanvas >(rCanvas,
+ uno::UNO_QUERY) ),
+ mxSpriteCanvas( rCanvas ),
+ mpTransformArbiter( new TransformationArbiter() )
+ {
+ OSL_ENSURE( mxSpriteCanvas.is(), "ImplSpriteCanvas::ImplSpriteCanvas(): Invalid canvas" );
+ }
+
+ ImplSpriteCanvas::ImplSpriteCanvas(const ImplSpriteCanvas& rOrig) :
+ Canvas(),
+ BitmapCanvas(),
+ SpriteCanvas(),
+ ImplCanvas( rOrig ),
+ ImplBitmapCanvas( rOrig ),
+ mxSpriteCanvas( rOrig.getUNOSpriteCanvas() ),
+ mpTransformArbiter( new TransformationArbiter() )
+ {
+ OSL_ENSURE( mxSpriteCanvas.is(), "ImplSpriteCanvas::ImplSpriteCanvas( const ImplSpriteCanvas& ): Invalid canvas" );
+
+ mpTransformArbiter->setTransformation( getTransformation() );
+ }
+
+ ImplSpriteCanvas::~ImplSpriteCanvas()
+ {
+ }
+
+ void ImplSpriteCanvas::setTransformation( const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ mpTransformArbiter->setTransformation( rMatrix );
+
+ ImplCanvas::setTransformation( rMatrix );
+ }
+
+ bool ImplSpriteCanvas::updateScreen( bool bUpdateAll ) const
+ {
+ OSL_ENSURE( mxSpriteCanvas.is(), "ImplSpriteCanvas::updateScreen(): Invalid canvas" );
+
+ if( !mxSpriteCanvas.is() )
+ return false;
+
+ return mxSpriteCanvas->updateScreen( bUpdateAll );
+ }
+
+ CustomSpriteSharedPtr ImplSpriteCanvas::createCustomSprite( const ::basegfx::B2DSize& rSize ) const
+ {
+ OSL_ENSURE( mxSpriteCanvas.is(), "ImplSpriteCanvas::createCustomSprite(): Invalid canvas" );
+
+ if( !mxSpriteCanvas.is() )
+ return CustomSpriteSharedPtr();
+
+ return CustomSpriteSharedPtr(
+ new ImplCustomSprite( mxSpriteCanvas,
+ mxSpriteCanvas->createCustomSprite( ::basegfx::unotools::size2DFromB2DSize(rSize) ),
+ mpTransformArbiter ) );
+ }
+
+ SpriteSharedPtr ImplSpriteCanvas::createClonedSprite( const SpriteSharedPtr& rSprite ) const
+ {
+ OSL_ENSURE( mxSpriteCanvas.is(), "ImplSpriteCanvas::createCustomSprite(): Invalid canvas" );
+ OSL_ENSURE( rSprite.get() != NULL && rSprite->getUNOSprite().is(),
+ "ImplSpriteCanvas::createCustomSprite(): Invalid sprite" );
+
+ if( !mxSpriteCanvas.is() ||
+ rSprite.get() == NULL ||
+ !rSprite->getUNOSprite().is() )
+ {
+ return SpriteSharedPtr();
+ }
+
+ return SpriteSharedPtr(
+ new ImplSprite( mxSpriteCanvas,
+ mxSpriteCanvas->createClonedSprite( rSprite->getUNOSprite() ),
+ mpTransformArbiter ) );
+ }
+
+ SpriteSharedPtr ImplSpriteCanvas::createSpriteFromBitmaps( const uno::Sequence< uno::Reference< rendering::XBitmap > >& rAnimationBitmaps,
+ sal_Int8 nInterpolationMode )
+ {
+ return SpriteSharedPtr( new internal::ImplSprite( mxSpriteCanvas,
+ mxSpriteCanvas->createSpriteFromBitmaps( rAnimationBitmaps,
+ nInterpolationMode ),
+ mpTransformArbiter ) );
+ }
+
+ CanvasSharedPtr ImplSpriteCanvas::clone() const
+ {
+ return SpriteCanvasSharedPtr( new ImplSpriteCanvas( *this ) );
+ }
+
+ uno::Reference< rendering::XSpriteCanvas > ImplSpriteCanvas::getUNOSpriteCanvas() const
+ {
+ return mxSpriteCanvas;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/implspritecanvas.hxx b/cppcanvas/source/wrapper/implspritecanvas.hxx
new file mode 100644
index 000000000000..d308b313b7dd
--- /dev/null
+++ b/cppcanvas/source/wrapper/implspritecanvas.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CPPCANVAS_IMPLSPRITECANVAS_HXX
+#define _CPPCANVAS_IMPLSPRITECANVAS_HXX
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+
+#include <cppcanvas/spritecanvas.hxx>
+
+#include <implbitmapcanvas.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+ class ImplSpriteCanvas : public virtual SpriteCanvas, protected virtual ImplBitmapCanvas
+ {
+ public:
+ ImplSpriteCanvas( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas >& rCanvas );
+ ImplSpriteCanvas(const ImplSpriteCanvas&);
+
+ virtual ~ImplSpriteCanvas();
+
+ virtual void setTransformation( const ::basegfx::B2DHomMatrix& rMatrix );
+
+ virtual bool updateScreen( bool bUpdateAll ) const;
+
+ virtual CustomSpriteSharedPtr createCustomSprite( const ::basegfx::B2DSize& ) const;
+ virtual SpriteSharedPtr createClonedSprite( const SpriteSharedPtr& ) const;
+
+ SpriteSharedPtr createSpriteFromBitmaps(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > >& animationBitmaps,
+ sal_Int8 interpolationMode );
+
+ virtual CanvasSharedPtr clone() const;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSpriteCanvas > getUNOSpriteCanvas() const;
+
+ /** This class passes the view transformation
+ to child sprites
+
+ This helper class is necessary, because the
+ ImplSpriteCanvas object cannot hand out shared ptrs of
+ itself, but has somehow pass an object to child
+ sprites those can query for the canvas' view transform.
+ */
+ class TransformationArbiter
+ {
+ public:
+ TransformationArbiter();
+
+ void setTransformation( const ::basegfx::B2DHomMatrix& rViewTransform );
+ ::basegfx::B2DHomMatrix getTransformation() const;
+
+ private:
+ ::basegfx::B2DHomMatrix maTransformation;
+ };
+
+ typedef ::boost::shared_ptr< TransformationArbiter > TransformationArbiterSharedPtr;
+
+ private:
+ // default: disabled assignment
+ ImplSpriteCanvas& operator=( const ImplSpriteCanvas& );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSpriteCanvas > mxSpriteCanvas;
+ TransformationArbiterSharedPtr mpTransformArbiter;
+ };
+ }
+}
+
+#endif /* _CPPCANVAS_IMPLSPRITECANVAS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/impltext.cxx b/cppcanvas/source/wrapper/impltext.cxx
new file mode 100644
index 000000000000..68592105c14a
--- /dev/null
+++ b/cppcanvas/source/wrapper/impltext.cxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_cppcanvas.hxx"
+
+#include <impltext.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <rtl/ustring.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ ImplText::ImplText( const CanvasSharedPtr& rParentCanvas,
+ const ::rtl::OUString& rText ) :
+ CanvasGraphicHelper( rParentCanvas ),
+ mpFont(),
+ maText(rText)
+ {
+ }
+
+ ImplText::~ImplText()
+ {
+ }
+
+ bool ImplText::draw() const
+ {
+ CanvasSharedPtr pCanvas( getCanvas() );
+
+ OSL_ENSURE( pCanvas.get() != NULL &&
+ pCanvas->getUNOCanvas().is(),
+ "ImplBitmap::draw: invalid canvas" );
+
+ rendering::StringContext aText;
+ aText.Text = maText;
+ aText.StartPosition = 0;
+ aText.Length = maText.getLength();
+
+ // TODO(P1): implement caching
+ // TODO(F2): where to get current BiDi status?
+ sal_Int8 nBidiOption = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
+ pCanvas->getUNOCanvas()->drawText( aText,
+ mpFont->getUNOFont(),
+ pCanvas->getViewState(),
+ getRenderState(),
+ nBidiOption );
+
+ return true;
+ }
+
+ void ImplText::setFont( const FontSharedPtr& rFont )
+ {
+ mpFont = rFont;
+ }
+
+ FontSharedPtr ImplText::getFont()
+ {
+ return mpFont;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/impltext.hxx b/cppcanvas/source/wrapper/impltext.hxx
new file mode 100644
index 000000000000..a45e7dab2114
--- /dev/null
+++ b/cppcanvas/source/wrapper/impltext.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CANVAS_IMPLTEXT_HXX
+#define _CANVAS_IMPLTEXT_HXX
+
+#include <com/sun/star/rendering/RenderState.hpp>
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <cppcanvas/text.hxx>
+#include <canvasgraphichelper.hxx>
+
+
+namespace cppcanvas
+{
+ namespace internal
+ {
+
+ class ImplText : public virtual ::cppcanvas::Text, protected CanvasGraphicHelper
+ {
+ public:
+
+ ImplText( const CanvasSharedPtr& rParentCanvas,
+ const ::rtl::OUString& rText );
+
+ virtual ~ImplText();
+
+ virtual bool draw() const;
+
+ virtual void setFont( const FontSharedPtr& );
+ virtual FontSharedPtr getFont();
+
+ private:
+ // default: disabled copy/assignment
+ ImplText(const ImplText&);
+ ImplText& operator= ( const ImplText& );
+
+ FontSharedPtr mpFont;
+ ::rtl::OUString maText;
+ };
+ }
+}
+
+#endif /* _CANVAS_IMPLTEXT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/wrapper/makefile.mk b/cppcanvas/source/wrapper/makefile.mk
new file mode 100644
index 000000000000..255cc023d75c
--- /dev/null
+++ b/cppcanvas/source/wrapper/makefile.mk
@@ -0,0 +1,60 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=cppcanvas
+TARGET=canvaswrapper
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+SLOFILES = $(SLO)$/implbitmap.obj \
+ $(SLO)$/implcanvas.obj \
+ $(SLO)$/implcolor.obj \
+ $(SLO)$/implfont.obj \
+ $(SLO)$/vclfactory.obj \
+ $(SLO)$/basegfxfactory.obj \
+ $(SLO)$/impltext.obj \
+ $(SLO)$/implpolypolygon.obj \
+ $(SLO)$/implbitmapcanvas.obj \
+ $(SLO)$/implspritecanvas.obj \
+ $(SLO)$/implsprite.obj \
+ $(SLO)$/implcustomsprite.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/cppcanvas/source/wrapper/vclfactory.cxx b/cppcanvas/source/wrapper/vclfactory.cxx
new file mode 100644
index 000000000000..c0646d0fdba5
--- /dev/null
+++ b/cppcanvas/source/wrapper/vclfactory.cxx
@@ -0,0 +1,366 @@
+/* -*- 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_cppcanvas.hxx"
+#include <rtl/instance.hxx>
+#include <osl/getglobalmutex.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/rendering/InterpolationMode.hpp>
+#include <vcl/window.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/canvastools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <cppcanvas/vclfactory.hxx>
+
+#include <implbitmapcanvas.hxx>
+#include <implspritecanvas.hxx>
+#include <implpolypolygon.hxx>
+#include <implbitmap.hxx>
+#include <implrenderer.hxx>
+#include <impltext.hxx>
+#include <implsprite.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace cppcanvas
+{
+ /* Singleton handling */
+ struct InitInstance
+ {
+ VCLFactory* operator()()
+ {
+ return new VCLFactory();
+ }
+ };
+
+ VCLFactory& VCLFactory::getInstance()
+ {
+ return *rtl_Instance< VCLFactory, InitInstance, ::osl::MutexGuard,
+ ::osl::GetGlobalMutex >::create(
+ InitInstance(), ::osl::GetGlobalMutex());
+ }
+
+ VCLFactory::VCLFactory()
+ {
+ }
+
+ VCLFactory::~VCLFactory()
+ {
+ }
+
+ BitmapCanvasSharedPtr VCLFactory::createCanvas( const ::Window& rVCLWindow )
+ {
+ return BitmapCanvasSharedPtr(
+ new internal::ImplBitmapCanvas(
+ uno::Reference< rendering::XBitmapCanvas >(
+ rVCLWindow.GetCanvas(),
+ uno::UNO_QUERY) ) );
+ }
+
+ BitmapCanvasSharedPtr VCLFactory::createCanvas( const uno::Reference< rendering::XBitmapCanvas >& xCanvas )
+ {
+ return BitmapCanvasSharedPtr(
+ new internal::ImplBitmapCanvas( xCanvas ) );
+ }
+
+ SpriteCanvasSharedPtr VCLFactory::createSpriteCanvas( const ::Window& rVCLWindow ) const
+ {
+ return SpriteCanvasSharedPtr(
+ new internal::ImplSpriteCanvas(
+ uno::Reference< rendering::XSpriteCanvas >(
+ rVCLWindow.GetSpriteCanvas(),
+ uno::UNO_QUERY) ) );
+ }
+
+ SpriteCanvasSharedPtr VCLFactory::createSpriteCanvas( const uno::Reference< rendering::XSpriteCanvas >& xCanvas ) const
+ {
+ return SpriteCanvasSharedPtr(
+ new internal::ImplSpriteCanvas( xCanvas ) );
+ }
+
+ SpriteCanvasSharedPtr VCLFactory::createFullscreenSpriteCanvas( const ::Window& rVCLWindow,
+ const Size& rFullscreenSize ) const
+ {
+ return SpriteCanvasSharedPtr(
+ new internal::ImplSpriteCanvas(
+ uno::Reference< rendering::XSpriteCanvas >(
+ rVCLWindow.GetFullscreenSpriteCanvas( rFullscreenSize ),
+ uno::UNO_QUERY) ) );
+ }
+
+ PolyPolygonSharedPtr VCLFactory::createPolyPolygon( const CanvasSharedPtr& rCanvas,
+ const ::Polygon& rPoly ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createPolyPolygon(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return PolyPolygonSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return PolyPolygonSharedPtr();
+
+ return PolyPolygonSharedPtr(
+ new internal::ImplPolyPolygon( rCanvas,
+ ::vcl::unotools::xPolyPolygonFromPolygon(
+ xCanvas->getDevice(),
+ rPoly) ) );
+ }
+
+ PolyPolygonSharedPtr VCLFactory::createPolyPolygon( const CanvasSharedPtr& rCanvas,
+ const ::PolyPolygon& rPolyPoly ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createPolyPolygon(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return PolyPolygonSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return PolyPolygonSharedPtr();
+
+ return PolyPolygonSharedPtr(
+ new internal::ImplPolyPolygon( rCanvas,
+ ::vcl::unotools::xPolyPolygonFromPolyPolygon(
+ xCanvas->getDevice(),
+ rPolyPoly) ) );
+ }
+
+ BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr& rCanvas,
+ const ::Size& rSize ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr(
+ new internal::ImplBitmap( rCanvas,
+ xCanvas->getDevice()->createCompatibleBitmap(
+ ::vcl::unotools::integerSize2DFromSize(rSize) ) ) );
+ }
+
+ BitmapSharedPtr VCLFactory::createAlphaBitmap( const CanvasSharedPtr& rCanvas,
+ const ::Size& rSize ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr(
+ new internal::ImplBitmap( rCanvas,
+ xCanvas->getDevice()->createCompatibleAlphaBitmap(
+ ::vcl::unotools::integerSize2DFromSize(rSize) ) ) );
+ }
+
+ BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr& rCanvas,
+ const ::Bitmap& rBitmap ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr( new internal::ImplBitmap( rCanvas,
+ ::vcl::unotools::xBitmapFromBitmap(
+ xCanvas->getDevice(),
+ rBitmap) ) );
+ }
+
+ BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr& rCanvas,
+ const ::BitmapEx& rBmpEx ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createBitmap(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return BitmapSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return BitmapSharedPtr();
+
+ return BitmapSharedPtr( new internal::ImplBitmap( rCanvas,
+ ::vcl::unotools::xBitmapFromBitmapEx(
+ xCanvas->getDevice(),
+ rBmpEx) ) );
+ }
+
+ RendererSharedPtr VCLFactory::createRenderer( const CanvasSharedPtr& rCanvas,
+ const ::Graphic& rGraphic,
+ const Renderer::Parameters& rParms ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createRenderer(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return RendererSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return RendererSharedPtr();
+
+ if( rGraphic.GetType() == GRAPHIC_GDIMETAFILE )
+ return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
+ rGraphic.GetGDIMetaFile(),
+ rParms ) );
+ else
+ return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
+ rGraphic.GetBitmapEx(),
+ rParms ) );
+ }
+
+ RendererSharedPtr VCLFactory::createRenderer( const CanvasSharedPtr& rCanvas,
+ const ::GDIMetaFile& rMtf,
+ const Renderer::Parameters& rParms ) const
+ {
+ return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
+ rMtf,
+ rParms ) );
+ }
+
+ SpriteSharedPtr VCLFactory::createAnimatedSprite( const SpriteCanvasSharedPtr& rCanvas, const ::Animation& rAnim ) const
+ {
+ OSL_ENSURE( rCanvas.get() != NULL &&
+ rCanvas->getUNOCanvas().is(),
+ "VCLFactory::createAnimatedSprite(): Invalid canvas" );
+
+ if( rCanvas.get() == NULL )
+ return SpriteSharedPtr();
+
+ uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
+ if( !xCanvas.is() )
+ return SpriteSharedPtr();
+
+ uno::Reference< rendering::XSpriteCanvas > xSpriteCanvas( rCanvas->getUNOSpriteCanvas() );
+ if( !xSpriteCanvas.is() )
+ return SpriteSharedPtr();
+
+ if( rAnim.IsEmpty() )
+ return SpriteSharedPtr();
+
+ internal::ImplSpriteCanvas* pSpriteCanvas = dynamic_cast< internal::ImplSpriteCanvas* >( rCanvas.get() );
+ if( !pSpriteCanvas )
+ return SpriteSharedPtr();
+
+ const sal_uInt16 nBitmaps( rAnim.Count() );
+ uno::Sequence< uno::Reference< rendering::XBitmap > > aBitmapSequence( nBitmaps );
+ uno::Reference< rendering::XBitmap >* pBitmaps = aBitmapSequence.getArray();
+
+ unsigned int i;
+ BitmapEx aBmpEx;
+ BitmapEx aRestoreBuffer;
+ aBmpEx.SetSizePixel( rAnim.GetDisplaySizePixel() );
+ aRestoreBuffer.SetSizePixel( rAnim.GetDisplaySizePixel() );
+ aBmpEx.Erase( ::Color( 255, 0,0,0 ) ); // clear alpha channel
+ aRestoreBuffer = aBmpEx;
+ const Point aEmptyPoint;
+
+ for( i=0; i<nBitmaps; ++i )
+ {
+ const AnimationBitmap& rAnimBmp( rAnim.Get((sal_uInt16)i) );
+
+ // Handle dispose according to GIF spec: a
+ // DISPOSE_PREVIOUS does _not_ mean to revert to the
+ // previous frame, but to revert to the last frame with
+ // DISPOSE_NOT
+
+ // dispose previous
+ if( rAnimBmp.eDisposal == DISPOSE_BACK )
+ {
+ // simply clear bitmap to transparent
+ aBmpEx.Erase( ::Color( 255, 0,0,0 ) );
+ }
+ else if( rAnimBmp.eDisposal == DISPOSE_PREVIOUS )
+ {
+ // copy in last known full frame
+ aBmpEx = aRestoreBuffer;
+ }
+ // I have exactly _no_ idea what DISPOSE_FULL is supposed
+ // to do. It's apparently not set anywhere in our code
+ OSL_ENSURE( rAnimBmp.eDisposal!=DISPOSE_FULL,
+ "VCLFactory::createAnimatedSprite(): Somebody set the deprecated DISPOSE_FULL at the Animation" );
+
+ // update display
+ aBmpEx.CopyPixel( Rectangle( rAnimBmp.aPosPix,
+ rAnimBmp.aSizePix ),
+ Rectangle( aEmptyPoint,
+ rAnimBmp.aSizePix ),
+ &rAnimBmp.aBmpEx );
+
+ // store last DISPOSE_NOT frame, for later
+ // DISPOSE_PREVIOUS updates
+ if( rAnimBmp.eDisposal == DISPOSE_NOT )
+ aRestoreBuffer = aBmpEx;
+
+ pBitmaps[i] = ::vcl::unotools::xBitmapFromBitmapEx(
+ xCanvas->getDevice(),
+ aBmpEx);
+ }
+
+ return pSpriteCanvas->createSpriteFromBitmaps( aBitmapSequence,
+ rendering::InterpolationMode::NEAREST_NEIGHBOR );
+ }
+
+ TextSharedPtr VCLFactory::createText( const CanvasSharedPtr& rCanvas, const ::rtl::OUString& rText ) const
+ {
+ return TextSharedPtr( new internal::ImplText( rCanvas,
+ rText ) );
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/util/cppcanvas.flt b/cppcanvas/util/cppcanvas.flt
new file mode 100644
index 000000000000..90ec48c26d4e
--- /dev/null
+++ b/cppcanvas/util/cppcanvas.flt
@@ -0,0 +1,4 @@
+__CT
+Impl
+IMP
+internal
diff --git a/cppcanvas/util/makefile.mk b/cppcanvas/util/makefile.mk
new file mode 100644
index 000000000000..01cf6234602c
--- /dev/null
+++ b/cppcanvas/util/makefile.mk
@@ -0,0 +1,70 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=cppcanvas
+TARGET=cppcanvas
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Common ----------------------------------------------------------
+
+LIB1TARGET=$(SLB)$/$(TARGET).lib
+LIB1FILES=\
+ $(SLB)$/canvaswrapper.lib \
+ $(SLB)$/metafilerenderer.lib \
+ $(SLB)$/cppcanvastools.lib
+
+SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
+SHL1IMPLIB= i$(TARGET)
+SHL1STDLIBS= $(TOOLSLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(I18NISOLANGLIB) $(SVTOOLLIB)
+
+.IF "$(debug)$(dbgutil)"!=""
+SHL1STDLIBS += $(CPPUHELPERLIB)
+.ENDIF # "$(debug)$(dbgutil)"!=""
+
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME =$(SHL1TARGET)
+DEF1DEPN =$(MISC)$/$(SHL1TARGET).flt \
+ $(LIB1TARGET)
+
+DEF1DES =CPPCanvas
+DEFLIB1NAME =$(TARGET)
+
+# ==========================================================================
+
+.INCLUDE : target.mk
+
+$(MISC)$/$(SHL1TARGET).flt : makefile.mk
+ @$(TYPE) $(TARGET).flt > $@