summaryrefslogtreecommitdiff
path: root/drawinglayer/source
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2011-12-19 15:41:21 +0000
committerArmin Le Grand <alg@apache.org>2011-12-19 15:41:21 +0000
commite2e16715893229b5d0ad2da6c8e84464e0c43a2e (patch)
tree79d1c632784b3de16fc82c1dfc27c1796a9ef451 /drawinglayer/source
parentea4f454ed956e08be47783b3bddd7789f905e350 (diff)
Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement to trunk, first version of Svg stable and done
Diffstat (limited to 'drawinglayer/source')
-rw-r--r--drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx95
-rw-r--r--drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx223
-rw-r--r--drawinglayer/source/primitive2d/baseprimitive2d.cxx21
-rw-r--r--drawinglayer/source/primitive2d/cropprimitive2d.cxx202
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitive2d.cxx165
-rw-r--r--drawinglayer/source/primitive2d/metafileprimitive2d.cxx28
-rw-r--r--drawinglayer/source/primitive2d/patternfillprimitive2d.cxx158
-rw-r--r--drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx92
-rw-r--r--drawinglayer/source/primitive2d/svggradientprimitive2d.cxx1249
-rw-r--r--drawinglayer/source/primitive2d/textbreakuphelper.cxx294
-rw-r--r--drawinglayer/source/processor2d/hittestprocessor2d.cxx1
-rw-r--r--drawinglayer/source/processor2d/linegeometryextractor2d.cxx1
-rw-r--r--drawinglayer/source/processor2d/textaspolygonextractor2d.cxx1
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx10
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx7
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx71
-rw-r--r--drawinglayer/source/processor3d/shadow3dextractor.cxx27
-rw-r--r--drawinglayer/source/tools/converters.cxx143
18 files changed, 2458 insertions, 330 deletions
diff --git a/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx b/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx
new file mode 100644
index 000000000000..8ead3d1023b9
--- /dev/null
+++ b/drawinglayer/source/drawinglayeruno/drawinglayeruno.cxx
@@ -0,0 +1,95 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http:\\www.apache.org\licenses\LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/drawinglayerdllapi.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <uno/environment.h>
+#include <cppuhelper/factory.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+namespace drawinglayer
+{
+ namespace unorenderer
+ {
+ extern uno::Sequence< rtl::OUString > SAL_CALL XPrimitive2DRenderer_getSupportedServiceNames();
+ extern rtl::OUString SAL_CALL XPrimitive2DRenderer_getImplementationName();
+ extern uno::Reference< uno::XInterface > SAL_CALL XPrimitive2DRenderer_createInstance( const uno::Reference< lang::XMultiServiceFactory > & );
+ } // end of namespace unorenderer
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// component_getImplementationEnvironment
+
+extern "C"
+{
+ DRAWINGLAYER_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
+ {
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// component_getFactory
+
+extern "C"
+{
+ DRAWINGLAYER_DLLPUBLIC void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ )
+ {
+ uno::Reference< lang::XSingleServiceFactory > xFactory;
+ void* pRet = 0;
+
+ if(drawinglayer::unorenderer::XPrimitive2DRenderer_getImplementationName().equalsAscii(pImplName))
+ {
+ xFactory = ::cppu::createSingleFactory(
+ reinterpret_cast< lang::XMultiServiceFactory * >(pServiceManager),
+ drawinglayer::unorenderer::XPrimitive2DRenderer_getImplementationName(),
+ drawinglayer::unorenderer::XPrimitive2DRenderer_createInstance,
+ drawinglayer::unorenderer::XPrimitive2DRenderer_getSupportedServiceNames());
+ }
+
+ if(xFactory.is())
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+
+ return pRet;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx
new file mode 100644
index 000000000000..c6667ad2319f
--- /dev/null
+++ b/drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx
@@ -0,0 +1,223 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http:\\www.apache.org\licenses\LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <com/sun/star/graphic/XPrimitive2DRenderer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <comphelper/processfactory.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <vcl/bitmapex.hxx>
+#include <drawinglayer/tools/converters.hxx>
+#include <vcl/canvastools.hxx>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace unorenderer
+ {
+ class XPrimitive2DRenderer : public ::cppu::WeakAggImplHelper2< graphic::XPrimitive2DRenderer, lang::XServiceInfo >
+ {
+ private:
+ XPrimitive2DRenderer(const XPrimitive2DRenderer&);
+ XPrimitive2DRenderer& operator=(const XPrimitive2DRenderer&);
+
+ protected:
+ public:
+ XPrimitive2DRenderer();
+ virtual ~XPrimitive2DRenderer();
+
+ // XPrimitive2DRenderer
+ virtual uno::Reference< rendering::XBitmap > SAL_CALL rasterize(
+ const uno::Sequence< uno::Reference< graphic::XPrimitive2D > >& Primitive2DSequence,
+ const uno::Sequence< beans::PropertyValue >& aViewInformationSequence,
+ ::sal_uInt32 DPI_X,
+ ::sal_uInt32 DPI_Y,
+ const ::com::sun::star::geometry::RealRectangle2D& Range,
+ ::sal_uInt32 MaximumQuadraticPixels) throw (uno::RuntimeException);
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName() throw(uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL supportsService(const rtl::OUString&) throw(uno::RuntimeException);
+ virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw(uno::RuntimeException);
+ };
+ } // end of namespace unorenderer
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// uno functions
+
+namespace drawinglayer
+{
+ namespace unorenderer
+ {
+ uno::Sequence< rtl::OUString > XPrimitive2DRenderer_getSupportedServiceNames()
+ {
+ static rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.Primitive2DTools" ) );
+ static uno::Sequence< rtl::OUString > aServiceNames( &aServiceName, 1 );
+
+ return( aServiceNames );
+ }
+
+ rtl::OUString XPrimitive2DRenderer_getImplementationName()
+ {
+ return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "drawinglayer::unorenderer::XPrimitive2DRenderer" ) );
+ }
+
+ uno::Reference< uno::XInterface > SAL_CALL XPrimitive2DRenderer_createInstance(const uno::Reference< lang::XMultiServiceFactory >&)
+ {
+ return static_cast< ::cppu::OWeakObject* >(new XPrimitive2DRenderer);
+ }
+ } // end of namespace unorenderer
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace unorenderer
+ {
+ XPrimitive2DRenderer::XPrimitive2DRenderer()
+ {
+ }
+
+ XPrimitive2DRenderer::~XPrimitive2DRenderer()
+ {
+ }
+
+ uno::Reference< rendering::XBitmap > XPrimitive2DRenderer::rasterize(
+ const uno::Sequence< uno::Reference< graphic::XPrimitive2D > >& Primitive2DSequence,
+ const uno::Sequence< beans::PropertyValue >& aViewInformationSequence,
+ ::sal_uInt32 DPI_X,
+ ::sal_uInt32 DPI_Y,
+ const ::com::sun::star::geometry::RealRectangle2D& Range,
+ ::sal_uInt32 MaximumQuadraticPixels) throw (uno::RuntimeException)
+ {
+ uno::Reference< rendering::XBitmap > XBitmap;
+
+ if(Primitive2DSequence.hasElements())
+ {
+ const basegfx::B2DRange aRange(Range.X1, Range.Y1, Range.X2, Range.Y2);
+ const double fWidth(aRange.getWidth());
+ const double fHeight(aRange.getHeight());
+
+ if(basegfx::fTools::more(fWidth, 0.0) && basegfx::fTools::more(fHeight, 0.0))
+ {
+ if(0 == DPI_X)
+ {
+ DPI_X = 75;
+ }
+
+ if(0 == DPI_Y)
+ {
+ DPI_Y = 75;
+ }
+
+ if(0 == MaximumQuadraticPixels)
+ {
+ MaximumQuadraticPixels = 500000;
+ }
+
+ const geometry::ViewInformation2D aViewInformation2D(aViewInformationSequence);
+ const double fFactor100th_mmToInch(2.54/1000.0);
+ const sal_uInt32 nDiscreteWidth(basegfx::fround((fWidth * fFactor100th_mmToInch) * DPI_X));
+ const sal_uInt32 nDiscreteHeight(basegfx::fround((fHeight * fFactor100th_mmToInch) * DPI_Y));
+
+ basegfx::B2DHomMatrix aEmbedding(
+ basegfx::tools::createTranslateB2DHomMatrix(
+ -aRange.getMinX(),
+ -aRange.getMinY()));
+
+ aEmbedding.scale(
+ nDiscreteWidth / fWidth,
+ nDiscreteHeight / fHeight);
+
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(
+ aEmbedding,
+ Primitive2DSequence));
+ const primitive2d::Primitive2DSequence xEmbedSeq(&xEmbedRef, 1);
+
+ BitmapEx aBitmapEx(
+ tools::convertToBitmapEx(
+ xEmbedSeq,
+ aViewInformation2D,
+ nDiscreteWidth,
+ nDiscreteHeight,
+ MaximumQuadraticPixels));
+
+ if(!aBitmapEx.IsEmpty())
+ {
+ const uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
+
+ aBitmapEx.SetPrefMapMode(MapMode(MAP_100TH_MM));
+ aBitmapEx.SetPrefSize(Size(basegfx::fround(fWidth), basegfx::fround(fHeight)));
+ XBitmap = vcl::unotools::xBitmapFromBitmapEx(xGraphicDevice, aBitmapEx);
+ }
+ }
+ }
+
+ return XBitmap;
+ }
+
+ rtl::OUString SAL_CALL XPrimitive2DRenderer::getImplementationName() throw(uno::RuntimeException)
+ {
+ return(XPrimitive2DRenderer_getImplementationName());
+ }
+
+ sal_Bool SAL_CALL XPrimitive2DRenderer::supportsService(const rtl::OUString& rServiceName) throw(uno::RuntimeException)
+ {
+ const uno::Sequence< rtl::OUString > aServices(XPrimitive2DRenderer_getSupportedServiceNames());
+
+ for(sal_Int32 nService(0); nService < aServices.getLength(); nService++)
+ {
+ if(rServiceName == aServices[nService])
+ {
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+ }
+
+ uno::Sequence< rtl::OUString > SAL_CALL XPrimitive2DRenderer::getSupportedServiceNames() throw(uno::RuntimeException)
+ {
+ return XPrimitive2DRenderer_getSupportedServiceNames();
+ }
+
+ } // end of namespace unorenderer
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx
index 8f5d7b14a157..868305b45208 100644
--- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx
@@ -115,6 +115,27 @@ namespace drawinglayer
{
namespace primitive2d
{
+ // convert helper stl vector of primitives to Primitive2DSequence
+ Primitive2DSequence Primitive2DVectorToPrimitive2DSequence(const Primitive2DVector& rSource, bool bInvert)
+ {
+ const sal_uInt32 nSize(rSource.size());
+ Primitive2DSequence aRetval;
+
+ aRetval.realloc(nSize);
+
+ for(sal_uInt32 a(0); a < nSize; a++)
+ {
+ aRetval[bInvert ? nSize - 1 - a : a] = rSource[a];
+ }
+
+ // all entries taken over to Uno References as owners. To avoid
+ // errors with users of this mechanism to delete pointers to BasePrimitive2D
+ // itself, clear given vector
+ const_cast< Primitive2DVector& >(rSource).clear();
+
+ return aRetval;
+ }
+
// get B2DRange from a given Primitive2DReference
basegfx::B2DRange getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate, const geometry::ViewInformation2D& aViewInformation)
{
diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
new file mode 100644
index 000000000000..f4b6e82b9df0
--- /dev/null
+++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
@@ -0,0 +1,202 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive2d/cropprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ CropPrimitive2D::CropPrimitive2D(
+ const Primitive2DSequence& rChildren,
+ const basegfx::B2DHomMatrix& rTransformation,
+ double fCropLeft,
+ double fCropTop,
+ double fCropRight,
+ double fCropBottom)
+ : GroupPrimitive2D(rChildren),
+ maTransformation(rTransformation),
+ mfCropLeft(fCropLeft),
+ mfCropTop(fCropTop),
+ mfCropRight(fCropRight),
+ mfCropBottom(fCropBottom)
+ {
+ }
+
+ bool CropPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(GroupPrimitive2D::operator==(rPrimitive))
+ {
+ const CropPrimitive2D& rCompare = static_cast< const CropPrimitive2D& >(rPrimitive);
+
+ return (getTransformation() == rCompare.getTransformation()
+ && getCropLeft() == rCompare.getCropLeft()
+ && getCropTop() == rCompare.getCropTop()
+ && getCropRight() == rCompare.getCropRight()
+ && getCropBottom() == rCompare.getCropBottom());
+ }
+
+ return false;
+ }
+
+ Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DSequence xRetval;
+
+ if(getChildren().hasElements())
+ {
+ // decompose to have current translate and scale
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+
+ getTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // detect 180 degree rotation, this is the same as mirrored in X and Y,
+ // thus change to mirroring. Prefer mirroring here. Use the equal call
+ // with getSmallValue here, the original which uses rtl::math::approxEqual
+ // is too correct here. Maybe this changes with enhanced precision in aw080
+ // to the better so that this can be reduced to the more precise call again
+ if(basegfx::fTools::equal(fRotate, F_PI, 0.000000001))
+ {
+ aScale.setX(aScale.getX() * -1.0);
+ aScale.setY(aScale.getY() * -1.0);
+ fRotate = 0.0;
+ }
+
+ // create target translate and scale
+ const bool bMirroredX(aScale.getX() < 0.0);
+ const bool bMirroredY(aScale.getY() < 0.0);
+ basegfx::B2DVector aTargetScale(aScale);
+ basegfx::B2DVector aTargetTranslate(aTranslate);
+
+ if(bMirroredX)
+ {
+ aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight());
+ aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight());
+ }
+ else
+ {
+ aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft());
+ aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft());
+ }
+
+ if(bMirroredY)
+ {
+ aTargetTranslate.setY(aTargetTranslate.getY() + getCropBottom());
+ aTargetScale.setY(aTargetScale.getY() - getCropTop() - getCropBottom());
+ }
+ else
+ {
+ aTargetTranslate.setY(aTargetTranslate.getY() - getCropTop());
+ aTargetScale.setY(aTargetScale.getY() + getCropBottom() + getCropTop());
+ }
+
+ // create ranges to make comparisons
+ const basegfx::B2DRange aCurrent(
+ aTranslate.getX(), aTranslate.getY(),
+ aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
+ const basegfx::B2DRange aCropped(
+ aTargetTranslate.getX(), aTargetTranslate.getY(),
+ aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
+
+ if(aCropped.isEmpty())
+ {
+ // nothing to return since cropped content is completely empty
+ }
+ else if(aCurrent.equal(aCropped))
+ {
+ // no crop, just use content
+ xRetval = getChildren();
+ }
+ else
+ {
+ // build new combined content transformation
+ basegfx::B2DHomMatrix aNewObjectTransform(getTransformation());
+
+ // remove content transform by inverting
+ aNewObjectTransform.invert();
+
+ // add target values and original shear/rotate
+ aNewObjectTransform = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
+ aTargetScale.getX(),
+ aTargetScale.getY(),
+ fShearX,
+ fRotate,
+ aTargetTranslate.getX(),
+ aTargetTranslate.getY())
+ * aNewObjectTransform;
+
+ // prepare TransformPrimitive2D with xPrimitive
+ const Primitive2DReference xTransformPrimitive(
+ new TransformPrimitive2D(
+ aNewObjectTransform,
+ getChildren()));
+
+ if(aCurrent.isInside(aCropped))
+ {
+ // crop just shrunk so that its inside content,
+ // no need to use a mask since not really cropped.
+ xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
+ }
+ else
+ {
+ // mask with original object's bounds
+ basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
+ aMaskPolyPolygon.transform(getTransformation());
+
+ // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
+ const Primitive2DReference xMask(
+ new MaskPrimitive2D(
+ aMaskPolyPolygon,
+ Primitive2DSequence(&xTransformPrimitive, 1)));
+
+ xRetval = Primitive2DSequence(&xMask, 1);
+ }
+ }
+ }
+
+ return xRetval;
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
index f7a3930610d1..0703f9225b45 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -27,14 +27,14 @@
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
#include <drawinglayer/animation/animationtiming.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
-#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/cropprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
//////////////////////////////////////////////////////////////////////////////
// helper class for animated graphics
@@ -259,8 +259,8 @@ namespace drawinglayer
aSuppressGraphicAttr.SetRotation(0);
aSuppressGraphicAttr.SetMirrorFlags(0);
- const GraphicObject& rGraphicObject = getGraphicObject();
- const Graphic aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr));
+ const GraphicObject& rGraphicObject = getGraphicObject();
+ const Graphic aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr));
switch(aTransformedGraphic.GetType())
{
@@ -293,6 +293,32 @@ namespace drawinglayer
xPrimitive = Primitive2DReference(new AnimatedSwitchPrimitive2D(aAnimationList, aBitmapPrimitives, false));
}
}
+ else if(aTransformedGraphic.getSvgData().get())
+ {
+ // embedded Svg fill, create embed transform
+ const basegfx::B2DRange& rSvgRange(aTransformedGraphic.getSvgData()->getRange());
+
+ if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0))
+ {
+ // translate back to origin, scale to unit coordinates
+ basegfx::B2DHomMatrix aEmbedSvg(
+ basegfx::tools::createTranslateB2DHomMatrix(
+ -rSvgRange.getMinX(),
+ -rSvgRange.getMinY()));
+
+ aEmbedSvg.scale(
+ 1.0 / rSvgRange.getWidth(),
+ 1.0 / rSvgRange.getHeight());
+
+ // apply created object transformation
+ aEmbedSvg = aTransform * aEmbedSvg;
+
+ // add Svg primitives embedded
+ xPrimitive = new TransformPrimitive2D(
+ aEmbedSvg,
+ aTransformedGraphic.getSvgData()->getPrimitive2DSequence());
+ }
+ }
else
{
xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), aTransform));
@@ -745,41 +771,31 @@ namespace drawinglayer
// create MetafilePrimitive2D
const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile();
- if( aTransformedGraphic.IsRenderGraphic() )
+ xPrimitive = Primitive2DReference(
+ new MetafilePrimitive2D(
+ aTransform,
+ rMetafile));
+
+ // #i100357# find out if clipping is needed for this primitive. Unfortunately,
+ // there exist Metafiles who's content is bigger than the proposed PrefSize set
+ // at them. This is an error, but we need to work around this
+ const Size aMetaFilePrefSize(rMetafile.GetPrefSize());
+ const Size aMetaFileRealSize(
+ const_cast< GDIMetaFile& >(rMetafile).GetBoundRect(
+ *Application::GetDefaultDevice()).GetSize());
+
+ if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth()
+ || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight())
{
+ // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon
+ const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1);
+ basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon());
+ aMaskPolygon.transform(aTransform);
+
xPrimitive = Primitive2DReference(
- new RenderGraphicPrimitive2D(
- static_cast< MetaRenderGraphicAction* >(rMetafile.GetAction(0))->GetRenderGraphic(),
- aTransform));
- }
- else
- {
- xPrimitive = Primitive2DReference(
- new MetafilePrimitive2D(
- aTransform,
- rMetafile));
-
- // #i100357# find out if clipping is needed for this primitive. Unfortunately,
- // there exist Metafiles who's content is bigger than the proposed PrefSize set
- // at them. This is an error, but we need to work around this
- const Size aMetaFilePrefSize(rMetafile.GetPrefSize());
- const Size aMetaFileRealSize(
- const_cast< GDIMetaFile& >(rMetafile).GetBoundRect(
- *Application::GetDefaultDevice()).GetSize());
-
- if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth()
- || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight())
- {
- // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon
- const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1);
- basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon());
- aMaskPolygon.transform(aTransform);
-
- xPrimitive = Primitive2DReference(
- new MaskPrimitive2D(
- basegfx::B2DPolyPolygon(aMaskPolygon),
- aChildContent));
- }
+ new MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(aMaskPolygon),
+ aChildContent));
}
#ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
}
@@ -800,16 +816,6 @@ namespace drawinglayer
// check for cropping
if(getGraphicAttr().IsCropped())
{
- // decompose to get current pos and size
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
-
- // create ranges. The current object range is just scale and translate
- const basegfx::B2DRange aCurrent(
- aTranslate.getX(), aTranslate.getY(),
- aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
-
// calculate scalings between real image size and logic object size. This
// is necessary since the crop values are relative to original bitmap size
double fFactorX(1.0);
@@ -831,68 +837,31 @@ namespace drawinglayer
const double fDivX(aBitmapSize.Width() - getGraphicAttr().GetLeftCrop() - getGraphicAttr().GetRightCrop());
const double fDivY(aBitmapSize.Height() - getGraphicAttr().GetTopCrop() - getGraphicAttr().GetBottomCrop());
+ const basegfx::B2DVector aScale(aTransform * basegfx::B2DVector(1.0, 1.0));
if(!basegfx::fTools::equalZero(fDivX))
{
- fFactorX = aScale.getX() / fDivX;
+ fFactorX = fabs(aScale.getX()) / fDivX;
}
if(!basegfx::fTools::equalZero(fDivY))
{
- fFactorY = aScale.getY() / fDivY;
+ fFactorY = fabs(aScale.getY()) / fDivY;
}
}
- // Create cropped range, describes the bounds of the original graphic
- basegfx::B2DRange aCropped;
- aCropped.expand(aCurrent.getMinimum() - basegfx::B2DPoint(getGraphicAttr().GetLeftCrop() * fFactorX, getGraphicAttr().GetTopCrop() * fFactorY));
- aCropped.expand(aCurrent.getMaximum() + basegfx::B2DPoint(getGraphicAttr().GetRightCrop() * fFactorX, getGraphicAttr().GetBottomCrop() * fFactorY));
-
- if(aCropped.isEmpty())
- {
- // nothing to add since cropped bitmap is completely empty
- // xPrimitive will not be used
- }
- else
- {
- // build new object transformation for transform primitive which contains xPrimitive
- basegfx::B2DHomMatrix aNewObjectTransform(getTransform());
- aNewObjectTransform.invert();
- aNewObjectTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
- aCropped.getWidth(), aCropped.getHeight(),
- aCropped.getMinX() - aCurrent.getMinX(), aCropped.getMinY() - aCurrent.getMinY())
- * aNewObjectTransform;
-
- // add shear, rotate and translate using combined matrix to speedup
- const basegfx::B2DHomMatrix aCombinedMatrix(basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
- fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
- aNewObjectTransform = aCombinedMatrix * aNewObjectTransform;
-
- // prepare TransformPrimitive2D with xPrimitive
- const Primitive2DReference xTransformPrimitive(new TransformPrimitive2D(aNewObjectTransform, Primitive2DSequence(&xPrimitive, 1L)));
-
- if(aCurrent.isInside(aCropped))
- {
- // cropped just got smaller, no need to really use a mask. Add to destination directly
- appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xTransformPrimitive);
- }
- else
- {
- // cropped got bigger, mask it with original object's bounds
- basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
- aMaskPolyPolygon.transform(getTransform());
-
- // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
- const Primitive2DReference xRefB(new MaskPrimitive2D(aMaskPolyPolygon, Primitive2DSequence(&xTransformPrimitive, 1L)));
- appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRefB);
- }
- }
- }
- else
- {
- // add to decomposition
- appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive);
+ // embed content in cropPrimitive
+ xPrimitive = new CropPrimitive2D(
+ Primitive2DSequence(&xPrimitive, 1),
+ aTransform,
+ getGraphicAttr().GetLeftCrop() * fFactorX,
+ getGraphicAttr().GetTopCrop() * fFactorY,
+ getGraphicAttr().GetRightCrop() * fFactorX,
+ getGraphicAttr().GetBottomCrop() * fFactorY);
}
+
+ // add to decomposition
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive);
}
}
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 4d11fe523754..a3eff771d4da 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -59,7 +59,6 @@
#include <drawinglayer/primitive2d/textlineprimitive2d.hxx>
#include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx>
#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
#include <numeric>
//////////////////////////////////////////////////////////////////////////////
@@ -3065,33 +3064,6 @@ namespace
break;
}
- case META_RENDERGRAPHIC_ACTION :
- {
- const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*)pAction;
- const Rectangle aRectangle(pA->GetPoint(), pA->GetSize());
-
- if(!aRectangle.IsEmpty())
- {
- // create object transform
- basegfx::B2DHomMatrix aObjectTransform;
-
- aObjectTransform.set(0, 0, aRectangle.GetWidth());
- aObjectTransform.set(1, 1, aRectangle.GetHeight());
- aObjectTransform.set(0, 2, aRectangle.Left());
- aObjectTransform.set(1, 2, aRectangle.Top());
-
- // add current transformation
- aObjectTransform = rPropertyHolders.Current().getTransformation() * aObjectTransform;
-
- // embed using EpsPrimitive
- rTargetHolders.Current().append(
- new drawinglayer::primitive2d::RenderGraphicPrimitive2D(
- pA->GetRenderGraphic(),
- aObjectTransform ) );
- }
-
- break;
- }
case META_COMMENT_ACTION :
{
/** CHECKED, WORKS WELL */
diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
new file mode 100644
index 000000000000..3c334d2770c9
--- /dev/null
+++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
@@ -0,0 +1,158 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive2d/patternfillprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/texture/texture.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DSequence PatternFillPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ Primitive2DSequence aRetval;
+
+ if(getChildren().hasElements())
+ {
+ if(!getReferenceRange().isEmpty() && getReferenceRange().getWidth() > 0.0 && getReferenceRange().getHeight() > 0.0)
+ {
+ const basegfx::B2DRange aMaskRange(getMask().getB2DRange());
+
+ if(!aMaskRange.isEmpty() && aMaskRange.getWidth() > 0.0 && aMaskRange.getHeight() > 0.0)
+ {
+ // create tiling matrices
+ ::std::vector< basegfx::B2DHomMatrix > aMatrices;
+ texture::GeoTexSvxTiled aTiling(getReferenceRange().getMinimum(), getReferenceRange().getRange());
+ aTiling.appendTransformations(aMatrices);
+
+ // check if content needs to be clipped
+ const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+ const basegfx::B2DRange aContentRange(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation));
+ Primitive2DSequence aContent(getChildren());
+
+ if(!aUnitRange.isInside(aContentRange))
+ {
+ const Primitive2DReference xRef(
+ new MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aUnitRange)),
+ aContent));
+
+ aContent = Primitive2DSequence(&xRef, 1);
+ }
+
+ // resize result
+ aRetval.realloc(aMatrices.size());
+
+ // create one primitive for each matrix
+ for(sal_uInt32 a(0); a < aMatrices.size(); a++)
+ {
+ aRetval[a] = new TransformPrimitive2D(
+ aMatrices[a],
+ aContent);
+ }
+
+ // transform result which is in unit coordinates to mask's object coordiantes
+ {
+ const basegfx::B2DHomMatrix aMaskTransform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aMaskRange.getRange(),
+ aMaskRange.getMinimum()));
+
+ const Primitive2DReference xRef(
+ new TransformPrimitive2D(
+ aMaskTransform,
+ aRetval));
+
+ aRetval = Primitive2DSequence(&xRef, 1);
+ }
+
+ // embed result in mask
+ {
+ const Primitive2DReference xRef(
+ new MaskPrimitive2D(
+ getMask(),
+ aRetval));
+
+ aRetval = Primitive2DSequence(&xRef, 1);
+ }
+
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ PatternFillPrimitive2D::PatternFillPrimitive2D(
+ const basegfx::B2DPolyPolygon& rMask,
+ const Primitive2DSequence& rChildren,
+ const basegfx::B2DRange& rReferenceRange)
+ : BufferedDecompositionPrimitive2D(),
+ maMask(rMask),
+ maChildren(rChildren),
+ maReferenceRange(rReferenceRange)
+ {
+ }
+
+ bool PatternFillPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const PatternFillPrimitive2D& rCompare = static_cast< const PatternFillPrimitive2D& >(rPrimitive);
+
+ return (getMask() == rCompare.getMask()
+ && getChildren() == rCompare.getChildren()
+ && getReferenceRange() == rCompare.getReferenceRange());
+ }
+
+ return false;
+ }
+
+ basegfx::B2DRange PatternFillPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ return getMask().getB2DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(PatternFillPrimitive2D, PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx
deleted file mode 100644
index 439937f5d0f5..000000000000
--- a/drawinglayer/source/primitive2d/rendergraphicprimitive2d.cxx
+++ /dev/null
@@ -1,92 +0,0 @@
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General 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_drawinglayer.hxx"
-
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
-#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <basegfx/tools/canvastools.hxx>
-#include <vcl/rendergraphicrasterizer.hxx>
-
-//////////////////////////////////////////////////////////////////////////////
-
-using namespace com::sun::star;
-
-//////////////////////////////////////////////////////////////////////////////
-
-namespace drawinglayer
-{
- namespace primitive2d
- {
- RenderGraphicPrimitive2D::RenderGraphicPrimitive2D(
- const vcl::RenderGraphic& rRenderGraphic,
- const basegfx::B2DHomMatrix& rTransform)
- : BasePrimitive2D(),
- maRenderGraphic(rRenderGraphic),
- maTransform(rTransform)
- {
- }
-
- void RenderGraphicPrimitive2D::setCurrentRasterizer() const
- {
- mapCurrentRasterizer.reset();
- }
-
- void RenderGraphicPrimitive2D::setCurrentRasterizer( const vcl::RenderGraphicRasterizer& rCurrentRasterizer ) const
- {
- mapCurrentRasterizer.reset( new vcl::RenderGraphicRasterizer( rCurrentRasterizer ) );
- }
-
- bool RenderGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
- {
- if(BasePrimitive2D::operator==(rPrimitive))
- {
- const RenderGraphicPrimitive2D& rCompare = (RenderGraphicPrimitive2D&)rPrimitive;
-
- return (getRenderGraphic() == rCompare.getRenderGraphic()
- && getTransform() == rCompare.getTransform());
- }
-
- return false;
- }
-
- basegfx::B2DRange RenderGraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
- {
- basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
- aRetval.transform(maTransform);
- return aRetval;
- }
-
- // provide unique ID
- ImplPrimitrive2DIDBlock(RenderGraphicPrimitive2D, PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D)
-
- } // end of namespace primitive2d
-} // end of namespace drawinglayer
-
-//////////////////////////////////////////////////////////////////////////////
-// eof
diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
new file mode 100644
index 000000000000..199fc3d3fb03
--- /dev/null
+++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
@@ -0,0 +1,1249 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http:\\www.apache.org\licenses\LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const
+ {
+ const SvgGradientEntryVector& rEntries = getGradientEntries();
+ const sal_uInt32 nCount(rEntries.size());
+ Primitive2DSequence xRetval;
+
+ if(nCount)
+ {
+ const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1];
+ const double fOpacity(rSingleEntry.getOpacity());
+
+ if(fOpacity > 0.0)
+ {
+ Primitive2DReference xRef(
+ new PolyPolygonColorPrimitive2D(
+ getPolyPolygon(),
+ rSingleEntry.getColor()));
+
+ if(fOpacity < 1.0)
+ {
+ const Primitive2DSequence aContent(&xRef, 1);
+
+ xRef = Primitive2DReference(
+ new UnifiedTransparencePrimitive2D(
+ aContent,
+ 1.0 - fOpacity));
+ }
+
+ xRetval = Primitive2DSequence(&xRef, 1);
+ }
+ }
+ else
+ {
+ OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
+ }
+
+ return xRetval;
+ }
+
+ void SvgGradientHelper::checkPreconditions()
+ {
+ mbPreconditionsChecked = true;
+ const SvgGradientEntryVector& rEntries = getGradientEntries();
+
+ if(rEntries.empty())
+ {
+ // no fill at all
+ }
+ else
+ {
+ const sal_uInt32 nCount(rEntries.size());
+
+ if(1 == nCount)
+ {
+ // fill with single existing color
+ setSingleEntry();
+ }
+ else
+ {
+ // sort maGradientEntries when more than one
+ std::sort(maGradientEntries.begin(), maGradientEntries.end());
+
+ // gradient with at least two colors
+ bool bAllInvisible(true);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const SvgGradientEntry& rCandidate = rEntries[a];
+
+ if(basegfx::fTools::equalZero(rCandidate.getOpacity()))
+ {
+ // invisible
+ mbFullyOpaque = false;
+ }
+ else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0))
+ {
+ // completely opaque
+ bAllInvisible = false;
+ }
+ else
+ {
+ // opacity
+ bAllInvisible = false;
+ mbFullyOpaque = false;
+ }
+ }
+
+ if(bAllInvisible)
+ {
+ // all invisible, nothing to do
+ }
+ else
+ {
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+
+ if(aPolyRange.isEmpty())
+ {
+ // no range to fill, nothing to do
+ }
+ else
+ {
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight))
+ {
+ // no width/height to fill, nothing to do
+ }
+ else
+ {
+ mbCreatesContent = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ double SvgGradientHelper::createRun(
+ Primitive2DVector& rTargetColor,
+ Primitive2DVector& rTargetOpacity,
+ double fPos,
+ double fMax,
+ const SvgGradientEntryVector& rEntries,
+ sal_Int32 nOffset) const
+ {
+ const sal_uInt32 nCount(rEntries.size());
+
+ if(nCount)
+ {
+ const SvgGradientEntry& rStart = rEntries[0];
+ const bool bCreateStartPad(fPos < 0.0 && Spread_pad == getSpreadMethod());
+ const bool bCreateStartFill(rStart.getOffset() > 0.0);
+ sal_uInt32 nIndex(0);
+
+ if(bCreateStartPad || bCreateStartFill)
+ {
+ const SvgGradientEntry aTemp(bCreateStartPad ? fPos : 0.0, rStart.getColor(), rStart.getOpacity());
+
+ createAtom(rTargetColor, rTargetOpacity, aTemp, rStart, nOffset);
+ fPos = rStart.getOffset();
+ }
+
+ while(fPos < 1.0 && nIndex + 1 < nCount)
+ {
+ const SvgGradientEntry& rCandidateA = rEntries[nIndex++];
+ const SvgGradientEntry& rCandidateB = rEntries[nIndex];
+
+ createAtom(rTargetColor, rTargetOpacity, rCandidateA, rCandidateB, nOffset);
+ fPos = rCandidateB.getOffset();
+ }
+
+ const SvgGradientEntry& rEnd = rEntries[nCount - 1];
+ const bool bCreateEndPad(fPos < fMax && Spread_pad == getSpreadMethod());
+ const bool bCreateEndFill(rEnd.getOffset() < 1.0);
+
+ if(bCreateEndPad || bCreateEndFill)
+ {
+ fPos = bCreateEndPad ? fMax : 1.0;
+ const SvgGradientEntry aTemp(fPos, rEnd.getColor(), rEnd.getOpacity());
+
+ createAtom(rTargetColor, rTargetOpacity, rEnd, aTemp, nOffset);
+ }
+ }
+ else
+ {
+ OSL_ENSURE(false, "GradientAtom creation without ColorStops (!)");
+ fPos = fMax;
+ }
+
+ return fPos;
+ }
+
+ Primitive2DSequence SvgGradientHelper::createResult(
+ const Primitive2DVector& rTargetColor,
+ const Primitive2DVector& rTargetOpacity,
+ const basegfx::B2DHomMatrix& rUnitGradientToObject,
+ bool bInvert) const
+ {
+ Primitive2DSequence xRetval;
+ const Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(rTargetColor, bInvert));
+ const Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(rTargetOpacity, bInvert));
+
+ if(aTargetColorEntries.hasElements())
+ {
+ Primitive2DReference xRefContent;
+
+ if(aTargetOpacityEntries.hasElements())
+ {
+ const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
+ aTargetColorEntries,
+ aTargetOpacityEntries);
+
+ xRefContent = new TransformPrimitive2D(
+ rUnitGradientToObject,
+ Primitive2DSequence(&xRefOpacity, 1));
+ }
+ else
+ {
+ xRefContent = new TransformPrimitive2D(
+ rUnitGradientToObject,
+ aTargetColorEntries);
+ }
+
+ xRefContent = new MaskPrimitive2D(
+ getPolyPolygon(),
+ Primitive2DSequence(&xRefContent, 1));
+
+ xRetval = Primitive2DSequence(&xRefContent, 1);
+ }
+
+ return xRetval;
+ }
+
+ SvgGradientHelper::SvgGradientHelper(
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const SvgGradientEntryVector& rGradientEntries,
+ const basegfx::B2DPoint& rStart,
+ SpreadMethod aSpreadMethod,
+ double fOverlapping)
+ : maPolyPolygon(rPolyPolygon),
+ maGradientEntries(rGradientEntries),
+ maStart(rStart),
+ maSpreadMethod(aSpreadMethod),
+ mfOverlapping(fOverlapping),
+ mbPreconditionsChecked(false),
+ mbCreatesContent(false),
+ mbSingleEntry(false),
+ mbFullyOpaque(true)
+ {
+ }
+
+ bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const
+ {
+ const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper);
+
+ return (getPolyPolygon() == rCompare.getPolyPolygon()
+ && getGradientEntries() == rCompare.getGradientEntries()
+ && getStart() == rCompare.getStart()
+ && getSpreadMethod() == rCompare.getSpreadMethod()
+ && getOverlapping() == rCompare.getOverlapping());
+ }
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ void SvgLinearGradientPrimitive2D::checkPreconditions()
+ {
+ // call parent
+ SvgGradientHelper::checkPreconditions();
+
+ if(getCreatesContent())
+ {
+ // Check Vector
+ const basegfx::B2DVector aVector(getEnd() - getStart());
+
+ if(basegfx::fTools::equalZero(aVector.getX()) && basegfx::fTools::equalZero(aVector.getY()))
+ {
+ // fill with single color using last stop color
+ setSingleEntry();
+ }
+ }
+ }
+
+ void SvgLinearGradientPrimitive2D::ensureGeometry(
+ basegfx::B2DPolyPolygon& rPolyPolygon,
+ const SvgGradientEntry& rFrom,
+ const SvgGradientEntry& rTo,
+ sal_Int32 nOffset) const
+ {
+ if(!rPolyPolygon.count())
+ {
+ rPolyPolygon.append(
+ basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(
+ rFrom.getOffset() - getOverlapping() + nOffset,
+ 0.0,
+ rTo.getOffset() + getOverlapping() + nOffset,
+ 1.0)));
+ }
+ }
+
+ void SvgLinearGradientPrimitive2D::createAtom(
+ Primitive2DVector& rTargetColor,
+ Primitive2DVector& rTargetOpacity,
+ const SvgGradientEntry& rFrom,
+ const SvgGradientEntry& rTo,
+ sal_Int32 nOffset) const
+ {
+ // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
+ if(rFrom.getOffset() == rTo.getOffset())
+ {
+ OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)");
+ }
+ else
+ {
+ const bool bColorChange(rFrom.getColor() != rTo.getColor());
+ const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity());
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ if(bColorChange)
+ {
+ rTargetColor.push_back(
+ new SvgLinearAtomPrimitive2D(
+ rFrom.getColor(), rFrom.getOffset() + nOffset,
+ rTo.getColor(), rTo.getOffset() + nOffset,
+ getOverlapping()));
+ }
+ else
+ {
+ ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
+ rTargetColor.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ rFrom.getColor()));
+ }
+
+ if(bOpacityChange)
+ {
+ const double fTransFrom(1.0 - rFrom.getOpacity());
+ const double fTransTo(1.0 - rTo.getOpacity());
+
+ rTargetOpacity.push_back(
+ new SvgLinearAtomPrimitive2D(
+ basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset,
+ basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset,
+ getOverlapping()));
+ }
+ else if(!getFullyOpaque())
+ {
+ const double fTransparence(1.0 - rFrom.getOpacity());
+
+ ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
+ rTargetOpacity.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ basegfx::BColor(fTransparence, fTransparence, fTransparence)));
+ }
+ }
+ }
+
+ Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DSequence xRetval;
+
+ if(!getPreconditionsChecked())
+ {
+ const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions();
+ }
+
+ if(getSingleEntry())
+ {
+ // fill with last existing color
+ xRetval = createSingleGradientEntryFill();
+ }
+ else if(getCreatesContent())
+ {
+ // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
+ // invisible, width and height to fill are not empty
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+
+ // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
+ // gradient vector defined by Start,End
+ const basegfx::B2DVector aVector(getEnd() - getStart());
+ const double fVectorLength(aVector.getLength());
+ basegfx::B2DHomMatrix aUnitGradientToGradient;
+
+ aUnitGradientToGradient.scale(fVectorLength, 1.0);
+ aUnitGradientToGradient.rotate(atan2(aVector.getY(), aVector.getX()));
+ aUnitGradientToGradient.translate(getStart().getX(), getStart().getY());
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient);
+
+ // create inverse from it
+ basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
+ aObjectToUnitGradient.invert();
+
+ // back-transform polygon to unit gradient coordinates and get
+ // UnitRage. This is the range the gradient has to cover
+ basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon());
+ aUnitPoly.transform(aObjectToUnitGradient);
+ const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange());
+
+ // prepare result vectors
+ Primitive2DVector aTargetColor;
+ Primitive2DVector aTargetOpacity;
+
+ if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0))
+ {
+ // add a pre-multiply to aUnitGradientToObject to allow
+ // multiplication of the polygon(xl, 0.0, xr, 1.0)
+ const basegfx::B2DHomMatrix aPreMultiply(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ 1.0, aUnitRange.getHeight(), 0.0, aUnitRange.getMinY()));
+ aUnitGradientToObject = aUnitGradientToObject * aPreMultiply;
+
+ // create central run, may also already do all necessary when
+ // Spread_pad is set as SpreadMethod and/or the range is smaller
+ double fPos(createRun(aTargetColor, aTargetOpacity, aUnitRange.getMinX(), aUnitRange.getMaxX(), getGradientEntries(), 0));
+
+ if(fPos < aUnitRange.getMaxX())
+ {
+ // can only happen when SpreadMethod is Spread_reflect or Spread_repeat,
+ // else the start and end pads are already created and fPos == aUnitRange.getMaxX().
+ // Its possible to express the repeated linear gradient by adding the
+ // transformed central run. Crete it this way
+ Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(aTargetColor));
+ Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(aTargetOpacity));
+ aTargetColor.clear();
+ aTargetOpacity.clear();
+
+ if(aTargetColorEntries.hasElements())
+ {
+ // add original central run as group primitive
+ aTargetColor.push_back(new GroupPrimitive2D(aTargetColorEntries));
+
+ if(aTargetOpacityEntries.hasElements())
+ {
+ aTargetOpacity.push_back(new GroupPrimitive2D(aTargetOpacityEntries));
+ }
+
+ // add negative runs
+ fPos = 0.0;
+ sal_Int32 nOffset(0);
+
+ while(fPos > aUnitRange.getMinX())
+ {
+ fPos -= 1.0;
+ nOffset++;
+
+ basegfx::B2DHomMatrix aTransform;
+ const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
+
+ if(bMirror)
+ {
+ aTransform.scale(-1.0, 1.0);
+ aTransform.translate(fPos + 1.0, 0.0);
+ }
+ else
+ {
+ aTransform.translate(fPos, 0.0);
+ }
+
+ aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
+
+ if(aTargetOpacityEntries.hasElements())
+ {
+ aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
+ }
+ }
+
+ // add positive runs
+ fPos = 1.0;
+ nOffset = 1;
+
+ while(fPos < aUnitRange.getMaxX())
+ {
+ basegfx::B2DHomMatrix aTransform;
+ const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
+
+ if(bMirror)
+ {
+ aTransform.scale(-1.0, 1.0);
+ aTransform.translate(fPos + 1.0, 0.0);
+ }
+ else
+ {
+ aTransform.translate(fPos, 0.0);
+ }
+
+ aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
+
+ if(aTargetOpacityEntries.hasElements())
+ {
+ aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
+ }
+
+ fPos += 1.0;
+ nOffset++;
+ }
+ }
+ }
+ }
+
+ xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject);
+ }
+
+ return xRetval;
+ }
+
+ SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const SvgGradientEntryVector& rGradientEntries,
+ const basegfx::B2DPoint& rStart,
+ const basegfx::B2DPoint& rEnd,
+ SpreadMethod aSpreadMethod,
+ double fOverlapping)
+ : BufferedDecompositionPrimitive2D(),
+ SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping),
+ maEnd(rEnd)
+ {
+ }
+
+ bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
+
+ if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
+ {
+ const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive);
+
+ return (getEnd() == rCompare.getEnd());
+ }
+
+ return false;
+ }
+
+ basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ // return ObjectRange
+ return getPolyPolygon().getB2DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ void SvgRadialGradientPrimitive2D::checkPreconditions()
+ {
+ // call parent
+ SvgGradientHelper::checkPreconditions();
+
+ if(getCreatesContent())
+ {
+ // Check Radius
+ if(basegfx::fTools::equalZero(getRadius()))
+ {
+ // fill with single color using last stop color
+ setSingleEntry();
+ }
+ }
+ }
+
+ void SvgRadialGradientPrimitive2D::ensureGeometry(
+ basegfx::B2DPolyPolygon& rPolyPolygon,
+ const SvgGradientEntry& rFrom,
+ const SvgGradientEntry& rTo,
+ sal_Int32 nOffset) const
+ {
+ if(!rPolyPolygon.count())
+ {
+ basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
+ basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
+ double fScaleFrom(rFrom.getOffset() + nOffset);
+ const double fScaleTo(rTo.getOffset() + nOffset);
+
+ if(fScaleFrom > getOverlapping())
+ {
+ fScaleFrom -= getOverlapping();
+ }
+
+ if(isFocalSet())
+ {
+ const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+
+ aPolygonA.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleFrom,
+ fScaleFrom,
+ aTranslateFrom.getX(),
+ aTranslateFrom.getY()));
+ aPolygonB.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleTo,
+ fScaleTo,
+ aTranslateTo.getX(),
+ aTranslateTo.getY()));
+ }
+ else
+ {
+ aPolygonA.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleFrom,
+ fScaleFrom));
+ aPolygonB.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleTo,
+ fScaleTo));
+ }
+
+ // add the outer polygon first
+ rPolyPolygon.append(aPolygonB);
+ rPolyPolygon.append(aPolygonA);
+ }
+ }
+
+ void SvgRadialGradientPrimitive2D::createAtom(
+ Primitive2DVector& rTargetColor,
+ Primitive2DVector& rTargetOpacity,
+ const SvgGradientEntry& rFrom,
+ const SvgGradientEntry& rTo,
+ sal_Int32 nOffset) const
+ {
+ // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
+ if(rFrom.getOffset() == rTo.getOffset())
+ {
+ OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)");
+ }
+ else
+ {
+ const bool bColorChange(rFrom.getColor() != rTo.getColor());
+ const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity());
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ if(bColorChange)
+ {
+ const double fScaleFrom(rFrom.getOffset() + nOffset);
+ const double fScaleTo(rTo.getOffset() + nOffset);
+
+ if(isFocalSet())
+ {
+ const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+
+ rTargetColor.push_back(
+ new SvgRadialAtomPrimitive2D(
+ rFrom.getColor(), fScaleFrom, aTranslateFrom,
+ rTo.getColor(), fScaleTo, aTranslateTo,
+ getOverlapping()));
+ }
+ else
+ {
+ rTargetColor.push_back(
+ new SvgRadialAtomPrimitive2D(
+ rFrom.getColor(), fScaleFrom,
+ rTo.getColor(), fScaleTo,
+ getOverlapping()));
+ }
+ }
+ else
+ {
+ ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
+ rTargetColor.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ rFrom.getColor()));
+ }
+
+ if(bOpacityChange)
+ {
+ const double fTransFrom(1.0 - rFrom.getOpacity());
+ const double fTransTo(1.0 - rTo.getOpacity());
+ const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom);
+ const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo);
+ const double fScaleFrom(rFrom.getOffset() + nOffset);
+ const double fScaleTo(rTo.getOffset() + nOffset);
+
+ if(isFocalSet())
+ {
+ const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+
+ rTargetOpacity.push_back(
+ new SvgRadialAtomPrimitive2D(
+ aColorFrom, fScaleFrom, aTranslateFrom,
+ aColorTo, fScaleTo, aTranslateTo,
+ getOverlapping()));
+ }
+ else
+ {
+ rTargetOpacity.push_back(
+ new SvgRadialAtomPrimitive2D(
+ aColorFrom, fScaleFrom,
+ aColorTo, fScaleTo,
+ getOverlapping()));
+ }
+ }
+ else if(!getFullyOpaque())
+ {
+ const double fTransparence(1.0 - rFrom.getOpacity());
+
+ ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
+ rTargetOpacity.push_back(
+ new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ basegfx::BColor(fTransparence, fTransparence, fTransparence)));
+ }
+ }
+ }
+
+ const SvgGradientEntryVector& SvgRadialGradientPrimitive2D::getMirroredGradientEntries() const
+ {
+ if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
+ {
+ const_cast< SvgRadialGradientPrimitive2D* >(this)->createMirroredGradientEntries();
+ }
+
+ return maMirroredGradientEntries;
+ }
+
+ void SvgRadialGradientPrimitive2D::createMirroredGradientEntries()
+ {
+ if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
+ {
+ const sal_uInt32 nCount(getGradientEntries().size());
+ maMirroredGradientEntries.clear();
+ maMirroredGradientEntries.reserve(nCount);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a];
+
+ maMirroredGradientEntries.push_back(
+ SvgGradientEntry(
+ 1.0 - rCandidate.getOffset(),
+ rCandidate.getColor(),
+ rCandidate.getOpacity()));
+ }
+ }
+ }
+
+ Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DSequence xRetval;
+
+ if(!getPreconditionsChecked())
+ {
+ const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions();
+ }
+
+ if(getSingleEntry())
+ {
+ // fill with last existing color
+ xRetval = createSingleGradientEntryFill();
+ }
+ else if(getCreatesContent())
+ {
+ // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
+ // invisible, width and height to fill are not empty
+ const SvgGradientEntryVector& rEntries = getGradientEntries();
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+
+ // create unit transform from unit vector to given linear gradient vector
+ basegfx::B2DHomMatrix aUnitGradientToGradient;
+
+ aUnitGradientToGradient.scale(getRadius(), getRadius());
+ aUnitGradientToGradient.translate(getStart().getX(), getStart().getY());
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient);
+
+ // create inverse from it
+ basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
+ aObjectToUnitGradient.invert();
+
+ // back-transform polygon to unit gradient coordinates and get
+ // UnitRage. This is the range the gradient has to cover
+ basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon());
+ aUnitPoly.transform(aObjectToUnitGradient);
+ const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange());
+
+ // create range which the gradient has to cover to cover the whole given geometry.
+ // For circle, go from 0.0 to max radius in all directions (the corners)
+ double fMax(basegfx::B2DVector(aUnitRange.getMinimum()).getLength());
+ fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaximum()).getLength());
+ fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMinX(), aUnitRange.getMaxY()).getLength());
+ fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaxX(), aUnitRange.getMinY()).getLength());
+
+ // prepare result vectors
+ Primitive2DVector aTargetColor;
+ Primitive2DVector aTargetOpacity;
+
+ if(0.0 < fMax)
+ {
+ // prepare maFocalVector
+ if(isFocalSet())
+ {
+ const_cast< SvgRadialGradientPrimitive2D* >(this)->maFocalLength = fMax;
+ }
+
+ // create central run, may also already do all necessary when
+ // Spread_pad is set as SpreadMethod and/or the range is smaller
+ double fPos(createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), 0));
+
+ if(fPos < fMax)
+ {
+ // can only happen when SpreadMethod is Spread_reflect or Spread_repeat,
+ // else the start and end pads are already created and fPos == fMax.
+ // For radial there is no way to transform the already created
+ // central run, it needs to be created from 1.0 to fMax
+ sal_Int32 nOffset(1);
+
+ while(fPos < fMax)
+ {
+ const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
+
+ if(bMirror)
+ {
+ createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getMirroredGradientEntries(), nOffset);
+ }
+ else
+ {
+ createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), nOffset);
+ }
+
+ nOffset++;
+ fPos += 1.0;
+ }
+ }
+ }
+
+ xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject, true);
+ }
+
+ return xRetval;
+ }
+
+ SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ const SvgGradientEntryVector& rGradientEntries,
+ const basegfx::B2DPoint& rStart,
+ double fRadius,
+ SpreadMethod aSpreadMethod,
+ const basegfx::B2DPoint* pFocal,
+ double fOverlapping)
+ : BufferedDecompositionPrimitive2D(),
+ SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping),
+ mfRadius(fRadius),
+ maFocal(rStart),
+ maFocalVector(0.0, 0.0),
+ maFocalLength(0.0),
+ maMirroredGradientEntries(),
+ mbFocalSet(false)
+ {
+ if(pFocal)
+ {
+ maFocal = *pFocal;
+ maFocalVector = maFocal - getStart();
+ mbFocalSet = true;
+ }
+ }
+
+ bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
+
+ if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
+ {
+ const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
+
+ if(getRadius() == rCompare.getRadius())
+ {
+ if(isFocalSet() == rCompare.isFocalSet())
+ {
+ if(isFocalSet())
+ {
+ return getFocal() == rCompare.getFocal();
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ // return ObjectRange
+ return getPolyPolygon().getB2DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// SvgLinearAtomPrimitive2D class
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DSequence SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ Primitive2DSequence xRetval;
+ const double fDelta(getOffsetB() - getOffsetA());
+
+ if(!basegfx::fTools::equalZero(fDelta))
+ {
+ if(getColorA() == getColorB())
+ {
+ const basegfx::B2DPolygon aPolygon(
+ basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(
+ getOffsetA() - getOverlapping(),
+ 0.0,
+ getOffsetB() + getOverlapping(),
+ 1.0)));
+
+ xRetval.realloc(1);
+ xRetval[0] = new PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ getColorA());
+ }
+ else
+ {
+ // calc discrete length to change color all 2.5 pixels
+ sal_uInt32 nSteps(basegfx::fround(fDelta / (getDiscreteUnit() * 2.5)));
+
+ // use color distance, assume to do every 3rd
+ const double fColorDistance(getColorA().getDistance(getColorB()));
+ const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3)));
+ nSteps = std::min(nSteps, nColorSteps);
+
+ // roughly cut when too big
+ nSteps = std::min(nSteps, sal_uInt32(100));
+ nSteps = std::max(nSteps, sal_uInt32(1));
+
+ // preapare iteration
+ double fStart(0.0);
+ double fStep(fDelta / nSteps);
+
+ xRetval.realloc(nSteps);
+
+ for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep)
+ {
+ const double fLeft(getOffsetA() + fStart);
+ const double fRight(fLeft + fStep);
+ const basegfx::B2DPolygon aPolygon(
+ basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(
+ fLeft - getOverlapping(),
+ 0.0,
+ fRight + getOverlapping(),
+ 1.0)));
+
+ xRetval[a] = new PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta));
+ }
+ }
+ }
+
+ return xRetval;
+ }
+
+ bool SvgLinearAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive);
+
+ return (getColorA() == rCompare.getColorA()
+ && getColorB() == rCompare.getColorB()
+ && getOffsetA() == rCompare.getOffsetA()
+ && getOffsetB() == rCompare.getOffsetB()
+ && getOverlapping() == rCompare.getOverlapping());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// SvgRadialAtomPrimitive2D class
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DSequence SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DSequence xRetval;
+ const double fDeltaScale(getScaleB() - getScaleA());
+
+ if(!basegfx::fTools::equalZero(fDeltaScale))
+ {
+ if(getColorA() == getColorB())
+ {
+ basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
+ basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
+ double fScaleA(getScaleA());
+ const double fScaleB(getScaleB());
+
+ if(fScaleA > getOverlapping())
+ {
+ fScaleA -= getOverlapping();
+ }
+
+ const bool bUseA(basegfx::fTools::equalZero(fScaleA));
+
+ if(getTranslateSet())
+ {
+ if(bUseA)
+ {
+ aPolygonA.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleA,
+ fScaleA,
+ getTranslateA().getX(),
+ getTranslateA().getY()));
+ }
+
+ aPolygonB.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleB,
+ fScaleB,
+ getTranslateB().getX(),
+ getTranslateB().getY()));
+ }
+ else
+ {
+ if(bUseA)
+ {
+ aPolygonA.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleA,
+ fScaleA));
+ }
+
+ aPolygonB.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleB,
+ fScaleB));
+ }
+
+ basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB);
+
+ if(bUseA)
+ {
+ aPolyPolygon.append(aPolygonA);
+ }
+
+ xRetval.realloc(1);
+
+ xRetval[0] = new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ getColorA());
+ }
+ else
+ {
+ // calc discrete length to change color all 2.5 pixels
+ sal_uInt32 nSteps(basegfx::fround(fDeltaScale / (getDiscreteUnit() * 2.5)));
+
+ // use color distance, assume to do every 3rd
+ const double fColorDistance(getColorA().getDistance(getColorB()));
+ const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3)));
+ nSteps = std::min(nSteps, nColorSteps);
+
+ // roughly cut when too big
+ nSteps = std::min(nSteps, sal_uInt32(100));
+ nSteps = std::max(nSteps, sal_uInt32(1));
+
+ // preapare iteration
+ double fStartScale(0.0);
+ double fStepScale(fDeltaScale / nSteps);
+
+ xRetval.realloc(nSteps);
+
+ for(sal_uInt32 a(0); a < nSteps; a++, fStartScale += fStepScale)
+ {
+ double fScaleA(getScaleA() + fStartScale);
+ const double fScaleB(fScaleA + fStepScale);
+ const double fUnitScale(fStartScale/fDeltaScale);
+ basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
+ basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
+
+ if(fScaleA > getOverlapping())
+ {
+ fScaleA -= getOverlapping();
+ }
+
+ const bool bUseA(basegfx::fTools::equalZero(fScaleA));
+
+ if(getTranslateSet())
+ {
+ const double fUnitScaleEnd((fStartScale + fStepScale)/fDeltaScale);
+ const basegfx::B2DVector aTranslateB(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScaleEnd));
+
+ if(bUseA)
+ {
+ const basegfx::B2DVector aTranslateA(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScale));
+
+ aPolygonA.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleA,
+ fScaleA,
+ aTranslateA.getX(),
+ aTranslateA.getY()));
+ }
+
+ aPolygonB.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fScaleB,
+ fScaleB,
+ aTranslateB.getX(),
+ aTranslateB.getY()));
+ }
+ else
+ {
+ if(bUseA)
+ {
+ aPolygonA.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleA,
+ fScaleA));
+ }
+
+ aPolygonB.transform(
+ basegfx::tools::createScaleB2DHomMatrix(
+ fScaleB,
+ fScaleB));
+ }
+
+ basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB);
+
+ if(bUseA)
+ {
+ aPolyPolygon.append(aPolygonA);
+ }
+
+ xRetval[nSteps - 1 - a] = new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
+ }
+ }
+ }
+
+ return xRetval;
+ }
+
+ bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+
+ return (getColorA() == rCompare.getColorA()
+ && getColorB() == rCompare.getColorB()
+ && getScaleA() == rCompare.getScaleA()
+ && getScaleB() == rCompare.getScaleB()
+ && getTranslateA() == rCompare.getTranslateA()
+ && getTranslateB() == rCompare.getTranslateB()
+ && getOverlapping() == rCompare.getOverlapping());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
new file mode 100644
index 000000000000..4979a9932cc2
--- /dev/null
+++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
@@ -0,0 +1,294 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http:\\www.apache.org\licenses\LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
+#include <com/sun/star/i18n/WordType.hpp>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ TextBreakupHelper::TextBreakupHelper(const Primitive2DReference& rxSource)
+ : mxSource(rxSource),
+ mxResult(),
+ mpSource(dynamic_cast< const TextSimplePortionPrimitive2D* >(rxSource.get())),
+ maTextLayouter(),
+ maDecTrans(),
+ mbNoDXArray()
+ {
+ if(mpSource)
+ {
+ maDecTrans = mpSource->getTextTransform();
+ mbNoDXArray = mpSource->getDXArray().empty();
+
+ if(mbNoDXArray)
+ {
+ // init TextLayouter when no dxarray
+ maTextLayouter.setFontAttribute(
+ mpSource->getFontAttribute(),
+ maDecTrans.getScale().getX(),
+ maDecTrans.getScale().getY(),
+ mpSource->getLocale());
+ }
+ }
+ }
+
+ TextBreakupHelper::~TextBreakupHelper()
+ {
+ }
+
+ void TextBreakupHelper::breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength)
+ {
+ if(mpSource && nLength && !(nIndex == mpSource->getTextPosition() && nLength == mpSource->getTextLength()))
+ {
+ // prepare values for new portion
+ basegfx::B2DHomMatrix aNewTransform;
+ ::std::vector< double > aNewDXArray;
+ const bool bNewStartIsNotOldStart(nIndex > mpSource->getTextPosition());
+
+ if(!mbNoDXArray)
+ {
+ // prepare new DXArray for the single word
+ aNewDXArray = ::std::vector< double >(
+ mpSource->getDXArray().begin() + (nIndex - mpSource->getTextPosition()),
+ mpSource->getDXArray().begin() + ((nIndex + nLength) - mpSource->getTextPosition()));
+ }
+
+ if(bNewStartIsNotOldStart)
+ {
+ // needs to be moved to a new start position
+ double fOffset(0.0);
+
+ if(mbNoDXArray)
+ {
+ // evaluate using TextLayouter
+ fOffset = maTextLayouter.getTextWidth(mpSource->getText(), mpSource->getTextPosition(), nIndex);
+ }
+ else
+ {
+ // get from DXArray
+ const sal_uInt32 nIndex(static_cast< sal_uInt32 >(nIndex - mpSource->getTextPosition()));
+ fOffset = mpSource->getDXArray()[nIndex - 1];
+ }
+
+ // need offset without FontScale for building the new transformation. The
+ // new transformation will be multiplied with the current text transformation
+ // so FontScale would be double
+ double fOffsetNoScale(fOffset);
+ const double fFontScaleX(maDecTrans.getScale().getX());
+
+ if(!basegfx::fTools::equal(fFontScaleX, 1.0)
+ && !basegfx::fTools::equalZero(fFontScaleX))
+ {
+ fOffsetNoScale /= fFontScaleX;
+ }
+
+ // apply needed offset to transformation
+ aNewTransform.translate(fOffsetNoScale, 0.0);
+
+ if(!mbNoDXArray)
+ {
+ // DXArray values need to be corrected with the offset, too. Here,
+ // take the scaled offset since the DXArray is scaled
+ const sal_uInt32 nArraySize(aNewDXArray.size());
+
+ for(sal_uInt32 a(0); a < nArraySize; a++)
+ {
+ aNewDXArray[a] -= fOffset;
+ }
+ }
+ }
+
+ // add text transformation to new transformation
+ aNewTransform = maDecTrans.getB2DHomMatrix() * aNewTransform;
+
+ // callback to allow evtl. changes
+ const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength));
+
+ if(bCreate)
+ {
+ // check if we have a decorated primitive as source
+ const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D =
+ dynamic_cast< const TextDecoratedPortionPrimitive2D* >(mpSource);
+
+ if(pTextDecoratedPortionPrimitive2D)
+ {
+ // create a TextDecoratedPortionPrimitive2D
+ rTempResult.push_back(
+ new TextDecoratedPortionPrimitive2D(
+ aNewTransform,
+ mpSource->getText(),
+ nIndex,
+ nLength,
+ aNewDXArray,
+ mpSource->getFontAttribute(),
+ mpSource->getLocale(),
+ mpSource->getFontColor(),
+
+ pTextDecoratedPortionPrimitive2D->getOverlineColor(),
+ pTextDecoratedPortionPrimitive2D->getTextlineColor(),
+ pTextDecoratedPortionPrimitive2D->getFontOverline(),
+ pTextDecoratedPortionPrimitive2D->getFontUnderline(),
+ pTextDecoratedPortionPrimitive2D->getUnderlineAbove(),
+ pTextDecoratedPortionPrimitive2D->getTextStrikeout(),
+ pTextDecoratedPortionPrimitive2D->getWordLineMode(),
+ pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(),
+ pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(),
+ pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(),
+ pTextDecoratedPortionPrimitive2D->getTextRelief(),
+ pTextDecoratedPortionPrimitive2D->getShadow()));
+ }
+ else
+ {
+ // create a SimpleTextPrimitive
+ rTempResult.push_back(
+ new TextSimplePortionPrimitive2D(
+ aNewTransform,
+ mpSource->getText(),
+ nIndex,
+ nLength,
+ aNewDXArray,
+ mpSource->getFontAttribute(),
+ mpSource->getLocale(),
+ mpSource->getFontColor()));
+ }
+ }
+ }
+ }
+
+ bool TextBreakupHelper::allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength)
+ {
+ return true;
+ }
+
+ void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit)
+ {
+ if(mpSource && mpSource->getTextLength())
+ {
+ Primitive2DVector aTempResult;
+ static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBreakIterator;
+
+ if(!xBreakIterator.is())
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
+ xBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY);
+ }
+
+ if(xBreakIterator.is())
+ {
+ const rtl::OUString& rTxt = mpSource->getText();
+ const sal_Int32 nTextLength(mpSource->getTextLength());
+ const ::com::sun::star::lang::Locale& rLocale = mpSource->getLocale();
+ const sal_Int32 nTextPosition(mpSource->getTextPosition());
+ sal_Int32 nCurrent(nTextPosition);
+
+ switch(aBreakupUnit)
+ {
+ case BreakupUnit_character:
+ {
+ sal_Int32 nDone;
+ sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
+ sal_Int32 a(nTextPosition);
+
+ for(; a < nTextPosition + nTextLength; a++)
+ {
+ if(a == nNextCellBreak)
+ {
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ nCurrent = a;
+ nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
+ }
+ }
+
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ break;
+ }
+ case BreakupUnit_word:
+ {
+ ::com::sun::star::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
+ sal_Int32 a(nTextPosition);
+
+ for(; a < nTextPosition + nTextLength; a++)
+ {
+ if(a == nNextWordBoundary.endPos)
+ {
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ nCurrent = a;
+ nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
+ }
+ }
+
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ break;
+ }
+ case BreakupUnit_sentence:
+ {
+ sal_Int32 nNextSentenceBreak(xBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
+ sal_Int32 a(nTextPosition);
+
+ for(; a < nTextPosition + nTextLength; a++)
+ {
+ if(a == nNextSentenceBreak)
+ {
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ nCurrent = a;
+ nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale);
+ }
+ }
+
+ breakupPortion(aTempResult, nCurrent, a - nCurrent);
+ break;
+ }
+ }
+ }
+
+ mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult);
+ }
+ }
+
+ const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const
+ {
+ if(mxResult.hasElements())
+ {
+ return mxResult;
+ }
+ else if(mpSource)
+ {
+ const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit);
+ }
+
+ return mxResult;
+ }
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
index 855535eb96e8..3b5e266f3bfd 100644
--- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -525,7 +525,6 @@ namespace drawinglayer
case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D :
case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
case PRIMITIVE2D_ID_MEDIAPRIMITIVE2D:
- case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D:
{
if(!getHitTextOnly())
{
diff --git a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
index 65a87c83f4a0..97ecf9da6952 100644
--- a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
+++ b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
@@ -119,7 +119,6 @@ namespace drawinglayer
case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
{
diff --git a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
index 13cbfcb3badb..59a47fc790a6 100644
--- a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
+++ b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
@@ -210,7 +210,6 @@ namespace drawinglayer
case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
{
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index c56909e9dfde..63dbabf2bce5 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -34,7 +34,6 @@
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
@@ -1284,12 +1283,6 @@ namespace drawinglayer
RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
break;
}
- case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
- {
- // direct draw of transformed RenderGraphic primitive; use default processing
- RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate));
- break;
- }
case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
{
// need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
@@ -1657,7 +1650,8 @@ namespace drawinglayer
// the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
mpOutputDevice->Push(PUSH_CLIPREGION);
//mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon))));
- mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
+ //mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
+ mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
}
// recursively paint content
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index f485aa182bd2..d71090ed7d5b 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -31,7 +31,6 @@
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
@@ -190,12 +189,6 @@ namespace drawinglayer
RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
break;
}
- case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
- {
- // direct draw of transformed BitmapEx primitive
- RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate));
- break;
- }
case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
{
// direct draw of fillBitmapPrimitive
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 8027f3284909..dc79dcce648a 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -31,7 +31,6 @@
#include <vcl/outdev.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
#include <vclhelperbitmaptransform.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <vclhelperbitmaprender.hxx>
@@ -57,7 +56,6 @@
#include <vcl/metric.hxx>
#include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
-#include <vcl/rendergraphicrasterizer.hxx>
//////////////////////////////////////////////////////////////////////////////
// control support
@@ -419,75 +417,6 @@ namespace drawinglayer
}
}
- void VclProcessor2D::RenderRenderGraphicPrimitive2D(const primitive2d::RenderGraphicPrimitive2D& rRenderGraphicCandidate)
- {
- // create local transform
- basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rRenderGraphicCandidate.getTransform());
- vcl::RenderGraphic aRenderGraphic(rRenderGraphicCandidate.getRenderGraphic());
- bool bPainted(false);
-
- if(maBColorModifierStack.count())
- {
- // !!! TODO
- // aRenderGraphic = impModifyRenderGraphic(maBColorModifierStack, aRenderGraphic);
-
- if(aRenderGraphic.IsEmpty())
- {
- // color gets completely replaced, get it
- const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
- aPolygon.transform(aLocalTransform);
-
- mpOutputDevice->SetFillColor(Color(aModifiedColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawPolygon(aPolygon);
-
- bPainted = true;
- }
- }
-
- if(!bPainted)
- {
- // decompose matrix to check for shear, rotate and mirroring
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
-
- if( basegfx::fTools::equalZero( fRotate ) )
- {
- aOutlineRange.transform( aLocalTransform );
- }
- else
- {
- // !!! TODO
- // if rotated, create the unrotated output rectangle for the GraphicManager paint
- /*
- const basegfx::B2DHomMatrix aSimpleObjectMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
- fabs(aScale.getX()), fabs(aScale.getY()),
- aTranslate.getX(), aTranslate.getY()));
-
- aOutlineRange.transform(aSimpleObjectMatrix);
- */
- }
-
- // prepare dest coordinates
- const Point aPoint( basegfx::fround(aOutlineRange.getMinX() ),
- basegfx::fround(aOutlineRange.getMinY() ) );
- const Size aSize( basegfx::fround(aOutlineRange.getWidth() ),
- basegfx::fround(aOutlineRange.getHeight() ) );
- const Size aSizePixel( mpOutputDevice->LogicToPixel( aSize ) );
- const vcl::RenderGraphicRasterizer aRasterizer( aRenderGraphic );
- const BitmapEx aBitmapEx( aRasterizer.Rasterize( aSizePixel, fRotate, fShearX ) );
-
- if( !aBitmapEx.IsEmpty() )
- {
- mpOutputDevice->DrawBitmapEx( aPoint, aSize, aBitmapEx );
- }
- }
- }
-
void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate)
{
const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap());
diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx
index 572610805e4c..497c020f5894 100644
--- a/drawinglayer/source/processor3d/shadow3dextractor.cxx
+++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx
@@ -47,25 +47,6 @@ namespace drawinglayer
{
namespace processor3d
{
- /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence
- const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequenceFromBasePrimitive2DVector(
- const BasePrimitive2DVector& rVector) const
- {
- const sal_uInt32 nCount(rVector.size());
- primitive2d::Primitive2DSequence aRetval(nCount);
-
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- aRetval[a] = rVector[a];
- }
-
- // all entries taken over; no need to delete entries, just reset to
- // mark as empty
- const_cast< BasePrimitive2DVector& >(rVector).clear();
-
- return aRetval;
- }
-
// as tooling, the process() implementation takes over API handling and calls this
// virtual render method when the primitive implementation is BasePrimitive3D-based.
void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
@@ -79,8 +60,8 @@ namespace drawinglayer
const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate);
// set new target
- BasePrimitive2DVector aNewSubList;
- BasePrimitive2DVector* pLastTargetSequence = mpPrimitive2DSequence;
+ primitive2d::Primitive2DVector aNewSubList;
+ primitive2d::Primitive2DVector* pLastTargetSequence = mpPrimitive2DSequence;
mpPrimitive2DSequence = &aNewSubList;
// activate convert
@@ -104,7 +85,7 @@ namespace drawinglayer
primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D(
rPrimitive.getShadowTransform(),
rPrimitive.getShadowColor(),
- getPrimitive2DSequenceFromBasePrimitive2DVector(aNewSubList));
+ primitive2d::Primitive2DVectorToPrimitive2DSequence(aNewSubList));
if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0))
{
@@ -328,7 +309,7 @@ namespace drawinglayer
const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequence() const
{
- return getPrimitive2DSequenceFromBasePrimitive2DVector(maPrimitive2DSequence);
+ return Primitive2DVectorToPrimitive2DSequence(maPrimitive2DSequence);
}
} // end of namespace processor3d
diff --git a/drawinglayer/source/tools/converters.cxx b/drawinglayer/source/tools/converters.cxx
new file mode 100644
index 000000000000..a7d22a5df698
--- /dev/null
+++ b/drawinglayer/source/tools/converters.cxx
@@ -0,0 +1,143 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http:\\www.apache.org\licenses\LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/tools/converters.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <vcl/virdev.hxx>
+
+#ifdef DBG_UTIL
+#include <tools/stream.hxx>
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace tools
+ {
+ BitmapEx DRAWINGLAYER_DLLPUBLIC convertToBitmapEx(
+ const drawinglayer::primitive2d::Primitive2DSequence& rSeq,
+ const geometry::ViewInformation2D& rViewInformation2D,
+ sal_uInt32 nDiscreteWidth,
+ sal_uInt32 nDiscreteHeight,
+ sal_uInt32 nMaxQuadratPixels)
+ {
+ BitmapEx aRetval;
+
+ if(rSeq.hasElements() && nDiscreteWidth && nDiscreteHeight)
+ {
+ // get destination size in pixels
+ const MapMode aMapModePixel(MAP_PIXEL);
+ const sal_uInt32 nViewVisibleArea(nDiscreteWidth * nDiscreteHeight);
+ double fReduceFactor(1.0);
+ drawinglayer::primitive2d::Primitive2DSequence aSequence(rSeq);
+
+ if(nViewVisibleArea > nMaxQuadratPixels)
+ {
+ // reduce render size
+ fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea);
+ nDiscreteWidth = basegfx::fround((double)nDiscreteWidth * fReduceFactor);
+ nDiscreteHeight = basegfx::fround((double)nDiscreteHeight * fReduceFactor);
+
+ const drawinglayer::primitive2d::Primitive2DReference aEmbed(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ basegfx::tools::createScaleB2DHomMatrix(fReduceFactor, fReduceFactor),
+ rSeq));
+
+ aSequence = drawinglayer::primitive2d::Primitive2DSequence(&aEmbed, 1);
+ }
+
+ const Point aEmptyPoint;
+ const Size aSizePixel(nDiscreteWidth, nDiscreteHeight);
+ geometry::ViewInformation2D aViewInformation2D(rViewInformation2D);
+ VirtualDevice maContent;
+
+ // prepare vdev
+ maContent.SetOutputSizePixel(aSizePixel, false);
+ maContent.SetMapMode(aMapModePixel);
+ maContent.SetAntialiasing(true);
+
+ // set to all white
+ maContent.SetBackground(Wallpaper(Color(COL_WHITE)));
+ maContent.Erase();
+
+ // create processor
+ processor2d::VclPixelProcessor2D aContentProcessor(aViewInformation2D, maContent);
+
+ // render content
+ aContentProcessor.process(aSequence);
+
+ // get content
+ maContent.EnableMapMode(false);
+ const Bitmap aContent(maContent.GetBitmap(aEmptyPoint, aSizePixel));
+
+ // prepare for mask creation
+ maContent.SetMapMode(aMapModePixel);
+ maContent.SetAntialiasing(true);
+
+ // set alpha to all white (fully transparent)
+ maContent.Erase();
+
+ // embed primitives to paint them black
+ const primitive2d::Primitive2DReference xRef(
+ new primitive2d::ModifiedColorPrimitive2D(
+ aSequence,
+ basegfx::BColorModifier(
+ basegfx::BColor(0.0, 0.0, 0.0),
+ 0.5,
+ basegfx::BCOLORMODIFYMODE_REPLACE)));
+ const primitive2d::Primitive2DSequence xSeq(&xRef, 1);
+
+ // render
+ aContentProcessor.process(xSeq);
+
+ // get alpha cahannel from vdev
+ maContent.EnableMapMode(false);
+ const AlphaMask aAlphaMask(maContent.GetBitmap(aEmptyPoint, aSizePixel));
+
+ // create BitmapEx result
+ aRetval = BitmapEx(aContent, aAlphaMask);
+ }
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false);
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
+ aNew << aRetval;
+ }
+#endif
+
+ return aRetval;
+ }
+
+ } // end of namespace tools
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof