summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
authorArmin Weiss <aw@openoffice.org>2007-12-18 14:10:54 +0000
committerArmin Weiss <aw@openoffice.org>2007-12-18 14:10:54 +0000
commit43f54a02f8aff4f4f9a0ad4be3c1edb3c5e9eb31 (patch)
treedc42dc23c3c382ea34e564ffad8903145a24129c /drawinglayer
parent9eb0f8b0cc4b61c3c99cc19e015f176498468cce (diff)
#i39532# added rudimentary canvas renderer
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx134
-rw-r--r--drawinglayer/inc/drawinglayer/processor2d/vclmetafileprocessor2d.hxx8
-rw-r--r--drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx8
-rw-r--r--drawinglayer/prj/d.lst1
-rw-r--r--drawinglayer/source/processor2d/canvasprocessor.cxx1456
-rw-r--r--drawinglayer/source/processor2d/makefile.mk7
-rw-r--r--drawinglayer/util/makefile.mk5
7 files changed, 1606 insertions, 13 deletions
diff --git a/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx
new file mode 100644
index 000000000000..dfc1db891d97
--- /dev/null
+++ b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx
@@ -0,0 +1,134 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: canvasprocessor.hxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: aw $ $Date: 2007-12-18 15:10:11 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+#define _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#endif
+
+#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#endif
+
+#ifndef _BGFX_COLOR_BCOLORMODIFIER_HXX
+#include <basegfx/color/bcolormodifier.hxx>
+#endif
+
+#ifndef INCLUDED_SVTOOLS_OPTIONSDRAWINGLAYER_HXX
+#include <svtools/optionsdrawinglayer.hxx>
+#endif
+
+#ifndef _COM_SUN_STAR_RENDERING_VIEWSTATE_HPP_
+#include <com/sun/star/rendering/ViewState.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_RENDERING_RENDERSTATE_HPP_
+#include <com/sun/star/rendering/RenderState.hpp>
+#endif
+
+#ifndef INCLUDED_I18NPOOL_LANG_H
+#include <i18npool/lang.h>
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// forward declaration
+
+namespace basegfx {
+ class BColor;
+ class B2DPolygon;
+ class B2DPolyPolygon;
+}
+
+namespace com { namespace sun { namespace star { namespace rendering {
+ class XCanvas;
+ class XPolyPolygon2D;
+}}}}
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ class canvasProcessor2D : public BaseProcessor2D
+ {
+ private:
+ // the destination canvas
+ com::sun::star::uno::Reference< com::sun::star::rendering::XCanvas > mxCanvas;
+ com::sun::star::rendering::ViewState maViewState;
+ com::sun::star::rendering::RenderState maRenderState;
+
+ // the modifiedColorPrimitive stack
+ basegfx::BColorModifierStack maBColorModifierStack;
+
+ // the current transformation
+ basegfx::B2DHomMatrix maCurrentTransformation;
+
+ // SvtOptionsDrawinglayer incarnation to react on diverse settings
+ const SvtOptionsDrawinglayer maDrawinglayerOpt;
+
+ // stack value (increment and decrement) to count how deep we are in
+ // PolygonStrokePrimitive2D's decompositions (normally only one)
+ sal_uInt32 mnPolygonStrokePrimitive2D;
+
+ // determined LanguageType
+ LanguageType meLang;
+
+ // as tooling, the process() implementation takes over API handling and calls this
+ // virtual render method when the primitive implementation is BasePrimitive2D-based.
+ virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate);
+
+ public:
+ canvasProcessor2D(
+ const geometry::ViewInformation2D& rViewInformation,
+ const com::sun::star::uno::Reference< com::sun::star::rendering::XCanvas >& rCanvas);
+ virtual ~canvasProcessor2D();
+
+ // the central processing method
+ virtual void process(const primitive2d::Primitive2DSequence& rSource);
+
+ // access to Drawinglayer configuration options
+ const SvtOptionsDrawinglayer& getOptionsDrawinglayer() const { return maDrawinglayerOpt; }
+ };
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif //_DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+
+// eof
diff --git a/drawinglayer/inc/drawinglayer/processor2d/vclmetafileprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/vclmetafileprocessor2d.hxx
index 4c9df575c58e..2bd792f98246 100644
--- a/drawinglayer/inc/drawinglayer/processor2d/vclmetafileprocessor2d.hxx
+++ b/drawinglayer/inc/drawinglayer/processor2d/vclmetafileprocessor2d.hxx
@@ -4,9 +4,9 @@
*
* $RCSfile: vclmetafileprocessor2d.hxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: aw $ $Date: 2007-11-07 14:27:17 $
+ * last change: $Author: aw $ $Date: 2007-12-18 15:10:11 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -44,6 +44,10 @@
#include <com/sun/star/i18n/XBreakIterator.hpp>
#endif
+#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#endif
+
//////////////////////////////////////////////////////////////////////////////
// vcl::PDFExtOutDevData support
diff --git a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
index 36a5f01e066e..e7c6b1682036 100644
--- a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
+++ b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
@@ -4,9 +4,9 @@
*
* $RCSfile: vclprocessor2d.hxx,v $
*
- * $Revision: 1.11 $
+ * $Revision: 1.12 $
*
- * last change: $Author: aw $ $Date: 2007-12-13 16:43:01 $
+ * last change: $Author: aw $ $Date: 2007-12-18 15:10:11 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -48,10 +48,6 @@
#include <basegfx/color/bcolormodifier.hxx>
#endif
-#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX
-#include <basegfx/polygon/b2dpolypolygon.hxx>
-#endif
-
#ifndef INCLUDED_SVTOOLS_OPTIONSDRAWINGLAYER_HXX
#include <svtools/optionsdrawinglayer.hxx>
#endif
diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst
index 4f79d2217bce..077b807a9d2b 100644
--- a/drawinglayer/prj/d.lst
+++ b/drawinglayer/prj/d.lst
@@ -76,6 +76,7 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor2d
..\inc\drawinglayer\processor2d\vclprocessor2d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor2d\vclprocessor2d.hxx
..\inc\drawinglayer\processor2d\vclpixelprocessor2d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor2d\vclpixelprocessor2d.hxx
..\inc\drawinglayer\processor2d\vclmetafileprocessor2d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor2d\vclmetafileprocessor2d.hxx
+..\inc\drawinglayer\processor2d\canvasprocessor.hxx %_DEST%\inc%_EXT%\drawinglayer\processor2d\canvasprocessor.hxx
mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor3d
..\inc\drawinglayer\processor3d\baseprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\baseprocessor3d.hxx
diff --git a/drawinglayer/source/processor2d/canvasprocessor.cxx b/drawinglayer/source/processor2d/canvasprocessor.cxx
new file mode 100644
index 000000000000..fcc978c84f25
--- /dev/null
+++ b/drawinglayer/source/processor2d/canvasprocessor.cxx
@@ -0,0 +1,1456 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: canvasprocessor.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: aw $ $Date: 2007-12-18 15:10:27 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+#include <drawinglayer/processor2d/canvasprocessor.hxx>
+#endif
+
+#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PRIMITIVETYPES2D_HXX
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#endif
+
+#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYGONPRIMITIVE2D_HXX
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#endif
+
+#ifndef _COM_SUN_STAR_RENDERING_XCANVAS_HPP_
+#include <com/sun/star/rendering/XCanvas.hpp>
+#endif
+
+#ifndef _VCL_CANVASTOOLS_HXX
+#include <vcl/canvastools.hxx>
+#endif
+
+#ifndef _BGFX_TOOLS_CANVASTOOLS_HXX
+#include <basegfx/tools/canvastools.hxx>
+#endif
+
+#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYPOLYGONPRIMITIVE2D_HXX
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#endif
+
+#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MODIFIEDCOLORPRIMITIVE2D_HXX
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#endif
+
+#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TRANSFORMPRIMITIVE2D_HXX
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#endif
+
+#ifndef INCLUDED_CANVAS_CANVASTOOLS_HXX
+#include <canvas/canvastools.hxx>
+#endif
+
+#ifndef _SVTOOLS_CTLOPTIONS_HXX
+#include <svtools/ctloptions.hxx>
+#endif
+
+#ifndef _SV_SVAPP_HXX
+#include <vcl/svapp.hxx>
+#endif
+
+using namespace com::sun::star;
+namespace css = com::sun::star;
+namespace cssgeom = com::sun::star::geometry;
+
+//////////////////////////////////////////////////////////////////////////////
+// AW: Adding the canvas example from THB here to extract stuff later
+/*
+ // TODO(Q3): share impCreateEmptyBitmapWithPattern() and other
+ // helper methods with vclprocessor.cxx
+ Bitmap impCreateEmptyBitmapWithPattern(Bitmap aSource, const Size& aTargetSizePixel)
+ {
+ Bitmap aRetval;
+ BitmapReadAccess* pReadAccess = aSource.AcquireReadAccess();
+
+ if(pReadAccess)
+ {
+ if(aSource.GetBitCount() <= 8)
+ {
+ BitmapPalette aPalette(pReadAccess->GetPalette());
+ aRetval = Bitmap(aTargetSizePixel, aSource.GetBitCount(), &aPalette);
+ }
+ else
+ {
+ aRetval = Bitmap(aTargetSizePixel, aSource.GetBitCount());
+ }
+
+ delete pReadAccess;
+ }
+
+ return aRetval;
+ }
+
+ Bitmap impModifyBitmap(const ::basegfx::BColorModifier& rModifier, const Bitmap& rSource)
+ {
+ Bitmap aRetval(rSource);
+
+ switch(rModifier.getMode())
+ {
+ case ::basegfx::BCOLORMODIFYMODE_REPLACE :
+ {
+ aRetval = impCreateEmptyBitmapWithPattern(aRetval, Size(1L, 1L));
+ aRetval.Erase(Color(rModifier.getBColor()));
+ break;
+ }
+
+ default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
+ {
+ BitmapWriteAccess* pContent = aRetval.AcquireWriteAccess();
+
+ if(pContent)
+ {
+ for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+ {
+ for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
+ {
+ const Color aColor = pContent->GetPixel(y, x);
+ const ::basegfx::BColor aBColor(rModifier.getModifiedColor(aColor.getBColor()));
+ pContent->SetPixel(y, x, BitmapColor(Color(aBColor)));
+ }
+ }
+
+ delete pContent;
+ }
+
+ break;
+ }
+ }
+
+ return aRetval;
+ }
+
+ Bitmap impModifyBitmap(const ::basegfx::BColorModifierStack& rBColorModifierStack, const Bitmap& rSource)
+ {
+ Bitmap aRetval(rSource);
+
+ for(sal_uInt32 a(rBColorModifierStack.count()); a; )
+ {
+ const ::basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
+ aRetval = impModifyBitmap(rModifier, aRetval);
+ }
+
+ return aRetval;
+ }
+
+ sal_uInt32 impCalcGradientSteps(sal_uInt32 nSteps, const ::basegfx::B2DRange& rRange, sal_uInt32 nMaxDist)
+ {
+ if(nSteps == 0L)
+ nSteps = (sal_uInt32)(rRange.getWidth() + rRange.getHeight()) / 8;
+
+ if(nSteps < 2L)
+ {
+ nSteps = 2L;
+ }
+
+ if(nSteps > nMaxDist)
+ {
+ nSteps = nMaxDist;
+ }
+
+ return nSteps;
+ }
+
+ void canvasProcessor::impDrawGradientSimple(
+ const ::basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< ::basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< ::basegfx::BColor >& rColors,
+ const ::basegfx::B2DPolygon& rUnitPolygon)
+ {
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rUnitPolygon));
+ uno::Reference< rendering::XPolyPolygon2D > xTargetPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm));
+
+ for(sal_uInt32 a(0L); a < rColors.size(); a++)
+ {
+ // set correct color
+ const ::basegfx::BColor aFillColor(rColors[a]);
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aFillColor);
+
+ if(a)
+ {
+ if(a - 1L < rMatrices.size())
+ {
+ canvas::tools::setRenderStateTransform( maRenderState,
+ rMatrices[a - 1L] );
+ mxCanvas->fillPolyPolygon(xPoly,maViewState,maRenderState);
+ }
+ }
+ else
+ {
+ canvas::tools::setRenderStateTransform( maRenderState,
+ basegfx::B2DHomMatrix() );
+ mxCanvas->fillPolyPolygon(xTargetPoly,maViewState,maRenderState);
+ }
+ }
+ }
+
+ void canvasProcessor::impDrawGradientComplex(
+ const ::basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< ::basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< ::basegfx::BColor >& rColors,
+ const ::basegfx::B2DPolygon& rUnitPolygon)
+ {
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rUnitPolygon));
+ uno::Reference< rendering::XPolyPolygon2D > xTargetPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm));
+
+ maRenderState.Clip = xTargetPoly;
+
+ // draw gradient PolyPolygons
+ for(std::size_t a = 0L; a < rMatrices.size(); a++)
+ {
+ // set correct color
+ if(rColors.size() > a)
+ {
+ const ::basegfx::BColor aFillColor(rColors[a]);
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aFillColor);
+ }
+
+ canvas::tools::setRenderStateTransform( maRenderState,
+ rMatrices[a] );
+
+ if(a)
+ mxCanvas->fillPolyPolygon(xPoly,maViewState,maRenderState);
+ else
+ mxCanvas->fillPolyPolygon(xTargetPoly,maViewState,maRenderState);
+ }
+
+ maRenderState.Clip.clear();
+ }
+
+ void canvasProcessor::impDrawGradient(
+ const ::basegfx::B2DPolyPolygon& rTargetForm,
+ ::drawinglayer::primitive::GradientStyle eGradientStyle,
+ sal_uInt32 nSteps,
+ const ::basegfx::BColor& rStart,
+ const ::basegfx::BColor& rEnd,
+ double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple)
+ {
+ fprintf(stderr,"impDrawGradient\n");
+
+ ::basegfx::B2DPolyPolygon aTmp(rTargetForm);
+ aTmp.transform( maWorldToView );
+ const ::basegfx::B2DRange aOutlineRangePixel(::basegfx::tools::getRange(aTmp));
+ const ::basegfx::B2DRange aOutlineRange(::basegfx::tools::getRange(rTargetForm));
+
+ fprintf(stderr,"impDrawGradient: #%d\n",nSteps);
+
+ 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< rendering::XParametricPolyPolygon2DFactory > xFactory(
+ mxCanvas->getDevice()->getParametricPolyPolygonFactory() );
+
+ if( xFactory.is() )
+ {
+ fprintf(stderr,"native gradient #1\n");
+
+ ::basegfx::B2DHomMatrix aTextureTransformation;
+ rendering::Texture aTexture;
+
+ aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
+ aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
+ aTexture.Alpha = 1.0;
+
+
+ // setup start/end color values
+ // ----------------------------
+
+ const uno::Sequence< double > aStartColor(
+ basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(),
+ rStart ));
+ const uno::Sequence< double > aEndColor(
+ basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(),
+ rEnd ));
+
+ // Setup texture transformation
+ // ----------------------------
+
+ const basegfx::B2DRange& rBounds(
+ basegfx::tools::getRange( rTargetForm ));
+
+ // setup rotation angle. VCL rotates
+ // counter-clockwise, while canvas transformation
+ // rotates clockwise
+ //fAngle = -fAngle;
+
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ {
+ // standard orientation for VCL linear
+ // gradient is vertical, thus, rotate 90
+ // degrees
+ fAngle += M_PI/2.0;
+
+ // shrink texture, to account for border
+ // (only in x direction, linear gradient
+ // is constant in y direction, anyway)
+ aTextureTransformation.scale(
+ basegfx::pruneScaleValue(1.0 - fBorder),
+ 1.0 );
+
+ double fBorderX(0.0);
+
+ // determine type of gradient (and necessary
+ // transformation matrix, should it be emulated by a
+ // generic gradient)
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ // linear gradients don't respect
+ // offsets (they are implicitely
+ // assumed to be 50%). linear
+ // gradients don't have border on
+ // both sides, only on the
+ // startColor side. Gradient is
+ // invariant in y direction: leave
+ // y offset alone.
+ fBorderX = fBorder;
+ aTexture.Gradient = xFactory->createLinearHorizontalGradient( aStartColor,
+ aEndColor );
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ // axial gradients have border on
+ // both sides. Gradient is
+ // invariant in y direction: leave
+ // y offset alone.
+ fBorderX = fBorder * .5;
+ aTexture.Gradient = xFactory->createAxialHorizontalGradient( aStartColor,
+ aEndColor );
+ break;
+ }
+
+ // apply border offset values
+ aTextureTransformation.translate( fBorderX,
+ 0.0 );
+
+ // rotate texture according to gradient rotation
+ aTextureTransformation.translate( -0.5, -0.5 );
+ aTextureTransformation.rotate( fAngle );
+
+ // to let the first strip of a rotated
+ // gradient start at the _edge_ of the
+ // bound rect (and not, due to rotation,
+ // slightly inside), slightly enlarge the
+ // gradient:
+ //
+ // y/2 sin(alpha) + x/2 cos(alpha)
+ //
+ // (values to change are not actual
+ // gradient scales, but original bound
+ // rect dimensions. Since we still want
+ // the border setting to apply after that,
+ // we multiply with that as above for
+ // nScaleX)
+ const double nScale(
+ ::basegfx::pruneScaleValue(
+ fabs( rBounds.getHeight()*sin(fAngle) ) +
+ fabs( rBounds.getWidth()*cos(fAngle) )));
+
+ aTextureTransformation.scale( nScale, nScale );
+
+ // translate back origin to center of
+ // primitive
+ aTextureTransformation.translate( 0.5*rBounds.getWidth(),
+ 0.5*rBounds.getHeight() );
+ break;
+ }
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ fprintf(stderr,"native gradient #2\n");
+
+ // determine scale factors for the gradient (must
+ // be scaled up from [0,1]x[0,1] rect to object
+ // bounds). Will potentially changed in switch
+ // statement below.
+ // Respect border value, while doing so, the VCL
+ // gradient's border will effectively shrink the
+ // resulting gradient.
+ double nScaleX( rBounds.getWidth() * (1.0 - fBorder) );
+ double nScaleY( rBounds.getHeight()* (1.0 - fBorder) );
+
+ // determine offset values. Since the
+ // border is divided half-by-half to both
+ // sides of the gradient, divide
+ // translation offset by an additional
+ // factor of 2. Also respect offset here,
+ // but since VCL gradients have their
+ // center at [0,0] for zero offset, but
+ // canvas gradients have their top, left
+ // edge aligned with the primitive, and
+ // offset of 50% effectively must yield
+ // zero shift. Both values will
+ // potentially be adapted in switch
+ // statement below.
+ double nOffsetX( rBounds.getWidth() *
+ (2.0 * fOffsetX - 1.0 + fBorder)*.5 );
+ double nOffsetY( rBounds.getHeight() *
+ (2.0 * fOffsetY - 1.0 + fBorder)*.5 );
+
+ // determine type of gradient (and necessary
+ // transformation matrix, should it be emulated by a
+ // generic gradient)
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ {
+ // create isotrophic scaling
+ if( nScaleX > nScaleY )
+ {
+ nOffsetY -= (nScaleX - nScaleY) * 0.5;
+ nScaleY = nScaleX;
+ }
+ else
+ {
+ nOffsetX -= (nScaleY - nScaleX) * 0.5;
+ nScaleX = nScaleY;
+ }
+
+ // enlarge gradient to match bound rect diagonal
+ aTextureTransformation.translate( -0.5, -0.5 );
+ const double nScale( hypot(rBounds.getWidth(),
+ rBounds.getHeight()) / nScaleX );
+ aTextureTransformation.scale( nScale, nScale );
+ aTextureTransformation.translate( 0.5, 0.5 );
+
+ aTexture.Gradient = xFactory->createEllipticalGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D(0.0,0.0,
+ 1.0,1.0) );
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ // enlarge gradient slightly
+ aTextureTransformation.translate( -0.5, -0.5 );
+ const double nSqrt2( sqrt(2.0) );
+ aTextureTransformation.scale( nSqrt2,nSqrt2 );
+ aTextureTransformation.translate( 0.5, 0.5 );
+
+ aTexture.Gradient = xFactory->createEllipticalGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D( rBounds.getMinX(),
+ rBounds.getMinY(),
+ rBounds.getMaxX(),
+ rBounds.getMaxY() ));
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ {
+ // create isotrophic scaling
+ if( nScaleX > nScaleY )
+ {
+ nOffsetY -= (nScaleX - nScaleY) * 0.5;
+ nScaleY = nScaleX;
+ }
+ else
+ {
+ nOffsetX -= (nScaleY - nScaleX) * 0.5;
+ nScaleX = nScaleY;
+ }
+
+ aTexture.Gradient = xFactory->createRectangularGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D(0.0,0.0,
+ 1.0,1.0));
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ aTexture.Gradient = xFactory->createRectangularGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D( rBounds.getMinX(),
+ rBounds.getMinY(),
+ rBounds.getMaxX(),
+ rBounds.getMaxY() ));
+ }
+ break;
+ }
+
+ nScaleX = basegfx::pruneScaleValue( nScaleX );
+ nScaleY = basegfx::pruneScaleValue( nScaleY );
+
+ aTextureTransformation.scale( nScaleX, nScaleY );
+
+ // rotate texture according to gradient rotation
+ aTextureTransformation.translate( -0.5*nScaleX, -0.5*nScaleY );
+ aTextureTransformation.rotate( fAngle );
+ aTextureTransformation.translate( 0.5*nScaleX, 0.5*nScaleY );
+
+ aTextureTransformation.translate( nOffsetX, nOffsetY );
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false,
+ "canvasProcessor::impDrawGradient(): 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).
+ aTextureTransformation.translate( rBounds.getMinX(),
+ rBounds.getMinY() );
+
+ ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
+ aTextureTransformation );
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = aTexture;
+
+ mxCanvas->fillTexturedPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm),
+ maViewState,
+ maRenderState,
+ aSeq );
+
+ // done, using native gradients
+ return;
+ }
+ }
+ else
+ {
+ // make sure steps is not too high/low
+ nSteps = impCalcGradientSteps(nSteps,
+ aOutlineRangePixel,
+ sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5));
+
+
+ ::std::vector< ::basegfx::B2DHomMatrix > aMatrices;
+ ::std::vector< ::basegfx::BColor > aColors;
+ ::basegfx::B2DPolygon aUnitPolygon;
+
+ if( drawinglayer::primitive::GRADIENTSTYLE_RADIAL == eGradientStyle ||
+ drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL == eGradientStyle)
+ {
+ const ::basegfx::B2DPoint aCircleCenter(0.5, 0.5);
+ aUnitPolygon = ::basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5);
+ aUnitPolygon = ::basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon);
+ }
+ else
+ {
+ aUnitPolygon = ::basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(0.0, 0.0, 1.0, 1.0));
+ }
+
+ // create geometries
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientLinear aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientAxial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientRadial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetY);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientElliptical aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientSquare aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientRect aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ }
+
+ // paint them with mask using the XOR method
+ if(aMatrices.size())
+ {
+ if(bSimple)
+ {
+ impDrawGradientSimple(rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ else
+ {
+ impDrawGradientComplex(rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ }
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+ // rendering support
+
+ // directdraw of text simple portion
+ void canvasProcessor::impRender_STXP(const textSimplePortionPrimitive& rTextCandidate)
+ {
+ const fontAttributes& rFontAttrs( rTextCandidate.getFontAttributes() );
+ rendering::FontRequest aFontRequest;
+
+ aFontRequest.FontDescription.FamilyName = rFontAttrs.maFamilyName;
+ aFontRequest.FontDescription.StyleName = rFontAttrs.maStyleName;
+ aFontRequest.FontDescription.IsSymbolFont = rFontAttrs.mbSymbol ? util::TriState_YES : util::TriState_NO;
+ aFontRequest.FontDescription.IsVertical = rFontAttrs.mbVertical ? util::TriState_YES : util::TriState_NO;
+
+ // TODO(F2): improve vclenum->panose conversion
+ aFontRequest.FontDescription.FontDescription.Weight =
+ rFontAttrs.mnWeight;
+ aFontRequest.FontDescription.FontDescription.Letterform =
+ rFontAttrs.mbItalic ? 9 : 0;
+
+ // font matrix should only be used for glyph rotations etc.
+ css::geometry::Matrix2D aFontMatrix;
+ canvas::tools::setIdentityMatrix2D( aFontMatrix );
+
+ uno::Reference<rendering::XCanvasFont> xFont(
+ mxCanvas->createFont( aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ aFontMatrix ));
+
+ if( !xFont.is() )
+ return;
+
+ uno::Reference<rendering::XTextLayout> xLayout(
+ xFont->createTextLayout(
+ rendering::StringContext( rTextCandidate.getText(),
+ 0,
+ rTextCandidate.getText().Len() ),
+ // TODO(F3): Is this sufficient?
+ rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
+ 0 ));
+ if( !xLayout.is() )
+ return;
+
+ xLayout->applyLogicalAdvancements(
+ uno::Sequence<double>(&rTextCandidate.getDXArray()[0],
+ rTextCandidate.getDXArray().size() ));
+
+ const ::basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rTextCandidate.getFontColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ // get render parameters and paint
+ mxCanvas->drawTextLayout( xLayout,
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of hairline
+ void canvasProcessor::impRender_POHL(const polygonHairlinePrimitive& rPolygonCandidate)
+ {
+ const ::basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ mxCanvas->drawPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rPolygonCandidate.getB2DPolygon()),
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of transformed BitmapEx primitive
+ void canvasProcessor::impRender_BMPR(const bitmapPrimitive& rBitmapCandidate)
+ {
+ BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
+
+ if(maBColorModifierStack.count())
+ {
+ // TODO(Q3): Share common bmp modification code with
+ // vclprocessor.cxx
+ Bitmap aChangedBitmap(impModifyBitmap(maBColorModifierStack, aBitmapEx.GetBitmap()));
+
+ if(aBitmapEx.IsTransparent())
+ {
+ if(aBitmapEx.IsAlpha())
+ aBitmapEx = BitmapEx(aChangedBitmap, aBitmapEx.GetAlpha());
+ else
+ aBitmapEx = BitmapEx(aChangedBitmap, aBitmapEx.GetMask());
+ }
+ else
+ aBitmapEx = BitmapEx(aChangedBitmap);
+ }
+
+ mxCanvas->drawBitmap(
+ vcl::unotools::xBitmapFromBitmapEx( mxCanvas->getDevice(),
+ aBitmapEx ),
+ maViewState,
+ maRenderState);
+ }
+
+ void canvasProcessor::impRender_PPLB(const polyPolygonBitmapPrimitive& rPolyBitmapCandidate )
+ {
+ const fillBitmapAttribute& rFillBmpAttr( rPolyBitmapCandidate.getFillBitmap() );
+ const basegfx::B2DPolyPolygon& rPoly( rPolyBitmapCandidate.getB2DPolyPolygon() );
+
+ // TODO(Q3): Share common bmp modification code with
+ // vclprocessor.cxx
+ Bitmap aChangedBitmap(
+ impModifyBitmap(maBColorModifierStack,
+ rFillBmpAttr.getBitmap()));
+
+ rendering::Texture aTexture;
+ const basegfx::B2DVector aBmpSize( rFillBmpAttr.getSize() );
+
+ const basegfx::B2DRange& rBounds(
+ basegfx::tools::getRange( rPoly ));
+
+ basegfx::B2DHomMatrix aScale;
+ aScale.scale( aBmpSize.getX() * rBounds.getWidth(),
+ aBmpSize.getY() * rBounds.getHeight() );
+
+ basegfx::unotools::affineMatrixFromHomMatrix(
+ aTexture.AffineTransform,
+ aScale );
+
+ aTexture.Alpha = 1.0;
+ aTexture.Bitmap =
+ ::vcl::unotools::xBitmapFromBitmapEx(
+ mxCanvas->getDevice(),
+ aChangedBitmap );
+ aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
+ aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
+
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = aTexture;
+
+ mxCanvas->fillTexturedPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rPoly),
+ maViewState,
+ maRenderState,
+ aSeq );
+ }
+
+ // direct draw of gradient
+ void canvasProcessor::impRender_PPLG(const polyPolygonGradientPrimitive& rPolygonCandidate)
+ {
+ const fillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
+ ::basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
+ ::basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
+ ::basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+
+ if(aStartColor == aEndColor)
+ {
+ // no gradient at all, draw as polygon
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aStartColor);
+
+ mxCanvas->drawPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aLocalPolyPolygon),
+ maViewState,
+ maRenderState );
+ }
+ else
+ {
+ // TODO(F3): if rGradient.getSteps() > 0, render
+ // gradient manually!
+ impDrawGradient(
+ aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(),
+ aStartColor, aEndColor, rGradient.getBorder(),
+ -rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), false);
+ }
+ }
+
+ // direct draw of PolyPolygon with color
+ void canvasProcessor::impRender_PPLC(const polyPolygonColorPrimitive& rPolygonCandidate)
+ {
+ const ::basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ mxCanvas->fillPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rPolygonCandidate.getB2DPolyPolygon()),
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of MetaFile
+ void canvasProcessor::impRender_META(const metafilePrimitive& rMetaCandidate)
+ {
+ // get metafile (copy it)
+ GDIMetaFile aMetaFile;
+
+ // TODO(Q3): Share common metafile modification code with
+ // vclprocessor.cxx
+ if(maBColorModifierStack.count())
+ {
+ const ::basegfx::BColor aRGBBaseColor(0, 0, 0);
+ const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
+ aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
+ }
+ else
+ {
+ aMetaFile = rMetaCandidate.getMetaFile();
+ }
+
+ cppcanvas::BitmapCanvasSharedPtr pCanvas(
+ cppcanvas::VCLFactory::getInstance().createCanvas(
+ uno::Reference<rendering::XBitmapCanvas>(
+ mxCanvas,
+ uno::UNO_QUERY_THROW) ));
+ cppcanvas::RendererSharedPtr pMtfRenderer(
+ cppcanvas::VCLFactory::getInstance().createRenderer(
+ pCanvas,
+ aMetaFile,
+ cppcanvas::Renderer::Parameters() ));
+ if( pMtfRenderer )
+ {
+ pCanvas->setTransformation(maWorldToView);
+ pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
+ pMtfRenderer->draw();
+ }
+ }
+
+ // mask group. Set mask polygon as clip
+ void canvasProcessor::impRender_MASK(const maskPrimitive& rMaskCandidate)
+ {
+ const primitiveVector& rSubList = rMaskCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ // TODO(F3): cannot use state-global renderstate, when recursing!
+ maRenderState.Clip =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rMaskCandidate.getMask());
+
+ // paint to it
+ process(rSubList);
+
+ maRenderState.Clip.clear();
+ }
+ }
+
+ // modified color group. Force output to unified color.
+ void canvasProcessor::impRender_MCOL(const modifiedColorPrimitive& rModifiedCandidate)
+ {
+ const primitiveVector& rSubList = rModifiedCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getPrimitiveVector());
+ maBColorModifierStack.pop();
+ }
+ }
+
+ // sub-transparence group. Draw to bitmap device first.
+ void canvasProcessor::impRender_TRPR(const transparencePrimitive& rTransCandidate)
+ {
+ const primitiveVector& rSubList = rTransCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ basegfx::B2DRange aRange(
+ get2DRangeFromVector(rSubList,
+ getViewInformation()));
+ aRange.transform(maWorldToView);
+ const basegfx::B2I64Tuple& rSize(
+ canvas::tools::spritePixelAreaFromB2DRange(aRange).getRange());
+ uno::Reference< rendering::XCanvas > xBitmap(
+ mxCanvas->getDevice()->createCompatibleAlphaBitmap(
+ css::geometry::IntegerSize2D(rSize.getX(),
+ rSize.getY())),
+ uno::UNO_QUERY_THROW);
+
+ // remember last worldToView and add pixel offset
+ ::basegfx::B2DHomMatrix aLastWorldToView(maWorldToView);
+ ::basegfx::B2DHomMatrix aPixelOffset;
+ aPixelOffset.translate(aRange.getMinX(),
+ aRange.getMinY());
+ setWorldToView(aPixelOffset * maWorldToView);
+
+ // remember last canvas, set bitmap as target
+ uno::Reference< rendering::XCanvas > xLastCanvas( mxCanvas );
+ mxCanvas = xBitmap;
+
+ // paint content to it
+ process(rSubList);
+
+ // TODO(F3): render transparent list to alpha
+ // channel. Note that the OutDev implementation has a
+ // shortcoming, in that nested transparency groups
+ // don't work - alpha is not combined properly.
+
+ // process(rTransCandidate.getTransparenceList());
+
+ // back to old OutDev and worldToView
+ mxCanvas = xLastCanvas;
+ setWorldToView(aLastWorldToView);
+
+ // DUMMY: add alpha modulation value to DeviceColor
+ // TODO(F3): color management
+ canvas::tools::setDeviceColor( maRenderState,
+ 1.0, 1.0, 1.0, 0.5 );
+ // finally, draw bitmap
+ mxCanvas->drawBitmapModulated(
+ uno::Reference< rendering::XBitmap >(
+ xBitmap,
+ uno::UNO_QUERY_THROW),
+ maViewState,
+ maRenderState );
+ }
+ }
+
+ // transform group.
+ void canvasProcessor::impRender_TRN2(const transformPrimitive& rTransformCandidate)
+ {
+ // remember current transformation
+ ::basegfx::B2DHomMatrix aLastWorldToView(maWorldToView);
+
+ // create new transformations
+ setWorldToView(maWorldToView * rTransformCandidate.getTransformation());
+
+ // let break down
+ process(rTransformCandidate.getPrimitiveVector());
+
+ // restore transformations
+ setWorldToView(aLastWorldToView);
+ }
+
+ // marker
+ void canvasProcessor::impRender_MARK(const markerPrimitive& rMarkCandidate)
+ {
+ const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rMarkCandidate.getRGBColor()));
+
+ canvas::tools::initRenderState(maMarkerRenderState);
+ maMarkerRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ // Markers are special objects - their position is
+ // determined by the view transformation, but their size
+ // is always the same
+ const basegfx::B2DPoint aViewPos(maWorldToView * rMarkCandidate.getPosition());
+
+ uno::Reference< rendering::XPolyPolygon2D > xMarkerPoly;
+ uno::Reference< rendering::XPolyPolygon2D > xHighlightMarkerPoly;
+ switch(rMarkCandidate.getStyle())
+ {
+ default:
+ case MARKERSTYLE_POINT:
+ mxCanvas->drawPoint( basegfx::unotools::point2DFromB2DPoint(aViewPos),
+ maMarkerViewState,
+ maMarkerRenderState );
+ return;
+
+ case MARKERSTYLE_CROSS:
+ if( !mxCrossMarkerPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-1 0 h2 m0 -1 v2" ));
+ mxCrossMarkerPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ xMarkerPoly = mxCrossMarkerPoly;
+ break;
+
+ case MARKERSTYLE_GLUEPOINT :
+ if( !mxGluePointPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-2 -3 l5 5 m-3 -2 l5 5 m-3 2 l5 -5 m-2 3 l5 -5" ));
+ mxGluePointPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ if( !mxGluePointHighlightPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-2 -2 l4 4 m-2 2 l4 -4" ));
+ mxGluePointHighlightPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ xMarkerPoly = mxGluePointPoly;
+ xHighlightMarkerPoly = mxGluePointHighlightPoly;
+ break;
+ }
+
+ basegfx::B2DRange aRange;
+ rMarkCandidate.getRealtiveViewRange(aRange);
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
+
+ basegfx::B2DHomMatrix aTranslate;
+ aTranslate.translate(aViewPos.getX()+aCenter.getX(),
+ aViewPos.getY()+aCenter.getY());
+
+ canvas::tools::setRenderStateTransform( maMarkerRenderState,
+ aTranslate );
+
+
+ mxCanvas->drawPolyPolygon( xMarkerPoly,
+ maMarkerViewState,
+ maMarkerRenderState );
+ if( xHighlightMarkerPoly.is() )
+ {
+ // TODO(F3): color management
+ canvas::tools::setDeviceColor(maMarkerRenderState,
+ 0.0, 0.0, 1.0, 1.0);
+ mxCanvas->drawPolyPolygon( xMarkerPoly,
+ maMarkerViewState,
+ maMarkerRenderState );
+ }
+ }
+
+ void canvasProcessor::setWorldToView(const basegfx::B2DHomMatrix& rMat)
+ {
+ maWorldToView = rMat;
+ canvas::tools::setViewStateTransform(maViewState,
+ maWorldToView);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // internal processing support
+
+ void canvasProcessor::process(const primitiveVector& rSource)
+ {
+ primitiveVector::const_iterator aCurr = rSource.begin();
+ const primitiveVector::const_iterator aEnd = rSource.end();
+ while( aCurr != aEnd )
+ {
+ const referencedPrimitive& rCandidate = *aCurr;
+
+ switch(rCandidate.getID())
+ {
+ case CreatePrimitiveID('S', 'T', 'X', 'P'):
+ {
+ // directdraw of text simple portion
+ impRender_STXP(static_cast< const textSimplePortionPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'O', 'H', 'L'):
+ {
+ // direct draw of hairline
+ impRender_POHL(static_cast< const polygonHairlinePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('B', 'M', 'P', 'R'):
+ {
+ // direct draw of transformed BitmapEx primitive
+ impRender_BMPR(static_cast< const bitmapPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('F', 'B', 'M', 'P'):
+ {
+ OSL_ENSURE(false,"fillBitmapPrimitive not yet implemented");
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'B'):
+ {
+ // direct draw of polygon with bitmap fill
+ impRender_PPLB(static_cast< const polyPolygonBitmapPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'G'):
+ {
+ // direct draw of gradient
+ impRender_PPLG(static_cast< const polyPolygonGradientPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'C'):
+ {
+ // direct draw of PolyPolygon with color
+ impRender_PPLC(static_cast< const polyPolygonColorPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'E', 'T', 'A'):
+ {
+ // direct draw of MetaFile
+ impRender_META(static_cast< const metafilePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'A', 'S', 'K'):
+ {
+ // mask group. Force output to VDev and create mask from given mask
+ impRender_MASK(static_cast< const maskPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'C', 'O', 'L'):
+ {
+ // modified color group. Force output to unified color.
+ impRender_MCOL(static_cast< const modifiedColorPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('T', 'R', 'P', 'R'):
+ {
+ // sub-transparence group. Draw to VDev first.
+ impRender_TRPR(static_cast< const transparencePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('T', 'R', 'N', '2'):
+ {
+ // transform group.
+ impRender_TRN2(static_cast< const transformPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'A', 'R', 'K'):
+ {
+ // marker
+ impRender_MARK(static_cast< const markerPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('A', 'N', 'S', 'W'):
+ case CreatePrimitiveID('A', 'N', 'B', 'L'):
+ case CreatePrimitiveID('A', 'N', 'I', 'N'):
+ {
+ // check timing, but do not accept
+ const animatedSwitchPrimitive& rAnimatedCandidate(static_cast< const animatedSwitchPrimitive& >(rCandidate.getBasePrimitive()));
+ const ::drawinglayer::animation::animationEntryList& rAnimationList = rAnimatedCandidate.getAnimationList();
+ const double fNewTime(rAnimationList.getNextEventTime(getViewInformation().getViewTime()));
+
+ // let break down
+ process(rAnimatedCandidate.getDecomposition(getViewInformation()));
+
+ break;
+ }
+
+ default:
+ {
+ // let break down
+ process(rCandidate.getBasePrimitive().getDecomposition(getViewInformation()));
+ }
+ }
+
+ ++aCurr;
+ }
+ }
+
+ canvasProcessor::canvasProcessor( const ::drawinglayer::geometry::viewInformation& rViewInformation,
+ const uno::Reference<rendering::XCanvas>& rCanvas ) :
+ processor(rViewInformation),
+ mxCanvas( rCanvas ),
+ mxCrossMarkerPoly(),
+ mxGluePointPoly(),
+ mxGluePointHighlightPoly(),
+ maBColorModifierStack(),
+ maWorldToView(),
+ maViewState(),
+ maRenderState(),
+ maMarkerViewState(),
+ maMarkerRenderState()
+ {
+ canvas::tools::initViewState(maViewState);
+ canvas::tools::initRenderState(maRenderState);
+ canvas::tools::initViewState(maMarkerViewState);
+ canvas::tools::initRenderState(maMarkerRenderState);
+
+ maWorldToView = maViewInformation.getViewTransformation();
+
+ canvas::tools::setViewStateTransform(maViewState,
+ maWorldToView);
+ }
+
+ canvasProcessor::~canvasProcessor()
+ {}
+*/
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+
+ //////////////////////////////////////////////////////////////////////////////
+ // internal processing support
+ void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ // direct draw of hairline
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
+ mxCanvas->drawPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()), maViewState, maRenderState);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ // direct draw of PolyPolygon with color
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
+ mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()), maViewState, maRenderState);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ // modified color group. Force output to unified color.
+ const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
+
+ if(rModifiedCandidate.getChildren().hasElements())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // transform group.
+ const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
+ const basegfx::B2DHomMatrix aLastCurrentTransformation(maCurrentTransformation);
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for CurrentTransformation
+ // and for local ViewInformation2D
+ maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
+ maViewInformation2D = geometry::ViewInformation2D(
+ getViewInformation2D().getViewTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getViewTime());
+
+ // set at canvas
+ canvas::tools::setViewStateTransform(maViewState, maCurrentTransformation);
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ maCurrentTransformation = aLastCurrentTransformation;
+ maViewInformation2D = aLastViewInformation2D;
+
+ // restore at canvas
+ canvas::tools::setViewStateTransform(maViewState, maCurrentTransformation);
+
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ break;
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // process support
+
+ void canvasProcessor2D::process(const primitive2d::Primitive2DSequence& rSource)
+ {
+ if(rSource.hasElements())
+ {
+ const sal_Int32 nCount(rSource.getLength());
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ // get reference
+ const primitive2d::Primitive2DReference xReference(rSource[a]);
+
+ if(xReference.is())
+ {
+ // try to cast to BasePrimitive2D implementation
+ const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
+
+ if(pBasePrimitive)
+ {
+ // it is a BasePrimitive2D implementation, use local processor
+ processBasePrimitive2D(*pBasePrimitive);
+ }
+ else
+ {
+ // unknown implementation, use UNO API call instead and process recursively
+ com::sun::star::graphic::Primitive2DParameters aPrimitive2DParameters;
+
+ basegfx::unotools::affineMatrixFromHomMatrix(aPrimitive2DParameters.ViewTransformation, getViewInformation2D().getViewTransformation());
+ aPrimitive2DParameters.Viewport = basegfx::unotools::rectangle2DFromB2DRectangle(getViewInformation2D().getViewport());
+ aPrimitive2DParameters.Time = getViewInformation2D().getViewTime();
+
+ process(xReference->getDecomposition(aPrimitive2DParameters));
+ }
+ }
+ }
+ }
+ }
+
+ canvasProcessor2D::canvasProcessor2D(
+ const geometry::ViewInformation2D& rViewInformation,
+ const uno::Reference< rendering::XCanvas >& rCanvas)
+ : BaseProcessor2D(rViewInformation),
+ mxCanvas( rCanvas ),
+ maViewState(),
+ maRenderState(),
+ maBColorModifierStack(),
+ maCurrentTransformation(),
+ maDrawinglayerOpt(),
+ mnPolygonStrokePrimitive2D(0),
+ meLang(LANGUAGE_SYSTEM)
+ {
+ const SvtCTLOptions aSvtCTLOptions;
+
+ canvas::tools::initViewState(maViewState);
+ canvas::tools::initRenderState(maRenderState);
+ maCurrentTransformation = getViewInformation2D().getViewTransformation();
+ canvas::tools::setViewStateTransform(maViewState, maCurrentTransformation);
+
+ if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ meLang = LANGUAGE_ARABIC;
+ }
+ else if(SvtCTLOptions::NUMERALS_ARABIC == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ meLang = LANGUAGE_ENGLISH;
+ }
+ else
+ {
+ meLang = (LanguageType)Application::GetSettings().GetLanguage();
+ }
+ }
+
+ canvasProcessor2D::~canvasProcessor2D()
+ {
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/makefile.mk b/drawinglayer/source/processor2d/makefile.mk
index 2d185d0e8af6..5e74c10cffc3 100644
--- a/drawinglayer/source/processor2d/makefile.mk
+++ b/drawinglayer/source/processor2d/makefile.mk
@@ -4,9 +4,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.4 $
+# $Revision: 1.5 $
#
-# last change: $Author: aw $ $Date: 2007-07-27 09:03:33 $
+# last change: $Author: aw $ $Date: 2007-12-18 15:10:27 $
#
# The Contents of this file are made available subject to
# the terms of GNU Lesser General Public License Version 2.1.
@@ -52,7 +52,8 @@ SLOFILES= \
$(SLO)$/vclhelperbufferdevice.obj \
$(SLO)$/vclprocessor2d.obj \
$(SLO)$/vclpixelprocessor2d.obj \
- $(SLO)$/vclmetafileprocessor2d.obj
+ $(SLO)$/vclmetafileprocessor2d.obj \
+ $(SLO)$/canvasprocessor.obj
# --- Targets ----------------------------------
diff --git a/drawinglayer/util/makefile.mk b/drawinglayer/util/makefile.mk
index 90d87767c208..ef4427294f15 100644
--- a/drawinglayer/util/makefile.mk
+++ b/drawinglayer/util/makefile.mk
@@ -4,9 +4,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.9 $
+# $Revision: 1.10 $
#
-# last change: $Author: aw $ $Date: 2007-10-16 15:46:52 $
+# last change: $Author: aw $ $Date: 2007-12-18 15:10:54 $
#
# The Contents of this file are made available subject to
# the terms of GNU Lesser General Public License Version 2.1.
@@ -65,6 +65,7 @@ SHL1STDLIBS=\
$(TOOLSLIB) \
$(SVLLIB) \
$(TKLIB) \
+ $(CANVASTOOLSLIB) \
$(SVTOOLLIB) \
$(SALLIB) \
$(CPPUHELPERLIB) \