summaryrefslogtreecommitdiff
path: root/drawinglayer/source/primitive3d
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer/source/primitive3d')
-rw-r--r--drawinglayer/source/primitive3d/baseprimitive3d.cxx278
-rw-r--r--drawinglayer/source/primitive3d/groupprimitive3d.cxx79
-rw-r--r--drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx319
-rw-r--r--drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx76
-rw-r--r--drawinglayer/source/primitive3d/makefile.mk62
-rw-r--r--drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx71
-rw-r--r--drawinglayer/source/primitive3d/polygonprimitive3d.cxx178
-rw-r--r--drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx579
-rw-r--r--drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx83
-rw-r--r--drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx222
-rw-r--r--drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx339
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx991
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx526
-rw-r--r--drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx387
-rw-r--r--drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx194
-rw-r--r--drawinglayer/source/primitive3d/sdrprimitive3d.cxx125
-rw-r--r--drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx224
-rw-r--r--drawinglayer/source/primitive3d/shadowprimitive3d.cxx80
-rw-r--r--drawinglayer/source/primitive3d/textureprimitive3d.cxx227
-rw-r--r--drawinglayer/source/primitive3d/transformprimitive3d.cxx79
20 files changed, 5119 insertions, 0 deletions
diff --git a/drawinglayer/source/primitive3d/baseprimitive3d.cxx b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
new file mode 100644
index 000000000000..d63d906139c6
--- /dev/null
+++ b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
@@ -0,0 +1,278 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/baseprimitive3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ BasePrimitive3D::BasePrimitive3D()
+ : BasePrimitive3DImplBase(m_aMutex)
+ {
+ }
+
+ BasePrimitive3D::~BasePrimitive3D()
+ {
+ }
+
+ bool BasePrimitive3D::operator==( const BasePrimitive3D& rPrimitive ) const
+ {
+ return (getPrimitive3DID() == rPrimitive.getPrimitive3DID());
+ }
+
+ basegfx::B3DRange BasePrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ return getB3DRangeFromPrimitive3DSequence(get3DDecomposition(rViewInformation), rViewInformation);
+ }
+
+ Primitive3DSequence BasePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return Primitive3DSequence();
+ }
+
+ Primitive3DSequence SAL_CALL BasePrimitive3D::getDecomposition( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException )
+ {
+ const geometry::ViewInformation3D aViewInformation(rViewParameters);
+ return get3DDecomposition(rViewParameters);
+ }
+
+ com::sun::star::geometry::RealRectangle3D SAL_CALL BasePrimitive3D::getRange( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException )
+ {
+ const geometry::ViewInformation3D aViewInformation(rViewParameters);
+ return basegfx::unotools::rectangle3DFromB3DRectangle(getB3DRange(aViewInformation));
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence BufferedDecompositionPrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return Primitive3DSequence();
+ }
+
+ BufferedDecompositionPrimitive3D::BufferedDecompositionPrimitive3D()
+ : BasePrimitive3D(),
+ maBuffered3DDecomposition()
+ {
+ }
+
+ Primitive3DSequence BufferedDecompositionPrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if(!getBuffered3DDecomposition().hasElements())
+ {
+ const Primitive3DSequence aNewSequence(create3DDecomposition(rViewInformation));
+ const_cast< BufferedDecompositionPrimitive3D* >(this)->setBuffered3DDecomposition(aNewSequence);
+ }
+
+ return getBuffered3DDecomposition();
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// tooling
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ // get range3D from a given Primitive3DReference
+ basegfx::B3DRange getB3DRangeFromPrimitive3DReference(const Primitive3DReference& rCandidate, const geometry::ViewInformation3D& aViewInformation)
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rCandidate.is())
+ {
+ // try to get C++ implementation base
+ const BasePrimitive3D* pCandidate(dynamic_cast< BasePrimitive3D* >(rCandidate.get()));
+
+ if(pCandidate)
+ {
+ // use it if possible
+ aRetval.expand(pCandidate->getB3DRange(aViewInformation));
+ }
+ else
+ {
+ // use UNO API call instead
+ const uno::Sequence< beans::PropertyValue >& rViewParameters(aViewInformation.getViewInformationSequence());
+ aRetval.expand(basegfx::unotools::b3DRectangleFromRealRectangle3D(rCandidate->getRange(rViewParameters)));
+ }
+ }
+
+ return aRetval;
+ }
+
+ // get range3D from a given Primitive3DSequence
+ basegfx::B3DRange getB3DRangeFromPrimitive3DSequence(const Primitive3DSequence& rCandidate, const geometry::ViewInformation3D& aViewInformation)
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rCandidate.hasElements())
+ {
+ const sal_Int32 nCount(rCandidate.getLength());
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ aRetval.expand(getB3DRangeFromPrimitive3DReference(rCandidate[a], aViewInformation));
+ }
+ }
+
+ return aRetval;
+ }
+
+ bool arePrimitive3DReferencesEqual(const Primitive3DReference& rxA, const Primitive3DReference& rxB)
+ {
+ const sal_Bool bAIs(rxA.is());
+
+ if(bAIs != rxB.is())
+ {
+ return false;
+ }
+
+ if(!bAIs)
+ {
+ return true;
+ }
+
+ const BasePrimitive3D* pA(dynamic_cast< const BasePrimitive3D* >(rxA.get()));
+ const BasePrimitive3D* pB(dynamic_cast< const BasePrimitive3D* >(rxB.get()));
+ const bool bAEqualZero(pA == 0L);
+
+ if(bAEqualZero != (pB == 0L))
+ {
+ return false;
+ }
+
+ if(bAEqualZero)
+ {
+ return false;
+ }
+
+ return (pA->operator==(*pB));
+ }
+
+ bool arePrimitive3DSequencesEqual(const Primitive3DSequence& rA, const Primitive3DSequence& rB)
+ {
+ const sal_Bool bAHasElements(rA.hasElements());
+
+ if(bAHasElements != rB.hasElements())
+ {
+ return false;
+ }
+
+ if(!bAHasElements)
+ {
+ return true;
+ }
+
+ const sal_Int32 nCount(rA.getLength());
+
+ if(nCount != rB.getLength())
+ {
+ return false;
+ }
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ if(!arePrimitive3DReferencesEqual(rA[a], rB[a]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // concatenate sequence
+ void appendPrimitive3DSequenceToPrimitive3DSequence(Primitive3DSequence& rDest, const Primitive3DSequence& rSource)
+ {
+ if(rSource.hasElements())
+ {
+ if(rDest.hasElements())
+ {
+ const sal_Int32 nSourceCount(rSource.getLength());
+ const sal_Int32 nDestCount(rDest.getLength());
+ const sal_Int32 nTargetCount(nSourceCount + nDestCount);
+ sal_Int32 nInsertPos(nDestCount);
+
+ rDest.realloc(nTargetCount);
+
+ for(sal_Int32 a(0L); a < nSourceCount; a++)
+ {
+ if(rSource[a].is())
+ {
+ rDest[nInsertPos++] = rSource[a];
+ }
+ }
+
+ if(nInsertPos != nTargetCount)
+ {
+ rDest.realloc(nInsertPos);
+ }
+ }
+ else
+ {
+ rDest = rSource;
+ }
+ }
+ }
+
+ // concatenate single Primitive3D
+ void appendPrimitive3DReferenceToPrimitive3DSequence(Primitive3DSequence& rDest, const Primitive3DReference& rSource)
+ {
+ if(rSource.is())
+ {
+ const sal_Int32 nDestCount(rDest.getLength());
+ rDest.realloc(nDestCount + 1L);
+ rDest[nDestCount] = rSource;
+ }
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/groupprimitive3d.cxx b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
new file mode 100644
index 000000000000..8ad65676cf24
--- /dev/null
+++ b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/groupprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ GroupPrimitive3D::GroupPrimitive3D( const Primitive3DSequence& rChildren )
+ : BasePrimitive3D(),
+ maChildren(rChildren)
+ {
+ }
+
+ /** The compare opertator uses the Sequence::==operator, so only checking if
+ the rererences are equal. All non-equal references are interpreted as
+ non-equal.
+ */
+ bool GroupPrimitive3D::operator==( const BasePrimitive3D& rPrimitive ) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const GroupPrimitive3D& rCompare = static_cast< const GroupPrimitive3D& >(rPrimitive);
+
+ return (arePrimitive3DSequencesEqual(getChildren(), rCompare.getChildren()));
+ }
+
+ return false;
+ }
+
+ /// default: just return children, so all renderers not supporting group will use it's content
+ Primitive3DSequence GroupPrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return getChildren();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(GroupPrimitive3D, PRIMITIVE3D_ID_GROUPPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
new file mode 100644
index 000000000000..d94fbb5f893c
--- /dev/null
+++ b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
@@ -0,0 +1,319 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <drawinglayer/texture/texture.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence HatchTexturePrimitive3D::impCreate3DDecomposition() const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getChildren().hasElements())
+ {
+ const Primitive3DSequence aSource(getChildren());
+ const sal_uInt32 nSourceCount(aSource.getLength());
+ std::vector< Primitive3DReference > aDestination;
+
+ for(sal_uInt32 a(0); a < nSourceCount; a++)
+ {
+ // get reference
+ const Primitive3DReference xReference(aSource[a]);
+
+ if(xReference.is())
+ {
+ // try to cast to BasePrimitive2D implementation
+ const BasePrimitive3D* pBasePrimitive = dynamic_cast< const BasePrimitive3D* >(xReference.get());
+
+ if(pBasePrimitive)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
+ // not all content is needed, remove transparencies and ModifiedColorPrimitives
+ switch(pBasePrimitive->getPrimitive3DID())
+ {
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // polyPolygonMaterialPrimitive3D, check texturing and hatching
+ const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive);
+ const basegfx::B3DPolyPolygon aFillPolyPolygon(rPrimitive.getB3DPolyPolygon());
+
+ if(maHatch.isFillBackground())
+ {
+ // add original primitive for background
+ aDestination.push_back(xReference);
+ }
+
+ if(aFillPolyPolygon.areTextureCoordinatesUsed())
+ {
+ const sal_uInt32 nPolyCount(aFillPolyPolygon.count());
+ basegfx::B2DPolyPolygon aTexPolyPolygon;
+ basegfx::B2DPoint a2N;
+ basegfx::B2DVector a2X, a2Y;
+ basegfx::B3DPoint a3N;
+ basegfx::B3DVector a3X, a3Y;
+ bool b2N(false), b2X(false), b2Y(false);
+
+ for(sal_uInt32 b(0); b < nPolyCount; b++)
+ {
+ const basegfx::B3DPolygon aPartPoly(aFillPolyPolygon.getB3DPolygon(b));
+ const sal_uInt32 nPointCount(aPartPoly.count());
+ basegfx::B2DPolygon aTexPolygon;
+
+ for(sal_uInt32 c(0); c < nPointCount; c++)
+ {
+ const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c));
+
+ if(!b2N)
+ {
+ a2N = a2Candidate;
+ a3N = aPartPoly.getB3DPoint(c);
+ b2N = true;
+ }
+ else if(!b2X && !a2N.equal(a2Candidate))
+ {
+ a2X = a2Candidate - a2N;
+ a3X = aPartPoly.getB3DPoint(c) - a3N;
+ b2X = true;
+ }
+ else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate))
+ {
+ a2Y = a2Candidate - a2N;
+
+ const double fCross(a2X.cross(a2Y));
+
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ a3Y = aPartPoly.getB3DPoint(c) - a3N;
+ b2Y = true;
+ }
+ }
+
+ aTexPolygon.append(a2Candidate);
+ }
+
+ aTexPolygon.setClosed(true);
+ aTexPolyPolygon.append(aTexPolygon);
+ }
+
+ if(b2N && b2X && b2Y)
+ {
+ // found two linearly independent 2D vectors
+ // get 2d range of texture coordinates
+ const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aTexPolyPolygon));
+ const basegfx::BColor aHatchColor(getHatch().getColor());
+ const double fAngle(getHatch().getAngle());
+ ::std::vector< basegfx::B2DHomMatrix > aMatrices;
+
+ // get hatch transformations
+ switch(getHatch().getStyle())
+ {
+ case attribute::HATCHSTYLE_TRIPLE:
+ {
+ // rotated 45 degrees
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI4);
+ aHatch.appendTransformations(aMatrices);
+ }
+ case attribute::HATCHSTYLE_DOUBLE:
+ {
+ // rotated 90 degrees
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI2);
+ aHatch.appendTransformations(aMatrices);
+ }
+ case attribute::HATCHSTYLE_SINGLE:
+ {
+ // angle as given
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle);
+ aHatch.appendTransformations(aMatrices);
+ }
+ }
+
+ // create geometry from unit line
+ basegfx::B2DPolyPolygon a2DHatchLines;
+ basegfx::B2DPolygon a2DUnitLine;
+ a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0));
+ a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0));
+
+ for(sal_uInt32 c(0); c < aMatrices.size(); c++)
+ {
+ const basegfx::B2DHomMatrix& rMatrix = aMatrices[c];
+ basegfx::B2DPolygon aNewLine(a2DUnitLine);
+ aNewLine.transform(rMatrix);
+ a2DHatchLines.append(aNewLine);
+ }
+
+ if(a2DHatchLines.count())
+ {
+ // clip against texture polygon
+ a2DHatchLines = basegfx::tools::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true);
+ }
+
+ if(a2DHatchLines.count())
+ {
+ // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the new coordinate system
+ basegfx::B2DHomMatrix a2D;
+ a2D.set(0, 0, a2X.getX());
+ a2D.set(1, 0, a2X.getY());
+ a2D.set(0, 1, a2Y.getX());
+ a2D.set(1, 1, a2Y.getY());
+ a2D.set(0, 2, a2N.getX());
+ a2D.set(1, 2, a2N.getY());
+
+ // invert that transformation, so we have a back-transformation from texture coordinates
+ // to unit coordinates
+ a2D.invert();
+ a2DHatchLines.transform(a2D);
+
+ // expand back-transformated geometry tpo 3D
+ basegfx::B3DPolyPolygon a3DHatchLines(basegfx::tools::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0));
+
+ // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the object's 3d coordinate system
+ basegfx::B3DHomMatrix a3D;
+ a3D.set(0, 0, a3X.getX());
+ a3D.set(1, 0, a3X.getY());
+ a3D.set(2, 0, a3X.getZ());
+ a3D.set(0, 1, a3Y.getX());
+ a3D.set(1, 1, a3Y.getY());
+ a3D.set(2, 1, a3Y.getZ());
+ a3D.set(0, 3, a3N.getX());
+ a3D.set(1, 3, a3N.getY());
+ a3D.set(2, 3, a3N.getZ());
+
+ // transform hatch lines to 3D object coordinates
+ a3DHatchLines.transform(a3D);
+
+ // build primitives from this geometry
+ const sal_uInt32 nHatchLines(a3DHatchLines.count());
+
+ for(sal_uInt32 d(0); d < nHatchLines; d++)
+ {
+ const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor));
+ aDestination.push_back(xRef);
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ default :
+ {
+ // add reference to result
+ aDestination.push_back(xReference);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // unknown implementation, add to result
+ aDestination.push_back(xReference);
+ }
+ }
+ }
+
+ // prepare return value
+ const sal_uInt32 nDestSize(aDestination.size());
+ aRetval.realloc(nDestSize);
+
+ for(sal_uInt32 b(0); b < nDestSize; b++)
+ {
+ aRetval[b] = aDestination[b];
+ }
+ }
+
+ return aRetval;
+ }
+
+ HatchTexturePrimitive3D::HatchTexturePrimitive3D(
+ const attribute::FillHatchAttribute& rHatch,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate,
+ bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maHatch(rHatch),
+ maBuffered3DDecomposition()
+ {
+ }
+
+ bool HatchTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const HatchTexturePrimitive3D& rCompare = (HatchTexturePrimitive3D&)rPrimitive;
+
+ return (getHatch() == rCompare.getHatch());
+ }
+
+ return false;
+ }
+
+ Primitive3DSequence HatchTexturePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if(!getBuffered3DDecomposition().hasElements())
+ {
+ const Primitive3DSequence aNewSequence(impCreate3DDecomposition());
+ const_cast< HatchTexturePrimitive3D* >(this)->setBuffered3DDecomposition(aNewSequence);
+ }
+
+ return getBuffered3DDecomposition();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(HatchTexturePrimitive3D, PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx b/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx
new file mode 100644
index 000000000000..e94eeb99f764
--- /dev/null
+++ b/drawinglayer/source/primitive3d/hiddengeometryprimitive3d.cxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: hittestprimitive3d.cxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/25 17:12:14 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ HiddenGeometryPrimitive3D::HiddenGeometryPrimitive3D(
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren)
+ {
+ }
+
+ basegfx::B3DRange HiddenGeometryPrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ return getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation);
+ }
+
+ Primitive3DSequence HiddenGeometryPrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // return empty sequence
+ return Primitive3DSequence();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(HiddenGeometryPrimitive3D, PRIMITIVE3D_ID_HIDDENGEOMETRYPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/makefile.mk b/drawinglayer/source/primitive3d/makefile.mk
new file mode 100644
index 000000000000..afad990c0e28
--- /dev/null
+++ b/drawinglayer/source/primitive3d/makefile.mk
@@ -0,0 +1,62 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJNAME=drawinglayer
+TARGET=primitive3d
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/baseprimitive3d.obj \
+ $(SLO)$/groupprimitive3d.obj \
+ $(SLO)$/hatchtextureprimitive3d.obj \
+ $(SLO)$/hiddengeometryprimitive3d.obj \
+ $(SLO)$/modifiedcolorprimitive3d.obj \
+ $(SLO)$/polypolygonprimitive3d.obj \
+ $(SLO)$/polygonprimitive3d.obj \
+ $(SLO)$/polygontubeprimitive3d.obj \
+ $(SLO)$/sdrcubeprimitive3d.obj \
+ $(SLO)$/sdrdecompositiontools3d.obj \
+ $(SLO)$/sdrextrudelathetools3d.obj \
+ $(SLO)$/sdrextrudeprimitive3d.obj \
+ $(SLO)$/sdrlatheprimitive3d.obj \
+ $(SLO)$/sdrpolypolygonprimitive3d.obj \
+ $(SLO)$/sdrprimitive3d.obj \
+ $(SLO)$/sdrsphereprimitive3d.obj \
+ $(SLO)$/shadowprimitive3d.obj \
+ $(SLO)$/textureprimitive3d.obj \
+ $(SLO)$/transformprimitive3d.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
new file mode 100644
index 000000000000..d840aaf49278
--- /dev/null
+++ b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ ModifiedColorPrimitive3D::ModifiedColorPrimitive3D(
+ const Primitive3DSequence& rChildren,
+ const basegfx::BColorModifier& rColorModifier)
+ : GroupPrimitive3D(rChildren),
+ maColorModifier(rColorModifier)
+ {
+ }
+
+ bool ModifiedColorPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const ModifiedColorPrimitive3D& rCompare = (ModifiedColorPrimitive3D&)rPrimitive;
+
+ return (maColorModifier == rCompare.maColorModifier);
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(ModifiedColorPrimitive3D, PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
new file mode 100644
index 000000000000..9899e565f69c
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
@@ -0,0 +1,178 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/polygontubeprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ PolygonHairlinePrimitive3D::PolygonHairlinePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const basegfx::BColor& rBColor)
+ : BasePrimitive3D(),
+ maPolygon(rPolygon),
+ maBColor(rBColor)
+ {
+ }
+
+ bool PolygonHairlinePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonHairlinePrimitive3D& rCompare = (PolygonHairlinePrimitive3D&)rPrimitive;
+
+ return (getB3DPolygon() == rCompare.getB3DPolygon()
+ && getBColor() == rCompare.getBColor());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange PolygonHairlinePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return basegfx::tools::getRange(getB3DPolygon());
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonHairlinePrimitive3D, PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence PolygonStrokePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getB3DPolygon().count())
+ {
+ basegfx::B3DPolyPolygon aHairLinePolyPolygon;
+
+ if(0.0 == getStrokeAttribute().getFullDotDashLen())
+ {
+ aHairLinePolyPolygon = basegfx::B3DPolyPolygon(getB3DPolygon());
+ }
+ else
+ {
+ // apply LineStyle
+ basegfx::tools::applyLineDashing(getB3DPolygon(), getStrokeAttribute().getDotDashArray(), &aHairLinePolyPolygon, 0, getStrokeAttribute().getFullDotDashLen());
+ }
+
+ // prepare result
+ aRetval.realloc(aHairLinePolyPolygon.count());
+
+ if(getLineAttribute().getWidth())
+ {
+ // create fat line data
+ const double fRadius(getLineAttribute().getWidth() / 2.0);
+ const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
+
+ for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
+ {
+ // create tube primitives
+ const Primitive3DReference xRef(new PolygonTubePrimitive3D(aHairLinePolyPolygon.getB3DPolygon(a), getLineAttribute().getColor(), fRadius, aLineJoin));
+ aRetval[a] = xRef;
+ }
+ }
+ else
+ {
+ // create hair line data for all sub polygons
+ for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B3DPolygon aCandidate = aHairLinePolyPolygon.getB3DPolygon(a);
+ const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(aCandidate, getLineAttribute().getColor()));
+ aRetval[a] = xRef;
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ PolygonStrokePrimitive3D::PolygonStrokePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute,
+ const attribute::StrokeAttribute& rStrokeAttribute)
+ : BufferedDecompositionPrimitive3D(),
+ maPolygon(rPolygon),
+ maLineAttribute(rLineAttribute),
+ maStrokeAttribute(rStrokeAttribute)
+ {
+ }
+
+ PolygonStrokePrimitive3D::PolygonStrokePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute)
+ : BufferedDecompositionPrimitive3D(),
+ maPolygon(rPolygon),
+ maLineAttribute(rLineAttribute),
+ maStrokeAttribute()
+ {
+ }
+
+ bool PolygonStrokePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonStrokePrimitive3D& rCompare = (PolygonStrokePrimitive3D&)rPrimitive;
+
+ return (getB3DPolygon() == rCompare.getB3DPolygon()
+ && getLineAttribute() == rCompare.getLineAttribute()
+ && getStrokeAttribute() == rCompare.getStrokeAttribute());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonStrokePrimitive3D, PRIMITIVE3D_ID_POLYGONSTROKEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
new file mode 100644
index 000000000000..7b5f183575b2
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
@@ -0,0 +1,579 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/polygontubeprimitive3d.hxx>
+#include <drawinglayer/attribute/materialattribute3d.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ namespace // anonymous namespace
+ {
+ Primitive3DSequence getLineTubeSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial)
+ {
+ // static data for buffered tube primitives
+ static Primitive3DSequence aLineTubeList;
+ static sal_uInt32 nLineTubeSegments(0L);
+ static attribute::MaterialAttribute3D aLineMaterial;
+
+ // may exclusively change static data, use mutex
+ ::osl::Mutex m_mutex;
+
+ if(nSegments != nLineTubeSegments || !(rMaterial == aLineMaterial))
+ {
+ nLineTubeSegments = nSegments;
+ aLineMaterial = rMaterial;
+ aLineTubeList = Primitive3DSequence();
+ }
+
+ if(!aLineTubeList.hasElements() && 0L != nLineTubeSegments)
+ {
+ const basegfx::B3DPoint aLeft(0.0, 0.0, 0.0);
+ const basegfx::B3DPoint aRight(1.0, 0.0, 0.0);
+ basegfx::B3DPoint aLastLeft(0.0, 1.0, 0.0);
+ basegfx::B3DPoint aLastRight(1.0, 1.0, 0.0);
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(F_2PI / (double)nLineTubeSegments, 0.0, 0.0);
+ aLineTubeList.realloc(nLineTubeSegments);
+
+ for(sal_uInt32 a(0L); a < nLineTubeSegments; a++)
+ {
+ const basegfx::B3DPoint aNextLeft(aRot * aLastLeft);
+ const basegfx::B3DPoint aNextRight(aRot * aLastRight);
+ basegfx::B3DPolygon aNewPolygon;
+
+ aNewPolygon.append(aNextLeft);
+ aNewPolygon.setNormal(0L, basegfx::B3DVector(aNextLeft - aLeft));
+
+ aNewPolygon.append(aLastLeft);
+ aNewPolygon.setNormal(1L, basegfx::B3DVector(aLastLeft - aLeft));
+
+ aNewPolygon.append(aLastRight);
+ aNewPolygon.setNormal(2L, basegfx::B3DVector(aLastRight - aRight));
+
+ aNewPolygon.append(aNextRight);
+ aNewPolygon.setNormal(3L, basegfx::B3DVector(aNextRight - aRight));
+
+ aNewPolygon.setClosed(true);
+
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false));
+ aLineTubeList[a] = xRef;
+
+ aLastLeft = aNextLeft;
+ aLastRight = aNextRight;
+ }
+ }
+
+ return aLineTubeList;
+ }
+
+ Primitive3DSequence getLineCapSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial)
+ {
+ // static data for buffered tube primitives
+ static Primitive3DSequence aLineCapList;
+ static sal_uInt32 nLineCapSegments(0L);
+ static attribute::MaterialAttribute3D aLineMaterial;
+
+ // may exclusively change static data, use mutex
+ ::osl::Mutex m_mutex;
+
+ if(nSegments != nLineCapSegments || !(rMaterial == aLineMaterial))
+ {
+ nLineCapSegments = nSegments;
+ aLineMaterial = rMaterial;
+ aLineCapList = Primitive3DSequence();
+ }
+
+ if(!aLineCapList.hasElements() && 0L != nLineCapSegments)
+ {
+ const basegfx::B3DPoint aNull(0.0, 0.0, 0.0);
+ basegfx::B3DPoint aLast(0.0, 1.0, 0.0);
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(F_2PI / (double)nLineCapSegments, 0.0, 0.0);
+ aLineCapList.realloc(nLineCapSegments);
+
+ for(sal_uInt32 a(0L); a < nLineCapSegments; a++)
+ {
+ const basegfx::B3DPoint aNext(aRot * aLast);
+ basegfx::B3DPolygon aNewPolygon;
+
+ aNewPolygon.append(aLast);
+ aNewPolygon.setNormal(0L, basegfx::B3DVector(aLast - aNull));
+
+ aNewPolygon.append(aNext);
+ aNewPolygon.setNormal(1L, basegfx::B3DVector(aNext - aNull));
+
+ aNewPolygon.append(aNull);
+ aNewPolygon.setNormal(2L, basegfx::B3DVector(-1.0, 0.0, 0.0));
+
+ aNewPolygon.setClosed(true);
+
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false));
+ aLineCapList[a] = xRef;
+
+ aLast = aNext;
+ }
+ }
+
+ return aLineCapList;
+ }
+
+ Primitive3DSequence getLineJoinSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial,
+ double fAngle,
+ double /*fDegreeStepWidth*/,
+ double fMiterMinimumAngle,
+ basegfx::B2DLineJoin aLineJoin)
+ {
+ // nSegments is for whole circle, adapt to half circle
+ const sal_uInt32 nVerSeg(nSegments >> 1L);
+ std::vector< BasePrimitive3D* > aResultVector;
+
+ if(nVerSeg)
+ {
+ if(basegfx::B2DLINEJOIN_ROUND == aLineJoin)
+ {
+ // calculate new horizontal segments
+ const sal_uInt32 nHorSeg((sal_uInt32)((fAngle / F_2PI) * (double)nSegments));
+
+ if(nHorSeg)
+ {
+ // create half-sphere
+ const basegfx::B3DPolyPolygon aSphere(basegfx::tools::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle));
+
+ for(sal_uInt32 a(0L); a < aSphere.count(); a++)
+ {
+ const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a));
+ const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aPartPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+ }
+ else
+ {
+ // fallback to bevel when there is not at least one segment hor and ver
+ aLineJoin = basegfx::B2DLINEJOIN_BEVEL;
+ }
+ }
+
+ if(basegfx::B2DLINEJOIN_MIDDLE == aLineJoin
+ || basegfx::B2DLINEJOIN_BEVEL == aLineJoin
+ || basegfx::B2DLINEJOIN_MITER == aLineJoin)
+ {
+ if(basegfx::B2DLINEJOIN_MITER == aLineJoin)
+ {
+ const double fMiterAngle(fAngle/2.0);
+
+ if(fMiterAngle < fMiterMinimumAngle)
+ {
+ // fallback to bevel when miter's angle is too small
+ aLineJoin = basegfx::B2DLINEJOIN_BEVEL;
+ }
+ }
+
+ const double fInc(F_PI / (double)nVerSeg);
+ const double fSin(sin(-fAngle));
+ const double fCos(cos(-fAngle));
+ const bool bMiter(basegfx::B2DLINEJOIN_MITER == aLineJoin);
+ const double fMiterSin(bMiter ? sin(-(fAngle/2.0)) : 0.0);
+ const double fMiterCos(bMiter ? cos(-(fAngle/2.0)) : 0.0);
+ double fPos(-F_PI2);
+ basegfx::B3DPoint aPointOnXY, aPointRotY, aNextPointOnXY, aNextPointRotY;
+ basegfx::B3DPoint aCurrMiter, aNextMiter;
+ basegfx::B3DPolygon aNewPolygon, aMiterPolygon;
+
+ // close polygon
+ aNewPolygon.setClosed(true);
+ aMiterPolygon.setClosed(true);
+
+ for(sal_uInt32 a(0L); a < nVerSeg; a++)
+ {
+ const bool bFirst(0L == a);
+ const bool bLast(a + 1L == nVerSeg);
+
+ if(bFirst || !bLast)
+ {
+ fPos += fInc;
+
+ aNextPointOnXY = basegfx::B3DPoint(
+ cos(fPos),
+ sin(fPos),
+ 0.0);
+
+ aNextPointRotY = basegfx::B3DPoint(
+ aNextPointOnXY.getX() * fCos,
+ aNextPointOnXY.getY(),
+ aNextPointOnXY.getX() * fSin);
+
+ if(bMiter)
+ {
+ aNextMiter = basegfx::B3DPoint(
+ aNextPointOnXY.getX(),
+ aNextPointOnXY.getY(),
+ fMiterSin * (aNextPointOnXY.getX() / fMiterCos));
+ }
+ }
+
+ if(bFirst)
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextMiter);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aMiterPolygon.append(aNextMiter);
+ aMiterPolygon.append(aNextPointRotY);
+ }
+ else
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextPointRotY);
+ }
+ }
+ else if(bLast)
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aNewPolygon.append(aCurrMiter);
+ aNewPolygon.append(aPointOnXY);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aMiterPolygon.append(aPointRotY);
+ aMiterPolygon.append(aCurrMiter);
+ }
+ else
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aNewPolygon.append(aPointRotY);
+ aNewPolygon.append(aPointOnXY);
+ }
+ }
+ else
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(aPointOnXY);
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextMiter);
+ aNewPolygon.append(aCurrMiter);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(aCurrMiter);
+ aMiterPolygon.append(aNextMiter);
+ aMiterPolygon.append(aNextPointRotY);
+ aMiterPolygon.append(aPointRotY);
+ }
+ else
+ {
+ aNewPolygon.append(aPointRotY);
+ aNewPolygon.append(aPointOnXY);
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextPointRotY);
+ }
+ }
+
+ // set normals
+ for(sal_uInt32 b(0L); b < aNewPolygon.count(); b++)
+ {
+ aNewPolygon.setNormal(b, basegfx::B3DVector(aNewPolygon.getB3DPoint(b)));
+ }
+
+ // create primitive
+ if(aNewPolygon.count())
+ {
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+
+ if(bMiter && aMiterPolygon.count())
+ {
+ // set normals
+ for(sal_uInt32 c(0L); c < aMiterPolygon.count(); c++)
+ {
+ aMiterPolygon.setNormal(c, basegfx::B3DVector(aMiterPolygon.getB3DPoint(c)));
+ }
+
+ // create primitive
+ const basegfx::B3DPolyPolygon aMiterPolyPolygon(aMiterPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aMiterPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+
+ // prepare next step
+ if(bFirst || !bLast)
+ {
+ aPointOnXY = aNextPointOnXY;
+ aPointRotY = aNextPointRotY;
+
+ if(bMiter)
+ {
+ aCurrMiter = aNextMiter;
+ }
+ }
+ }
+ }
+ }
+
+ Primitive3DSequence aRetval(aResultVector.size());
+
+ for(sal_uInt32 a(0L); a < aResultVector.size(); a++)
+ {
+ aRetval[a] = Primitive3DReference(aResultVector[a]);
+ }
+
+ return aRetval;
+ }
+
+ basegfx::B3DHomMatrix getRotationFromVector(const basegfx::B3DVector& rVector)
+ {
+ // build transformation from unit vector to vector
+ basegfx::B3DHomMatrix aRetval;
+
+ // get applied rotations from angles in XY and in XZ (cartesian)
+ const double fRotInXY(atan2(rVector.getY(), rVector.getXZLength()));
+ const double fRotInXZ(atan2(-rVector.getZ(), rVector.getX()));
+
+ // apply rotations. Rot around Z needs to be done first, so apply in two steps
+ aRetval.rotate(0.0, 0.0, fRotInXY);
+ aRetval.rotate(0.0, fRotInXZ, 0.0);
+
+ return aRetval;
+ }
+ } // end of anonymous namespace
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ const sal_uInt32 nPointCount(getB3DPolygon().count());
+ std::vector< BasePrimitive3D* > aResultVector;
+
+ if(0L != nPointCount)
+ {
+ if(basegfx::fTools::more(getRadius(), 0.0))
+ {
+ const attribute::MaterialAttribute3D aMaterial(getBColor());
+ static sal_uInt32 nSegments(8L); // default for 3d line segments, for more quality just raise this value (in even steps)
+ const bool bClosed(getB3DPolygon().isClosed());
+ const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin());
+ const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1L);
+ basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1L));
+ basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0L));
+
+ for(sal_uInt32 a(0L); a < nLoopCount; a++)
+ {
+ // get next data
+ const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1L) % nPointCount));
+ const basegfx::B3DVector aForw(aNext - aCurr);
+ const double fForwLen(aForw.getLength());
+
+ if(basegfx::fTools::more(fForwLen, 0.0))
+ {
+ // get rotation from vector, this describes rotation from (1, 0, 0) to aForw
+ basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw));
+
+ // create default transformation with scale and rotate
+ basegfx::B3DHomMatrix aVectorTrans;
+ aVectorTrans.scale(fForwLen, getRadius(), getRadius());
+ aVectorTrans *= aRotVector;
+ aVectorTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ if(bNoLineJoin || (!bClosed && !a))
+ {
+ // line start edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aVectorTrans, getLineCapSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedA);
+ }
+ else
+ {
+ const basegfx::B3DVector aBack(aCurr - aLast);
+ const double fCross(basegfx::cross(aBack, aForw).getLength());
+
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ // line connect non-parallel, aBack, aForw, use getLineJoin()
+ const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2
+ Primitive3DSequence aNewList(getLineJoinSegments(nSegments, aMaterial, fAngle, getDegreeStepWidth(), getMiterMinimumAngle(), getLineJoin()));
+
+ // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack
+ basegfx::B3DHomMatrix aInvRotVector(aRotVector);
+ aInvRotVector.invert();
+ basegfx::B3DVector aTransBack(aInvRotVector * aBack);
+ const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ()));
+
+ // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X.
+ // Also apply usual scaling and translation
+ basegfx::B3DHomMatrix aSphereTrans;
+ aSphereTrans.rotate(0.0, F_PI2, 0.0);
+ aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0);
+ aSphereTrans *= aRotVector;
+ aSphereTrans.scale(getRadius(), getRadius(), getRadius());
+ aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // line start edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedB = new TransformPrimitive3D(aSphereTrans, aNewList);
+ aResultVector.push_back(pNewTransformedB);
+ }
+ }
+
+ // create line segments, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedC = new TransformPrimitive3D(aVectorTrans, getLineTubeSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedC);
+
+ if(bNoLineJoin || (!bClosed && ((a + 1L) == nLoopCount)))
+ {
+ // line end edge, first rotate (mirror) and translate, then use use aRotVector
+ basegfx::B3DHomMatrix aBackTrans;
+ aBackTrans.rotate(0.0, F_PI, 0.0);
+ aBackTrans.translate(1.0, 0.0, 0.0);
+ aBackTrans.scale(fForwLen, getRadius(), getRadius());
+ aBackTrans *= aRotVector;
+ aBackTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // line end edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedD = new TransformPrimitive3D(aBackTrans, getLineCapSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedD);
+ }
+ }
+
+ // prepare next loop step
+ aLast = aCurr;
+ aCurr = aNext;
+ }
+ }
+ else
+ {
+ // create hairline
+ PolygonHairlinePrimitive3D* pNew = new PolygonHairlinePrimitive3D(getB3DPolygon(), getBColor());
+ aResultVector.push_back(pNew);
+ }
+ }
+
+ // prepare return value
+ Primitive3DSequence aRetval(aResultVector.size());
+
+ for(sal_uInt32 a(0L); a < aResultVector.size(); a++)
+ {
+ aRetval[a] = Primitive3DReference(aResultVector[a]);
+ }
+
+ return aRetval;
+ }
+
+ PolygonTubePrimitive3D::PolygonTubePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const basegfx::BColor& rBColor,
+ double fRadius, basegfx::B2DLineJoin aLineJoin,
+ double fDegreeStepWidth,
+ double fMiterMinimumAngle)
+ : PolygonHairlinePrimitive3D(rPolygon, rBColor),
+ maLast3DDecomposition(),
+ mfRadius(fRadius),
+ mfDegreeStepWidth(fDegreeStepWidth),
+ mfMiterMinimumAngle(fMiterMinimumAngle),
+ maLineJoin(aLineJoin)
+ {
+ }
+
+ bool PolygonTubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(PolygonHairlinePrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonTubePrimitive3D& rCompare = (PolygonTubePrimitive3D&)rPrimitive;
+
+ return (getRadius() == rCompare.getRadius()
+ && getDegreeStepWidth() == rCompare.getDegreeStepWidth()
+ && getMiterMinimumAngle() == rCompare.getMiterMinimumAngle()
+ && getLineJoin() == rCompare.getLineJoin());
+ }
+
+ return false;
+ }
+
+ Primitive3DSequence PolygonTubePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if(!getLast3DDecomposition().hasElements())
+ {
+ const Primitive3DSequence aNewSequence(impCreate3DDecomposition(rViewInformation));
+ const_cast< PolygonTubePrimitive3D* >(this)->setLast3DDecomposition(aNewSequence);
+ }
+
+ return getLast3DDecomposition();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonTubePrimitive3D, PRIMITIVE3D_ID_POLYGONTUBEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
new file mode 100644
index 000000000000..b3e6655a001a
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ PolyPolygonMaterialPrimitive3D::PolyPolygonMaterialPrimitive3D(
+ const basegfx::B3DPolyPolygon& rPolyPolygon,
+ const attribute::MaterialAttribute3D& rMaterial,
+ bool bDoubleSided)
+ : BasePrimitive3D(),
+ maPolyPolygon(rPolyPolygon),
+ maMaterial(rMaterial),
+ mbDoubleSided(bDoubleSided)
+ {
+ }
+
+ bool PolyPolygonMaterialPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const PolyPolygonMaterialPrimitive3D& rCompare = (PolyPolygonMaterialPrimitive3D&)rPrimitive;
+
+ return (getB3DPolyPolygon() == rCompare.getB3DPolyPolygon()
+ && getMaterial() == rCompare.getMaterial()
+ && getDoubleSided() == rCompare.getDoubleSided());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange PolyPolygonMaterialPrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return basegfx::tools::getRange(getB3DPolyPolygon());
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolyPolygonMaterialPrimitive3D, PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx
new file mode 100644
index 000000000000..6dcea7b0d759
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx
@@ -0,0 +1,222 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrcubeprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrCubePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ Primitive3DSequence aRetval;
+ basegfx::B3DPolyPolygon aFill(basegfx::tools::createCubeFillPolyPolygonFromB3DRange(aUnitRange));
+
+ // normal creation
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()
+ || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ // create sphere normals
+ const basegfx::B3DPoint aCenter(basegfx::tools::getRange(aFill).getCenter());
+ aFill = basegfx::tools::applyDefaultNormalsSphere(aFill, aCenter);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ // invert normals
+ aFill = basegfx::tools::invertNormals(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX()));
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY()));
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY);
+ }
+
+ if(bSphereX || bSphereY)
+ {
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ const basegfx::B3DPoint aCenter(aRange.getCenter());
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, bSphereX, bSphereY);
+ }
+
+ if(bObjectSpecificX || bObjectSpecificY)
+ {
+ // object-specific
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ basegfx::B3DPolygon aTmpPoly(aFill.getB3DPolygon(a));
+
+ if(aTmpPoly.count() >= 4L)
+ {
+ for(sal_uInt32 b(0L); b < 4L; b++)
+ {
+ basegfx::B2DPoint aPoint(aTmpPoly.getTextureCoordinate(b));
+
+ if(bObjectSpecificX)
+ {
+ aPoint.setX((1L == b || 2L == b) ? 1.0 : 0.0);
+ }
+
+ if(bObjectSpecificY)
+ {
+ aPoint.setY((2L == b || 3L == b) ? 1.0 : 0.0);
+ }
+
+ aTmpPoly.setTextureCoordinate(b, aPoint);
+ }
+
+ aFill.setB3DPolygon(a, aTmpPoly);
+ }
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY());
+ aFill.transformTextureCoordiantes(aTexMatrix);
+ }
+
+ // build vector of PolyPolygons
+ ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector;
+
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a)));
+ }
+
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ aRetval = createHiddenGeometryPrimitives3D(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute());
+ }
+
+ // add line
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ basegfx::B3DPolyPolygon aLine(basegfx::tools::createCubePolyPolygonFromB3DRange(aUnitRange));
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
+ aLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(!getSdrLFSAttribute().getShadow().isDefault() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(
+ aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+
+ return aRetval;
+ }
+
+ SdrCubePrimitive3D::SdrCubePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute)
+ {
+ }
+
+ bool SdrCubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ return SdrPrimitive3D::operator==(rPrimitive);
+ }
+
+ basegfx::B3DRange SdrCubePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2.
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return getStandard3DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrCubePrimitive3D, PRIMITIVE3D_ID_SDRCUBEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
new file mode 100644
index 000000000000..471d18ed846e
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
@@ -0,0 +1,339 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
+#include <drawinglayer/primitive3d/baseprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <vcl/vclenum.hxx>
+#include <drawinglayer/attribute/fillbitmapattribute.hxx>
+#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
+#include <vcl/bmpacc.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrobjectattribute3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+#include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ basegfx::B3DRange getRangeFrom3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ basegfx::B3DRange aRetval;
+
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ aRetval.expand(basegfx::tools::getRange(rFill[a]));
+ }
+
+ return aRetval;
+ }
+
+ void applyNormalsKindSphereTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill, const basegfx::B3DRange& rRange)
+ {
+ // create sphere normals
+ const basegfx::B3DPoint aCenter(rRange.getCenter());
+
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultNormalsSphere(rFill[a], aCenter);
+ }
+ }
+
+ void applyNormalsKindFlatTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a].clearNormals();
+ }
+ }
+
+ void applyNormalsInvertTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ // invert normals
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::invertNormals(rFill[a]);
+ }
+ }
+
+ void applyTextureTo3DGeometry(
+ ::com::sun::star::drawing::TextureProjectionMode eModeX,
+ ::com::sun::star::drawing::TextureProjectionMode eModeY,
+ ::std::vector< basegfx::B3DPolyPolygon >& rFill,
+ const basegfx::B3DRange& rRange,
+ const basegfx::B2DVector& rTextureSize)
+ {
+ sal_uInt32 a;
+
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeX);
+ const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeX));
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeY);
+ const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeY));
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(rFill[a], rRange, bParallelX, bParallelY);
+ }
+ }
+
+ if(bSphereX || bSphereY)
+ {
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DPoint aCenter(rRange.getCenter());
+
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(rFill[a], aCenter, bSphereX, bSphereY);
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(rTextureSize.getX(), rTextureSize.getY());
+
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a].transformTextureCoordiantes(aTexMatrix);
+ }
+ }
+
+ Primitive3DSequence create3DPolyPolygonLinePrimitives(
+ const basegfx::B3DPolyPolygon& rUnitPolyPolygon,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const attribute::SdrLineAttribute& rLine)
+ {
+ // prepare fully scaled polyPolygon
+ basegfx::B3DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon);
+ aScaledPolyPolygon.transform(rObjectTransform);
+
+ // create line and stroke attribute
+ const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin());
+ const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen());
+
+ // create primitives
+ Primitive3DSequence aRetval(aScaledPolyPolygon.count());
+
+ for(sal_uInt32 a(0L); a < aScaledPolyPolygon.count(); a++)
+ {
+ const Primitive3DReference xRef(new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute));
+ aRetval[a] = xRef;
+ }
+
+ if(0.0 != rLine.getTransparence())
+ {
+ // create UnifiedTransparenceTexturePrimitive3D, add created primitives and exchange
+ const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rLine.getTransparence(), aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ return aRetval;
+ }
+
+ Primitive3DSequence create3DPolyPolygonFillPrimitives(
+ const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute,
+ const attribute::SdrFillAttribute& rFill,
+ const attribute::FillGradientAttribute& rFillGradient)
+ {
+ Primitive3DSequence aRetval;
+
+ if(r3DPolyPolygonVector.size())
+ {
+ // create list of simple fill primitives
+ aRetval.realloc(r3DPolyPolygonVector.size());
+
+ for(sal_uInt32 a(0L); a < r3DPolyPolygonVector.size(); a++)
+ {
+ // get scaled PolyPolygon
+ basegfx::B3DPolyPolygon aScaledPolyPolygon(r3DPolyPolygonVector[a]);
+ aScaledPolyPolygon.transform(rObjectTransform);
+
+ if(aScaledPolyPolygon.areNormalsUsed())
+ {
+ aScaledPolyPolygon.transformNormals(rObjectTransform);
+ }
+
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(
+ aScaledPolyPolygon,
+ aSdr3DObjectAttribute.getMaterial(),
+ aSdr3DObjectAttribute.getDoubleSided()));
+ aRetval[a] = xRef;
+ }
+
+ // look for and evtl. build texture sub-group primitive
+ if(!rFill.getGradient().isDefault()
+ || !rFill.getHatch().isDefault()
+ || !rFill.getBitmap().isDefault())
+ {
+ bool bModulate(::com::sun::star::drawing::TextureMode_MODULATE == aSdr3DObjectAttribute.getTextureMode());
+ bool bFilter(aSdr3DObjectAttribute.getTextureFilter());
+ BasePrimitive3D* pNewTexturePrimitive3D = 0;
+
+ if(!rFill.getGradient().isDefault())
+ {
+ // create gradientTexture3D with sublist, add to local aRetval
+ pNewTexturePrimitive3D = new GradientTexturePrimitive3D(
+ rFill.getGradient(),
+ aRetval,
+ rTextureSize,
+ bModulate,
+ bFilter);
+ }
+ else if(!rFill.getHatch().isDefault())
+ {
+ // create hatchTexture3D with sublist, add to local aRetval
+ pNewTexturePrimitive3D = new HatchTexturePrimitive3D(
+ rFill.getHatch(),
+ aRetval,
+ rTextureSize,
+ bModulate,
+ bFilter);
+ }
+ else // if(!rFill.getBitmap().isDefault())
+ {
+ // create bitmapTexture3D with sublist, add to local aRetval
+ basegfx::B2DRange aTexRange(0.0, 0.0, rTextureSize.getX(), rTextureSize.getY());
+
+ pNewTexturePrimitive3D = new BitmapTexturePrimitive3D(
+ rFill.getBitmap().getFillBitmapAttribute(aTexRange),
+ aRetval,
+ rTextureSize,
+ bModulate,
+ bFilter);
+ }
+
+ // exchange aRetval content with texture group
+ const Primitive3DReference xRef(pNewTexturePrimitive3D);
+ aRetval = Primitive3DSequence(&xRef, 1L);
+
+ if(::com::sun::star::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind())
+ {
+ // use modified color primitive to force textures to gray
+ const basegfx::BColorModifier aBColorModifier(basegfx::BColor(), 0.0, basegfx::BCOLORMODIFYMODE_GRAY);
+ const Primitive3DReference xRef2(new ModifiedColorPrimitive3D(aRetval, aBColorModifier));
+ aRetval = Primitive3DSequence(&xRef2, 1L);
+ }
+ }
+
+ if(0.0 != rFill.getTransparence())
+ {
+ // create UnifiedTransparenceTexturePrimitive3D with sublist and exchange
+ const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rFill.getTransparence(), aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+ else if(!rFillGradient.isDefault())
+ {
+ // create TransparenceTexturePrimitive3D with sublist and exchange
+ const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(rFillGradient, aRetval, rTextureSize));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+ }
+
+ return aRetval;
+ }
+
+ Primitive3DSequence createShadowPrimitive3D(
+ const Primitive3DSequence& rSource,
+ const attribute::SdrShadowAttribute& rShadow,
+ bool bShadow3D)
+ {
+ // create Shadow primitives. Uses already created primitives
+ if(rSource.hasElements() && !basegfx::fTools::moreOrEqual(rShadow.getTransparence(), 1.0))
+ {
+ // prepare new list for shadow geometry
+ basegfx::B2DHomMatrix aShadowOffset;
+ aShadowOffset.set(0, 2, rShadow.getOffset().getX());
+ aShadowOffset.set(1, 2, rShadow.getOffset().getY());
+
+ // create shadow primitive and add primitives
+ const Primitive3DReference xRef(new ShadowPrimitive3D(aShadowOffset, rShadow.getColor(), rShadow.getTransparence(), bShadow3D, rSource));
+ return Primitive3DSequence(&xRef, 1L);
+ }
+ else
+ {
+ return Primitive3DSequence();
+ }
+ }
+
+ Primitive3DSequence createHiddenGeometryPrimitives3D(
+ const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute)
+ {
+ // create hidden sub-geometry which can be used for HitTest
+ // and BoundRect calculations, but will not be visualized
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(
+ 0.0,
+ basegfx::BColor(),
+ attribute::FillGradientAttribute(),
+ attribute::FillHatchAttribute(),
+ attribute::SdrFillBitmapAttribute());
+
+ const Primitive3DReference aHidden(
+ new HiddenGeometryPrimitive3D(
+ create3DPolyPolygonFillPrimitives(
+ r3DPolyPolygonVector,
+ rObjectTransform,
+ rTextureSize,
+ aSdr3DObjectAttribute,
+ aSimplifiedFillAttribute,
+ attribute::FillGradientAttribute())));
+
+ return Primitive3DSequence(&aHidden, 1);
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
new file mode 100644
index 000000000000..98ce52b5c0a7
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
@@ -0,0 +1,991 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrextrudelathetools3d.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b3dpoint.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/range/b3drange.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <numeric>
+
+//////////////////////////////////////////////////////////////////////////////
+// decompositon helpers for extrude/lathe (rotation) objects
+
+namespace
+{
+ //////////////////////////////////////////////////////////////////////////////
+ // common helpers
+
+ basegfx::B2DPolyPolygon impScalePolyPolygonOnCenter(
+ const basegfx::B2DPolyPolygon& rSource,
+ double fScale)
+ {
+ basegfx::B2DPolyPolygon aRetval(rSource);
+
+ if(!basegfx::fTools::equalZero(fScale))
+ {
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(rSource));
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
+ basegfx::B2DHomMatrix aTrans;
+
+ aTrans.translate(-aCenter.getX(), -aCenter.getY());
+ aTrans.scale(fScale, fScale);
+ aTrans.translate(aCenter.getX(), aCenter.getY());
+ aRetval.transform(aTrans);
+ }
+
+ return aRetval;
+ }
+
+ void impGetOuterPolyPolygon(
+ basegfx::B2DPolyPolygon& rPolygon,
+ basegfx::B2DPolyPolygon& rOuterPolyPolygon,
+ double fOffset,
+ bool bCharacterMode)
+ {
+ rOuterPolyPolygon = rPolygon;
+
+ if(basegfx::fTools::more(fOffset, 0.0))
+ {
+ if(bCharacterMode)
+ {
+ // grow the outside polygon and scale all polygons to original size. This is done
+ // to avoid a shrink which potentially would lead to self-intersections, but changes
+ // the original polygon -> not a precision step, so e.g. not usable for charts
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(rPolygon));
+ rPolygon = basegfx::tools::growInNormalDirection(rPolygon, fOffset);
+ const basegfx::B2DRange aGrownRange(basegfx::tools::getRange(rPolygon));
+ const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth());
+ const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight());
+ basegfx::B2DHomMatrix aScaleTrans;
+
+ aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY());
+ aScaleTrans.scale(fScaleX, fScaleY);
+ aScaleTrans.translate(aRange.getMinX(), aRange.getMinY());
+ rPolygon.transform(aScaleTrans);
+ rOuterPolyPolygon.transform(aScaleTrans);
+ }
+ else
+ {
+ // use more precision, shrink the outer polygons. Since this may lead to self-intersections,
+ // some kind of correction should be applied here after that step
+ rOuterPolyPolygon = basegfx::tools::growInNormalDirection(rPolygon, -fOffset);
+ basegfx::tools::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon);
+ }
+ }
+ }
+
+ void impAddInBetweenFill(
+ basegfx::B3DPolyPolygon& rTarget,
+ const basegfx::B3DPolyPolygon& rPolA,
+ const basegfx::B3DPolyPolygon& rPolB,
+ double fTexVerStart,
+ double fTexVerStop,
+ bool bCreateNormals,
+ bool bCreateTextureCoordinates)
+ {
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
+ const sal_uInt32 nPolygonCount(rPolA.count());
+
+ for(sal_uInt32 a(0L); a < nPolygonCount; a++)
+ {
+ const basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ if(nPointCount)
+ {
+ const sal_uInt32 nEdgeCount(aSubA.isClosed() ? nPointCount : nPointCount - 1L);
+ double fTexHorMultiplicatorA(0.0), fTexHorMultiplicatorB(0.0);
+ double fPolygonPosA(0.0), fPolygonPosB(0.0);
+
+ if(bCreateTextureCoordinates)
+ {
+ const double fPolygonLengthA(basegfx::tools::getLength(aSubA));
+ fTexHorMultiplicatorA = basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA;
+
+ const double fPolygonLengthB(basegfx::tools::getLength(aSubB));
+ fTexHorMultiplicatorB = basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB;
+ }
+
+ for(sal_uInt32 b(0L); b < nEdgeCount; b++)
+ {
+ const sal_uInt32 nIndexA(b);
+ const sal_uInt32 nIndexB((b + 1L) % nPointCount);
+
+ const basegfx::B3DPoint aStartA(aSubA.getB3DPoint(nIndexA));
+ const basegfx::B3DPoint aEndA(aSubA.getB3DPoint(nIndexB));
+ const basegfx::B3DPoint aStartB(aSubB.getB3DPoint(nIndexA));
+ const basegfx::B3DPoint aEndB(aSubB.getB3DPoint(nIndexB));
+
+ basegfx::B3DPolygon aNew;
+ aNew.setClosed(true);
+
+ aNew.append(aStartA);
+ aNew.append(aStartB);
+ aNew.append(aEndB);
+ aNew.append(aEndA);
+
+ if(bCreateNormals)
+ {
+ aNew.setNormal(0L, aSubA.getNormal(nIndexA));
+ aNew.setNormal(1L, aSubB.getNormal(nIndexA));
+ aNew.setNormal(2L, aSubB.getNormal(nIndexB));
+ aNew.setNormal(3L, aSubA.getNormal(nIndexB));
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ const double fRelTexAL(fPolygonPosA * fTexHorMultiplicatorA);
+ const double fEdgeLengthA(basegfx::B3DVector(aEndA - aStartA).getLength());
+ fPolygonPosA += fEdgeLengthA;
+ const double fRelTexAR(fPolygonPosA * fTexHorMultiplicatorA);
+
+ const double fRelTexBL(fPolygonPosB * fTexHorMultiplicatorB);
+ const double fEdgeLengthB(basegfx::B3DVector(aEndB - aStartB).getLength());
+ fPolygonPosB += fEdgeLengthB;
+ const double fRelTexBR(fPolygonPosB * fTexHorMultiplicatorB);
+
+ aNew.setTextureCoordinate(0L, basegfx::B2DPoint(fRelTexAL, fTexVerStart));
+ aNew.setTextureCoordinate(1L, basegfx::B2DPoint(fRelTexBL, fTexVerStop));
+ aNew.setTextureCoordinate(2L, basegfx::B2DPoint(fRelTexBR, fTexVerStop));
+ aNew.setTextureCoordinate(3L, basegfx::B2DPoint(fRelTexAR, fTexVerStart));
+ }
+
+ rTarget.append(aNew);
+ }
+ }
+ }
+ }
+
+ void impSetNormal(
+ basegfx::B3DPolyPolygon& rCandidate,
+ const basegfx::B3DVector& rNormal)
+ {
+ for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
+ {
+ basegfx::B3DPolygon aSub(rCandidate.getB3DPolygon(a));
+
+ for(sal_uInt32 b(0L); b < aSub.count(); b++)
+ {
+ aSub.setNormal(b, rNormal);
+ }
+
+ rCandidate.setB3DPolygon(a, aSub);
+ }
+ }
+
+ void impCreateInBetweenNormals(
+ basegfx::B3DPolyPolygon& rPolA,
+ basegfx::B3DPolyPolygon& rPolB,
+ bool bSmoothHorizontalNormals)
+ {
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+
+ for(sal_uInt32 a(0L); a < rPolA.count(); a++)
+ {
+ basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ if(nPointCount)
+ {
+ basegfx::B3DPoint aPrevA(aSubA.getB3DPoint(nPointCount - 1L));
+ basegfx::B3DPoint aCurrA(aSubA.getB3DPoint(0L));
+ const bool bClosed(aSubA.isClosed());
+
+ for(sal_uInt32 b(0L); b < nPointCount; b++)
+ {
+ const sal_uInt32 nIndNext((b + 1L) % nPointCount);
+ const basegfx::B3DPoint aNextA(aSubA.getB3DPoint(nIndNext));
+ const basegfx::B3DPoint aCurrB(aSubB.getB3DPoint(b));
+
+ // vector to back
+ basegfx::B3DVector aDepth(aCurrB - aCurrA);
+ aDepth.normalize();
+
+ if(aDepth.equalZero())
+ {
+ // no difference, try to get depth from next point
+ const basegfx::B3DPoint aNextB(aSubB.getB3DPoint(nIndNext));
+ aDepth = aNextB - aNextA;
+ aDepth.normalize();
+ }
+
+ // vector to left (correct for non-closed lines)
+ const bool bFirstAndNotClosed(!bClosed && 0L == b);
+ basegfx::B3DVector aLeft(bFirstAndNotClosed ? aCurrA - aNextA : aPrevA - aCurrA);
+ aLeft.normalize();
+
+ // create left normal
+ const basegfx::B3DVector aNormalLeft(aDepth.getPerpendicular(aLeft));
+
+ if(bSmoothHorizontalNormals)
+ {
+ // vector to right (correct for non-closed lines)
+ const bool bLastAndNotClosed(!bClosed && b + 1L == nPointCount);
+ basegfx::B3DVector aRight(bLastAndNotClosed ? aCurrA - aPrevA : aNextA - aCurrA);
+ aRight.normalize();
+
+ // create right normal
+ const basegfx::B3DVector aNormalRight(aRight.getPerpendicular(aDepth));
+
+ // create smoothed in-between normal
+ basegfx::B3DVector aNewNormal(aNormalLeft + aNormalRight);
+ aNewNormal.normalize();
+
+ // set as new normal at polygons
+ aSubA.setNormal(b, aNewNormal);
+ aSubB.setNormal(b, aNewNormal);
+ }
+ else
+ {
+ // set aNormalLeft as new normal at polygons
+ aSubA.setNormal(b, aNormalLeft);
+ aSubB.setNormal(b, aNormalLeft);
+ }
+
+ // prepare next step
+ aPrevA = aCurrA;
+ aCurrA = aNextA;
+ }
+
+ rPolA.setB3DPolygon(a, aSubA);
+ rPolB.setB3DPolygon(a, aSubB);
+ }
+ }
+ }
+
+ void impMixNormals(
+ basegfx::B3DPolyPolygon& rPolA,
+ const basegfx::B3DPolyPolygon& rPolB,
+ double fWeightA)
+ {
+ const double fWeightB(1.0 - fWeightA);
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+
+ for(sal_uInt32 a(0L); a < rPolA.count(); a++)
+ {
+ basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ for(sal_uInt32 b(0L); b < nPointCount; b++)
+ {
+ const basegfx::B3DVector aVA(aSubA.getNormal(b) * fWeightA);
+ const basegfx::B3DVector aVB(aSubB.getNormal(b) * fWeightB);
+ basegfx::B3DVector aVNew(aVA + aVB);
+ aVNew.normalize();
+ aSubA.setNormal(b, aVNew);
+ }
+
+ rPolA.setB3DPolygon(a, aSubA);
+ }
+ }
+
+ bool impHasCutWith(const basegfx::B2DPolygon& rPoly, const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd)
+ {
+ // polygon is closed, one of the points is a member
+ const sal_uInt32 nPointCount(rPoly.count());
+
+ if(nPointCount)
+ {
+ basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
+ const basegfx::B2DVector aVector(rEnd - rStart);
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
+ const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
+
+ if(basegfx::tools::findCut(
+ rStart, aVector,
+ aCurrent, aEdgeVector))
+ {
+ return true;
+ }
+
+ aCurrent = aNext;
+ }
+ }
+
+ return false;
+ }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ void createLatheSlices(
+ Slice3DVector& rSliceVector,
+ const basegfx::B2DPolyPolygon& rSource,
+ double fBackScale,
+ double fDiagonal,
+ double fRotation,
+ sal_uInt32 nSteps,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ {
+ if(basegfx::fTools::equalZero(fRotation) || 0L == nSteps)
+ {
+ // no rotation or no steps, just one plane
+ rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
+ }
+ else
+ {
+ const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
+ const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, F_2PI));
+ basegfx::B2DPolyPolygon aFront(rSource);
+ basegfx::B2DPolyPolygon aBack(rSource);
+ basegfx::B3DHomMatrix aTransformBack;
+ basegfx::B2DPolyPolygon aOuterBack;
+
+ if(bClosedRotation)
+ {
+ bCloseFront = bCloseBack = false;
+ }
+
+ if(bBackScale)
+ {
+ // avoid null zoom
+ if(basegfx::fTools::equalZero(fBackScale))
+ {
+ fBackScale = 0.000001;
+ }
+
+ // back is scaled compared to front, create scaled version
+ aBack = impScalePolyPolygonOnCenter(aBack, fBackScale);
+ }
+
+ if(bCloseFront || bCloseBack)
+ {
+ const basegfx::B2DRange aBaseRange(basegfx::tools::getRange(aFront));
+ const double fOuterLength(aBaseRange.getMaxX() * fRotation);
+ const double fInnerLength(aBaseRange.getMinX() * fRotation);
+ const double fAverageLength((fOuterLength + fInnerLength) * 0.5);
+
+ if(bCloseFront)
+ {
+ const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
+ basegfx::B2DPolyPolygon aOuterFront;
+ impGetOuterPolyPolygon(aFront, aOuterFront, fOffsetLen, bCharacterMode);
+ basegfx::B3DHomMatrix aTransform;
+ aTransform.translate(0.0, 0.0, fOffsetLen);
+ rSliceVector.push_back(Slice3D(aOuterFront, aTransform, SLICETYPE3D_FRONTCAP));
+ }
+
+ if(bCloseBack)
+ {
+ const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
+ impGetOuterPolyPolygon(aBack, aOuterBack, fOffsetLen, bCharacterMode);
+ aTransformBack.translate(0.0, 0.0, -fOffsetLen);
+ aTransformBack.rotate(0.0, fRotation, 0.0);
+ }
+ }
+
+ // add start polygon (a = 0L)
+ if(!bClosedRotation)
+ {
+ rSliceVector.push_back(Slice3D(aFront, basegfx::B3DHomMatrix()));
+ }
+
+ // create segments (a + 1 .. nSteps)
+ const double fStepSize(1.0 / (double)nSteps);
+
+ for(sal_uInt32 a(0L); a < nSteps; a++)
+ {
+ const double fStep((double)(a + 1L) * fStepSize);
+ basegfx::B2DPolyPolygon aNewPoly(bBackScale ? basegfx::tools::interpolate(aFront, aBack, fStep) : aFront);
+ basegfx::B3DHomMatrix aNewMat;
+ aNewMat.rotate(0.0, fRotation * fStep, 0.0);
+ rSliceVector.push_back(Slice3D(aNewPoly, aNewMat));
+ }
+
+ if(bCloseBack)
+ {
+ rSliceVector.push_back(Slice3D(aOuterBack, aTransformBack, SLICETYPE3D_BACKCAP));
+ }
+ }
+ }
+
+ void createExtrudeSlices(
+ Slice3DVector& rSliceVector,
+ const basegfx::B2DPolyPolygon& rSource,
+ double fBackScale,
+ double fDiagonal,
+ double fDepth,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ {
+ if(basegfx::fTools::equalZero(fDepth))
+ {
+ // no depth, just one plane
+ rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
+ }
+ else
+ {
+ // there is depth, create Polygons for front,back and their default depth positions
+ basegfx::B2DPolyPolygon aFront(rSource);
+ basegfx::B2DPolyPolygon aBack(rSource);
+ const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
+ double fZFront(fDepth); // default depth for aFront
+ double fZBack(0.0); // default depth for aBack
+ basegfx::B2DPolyPolygon aOuterBack;
+
+ if(bBackScale)
+ {
+ // avoid null zoom
+ if(basegfx::fTools::equalZero(fBackScale))
+ {
+ fBackScale = 0.000001;
+ }
+
+ // aFront is scaled compared to aBack, create scaled version
+ aFront = impScalePolyPolygonOnCenter(aFront, fBackScale);
+ }
+
+ if(bCloseFront)
+ {
+ const double fOffset(fDepth * fDiagonal * 0.5);
+ fZFront = fDepth - fOffset;
+ basegfx::B2DPolyPolygon aOuterFront;
+ impGetOuterPolyPolygon(aFront, aOuterFront, fOffset, bCharacterMode);
+ basegfx::B3DHomMatrix aTransformFront;
+ aTransformFront.translate(0.0, 0.0, fDepth);
+ rSliceVector.push_back(Slice3D(aOuterFront, aTransformFront, SLICETYPE3D_FRONTCAP));
+ }
+
+ if(bCloseBack)
+ {
+ const double fOffset(fDepth * fDiagonal * 0.5);
+ fZBack = fOffset;
+ impGetOuterPolyPolygon(aBack, aOuterBack, fOffset, bCharacterMode);
+ }
+
+ // add front and back polygons at evtl. changed depths
+ {
+ basegfx::B3DHomMatrix aTransformA, aTransformB;
+
+ aTransformA.translate(0.0, 0.0, fZFront);
+ rSliceVector.push_back(Slice3D(aFront, aTransformA));
+
+ aTransformB.translate(0.0, 0.0, fZBack);
+ rSliceVector.push_back(Slice3D(aBack, aTransformB));
+ }
+
+ if(bCloseBack)
+ {
+ rSliceVector.push_back(Slice3D(aOuterBack, basegfx::B3DHomMatrix(), SLICETYPE3D_BACKCAP));
+ }
+ }
+ }
+
+ basegfx::B3DPolyPolygon extractHorizontalLinesFromSlice(const Slice3DVector& rSliceVector, bool bCloseHorLines)
+ {
+ basegfx::B3DPolyPolygon aRetval;
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ if(nNumSlices)
+ {
+ const sal_uInt32 nSlideSubPolygonCount(rSliceVector[0].getB3DPolyPolygon().count());
+
+ for(sal_uInt32 b(0); b < nSlideSubPolygonCount; b++)
+ {
+ const sal_uInt32 nSubPolygonPointCount(rSliceVector[0].getB3DPolyPolygon().getB3DPolygon(b).count());
+
+ for(sal_uInt32 c(0); c < nSubPolygonPointCount; c++)
+ {
+ basegfx::B3DPolygon aNew;
+
+ for(sal_uInt32 d(0); d < nNumSlices; d++)
+ {
+ OSL_ENSURE(nSlideSubPolygonCount == rSliceVector[d].getB3DPolyPolygon().count(),
+ "Slice PolyPolygon with different Polygon count (!)");
+ OSL_ENSURE(nSubPolygonPointCount == rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).count(),
+ "Slice Polygon with different point count (!)");
+ aNew.append(rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).getB3DPoint(c));
+ }
+
+ aNew.setClosed(bCloseHorLines);
+ aRetval.append(aNew);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ basegfx::B3DPolyPolygon extractVerticalLinesFromSlice(const Slice3DVector& rSliceVector)
+ {
+ basegfx::B3DPolyPolygon aRetval;
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ for(sal_uInt32 a(0L); a < nNumSlices; a++)
+ {
+ aRetval.append(rSliceVector[a].getB3DPolyPolygon());
+ }
+
+ return aRetval;
+ }
+
+ void extractPlanesFromSlice(
+ ::std::vector< basegfx::B3DPolyPolygon >& rFill,
+ const Slice3DVector& rSliceVector,
+ bool bCreateNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothNormals,
+ bool bSmoothLids,
+ bool bClosed,
+ double fSmoothNormalsMix,
+ double fSmoothLidsMix,
+ bool bCreateTextureCoordinates,
+ const basegfx::B2DHomMatrix& rTexTransform)
+ {
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ if(nNumSlices)
+ {
+ // common parameters
+ const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1L);
+ basegfx::B3DPolyPolygon aEdgeRounding;
+ sal_uInt32 a;
+
+ // tetxture parameters
+ double fInvTexHeight(1.0);
+ double fTexHeightPos(0.0);
+ double fTexStart(0.0);
+ double fTexStop(1.0);
+ ::std::vector<double> aTexHeightArray;
+ basegfx::B3DRange aTexRangeFront;
+ basegfx::B3DRange aTexRangeBack;
+
+ if(bCreateTextureCoordinates)
+ {
+ aTexRangeFront = basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon());
+ aTexRangeBack = basegfx::tools::getRange(rSliceVector[nNumSlices - 1L].getB3DPolyPolygon());
+
+ if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth())
+ {
+ // last polygon is rotated so that depth is bigger than width, exchange X and Z
+ // for making applyDefaultTextureCoordinatesParallel use Z instead of X for
+ // horizontal texture coordinate
+ aTexRangeBack = basegfx::B3DRange(
+ aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(),
+ aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX());
+ }
+
+ basegfx::B3DPoint aCenter(basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()).getCenter());
+
+ for(a = 0L; a < nLoopCount; a++)
+ {
+ const basegfx::B3DPoint aNextCenter(basegfx::tools::getRange(rSliceVector[(a + 1L) % nNumSlices].getB3DPolyPolygon()).getCenter());
+ const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength());
+ aTexHeightArray.push_back(fLength);
+ aCenter = aNextCenter;
+ }
+
+ const double fTexHeight(::std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0));
+
+ if(!basegfx::fTools::equalZero(fTexHeight))
+ {
+ fInvTexHeight = 1.0 / fTexHeight;
+ }
+ }
+
+ if(nLoopCount)
+ {
+ for(a = 0L; a < nLoopCount; a++)
+ {
+ const Slice3D& rSliceA(rSliceVector[a]);
+ const Slice3D& rSliceB(rSliceVector[(a + 1L) % nNumSlices]);
+ const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType());
+ basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon());
+
+ if(bAcceptPair)
+ {
+ if(bCreateNormals)
+ {
+ impCreateInBetweenNormals(aPolB, aPolA, bSmoothHorizontalNormals);
+ }
+
+ {
+ const sal_uInt32 nIndPrev((a + nNumSlices - 1L) % nNumSlices);
+ const Slice3D& rSlicePrev(rSliceVector[nIndPrev]);
+ basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon());
+
+ if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType())
+ {
+ basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon());
+ const bool bHasSlant(aPolAA != aPrev);
+
+ if(bCreateTextureCoordinates)
+ {
+ aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
+ }
+
+ if(bCreateNormals)
+ {
+ basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
+
+ if(aFront.count())
+ {
+ aNormal = -aFront.getB3DPolygon(0L).getNormal();
+ }
+
+ impSetNormal(aFront, aNormal);
+
+ if(bHasSlant)
+ {
+ impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
+
+ if(bSmoothNormals)
+ {
+ // smooth and copy
+ impMixNormals(aPolA, aPolAA, fSmoothNormalsMix);
+ aPolAA = aPolA;
+ }
+ else
+ {
+ // take over from surface
+ aPolAA = aPolA;
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aFront, aPrev, fSmoothLidsMix);
+ aPrev = aFront;
+ }
+ else
+ {
+ // take over from front
+ aPrev = aFront;
+ }
+ }
+ else
+ {
+ if(bSmoothNormals)
+ {
+ // smooth
+ impMixNormals(aPolA, aFront, fSmoothNormalsMix);
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aFront, aPolA, fSmoothLidsMix);
+ aPolA = aFront;
+ }
+ }
+ }
+
+ if(bHasSlant)
+ {
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = fTexHeightPos * fInvTexHeight;
+ fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1L) % nLoopCount]) * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ aFront.flip();
+ rFill.push_back(aFront);
+ }
+ else
+ {
+ if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1L))
+ {
+ impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
+ impMixNormals(aPolA, aPolAA, 0.5);
+ }
+ }
+ }
+
+ {
+ const sal_uInt32 nIndNext((a + 2L) % nNumSlices);
+ const Slice3D& rSliceNext(rSliceVector[nIndNext]);
+ basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon());
+
+ if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType())
+ {
+ basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon());
+ const bool bHasSlant(aPolBB != aNext);
+
+ if(bCreateTextureCoordinates)
+ {
+ aBack = basegfx::tools::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack);
+ }
+
+ if(bCreateNormals)
+ {
+ const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0L).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0));
+ impSetNormal(aBack, aNormal);
+
+ if(bHasSlant)
+ {
+ impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
+
+ if(bSmoothNormals)
+ {
+ // smooth and copy
+ impMixNormals(aPolB, aPolBB, fSmoothNormalsMix);
+ aPolBB = aPolB;
+ }
+ else
+ {
+ // take over from surface
+ aPolBB = aPolB;
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aBack, aNext, fSmoothLidsMix);
+ aNext = aBack;
+ }
+ else
+ {
+ // take over from back
+ aNext = aBack;
+ }
+ }
+ else
+ {
+ if(bSmoothNormals)
+ {
+ // smooth
+ impMixNormals(aPolB, aBack, fSmoothNormalsMix);
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aBack, aPolB, fSmoothLidsMix);
+ aPolB = aBack;
+ }
+ }
+ }
+
+ if(bHasSlant)
+ {
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1L) % nLoopCount]) * fInvTexHeight;
+ fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ rFill.push_back(aBack);
+ }
+ else
+ {
+ if(bCreateNormals && bSmoothNormals && (nIndNext != a))
+ {
+ impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
+ impMixNormals(aPolB, aPolBB, 0.5);
+ }
+ }
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
+ fTexStop = fTexHeightPos * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ fTexHeightPos += aTexHeightArray[a];
+ }
+ }
+ }
+ else
+ {
+ // no loop, but a single slice (1 == nNumSlices), create a filling from the single
+ // front plane
+ const Slice3D& rSlice(rSliceVector[0]);
+ basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon());
+
+ if(bCreateTextureCoordinates)
+ {
+ aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
+ }
+
+ if(bCreateNormals)
+ {
+ basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
+
+ if(aFront.count())
+ {
+ aNormal = -aFront.getB3DPolygon(0L).getNormal();
+ }
+
+ impSetNormal(aFront, aNormal);
+ }
+
+ aFront.flip();
+ rFill.push_back(aFront);
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ aEdgeRounding.transformTextureCoordiantes(rTexTransform);
+ }
+
+ for(a = 0L; a < aEdgeRounding.count(); a++)
+ {
+ rFill.push_back(basegfx::B3DPolyPolygon(aEdgeRounding.getB3DPolygon(a)));
+ }
+ }
+ }
+
+ void createReducedOutlines(
+ const geometry::ViewInformation3D& rViewInformation,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const basegfx::B3DPolygon& rLoopA,
+ const basegfx::B3DPolygon& rLoopB,
+ basegfx::B3DPolyPolygon& rTarget)
+ {
+ const sal_uInt32 nPointCount(rLoopA.count());
+
+ // with idetic polygons there are no outlines
+ if(rLoopA != rLoopB)
+ {
+ if(nPointCount && nPointCount == rLoopB.count())
+ {
+ const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform);
+ const basegfx::B2DPolygon a2DLoopA(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform));
+ const basegfx::B2DPolygon a2DLoopB(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform));
+ const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter());
+ const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter());
+
+ // without detectable Y-Axis there are no outlines
+ if(!a2DCenterA.equal(a2DCenterB))
+ {
+ // search for outmost left and right inter-loop-edges which do not cut the loops
+ const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB));
+ const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB);
+ double fMaxLeft(0.0);
+ double fMaxRight(0.0);
+ sal_uInt32 nIndexLeft(0);
+ sal_uInt32 nIndexRight(0);
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a));
+ const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a));
+ const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd));
+
+ if(!basegfx::tools::isInside(a2DLoopA, aMiddle))
+ {
+ if(!basegfx::tools::isInside(a2DLoopB, aMiddle))
+ {
+ if(!impHasCutWith(a2DLoopA, aStart, aEnd))
+ {
+ if(!impHasCutWith(a2DLoopB, aStart, aEnd))
+ {
+ const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter);
+ const double fCross(aCandidateVector.cross(aAxisVector));
+ const double fDistance(aCandidateVector.getLength());
+
+ if(fCross > 0.0)
+ {
+ if(fDistance > fMaxLeft)
+ {
+ fMaxLeft = fDistance;
+ nIndexLeft = a;
+ }
+ }
+ else if(fCross < 0.0)
+ {
+ if(fDistance > fMaxRight)
+ {
+ fMaxRight = fDistance;
+ nIndexRight = a;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(fMaxLeft != 0.0)
+ {
+ basegfx::B3DPolygon aToBeAdded;
+ aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft));
+ aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft));
+ rTarget.append(aToBeAdded);
+ }
+
+ if(fMaxRight != 0.0)
+ {
+ basegfx::B3DPolygon aToBeAdded;
+ aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight));
+ aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight));
+ rTarget.append(aToBeAdded);
+ }
+ }
+ }
+ }
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
new file mode 100644
index 000000000000..2485d467b7f4
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
@@ -0,0 +1,526 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrextrudeprimitive3d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrExtrudePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ Primitive3DSequence aRetval;
+
+ // get slices
+ const Slice3DVector& rSliceVector = getSlices();
+
+ if(rSliceVector.size())
+ {
+ sal_uInt32 a;
+
+ // decide what to create
+ const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind);
+ const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ double fRelativeTextureWidth(1.0);
+ basegfx::B2DHomMatrix aTexTransform;
+
+ if(!getSdrLFSAttribute().getFill().isDefault() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY))
+ {
+ const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0L));
+ const double fFrontLength(basegfx::tools::getLength(aFirstPolygon));
+ const double fFrontArea(basegfx::tools::getArea(aFirstPolygon));
+ const double fSqrtFrontArea(sqrt(fFrontArea));
+ fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea;
+ fRelativeTextureWidth = (double)((sal_uInt32)(fRelativeTextureWidth - 0.5));
+
+ if(fRelativeTextureWidth < 1.0)
+ {
+ fRelativeTextureWidth = 1.0;
+ }
+
+ aTexTransform.translate(-0.5, -0.5);
+ aTexTransform.scale(-1.0, -1.0);
+ aTexTransform.translate(0.5, 0.5);
+ aTexTransform.scale(fRelativeTextureWidth, 1.0);
+ }
+
+ // create geometry
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ extractPlanesFromSlice(aFill, rSliceVector,
+ bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), false,
+ 0.5, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform);
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // normal creation
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind)
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind)
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ aRetval = createHiddenGeometryPrimitives3D(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute());
+ }
+
+ // add line
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ // create geometric outlines with reduced line geometry for chart.
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+ const sal_uInt32 nCount(aVerLine.count());
+ basegfx::B3DPolyPolygon aReducedLoops;
+ basegfx::B3DPolyPolygon aNewLineGeometry;
+
+ // sort out doubles (front and back planes when no edge rounding is done). Since
+ // this is a line geometry merged from PolyPolygons, loop over all Polygons
+ for(a = 0; a < nCount; a++)
+ {
+ const sal_uInt32 nReducedCount(aReducedLoops.count());
+ const basegfx::B3DPolygon aCandidate(aVerLine.getB3DPolygon(a));
+ bool bAdd(true);
+
+ if(nReducedCount)
+ {
+ for(sal_uInt32 b(0); bAdd && b < nReducedCount; b++)
+ {
+ if(aCandidate == aReducedLoops.getB3DPolygon(b))
+ {
+ bAdd = false;
+ }
+ }
+ }
+
+ if(bAdd)
+ {
+ aReducedLoops.append(aCandidate);
+ }
+ }
+
+ // from here work with reduced loops and reduced count without changing them
+ const sal_uInt32 nReducedCount(aReducedLoops.count());
+
+ if(nReducedCount > 1)
+ {
+ for(sal_uInt32 b(1); b < nReducedCount; b++)
+ {
+ // get loop pair
+ const basegfx::B3DPolygon aCandA(aReducedLoops.getB3DPolygon(b - 1));
+ const basegfx::B3DPolygon aCandB(aReducedLoops.getB3DPolygon(b));
+
+ // for each loop pair create the connection edges
+ createReducedOutlines(
+ rViewInformation,
+ getTransform(),
+ aCandA,
+ aCandB,
+ aNewLineGeometry);
+ }
+ }
+
+ // add reduced loops themselves
+ aNewLineGeometry.append(aReducedLoops);
+
+ // to create vertical edges at non-C1/C2 steady loops, use maCorrectedPolyPolygon
+ // directly since the 3D Polygons do not suport this.
+ //
+ // Unfortunately there is no bezier polygon provided by the chart module; one reason is
+ // that the API for extrude wants a 3D polygon geometry (for historical reasons, i guess)
+ // and those have no beziers. Another reason is that he chart module uses self-created
+ // stuff to create the 2D geometry (in ShapeFactory::createPieSegment), but this geometry
+ // does not contain bezier infos, either. The only way which is possible for now is to 'detect'
+ // candidates for vertical edges of pie segments by looking for the angles in the polygon.
+ //
+ // This is all not very well designed ATM. Ideally, the ReducedLineGeometry is responsible
+ // for creating the outer geometry edges (createReducedOutlines), but for special edges
+ // like the vertical ones for pie center and both start/end, the incarnation with the
+ // knowledge about that it needs to create those and IS a pie segment -> in this case,
+ // the chart itself.
+ const sal_uInt32 nPolyCount(maCorrectedPolyPolygon.count());
+
+ for(sal_uInt32 c(0); c < nPolyCount; c++)
+ {
+ const basegfx::B2DPolygon aCandidate(maCorrectedPolyPolygon.getB2DPolygon(c));
+ const sal_uInt32 nPointCount(aCandidate.count());
+
+ if(nPointCount > 2)
+ {
+ sal_uInt32 nIndexA(nPointCount);
+ sal_uInt32 nIndexB(nPointCount);
+ sal_uInt32 nIndexC(nPointCount);
+
+ for(sal_uInt32 d(0); d < nPointCount; d++)
+ {
+ const sal_uInt32 nPrevInd((d + nPointCount - 1) % nPointCount);
+ const sal_uInt32 nNextInd((d + 1) % nPointCount);
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(d));
+ const basegfx::B2DVector aPrev(aCandidate.getB2DPoint(nPrevInd) - aPoint);
+ const basegfx::B2DVector aNext(aCandidate.getB2DPoint(nNextInd) - aPoint);
+ const double fAngle(aPrev.angle(aNext));
+
+ // take each angle which deviates more than 10% from going straight as
+ // special edge. This will detect the two outer edges of pie segments,
+ // but not always the center one (think about a near 180 degree pie)
+ if(F_PI - fabs(fAngle) > F_PI * 0.1)
+ {
+ if(nPointCount == nIndexA)
+ {
+ nIndexA = d;
+ }
+ else if(nPointCount == nIndexB)
+ {
+ nIndexB = d;
+ }
+ else if(nPointCount == nIndexC)
+ {
+ nIndexC = d;
+ d = nPointCount;
+ }
+ }
+ }
+
+ const bool bIndexAUsed(nIndexA != nPointCount);
+ const bool bIndexBUsed(nIndexB != nPointCount);
+ bool bIndexCUsed(nIndexC != nPointCount);
+
+ if(bIndexCUsed)
+ {
+ // already three special edges found, so the center one was already detected
+ // and does not need to be searched
+ }
+ else if(bIndexAUsed && bIndexBUsed)
+ {
+ // outer edges detected (they are approx. 90 degrees), but center one not.
+ // Look with the knowledge that it's in-between the two found ones
+ if(((nIndexA + 2) % nPointCount) == nIndexB)
+ {
+ nIndexC = (nIndexA + 1) % nPointCount;
+ }
+ else if(((nIndexA + nPointCount - 2) % nPointCount) == nIndexB)
+ {
+ nIndexC = (nIndexA + nPointCount - 1) % nPointCount;
+ }
+
+ bIndexCUsed = (nIndexC != nPointCount);
+ }
+
+ if(bIndexAUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexA));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+
+ if(bIndexBUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexB));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+
+ if(bIndexCUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexC));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+ }
+ }
+
+ // append loops themselves
+ aNewLineGeometry.append(aReducedLoops);
+
+ if(aNewLineGeometry.count())
+ {
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
+ aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+ }
+ else
+ {
+ // extract line geometry from slices
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, false));
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+
+ // add horizontal lines
+ const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives(
+ aHorLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines);
+
+ // add vertical lines
+ const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives(
+ aVerLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines);
+ }
+ }
+
+ // add shadow
+ if(!getSdrLFSAttribute().getShadow().isDefault() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(
+ aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void SdrExtrudePrimitive3D::impCreateSlices()
+ {
+ // prepare the polygon. No double points, correct orientations and a correct
+ // outmost polygon are needed
+ maCorrectedPolyPolygon = getPolyPolygon();
+ maCorrectedPolyPolygon.removeDoublePoints();
+ maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon);
+ maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon);
+
+ // prepare slices as geometry
+ createExtrudeSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getDepth(), getCharacterMode(), getCloseFront(), getCloseBack());
+ }
+
+ const Slice3DVector& SdrExtrudePrimitive3D::getSlices() const
+ {
+ // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
+ // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
+ if(getPolyPolygon().count() && !maSlices.size())
+ {
+ ::osl::Mutex m_mutex;
+ const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices();
+ }
+
+ return maSlices;
+ }
+
+ SdrExtrudePrimitive3D::SdrExtrudePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fDepth,
+ double fDiagonal,
+ double fBackScale,
+ bool bSmoothNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothLids,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maCorrectedPolyPolygon(),
+ maSlices(),
+ maPolyPolygon(rPolyPolygon),
+ mfDepth(fDepth),
+ mfDiagonal(fDiagonal),
+ mfBackScale(fBackScale),
+ mpLastRLGViewInformation(0),
+ mbSmoothNormals(bSmoothNormals),
+ mbSmoothHorizontalNormals(bSmoothHorizontalNormals),
+ mbSmoothLids(bSmoothLids),
+ mbCharacterMode(bCharacterMode),
+ mbCloseFront(bCloseFront),
+ mbCloseBack(bCloseBack)
+ {
+ // make sure depth is positive
+ if(basegfx::fTools::lessOrEqual(getDepth(), 0.0))
+ {
+ mfDepth = 0.0;
+ }
+
+ // make sure the percentage value getDiagonal() is between 0.0 and 1.0
+ if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ {
+ mfDiagonal = 0.0;
+ }
+ else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
+ {
+ mfDiagonal = 1.0;
+ }
+
+ // no close front/back when polygon is not closed
+ if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
+ {
+ mbCloseFront = mbCloseBack = false;
+ }
+
+ // no edge rounding when not closing
+ if(!getCloseFront() && !getCloseBack())
+ {
+ mfDiagonal = 0.0;
+ }
+ }
+
+ SdrExtrudePrimitive3D::~SdrExtrudePrimitive3D()
+ {
+ if(mpLastRLGViewInformation)
+ {
+ delete mpLastRLGViewInformation;
+ }
+ }
+
+ bool SdrExtrudePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrExtrudePrimitive3D& rCompare = static_cast< const SdrExtrudePrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon() == rCompare.getPolyPolygon()
+ && getDepth() == rCompare.getDepth()
+ && getDiagonal() == rCompare.getDiagonal()
+ && getBackScale() == rCompare.getBackScale()
+ && getSmoothNormals() == rCompare.getSmoothNormals()
+ && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals()
+ && getSmoothLids() == rCompare.getSmoothLids()
+ && getCharacterMode() == rCompare.getCharacterMode()
+ && getCloseFront() == rCompare.getCloseFront()
+ && getCloseBack() == rCompare.getCloseBack());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrExtrudePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return get3DRangeFromSlices(getSlices());
+ }
+
+ Primitive3DSequence SdrExtrudePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ if(!mpLastRLGViewInformation ||
+ (getBuffered3DDecomposition().hasElements()
+ && *mpLastRLGViewInformation != rViewInformation))
+ {
+ // conditions of last local decomposition with reduced lines have changed. Remember
+ // new one and clear current decompositiopn
+ ::osl::Mutex m_mutex;
+ SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this);
+ pThat->setBuffered3DDecomposition(Primitive3DSequence());
+ delete pThat->mpLastRLGViewInformation;
+ pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation);
+ }
+ }
+
+ // no test for buffering needed, call parent
+ return SdrPrimitive3D::get3DDecomposition(rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrExtrudePrimitive3D, PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
new file mode 100644
index 000000000000..d2ca2f5786bc
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
@@ -0,0 +1,387 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrlatheprimitive3d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrLathePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ Primitive3DSequence aRetval;
+
+ // get slices
+ const Slice3DVector& rSliceVector = getSlices();
+
+ if(rSliceVector.size())
+ {
+ const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
+ const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI));
+ sal_uInt32 a;
+
+ // decide what to create
+ const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind);
+ const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ basegfx::B2DHomMatrix aTexTransform;
+
+ if(!getSdrLFSAttribute().getFill().isDefault()
+ && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY))
+ {
+ aTexTransform.set(0, 0, 0.0);
+ aTexTransform.set(0, 1, 1.0);
+ aTexTransform.set(1, 0, 1.0);
+ aTexTransform.set(1, 1, 0.0);
+
+ aTexTransform.translate(0.0, -0.5);
+ aTexTransform.scale(1.0, -1.0);
+ aTexTransform.translate(0.0, 0.5);
+ }
+
+ // create geometry
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ extractPlanesFromSlice(aFill, rSliceVector,
+ bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation,
+ 0.85, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform);
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // normal creation
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind)
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind)
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ aRetval = createHiddenGeometryPrimitives3D(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute());
+ }
+
+ // add line
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ // create geometric outlines with reduced line geometry for chart
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
+ const sal_uInt32 nCount(aHorLine.count());
+ basegfx::B3DPolyPolygon aNewLineGeometry;
+
+ for(a = 1; a < nCount; a++)
+ {
+ // for each loop pair create the connection edges
+ createReducedOutlines(
+ rViewInformation,
+ getTransform(),
+ aHorLine.getB3DPolygon(a - 1),
+ aHorLine.getB3DPolygon(a),
+ aNewLineGeometry);
+ }
+
+ for(a = 0; a < nCount; a++)
+ {
+ // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
+ basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a));
+ aCandidate.removeDoublePoints();
+
+ if(aCandidate.count())
+ {
+ aNewLineGeometry.append(aCandidate);
+ }
+ }
+
+ if(aNewLineGeometry.count())
+ {
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
+ aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+ }
+ else
+ {
+ // extract line geometry from slices
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+
+ // add horizontal lines
+ const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives(
+ aHorLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines);
+
+ // add vertical lines
+ const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives(
+ aVerLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines);
+ }
+ }
+
+ // add shadow
+ if(!getSdrLFSAttribute().getShadow().isDefault()
+ && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(
+ aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void SdrLathePrimitive3D::impCreateSlices()
+ {
+ // prepare the polygon. No double points, correct orientations and a correct
+ // outmost polygon are needed
+ maCorrectedPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(getPolyPolygon());
+ maCorrectedPolyPolygon.removeDoublePoints();
+ maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon);
+ maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon);
+
+ // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
+ // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0L is different
+ // at all (and not always)
+ const basegfx::B2DPolygon aSubCandidate(maCorrectedPolyPolygon.getB2DPolygon(0));
+ const sal_uInt32 nSubEdgeCount(aSubCandidate.isClosed() ? aSubCandidate.count() : (aSubCandidate.count() ? aSubCandidate.count() - 1L : 0L));
+
+ if(nSubEdgeCount != getVerticalSegments())
+ {
+ maCorrectedPolyPolygon = basegfx::tools::reSegmentPolyPolygon(maCorrectedPolyPolygon, getVerticalSegments());
+ }
+
+ // prepare slices as geometry
+ createLatheSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
+ }
+
+ const Slice3DVector& SdrLathePrimitive3D::getSlices() const
+ {
+ // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
+ // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
+ if(getPolyPolygon().count() && !maSlices.size())
+ {
+ ::osl::Mutex m_mutex;
+ const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
+ }
+
+ return maSlices;
+ }
+
+ SdrLathePrimitive3D::SdrLathePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ sal_uInt32 nHorizontalSegments,
+ sal_uInt32 nVerticalSegments,
+ double fDiagonal,
+ double fBackScale,
+ double fRotation,
+ bool bSmoothNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothLids,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maCorrectedPolyPolygon(),
+ maSlices(),
+ maPolyPolygon(rPolyPolygon),
+ mnHorizontalSegments(nHorizontalSegments),
+ mnVerticalSegments(nVerticalSegments),
+ mfDiagonal(fDiagonal),
+ mfBackScale(fBackScale),
+ mfRotation(fRotation),
+ mpLastRLGViewInformation(0),
+ mbSmoothNormals(bSmoothNormals),
+ mbSmoothHorizontalNormals(bSmoothHorizontalNormals),
+ mbSmoothLids(bSmoothLids),
+ mbCharacterMode(bCharacterMode),
+ mbCloseFront(bCloseFront),
+ mbCloseBack(bCloseBack)
+ {
+ // make sure Rotation is positive
+ if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
+ {
+ mfRotation = 0.0;
+ }
+
+ // make sure the percentage value getDiagonal() is between 0.0 and 1.0
+ if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ {
+ mfDiagonal = 0.0;
+ }
+ else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
+ {
+ mfDiagonal = 1.0;
+ }
+
+ // no close front/back when polygon is not closed
+ if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
+ {
+ mbCloseFront = mbCloseBack = false;
+ }
+
+ // no edge rounding when not closing
+ if(!getCloseFront() && !getCloseBack())
+ {
+ mfDiagonal = 0.0;
+ }
+ }
+
+ SdrLathePrimitive3D::~SdrLathePrimitive3D()
+ {
+ if(mpLastRLGViewInformation)
+ {
+ delete mpLastRLGViewInformation;
+ }
+ }
+
+ bool SdrLathePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrLathePrimitive3D& rCompare = static_cast< const SdrLathePrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon() == rCompare.getPolyPolygon()
+ && getHorizontalSegments() == rCompare.getHorizontalSegments()
+ && getVerticalSegments() == rCompare.getVerticalSegments()
+ && getDiagonal() == rCompare.getDiagonal()
+ && getBackScale() == rCompare.getBackScale()
+ && getRotation() == rCompare.getRotation()
+ && getSmoothNormals() == rCompare.getSmoothNormals()
+ && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals()
+ && getSmoothLids() == rCompare.getSmoothLids()
+ && getCharacterMode() == rCompare.getCharacterMode()
+ && getCloseFront() == rCompare.getCloseFront()
+ && getCloseBack() == rCompare.getCloseBack());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return get3DRangeFromSlices(getSlices());
+ }
+
+ Primitive3DSequence SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ if(!mpLastRLGViewInformation ||
+ (getBuffered3DDecomposition().hasElements()
+ && *mpLastRLGViewInformation != rViewInformation))
+ {
+ // conditions of last local decomposition with reduced lines have changed. Remember
+ // new one and clear current decompositiopn
+ ::osl::Mutex m_mutex;
+ SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
+ pThat->setBuffered3DDecomposition(Primitive3DSequence());
+ delete pThat->mpLastRLGViewInformation;
+ pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation);
+ }
+ }
+
+ // no test for buffering needed, call parent
+ return SdrPrimitive3D::get3DDecomposition(rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrLathePrimitive3D, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
new file mode 100644
index 000000000000..825bd6ee4671
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
@@ -0,0 +1,194 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrpolypolygonprimitive3d.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrPolyPolygonPrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getPolyPolygon3D().count())
+ {
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ aFill.push_back(getPolyPolygon3D());
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // #i98295# normal creation
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // #i98314# texture coordinates
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ aRetval = createHiddenGeometryPrimitives3D(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute());
+ }
+
+ // add line
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ basegfx::B3DPolyPolygon aLine(getPolyPolygon3D());
+ aLine.clearNormals();
+ aLine.clearTextureCoordinates();
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
+ aLine, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(!getSdrLFSAttribute().getShadow().isDefault()
+ && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(
+ aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ SdrPolyPolygonPrimitive3D::SdrPolyPolygonPrimitive3D(
+ const basegfx::B3DPolyPolygon& rPolyPolygon3D,
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maPolyPolygon3D(rPolyPolygon3D)
+ {
+ }
+
+ bool SdrPolyPolygonPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrPolyPolygonPrimitive3D& rCompare = static_cast< const SdrPolyPolygonPrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon3D() == rCompare.getPolyPolygon3D());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrPolyPolygonPrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // added this implementation to make sure that non-visible objects of this
+ // kind will deliver their expansion. If not implemented, it would never deliver
+ // the used space for non-visible objects since the decomposition for that
+ // case will be empty (what is correct). To support chart ATM which relies on
+ // non-visible objects occupying space in 3D, this method was added
+ basegfx::B3DRange aRetval;
+
+ if(getPolyPolygon3D().count())
+ {
+ aRetval = basegfx::tools::getRange(getPolyPolygon3D());
+ aRetval.transform(getTransform());
+
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ const attribute::SdrLineAttribute& rLine = getSdrLFSAttribute().getLine();
+
+ if(!rLine.isDefault() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by half LineWidth as tube radius
+ aRetval.grow(rLine.getWidth() / 2.0);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrPolyPolygonPrimitive3D, PRIMITIVE3D_ID_SDRPOLYPOLYGONPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
new file mode 100644
index 000000000000..e5f722126d42
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
@@ -0,0 +1,125 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ basegfx::B3DRange SdrPrimitive3D::getStandard3DRange() const
+ {
+ basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ aUnitRange.transform(getTransform());
+
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ const attribute::SdrLineAttribute& rLine = getSdrLFSAttribute().getLine();
+
+ if(!rLine.isDefault() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by hald LineWidth as tube radius
+ aUnitRange.grow(rLine.getWidth() / 2.0);
+ }
+ }
+
+ return aUnitRange;
+ }
+
+ basegfx::B3DRange SdrPrimitive3D::get3DRangeFromSlices(const Slice3DVector& rSlices) const
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rSlices.size())
+ {
+ for(sal_uInt32 a(0L); a < rSlices.size(); a++)
+ {
+ aRetval.expand(basegfx::tools::getRange(rSlices[a].getB3DPolyPolygon()));
+ }
+
+ aRetval.transform(getTransform());
+
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ const attribute::SdrLineAttribute& rLine = getSdrLFSAttribute().getLine();
+
+ if(!rLine.isDefault() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by half LineWidth as tube radius
+ aRetval.grow(rLine.getWidth() / 2.0);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ SdrPrimitive3D::SdrPrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : BufferedDecompositionPrimitive3D(),
+ maTransform(rTransform),
+ maTextureSize(rTextureSize),
+ maSdrLFSAttribute(rSdrLFSAttribute),
+ maSdr3DObjectAttribute(rSdr3DObjectAttribute)
+ {
+ }
+
+ bool SdrPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrPrimitive3D& rCompare = static_cast< const SdrPrimitive3D& >(rPrimitive);
+
+ return (getTransform() == rCompare.getTransform()
+ && getTextureSize() == rCompare.getTextureSize()
+ && getSdrLFSAttribute() == rCompare.getSdrLFSAttribute()
+ && getSdr3DObjectAttribute() == rCompare.getSdr3DObjectAttribute());
+ }
+
+ return false;
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
new file mode 100644
index 000000000000..b10b4ad6164b
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
@@ -0,0 +1,224 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/sdrsphereprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/attribute/sdrfillattribute.hxx>
+#include <drawinglayer/attribute/sdrlineattribute.hxx>
+#include <drawinglayer/attribute/sdrshadowattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrSpherePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+ const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()
+ || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind());
+
+ // create unit geometry
+ basegfx::B3DPolyPolygon aFill(basegfx::tools::createSphereFillPolyPolygonFromB3DRange(aUnitRange,
+ getHorizontalSegments(), getVerticalSegments(), bCreateNormals));
+
+ // normal inversion
+ if(!getSdrLFSAttribute().getFill().isDefault()
+ && bCreateNormals
+ && getSdr3DObjectAttribute().getNormalsInvert()
+ && aFill.areNormalsUsed())
+ {
+ // invert normals
+ aFill = basegfx::tools::invertNormals(aFill);
+ }
+
+ // texture coordinates
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bSphereX(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX());
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bSphereY(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY());
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY);
+ }
+
+ if(bSphereX || bObjectSpecificX || bSphereY || bObjectSpecificY)
+ {
+ double fRelativeAngle(0.0);
+
+ if(bObjectSpecificX)
+ {
+ // Since the texture coordinates are (for historical reasons)
+ // different from forced to sphere texture coordinates,
+ // create a old version from it by rotating to old state before applying
+ // the texture coordinates to emulate old behaviour
+ fRelativeAngle = F_2PI * ((double)((getHorizontalSegments() >> 1L) - 1L) / (double)getHorizontalSegments());
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(0.0, fRelativeAngle, 0.0);
+ aFill.transform(aRot);
+ }
+
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ const basegfx::B3DPoint aCenter(aRange.getCenter());
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter,
+ bSphereX || bObjectSpecificX, bSphereY || bObjectSpecificY);
+
+ if(bObjectSpecificX)
+ {
+ // rotate back again
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(0.0, -fRelativeAngle, 0.0);
+ aFill.transform(aRot);
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY());
+ aFill.transformTextureCoordiantes(aTexMatrix);
+ }
+
+ // build vector of PolyPolygons
+ ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector;
+
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a)));
+ }
+
+ if(!getSdrLFSAttribute().getFill().isDefault())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ aRetval = createHiddenGeometryPrimitives3D(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute());
+ }
+
+ // add line
+ if(!getSdrLFSAttribute().getLine().isDefault())
+ {
+ basegfx::B3DPolyPolygon aSphere(basegfx::tools::createSpherePolyPolygonFromB3DRange(aUnitRange, getHorizontalSegments(), getVerticalSegments()));
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
+ aSphere, getTransform(), getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(!getSdrLFSAttribute().getShadow().isDefault()
+ && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(
+ aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+
+ return aRetval;
+ }
+
+ SdrSpherePrimitive3D::SdrSpherePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ sal_uInt32 nHorizontalSegments,
+ sal_uInt32 nVerticalSegments)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ mnHorizontalSegments(nHorizontalSegments),
+ mnVerticalSegments(nVerticalSegments)
+ {
+ }
+
+ bool SdrSpherePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrSpherePrimitive3D& rCompare = static_cast< const SdrSpherePrimitive3D& >(rPrimitive);
+
+ return (getHorizontalSegments() == rCompare.getHorizontalSegments()
+ && getVerticalSegments() == rCompare.getVerticalSegments());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrSpherePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return getStandard3DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrSpherePrimitive3D, PRIMITIVE3D_ID_SDRSPHEREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/shadowprimitive3d.cxx b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
new file mode 100644
index 000000000000..97ac5d930d62
--- /dev/null
+++ b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/shadowprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ ShadowPrimitive3D::ShadowPrimitive3D(
+ const basegfx::B2DHomMatrix& rShadowTransform,
+ const basegfx::BColor& rShadowColor,
+ double fShadowTransparence,
+ bool bShadow3D,
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren),
+ maShadowTransform(rShadowTransform),
+ maShadowColor(rShadowColor),
+ mfShadowTransparence(fShadowTransparence),
+ mbShadow3D(bShadow3D)
+ {
+ }
+
+ bool ShadowPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const ShadowPrimitive3D& rCompare = (ShadowPrimitive3D&)rPrimitive;
+
+ return (getShadowTransform() == rCompare.getShadowTransform()
+ && getShadowColor() == rCompare.getShadowColor()
+ && getShadowTransparence() == rCompare.getShadowTransparence()
+ && getShadow3D() == rCompare.getShadow3D());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(ShadowPrimitive3D, PRIMITIVE3D_ID_SHADOWPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/textureprimitive3d.cxx b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
new file mode 100644
index 000000000000..d10fc52b8bb2
--- /dev/null
+++ b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <basegfx/color/bcolor.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ TexturePrimitive3D::TexturePrimitive3D(
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate, bool bFilter)
+ : GroupPrimitive3D(rChildren),
+ maTextureSize(rTextureSize),
+ mbModulate(bModulate),
+ mbFilter(bFilter)
+ {
+ }
+
+ bool TexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const TexturePrimitive3D& rCompare = (TexturePrimitive3D&)rPrimitive;
+
+ return (getModulate() == rCompare.getModulate()
+ && getFilter() == rCompare.getFilter());
+ }
+
+ return false;
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ UnifiedTransparenceTexturePrimitive3D::UnifiedTransparenceTexturePrimitive3D(
+ double fTransparence,
+ const Primitive3DSequence& rChildren)
+ : TexturePrimitive3D(rChildren, basegfx::B2DVector(), false, false),
+ mfTransparence(fTransparence)
+ {
+ }
+
+ bool UnifiedTransparenceTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const UnifiedTransparenceTexturePrimitive3D& rCompare = (UnifiedTransparenceTexturePrimitive3D&)rPrimitive;
+
+ return (getTransparence() == rCompare.getTransparence());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange UnifiedTransparenceTexturePrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ // do not use the fallback to decomposition here since for a correct BoundRect we also
+ // need invisible (1.0 == getTransparence()) geometry; these would be deleted in the decomposition
+ return getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation);
+ }
+
+ Primitive3DSequence UnifiedTransparenceTexturePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ if(0.0 == getTransparence())
+ {
+ // no transparence used, so just use content
+ return getChildren();
+ }
+ else if(getTransparence() > 0.0 && getTransparence() < 1.0)
+ {
+ // create TransparenceTexturePrimitive3D with fixed transparence as replacement
+ const basegfx::BColor aGray(getTransparence(), getTransparence(), getTransparence());
+ const attribute::FillGradientAttribute aFillGradient(attribute::GRADIENTSTYLE_LINEAR, 0.0, 0.0, 0.0, 0.0, aGray, aGray, 1);
+ const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(aFillGradient, getChildren(), getTextureSize()));
+ return Primitive3DSequence(&xRef, 1L);
+ }
+ else
+ {
+ // completely transparent or invalid definition, add nothing
+ return Primitive3DSequence();
+ }
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(UnifiedTransparenceTexturePrimitive3D, PRIMITIVE3D_ID_UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ GradientTexturePrimitive3D::GradientTexturePrimitive3D(
+ const attribute::FillGradientAttribute& rGradient,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate,
+ bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maGradient(rGradient)
+ {
+ }
+
+ bool GradientTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const GradientTexturePrimitive3D& rCompare = (GradientTexturePrimitive3D&)rPrimitive;
+
+ return (getGradient() == rCompare.getGradient());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(GradientTexturePrimitive3D, PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ BitmapTexturePrimitive3D::BitmapTexturePrimitive3D(
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate, bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maFillBitmapAttribute(rFillBitmapAttribute)
+ {
+ }
+
+ bool BitmapTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const BitmapTexturePrimitive3D& rCompare = (BitmapTexturePrimitive3D&)rPrimitive;
+
+ return (getFillBitmapAttribute() == rCompare.getFillBitmapAttribute());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(BitmapTexturePrimitive3D, PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ TransparenceTexturePrimitive3D::TransparenceTexturePrimitive3D(
+ const attribute::FillGradientAttribute& rGradient,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize)
+ : GradientTexturePrimitive3D(rGradient, rChildren, rTextureSize, false, false)
+ {
+ }
+
+ bool TransparenceTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ return (GradientTexturePrimitive3D::operator==(rPrimitive));
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(TransparenceTexturePrimitive3D, PRIMITIVE3D_ID_TRANSPARENCETEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/transformprimitive3d.cxx b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
new file mode 100644
index 000000000000..f50fb061df04
--- /dev/null
+++ b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General 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/primitive3d/transformprimitive3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ TransformPrimitive3D::TransformPrimitive3D(
+ const basegfx::B3DHomMatrix& rTransformation,
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren),
+ maTransformation(rTransformation)
+ {
+ }
+
+ bool TransformPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const TransformPrimitive3D& rCompare = static_cast< const TransformPrimitive3D& >(rPrimitive);
+
+ return (getTransformation() == rCompare.getTransformation());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange TransformPrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ basegfx::B3DRange aRetval(getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation));
+ aRetval.transform(getTransformation());
+ return aRetval;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(TransformPrimitive3D, PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof