diff options
Diffstat (limited to 'drawinglayer/source/primitive2d')
40 files changed, 8855 insertions, 0 deletions
diff --git a/drawinglayer/source/primitive2d/alphaprimitive2d.cxx b/drawinglayer/source/primitive2d/alphaprimitive2d.cxx new file mode 100644 index 000000000000..a503c2979c41 --- /dev/null +++ b/drawinglayer/source/primitive2d/alphaprimitive2d.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: alphaprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/alphaprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + AlphaPrimitive2D::AlphaPrimitive2D( + const Primitive2DSequence& rChildren, + const Primitive2DSequence& rAlpha) + : GroupPrimitive2D(rChildren), + maAlpha(rAlpha) + { + } + + bool AlphaPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const AlphaPrimitive2D& rCompare = (AlphaPrimitive2D&)rPrimitive; + + return (getAlpha() == rCompare.getAlpha()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(AlphaPrimitive2D, PRIMITIVE2D_ID_ALPHAPRIMITIVE2D) + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx new file mode 100644 index 000000000000..13f1f699f1ab --- /dev/null +++ b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx @@ -0,0 +1,293 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animatedprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/animatedprimitive2d.hxx> +#include <drawinglayer/animation/animationtiming.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence AnimatedSwitchPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + if(getChildren().hasElements()) + { + const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); + const sal_uInt32 nLen(getChildren().getLength()); + sal_uInt32 nIndex(basegfx::fround(fState * (double)nLen)); + + if(nIndex >= nLen) + { + nIndex = nLen - 1L; + } + + const Primitive2DReference xRef(getChildren()[nIndex], uno::UNO_QUERY_THROW); + return Primitive2DSequence(&xRef, 1L); + } + + return Primitive2DSequence(); + } + + AnimatedSwitchPrimitive2D::AnimatedSwitchPrimitive2D( + const animation::AnimationEntry& rAnimationEntry, + const Primitive2DSequence& rChildren, + bool bIsTextAnimation) + : GroupPrimitive2D(rChildren), + mpAnimationEntry(0), + mfDecomposeViewTime(0.0), + mbIsTextAnimation(bIsTextAnimation) + { + // clone given animation description + mpAnimationEntry = rAnimationEntry.clone(); + } + + AnimatedSwitchPrimitive2D::~AnimatedSwitchPrimitive2D() + { + // delete cloned animation description + delete mpAnimationEntry; + } + + bool AnimatedSwitchPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const AnimatedSwitchPrimitive2D& rCompare = static_cast< const AnimatedSwitchPrimitive2D& >(rPrimitive); + + return (getAnimationEntry() == rCompare.getAnimationEntry()); + } + + return false; + } + + Primitive2DSequence AnimatedSwitchPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements() && mfDecomposeViewTime != rViewInformation.getViewTime()) + { + // conditions of last local decomposition have changed, delete + const_cast< AnimatedSwitchPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + // remember time + const_cast< AnimatedSwitchPrimitive2D* >(this)->mfDecomposeViewTime = rViewInformation.getViewTime(); + } + + // use parent implementation + return GroupPrimitive2D::get2DDecomposition(rViewInformation); + } + + basegfx::B2DRange AnimatedSwitchPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // to get range from decomposition and not from group content, call implementation from + // BasePrimitive2D here + return BasePrimitive2D::getB2DRange(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(AnimatedSwitchPrimitive2D, PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence AnimatedBlinkPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + if(getChildren().hasElements()) + { + const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); + + if(fState < 0.5) + { + return getChildren(); + } + } + + return Primitive2DSequence(); + } + + AnimatedBlinkPrimitive2D::AnimatedBlinkPrimitive2D( + const animation::AnimationEntry& rAnimationEntry, + const Primitive2DSequence& rChildren, + bool bIsTextAnimation) + : AnimatedSwitchPrimitive2D(rAnimationEntry, rChildren, bIsTextAnimation) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(AnimatedBlinkPrimitive2D, PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// helper class for AnimatedInterpolatePrimitive2D + +namespace drawinglayer +{ + namespace primitive2d + { + BufferedMatrixDecompose::BufferedMatrixDecompose(const basegfx::B2DHomMatrix& rMatrix) + : maB2DHomMatrix(rMatrix), + maScale(0.0, 0.0), + maTranslate(0.0, 0.0), + mfRotate(0.0), + mfShearX(0.0), + mbDecomposed(false) + { + } + + void BufferedMatrixDecompose::ensureDecompose() const + { + if(!mbDecomposed) + { + BufferedMatrixDecompose* pThis = const_cast< BufferedMatrixDecompose* >(this); + maB2DHomMatrix.decompose(pThis->maScale, pThis->maTranslate, pThis->mfRotate, pThis->mfShearX); + pThis->mbDecomposed = true; + } + } + } // end of anonymous namespace +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence AnimatedInterpolatePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + const sal_uInt32 nSize(maMatrixStack.size()); + + if(nSize) + { + double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); + + if(fState < 0.0) + { + fState = 0.0; + } + else if(fState > 1.0) + { + fState = 1.0; + } + + const double fIndex(fState * (double)(nSize - 1L)); + const sal_uInt32 nIndA(sal_uInt32(floor(fIndex))); + const double fOffset(fIndex - (double)nIndA); + basegfx::B2DHomMatrix aTargetTransform; + + if(basegfx::fTools::equalZero(fOffset)) + { + // use matrix from nIndA directly + aTargetTransform = maMatrixStack[nIndA].getB2DHomMatrix(); + } + else + { + // interpolate. Get involved matrices and ensure they are decomposed + const sal_uInt32 nIndB((nIndA + 1L) % nSize); + std::vector< BufferedMatrixDecompose >::const_iterator aMatA(maMatrixStack.begin() + nIndA); + std::vector< BufferedMatrixDecompose >::const_iterator aMatB(maMatrixStack.begin() + nIndB); + + aMatA->ensureDecompose(); + aMatB->ensureDecompose(); + + // interpolate for fOffset [0.0 .. 1.0[ + const basegfx::B2DVector aScale(basegfx::interpolate(aMatA->getScale(), aMatB->getScale(), fOffset)); + const basegfx::B2DVector aTranslate(basegfx::interpolate(aMatA->getTranslate(), aMatB->getTranslate(), fOffset)); + const double fRotate(((aMatB->getRotate() - aMatA->getRotate()) * fOffset) + aMatA->getRotate()); + const double fShearX(((aMatB->getShearX() - aMatA->getShearX()) * fOffset) + aMatA->getShearX()); + + // build matrix for state + aTargetTransform.scale(aScale.getX(), aScale.getY()); + aTargetTransform.shearX(fShearX); + aTargetTransform.rotate(fRotate); + aTargetTransform.translate(aTranslate.getX(), aTranslate.getY()); + } + + // create new transform primitive reference, return new sequence + const Primitive2DReference xRef(new TransformPrimitive2D(aTargetTransform, getChildren())); + return Primitive2DSequence(&xRef, 1L); + } + else + { + return getChildren(); + } + } + + AnimatedInterpolatePrimitive2D::AnimatedInterpolatePrimitive2D( + const std::vector< basegfx::B2DHomMatrix >& rmMatrixStack, + const animation::AnimationEntry& rAnimationEntry, + const Primitive2DSequence& rChildren, + bool bIsTextAnimation) + : AnimatedSwitchPrimitive2D(rAnimationEntry, rChildren, bIsTextAnimation), + maMatrixStack() + { + // copy matrices + const sal_uInt32 nCount(rmMatrixStack.size()); + + for(sal_uInt32 a(0L); a < nCount; a++) + { + maMatrixStack.push_back(BufferedMatrixDecompose(rmMatrixStack[a])); + } + } + + // provide unique ID + ImplPrimitrive2DIDBlock(AnimatedInterpolatePrimitive2D, PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx new file mode 100644 index 000000000000..cff797451954 --- /dev/null +++ b/drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: backgroundcolorprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/backgroundcolorprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence BackgroundColorPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + if(!rViewInformation.getViewport().isEmpty()) + { + const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(rViewInformation.getViewport())); + const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), getBColor())); + return Primitive2DSequence(&xRef, 1L); + } + else + { + return Primitive2DSequence(); + } + } + + BackgroundColorPrimitive2D::BackgroundColorPrimitive2D( + const basegfx::BColor& rBColor) + : BasePrimitive2D(), + maBColor(rBColor), + maLastViewport() + { + } + + bool BackgroundColorPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const BackgroundColorPrimitive2D& rCompare = (BackgroundColorPrimitive2D&)rPrimitive; + + return (getBColor() == rCompare.getBColor()); + } + + return false; + } + + basegfx::B2DRange BackgroundColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // always as big as the view + return rViewInformation.getViewport(); + } + + Primitive2DSequence BackgroundColorPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements() && (maLastViewport != rViewInformation.getViewport())) + { + // conditions of last local decomposition have changed, delete + const_cast< BackgroundColorPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewRange + const_cast< BackgroundColorPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(BackgroundColorPrimitive2D, PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx new file mode 100644 index 000000000000..63941512bfb0 --- /dev/null +++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx @@ -0,0 +1,264 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: baseprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/baseprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <basegfx/tools/canvastools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence BasePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + return Primitive2DSequence(); + } + + BasePrimitive2D::BasePrimitive2D() + : BasePrimitive2DImplBase(m_aMutex), + maLocalDecomposition() + { + } + + bool BasePrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const + { + return (getPrimitiveID() == rPrimitive.getPrimitiveID()); + } + + basegfx::B2DRange BasePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + return getB2DRangeFromPrimitive2DSequence(get2DDecomposition(rViewInformation), rViewInformation); + } + + Primitive2DSequence BasePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(!getLocalDecomposition().hasElements()) + { + const Primitive2DSequence aNewSequence(createLocalDecomposition(rViewInformation)); + const_cast< BasePrimitive2D* >(this)->setLocalDecomposition(aNewSequence); + } + + return getLocalDecomposition(); + } + + Primitive2DSequence SAL_CALL BasePrimitive2D::getDecomposition( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException ) + { + const geometry::ViewInformation2D aViewInformation(rViewParameters); + return get2DDecomposition(aViewInformation); + } + + com::sun::star::geometry::RealRectangle2D SAL_CALL BasePrimitive2D::getRange( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException ) + { + const geometry::ViewInformation2D aViewInformation(rViewParameters); + return basegfx::unotools::rectangle2DFromB2DRectangle(getB2DRange(aViewInformation)); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// tooling + +namespace drawinglayer +{ + namespace primitive2d + { + // get B2DRange from a given Primitive2DReference + basegfx::B2DRange getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate, const geometry::ViewInformation2D& aViewInformation) + { + basegfx::B2DRange aRetval; + + if(rCandidate.is()) + { + // try to get C++ implementation base + const BasePrimitive2D* pCandidate(dynamic_cast< BasePrimitive2D* >(rCandidate.get())); + + if(pCandidate) + { + // use it if possible + aRetval.expand(pCandidate->getB2DRange(aViewInformation)); + } + else + { + // use UNO API call instead + const uno::Sequence< beans::PropertyValue >& rViewParameters(aViewInformation.getViewInformationSequence()); + aRetval.expand(basegfx::unotools::b2DRectangleFromRealRectangle2D(rCandidate->getRange(rViewParameters))); + } + } + + return aRetval; + } + + // get B2DRange from a given Primitive2DSequence + basegfx::B2DRange getB2DRangeFromPrimitive2DSequence(const Primitive2DSequence& rCandidate, const geometry::ViewInformation2D& aViewInformation) + { + basegfx::B2DRange aRetval; + + if(rCandidate.hasElements()) + { + const sal_Int32 nCount(rCandidate.getLength()); + + for(sal_Int32 a(0L); a < nCount; a++) + { + aRetval.expand(getB2DRangeFromPrimitive2DReference(rCandidate[a], aViewInformation)); + } + } + + return aRetval; + } + + bool arePrimitive2DReferencesEqual(const Primitive2DReference& rxA, const Primitive2DReference& rxB) + { + const sal_Bool bAIs(rxA.is()); + + if(bAIs != rxB.is()) + { + return false; + } + + if(!bAIs) + { + return true; + } + + const BasePrimitive2D* pA(dynamic_cast< const BasePrimitive2D* >(rxA.get())); + const BasePrimitive2D* pB(dynamic_cast< const BasePrimitive2D* >(rxB.get())); + const bool bAEqualZero(pA == 0L); + + if(bAEqualZero != (pB == 0L)) + { + return false; + } + + if(bAEqualZero) + { + return false; + } + + return (pA->operator==(*pB)); + } + + bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive2DSequence& 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(!arePrimitive2DReferencesEqual(rA[a], rB[a])) + { + return false; + } + } + + return true; + } + + // concatenate sequence + void appendPrimitive2DSequenceToPrimitive2DSequence(Primitive2DSequence& rDest, const Primitive2DSequence& 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 Primitive2D + void appendPrimitive2DReferenceToPrimitive2DSequence(Primitive2DSequence& rDest, const Primitive2DReference& rSource) + { + if(rSource.is()) + { + const sal_Int32 nDestCount(rDest.getLength()); + rDest.realloc(nDestCount + 1L); + rDest[nDestCount] = rSource; + } + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx b/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx new file mode 100644 index 000000000000..5900900bcf06 --- /dev/null +++ b/drawinglayer/source/primitive2d/bitmapprimitive2d.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: bitmapprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/bitmapprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + BitmapPrimitive2D::BitmapPrimitive2D( + const BitmapEx& rBitmapEx, + const basegfx::B2DHomMatrix& rTransform) + : BasePrimitive2D(), + maBitmapEx(rBitmapEx), + maTransform(rTransform) + { + } + + bool BitmapPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const BitmapPrimitive2D& rCompare = (BitmapPrimitive2D&)rPrimitive; + + return (maBitmapEx == rCompare.maBitmapEx + && maTransform == rCompare.maTransform); + } + + return false; + } + + basegfx::B2DRange BitmapPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(maTransform); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(BitmapPrimitive2D, PRIMITIVE2D_ID_BITMAPPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx new file mode 100644 index 000000000000..ba73f920cb08 --- /dev/null +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -0,0 +1,243 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: borderlineprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/borderlineprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <numeric> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence BorderLinePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + + if(!getStart().equal(getEnd()) && (getCreateInside() || getCreateOutside())) + { + if(isInsideUsed()) + { + // get data and vectors + const double fWidth(getWidth()); + basegfx::B2DVector aVector(getEnd() - getStart()); + aVector.normalize(); + const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); + + if(isOutsideUsed()) + { + // both used, double line definition. Create left and right offset + xRetval.realloc(getCreateInside() && getCreateOutside() ? 2 : 1); + sal_uInt32 nInsert(0); + + if(getCreateInside()) + { + // create geometry for left + const basegfx::B2DVector aLeftOff(aPerpendicular * (0.5 * (getCorrectedLeftWidth() - fWidth))); + const basegfx::B2DPoint aTmpStart(getStart() + aLeftOff - (getExtendInnerStart() * aVector)); + const basegfx::B2DPoint aTmpEnd(getEnd() + aLeftOff + (getExtendInnerEnd() * aVector)); + basegfx::B2DPolygon aLeft; + + if(leftIsHairline()) + { + // create hairline primitive + aLeft.append(aTmpStart); + aLeft.append(aTmpEnd); + + xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D( + aLeft, + getRGBColor())); + } + else + { + // create filled polygon primitive. Already tried to create thick lines + // with the correct LineWidth, but this leads to problems when no AA + // is available and fat line special case reductions between 0.5 < x < 2.5 line widths + // are executed due to the FilledPolygon-do-not-paint-their-bottom-and-right-lines. + const basegfx::B2DVector aLineWidthOffset((getCorrectedLeftWidth() * 0.5) * aPerpendicular); + + aLeft.append(aTmpStart + aLineWidthOffset); + aLeft.append(aTmpEnd + aLineWidthOffset); + aLeft.append(aTmpEnd - aLineWidthOffset); + aLeft.append(aTmpStart - aLineWidthOffset); + aLeft.setClosed(true); + + xRetval[nInsert++] = Primitive2DReference(new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aLeft), getRGBColor())); + } + } + + if(getCreateOutside()) + { + // create geometry for right + const basegfx::B2DVector aRightOff(aPerpendicular * (0.5 * (fWidth - getCorrectedRightWidth()))); + const basegfx::B2DPoint aTmpStart(getStart() + aRightOff - (getExtendOuterStart() * aVector)); + const basegfx::B2DPoint aTmpEnd(getEnd() + aRightOff + (getExtendOuterEnd() * aVector)); + basegfx::B2DPolygon aRight; + + if(rightIsHairline()) + { + // create hairline primitive + aRight.append(aTmpStart); + aRight.append(aTmpEnd); + + xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D( + aRight, + getRGBColor())); + } + else + { + // create filled polygon primitive + const basegfx::B2DVector aLineWidthOffset((getCorrectedRightWidth() * 0.5) * aPerpendicular); + + aRight.append(aTmpStart + aLineWidthOffset); + aRight.append(aTmpEnd + aLineWidthOffset); + aRight.append(aTmpEnd - aLineWidthOffset); + aRight.append(aTmpStart - aLineWidthOffset); + aRight.setClosed(true); + + xRetval[nInsert++] = Primitive2DReference(new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aRight), getRGBColor())); + } + } + } + else + { + // single line, create geometry + basegfx::B2DPolygon aPolygon; + const double fMaxExtStart(::std::max(getExtendInnerStart(), getExtendOuterStart())); + const double fMaxExtEnd(::std::max(getExtendInnerEnd(), getExtendOuterEnd())); + const basegfx::B2DPoint aTmpStart(getStart() - (fMaxExtStart * aVector)); + const basegfx::B2DPoint aTmpEnd(getEnd() + (fMaxExtEnd * aVector)); + xRetval.realloc(1); + + if(leftIsHairline()) + { + // create hairline primitive + aPolygon.append(aTmpStart); + aPolygon.append(aTmpEnd); + + xRetval[0] = Primitive2DReference(new PolygonHairlinePrimitive2D( + aPolygon, + getRGBColor())); + } + else + { + // create filled polygon primitive + const basegfx::B2DVector aLineWidthOffset((getCorrectedLeftWidth() * 0.5) * aPerpendicular); + + aPolygon.append(aTmpStart + aLineWidthOffset); + aPolygon.append(aTmpEnd + aLineWidthOffset); + aPolygon.append(aTmpEnd - aLineWidthOffset); + aPolygon.append(aTmpStart - aLineWidthOffset); + aPolygon.setClosed(true); + + xRetval[0] = Primitive2DReference(new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), getRGBColor())); + } + } + } + } + + return xRetval; + } + + BorderLinePrimitive2D::BorderLinePrimitive2D( + const basegfx::B2DPoint& rStart, + const basegfx::B2DPoint& rEnd, + double fLeftWidth, + double fDistance, + double fRightWidth, + double fExtendInnerStart, + double fExtendInnerEnd, + double fExtendOuterStart, + double fExtendOuterEnd, + bool bCreateInside, + bool bCreateOutside, + const basegfx::BColor& rRGBColor) + : BasePrimitive2D(), + maStart(rStart), + maEnd(rEnd), + mfLeftWidth(fLeftWidth), + mfDistance(fDistance), + mfRightWidth(fRightWidth), + mfExtendInnerStart(fExtendInnerStart), + mfExtendInnerEnd(fExtendInnerEnd), + mfExtendOuterStart(fExtendOuterStart), + mfExtendOuterEnd(fExtendOuterEnd), + maRGBColor(rRGBColor), + mbCreateInside(bCreateInside), + mbCreateOutside(bCreateOutside) + { + } + + bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const BorderLinePrimitive2D& rCompare = (BorderLinePrimitive2D&)rPrimitive; + + return (getStart() == rCompare.getStart() + && getEnd() == rCompare.getEnd() + && getLeftWidth() == rCompare.getLeftWidth() + && getDistance() == rCompare.getDistance() + && getRightWidth() == rCompare.getRightWidth() + && getExtendInnerStart() == rCompare.getExtendInnerStart() + && getExtendInnerEnd() == rCompare.getExtendInnerEnd() + && getExtendOuterStart() == rCompare.getExtendOuterStart() + && getExtendOuterEnd() == rCompare.getExtendOuterEnd() + && getCreateInside() == rCompare.getCreateInside() + && getCreateOutside() == rCompare.getCreateOutside() + && getRGBColor() == rCompare.getRGBColor()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/chartprimitive2d.cxx b/drawinglayer/source/primitive2d/chartprimitive2d.cxx new file mode 100644 index 000000000000..3df6464f8aeb --- /dev/null +++ b/drawinglayer/source/primitive2d/chartprimitive2d.cxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: chartprimitive2d.cxx,v $ + * + * $Revision: 1.3 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/chartprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + ChartPrimitive2D::ChartPrimitive2D( + const uno::Reference< frame::XModel >& rxChartModel, + const basegfx::B2DHomMatrix& rTransformation, + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren), + mxChartModel(rxChartModel), + maTransformation(rTransformation) + { + } + + bool ChartPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const ChartPrimitive2D& rCompare = static_cast< const ChartPrimitive2D& >(rPrimitive); + + return (getChartModel() == rCompare.getChartModel() + && getTransformation() == rCompare.getTransformation()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(ChartPrimitive2D, PRIMITIVE2D_ID_CHARTPRIMITIVE2D) + + basegfx::B2DRange ChartPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransformation()); + return aRetval; + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx new file mode 100644 index 000000000000..6241eeb2fa73 --- /dev/null +++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx @@ -0,0 +1,394 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: controlprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/controlprimitive2d.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/awt/XWindow2.hpp> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/awt/PosSize.hpp> +#include <vcl/bitmapex.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <tools/diagnose_ex.h> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <svtools/optionsdrawinglayer.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <vcl/window.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + void ControlPrimitive2D::createXControl() + { + if(!mxXControl.is() && getControlModel().is()) + { + uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY); + + if(xSet.is()) + { + uno::Any aValue(xSet->getPropertyValue(rtl::OUString::createFromAscii("DefaultControl"))); + rtl::OUString aUnoControlTypeName; + + if(aValue >>= aUnoControlTypeName) + { + if(aUnoControlTypeName.getLength()) + { + uno::Reference< lang::XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); + + if(xFactory.is()) + { + uno::Reference< awt::XControl > xXControl(xFactory->createInstance(aUnoControlTypeName), uno::UNO_QUERY); + + if(xXControl.is()) + { + xXControl->setModel(getControlModel()); + + // remember XControl + mxXControl = xXControl; + } + } + } + } + } + } + } + + Primitive2DReference ControlPrimitive2D::createBitmapDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DReference xRetval; + const uno::Reference< awt::XControl >& rXControl(getXControl()); + + if(rXControl.is()) + { + uno::Reference< awt::XWindow > xControlWindow(rXControl, uno::UNO_QUERY); + + if(xControlWindow.is()) + { + // get decomposition to get size + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // get absolute discrete size (no mirror or rotate here) + aScale = basegfx::absolute(aScale); + basegfx::B2DVector aDiscreteSize(rViewInformation.getObjectToViewTransformation() * aScale); + + // limit to a maximum square size, e.g. 300x150 pixels (45000) + const SvtOptionsDrawinglayer aDrawinglayerOpt; + const double fDiscreteMax(aDrawinglayerOpt.GetQuadraticFormControlRenderLimit()); + const double fDiscreteQuadratic(aDiscreteSize.getX() * aDiscreteSize.getY()); + const bool bScaleUsed(fDiscreteQuadratic > fDiscreteMax); + double fFactor(1.0); + + if(bScaleUsed) + { + // get factor and adapt to scaled size + fFactor = sqrt(fDiscreteMax / fDiscreteQuadratic); + aDiscreteSize *= fFactor; + } + + // go to integer + const sal_Int32 nSizeX(basegfx::fround(aDiscreteSize.getX())); + const sal_Int32 nSizeY(basegfx::fround(aDiscreteSize.getY())); + + if(nSizeX > 0 && nSizeY > 0) + { + // prepare VirtualDevice + VirtualDevice aVirtualDevice(*Application::GetDefaultDevice()); + const Size aSizePixel(nSizeX, nSizeY); + aVirtualDevice.SetOutputSizePixel(aSizePixel); + + // set size at control + xControlWindow->setPosSize(0, 0, nSizeX, nSizeY, awt::PosSize::POSSIZE); + + // get graphics and view + uno::Reference< awt::XGraphics > xGraphics(aVirtualDevice.CreateUnoGraphics()); + uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY); + + if(xGraphics.is() && xControlView.is()) + { + // link graphics and view + xControlView->setGraphics(xGraphics); + + { // #i93162# For painting the control setting a Zoom (using setZoom() at the xControlView) + // is needed to define the font size. Normally this is done in + // ViewObjectContactOfUnoControl::createPrimitive2DSequence by using positionControlForPaint(). + // For some reason the difference between MAP_TWIPS and MAP_100TH_MM still plays + // a role there so that for Draw/Impress/Calc (the MAP_100TH_MM users) i need to set a zoom + // here, too. The factor includes the needed scale, but is calculated by pure comparisons. It + // is somehow related to the twips/100thmm relationship. + bool bUserIs100thmm(false); + const uno::Reference< awt::XControl > xControl(xControlView, uno::UNO_QUERY); + + if(xControl.is()) + { + uno::Reference< awt::XWindowPeer > xWindowPeer(xControl->getPeer()); + + if(xWindowPeer.is()) + { + VCLXWindow* pVCLXWindow = VCLXWindow::GetImplementation(xWindowPeer); + + if(pVCLXWindow) + { + Window* pWindow = pVCLXWindow->GetWindow(); + + if(pWindow) + { + pWindow = pWindow->GetParent(); + + if(pWindow) + { + if(MAP_100TH_MM == pWindow->GetMapMode().GetMapUnit()) + { + bUserIs100thmm = true; + } + } + } + } + } + } + + if(bUserIs100thmm) + { + // calc screen zoom for text display. fFactor is already added indirectly in aDiscreteSize + basegfx::B2DVector aScreenZoom( + basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : aDiscreteSize.getX() / aScale.getX(), + basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : aDiscreteSize.getY() / aScale.getY()); + static double fZoomScale(28.0); // do not ask for this constant factor, but it gets the zoom right + aScreenZoom *= fZoomScale; + + // set zoom at control view for text scaling + xControlView->setZoom((float)aScreenZoom.getX(), (float)aScreenZoom.getY()); + } + } + + try + { + // try to paint it to VirtualDevice + xControlView->draw(0, 0); + + // get bitmap + const Bitmap aContent(aVirtualDevice.GetBitmap(Point(), aSizePixel)); + + // to avoid scaling, use the Bitmap pixel size as primitive size + const Size aBitmapSize(aContent.GetSizePixel()); + basegfx::B2DVector aBitmapSizeLogic( + rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1)); + + if(bScaleUsed) + { + // if scaled adapt to scaled size + aBitmapSizeLogic /= fFactor; + } + + // short form for scale and translate transformation + basegfx::B2DHomMatrix aBitmapTransform; + + aBitmapTransform.set(0L, 0L, aBitmapSizeLogic.getX()); + aBitmapTransform.set(1L, 1L, aBitmapSizeLogic.getY()); + aBitmapTransform.set(0L, 2L, aTranslate.getX()); + aBitmapTransform.set(1L, 2L, aTranslate.getY()); + + // create primitive + xRetval = new BitmapPrimitive2D(BitmapEx(aContent), aBitmapTransform); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + } + } + + return xRetval; + } + + Primitive2DReference ControlPrimitive2D::createPlaceholderDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // create a gray placeholder hairline polygon in object size + basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0); + aObjectRange.transform(getTransform()); + const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aObjectRange)); + const basegfx::BColor aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0); + + // The replacement object may also get a text like 'empty group' here later + Primitive2DReference xRetval(new PolygonHairlinePrimitive2D(aOutline, aGrayTone)); + + return xRetval; + } + + Primitive2DSequence ControlPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + // try to create a bitmap decomposition. If that fails for some reason, + // at least create a replacement decomposition. + Primitive2DReference xReference(createBitmapDecomposition(rViewInformation)); + + if(!xReference.is()) + { + xReference = createPlaceholderDecomposition(rViewInformation); + } + + return Primitive2DSequence(&xReference, 1L); + } + + ControlPrimitive2D::ControlPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const uno::Reference< awt::XControlModel >& rxControlModel) + : BasePrimitive2D(), + maTransform(rTransform), + mxControlModel(rxControlModel), + mxXControl(), + maLastViewScaling() + { + } + + ControlPrimitive2D::ControlPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const uno::Reference< awt::XControlModel >& rxControlModel, + const uno::Reference< awt::XControl >& rxXControl) + : BasePrimitive2D(), + maTransform(rTransform), + mxControlModel(rxControlModel), + mxXControl(rxXControl), + maLastViewScaling() + { + } + + const uno::Reference< awt::XControl >& ControlPrimitive2D::getXControl() const + { + if(!mxXControl.is()) + { + const_cast< ControlPrimitive2D* >(this)->createXControl(); + } + + return mxXControl; + } + + bool ControlPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + // use base class compare operator + if(BasePrimitive2D::operator==(rPrimitive)) + { + const ControlPrimitive2D& rCompare = (ControlPrimitive2D&)rPrimitive; + + if(getTransform() == rCompare.getTransform()) + { + // check if ControlModel references both are/are not + bool bRetval(getControlModel().is() == rCompare.getControlModel().is()); + + if(bRetval && getControlModel().is()) + { + // both exist, check for equality + bRetval = (getControlModel() == rCompare.getControlModel()); + } + + if(bRetval) + { + // check if XControl references both are/are not + bRetval = (getXControl().is() == rCompare.getXControl().is()); + } + + if(bRetval && getXControl().is()) + { + // both exist, check for equality + bRetval = (getXControl() == rCompare.getXControl()); + } + + return bRetval; + } + } + + return false; + } + + basegfx::B2DRange ControlPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // simply derivate from unit range + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + return aRetval; + } + + Primitive2DSequence ControlPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + // this primitive is view-dependent related to the scaling. If scaling has changed, + // destroy existing decomposition. To detect change, use size of unit size in view coordinates + ::osl::MutexGuard aGuard( m_aMutex ); + const basegfx::B2DVector aNewScaling(rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + + if(getLocalDecomposition().hasElements()) + { + if(!maLastViewScaling.equal(aNewScaling)) + { + // conditions of last local decomposition have changed, delete + const_cast< ControlPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewTransformation + const_cast< ControlPrimitive2D* >(this)->maLastViewScaling = aNewScaling; + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(ControlPrimitive2D, PRIMITIVE2D_ID_CONTROLPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx b/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx new file mode 100644 index 000000000000..5805c02a61ed --- /dev/null +++ b/drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx @@ -0,0 +1,176 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: embedded3dprimitive2d.cxx,v $ + * + * $Revision: 1.8 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/embedded3dprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/color/bcolor.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/geometry/viewinformation3d.hxx> +#include <drawinglayer/processor3d/shadow3dextractor.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + bool Embedded3DPrimitive2D::impGetShadow3D(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + osl::MutexGuard aGuard( m_aMutex ); + + // create on demand + if(!mbShadow3DChecked && getChildren3D().hasElements()) + { + // create shadow extraction processor + processor3d::Shadow3DExtractingProcessor aShadowProcessor( + getViewInformation3D(), + getObjectTransformation(), + getLightNormal(), + getShadowSlant(), + getScene3DRange()); + + // process local primitives + aShadowProcessor.process(getChildren3D()); + + // fetch result and set checked flag + const_cast< Embedded3DPrimitive2D* >(this)->maShadowPrimitives = aShadowProcessor.getPrimitive2DSequence(); + const_cast< Embedded3DPrimitive2D* >(this)->mbShadow3DChecked = true; + } + + // return if there are shadow primitives + return maShadowPrimitives.hasElements(); + } + + Primitive2DSequence Embedded3DPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + // use info to create a yellow 2d rectangle, similar to empty 3d scenes and/or groups + const basegfx::B2DRange aLocal2DRange(getB2DRange(rViewInformation)); + const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aLocal2DRange)); + const basegfx::BColor aYellow(1.0, 1.0, 0.0); + const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(aOutline, aYellow)); + + return Primitive2DSequence(&xRef, 1L); + } + + Embedded3DPrimitive2D::Embedded3DPrimitive2D( + const primitive3d::Primitive3DSequence& rxChildren3D, + const basegfx::B2DHomMatrix& rObjectTransformation, + const geometry::ViewInformation3D& rViewInformation3D, + const basegfx::B3DVector& rLightNormal, + double fShadowSlant, + const basegfx::B3DRange& rScene3DRange) + : BasePrimitive2D(), + mxChildren3D(rxChildren3D), + maObjectTransformation(rObjectTransformation), + maViewInformation3D(rViewInformation3D), + maLightNormal(rLightNormal), + mfShadowSlant(fShadowSlant), + maScene3DRange(rScene3DRange), + maShadowPrimitives(), + maB2DRange(), + mbShadow3DChecked(false) + { + maLightNormal.normalize(); + } + + bool Embedded3DPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const Embedded3DPrimitive2D& rCompare = static_cast< const Embedded3DPrimitive2D& >(rPrimitive); + + return (primitive3d::arePrimitive3DSequencesEqual(getChildren3D(), rCompare.getChildren3D()) + && getObjectTransformation() == rCompare.getObjectTransformation() + && getViewInformation3D() == rCompare.getViewInformation3D() + && getLightNormal() == rCompare.getLightNormal() + && getShadowSlant() == rCompare.getShadowSlant() + && getScene3DRange() == rCompare.getScene3DRange()); + } + + return false; + } + + basegfx::B2DRange Embedded3DPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + if(maB2DRange.isEmpty()) + { + // use the 3d transformation stack to create a projection of the 3D range + basegfx::B3DRange a3DRange(primitive3d::getB3DRangeFromPrimitive3DSequence(getChildren3D(), getViewInformation3D())); + a3DRange.transform(getViewInformation3D().getObjectToView()); + + // create 2d range from projected 3d and transform with scene's object transformation + basegfx::B2DRange aNewRange; + aNewRange.expand(basegfx::B2DPoint(a3DRange.getMinX(), a3DRange.getMinY())); + aNewRange.expand(basegfx::B2DPoint(a3DRange.getMaxX(), a3DRange.getMaxY())); + aNewRange.transform(getObjectTransformation()); + + // cehck for 3D shadows and their 2D projections. If those exist, they need to be + // taken into account + if(impGetShadow3D(rViewInformation)) + { + const basegfx::B2DRange aShadow2DRange(getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation)); + + if(!aShadow2DRange.isEmpty()) + { + aNewRange.expand(aShadow2DRange); + } + } + + // assign to buffered value + const_cast< Embedded3DPrimitive2D* >(this)->maB2DRange = aNewRange; + } + + return maB2DRange; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(Embedded3DPrimitive2D, PRIMITIVE2D_ID_EMBEDDED3DPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/fillbitmapprimitive2d.cxx b/drawinglayer/source/primitive2d/fillbitmapprimitive2d.cxx new file mode 100644 index 000000000000..125c2cb42193 --- /dev/null +++ b/drawinglayer/source/primitive2d/fillbitmapprimitive2d.cxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fillbitmapprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/texture/texture.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence FillBitmapPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const Size aTileSizePixel(getFillBitmap().getBitmap().GetSizePixel()); + Primitive2DSequence aRetval; + + // is there a tile with some size at all? + if(aTileSizePixel.getWidth() && aTileSizePixel.getHeight()) + { + if(getFillBitmap().getTiling()) + { + // get object range and create tiling matrices + ::std::vector< basegfx::B2DHomMatrix > aMatrices; + texture::GeoTexSvxTiled aTiling(getFillBitmap().getTopLeft(), getFillBitmap().getSize()); + aTiling.appendTransformations(aMatrices); + + // resize result + aRetval.realloc(aMatrices.size()); + + // create one primitive for each matrix + for(sal_uInt32 a(0L); a < aMatrices.size(); a++) + { + basegfx::B2DHomMatrix aNewMatrix = aMatrices[a]; + aNewMatrix *= getTransformation(); + + // create bitmap primitive and add to result + const Primitive2DReference xRef(new BitmapPrimitive2D(BitmapEx(getFillBitmap().getBitmap()), aNewMatrix)); + aRetval[a] = xRef; + } + } + else + { + // create new object transform + basegfx::B2DHomMatrix aObjectTransform; + aObjectTransform.set(0L, 0L, getFillBitmap().getSize().getX()); + aObjectTransform.set(1L, 1L, getFillBitmap().getSize().getY()); + aObjectTransform.set(0L, 2L, getFillBitmap().getTopLeft().getX()); + aObjectTransform.set(1L, 2L, getFillBitmap().getTopLeft().getY()); + aObjectTransform *= getTransformation(); + + // create bitmap primitive and add exclusive to decomposition (hand over ownership) + const Primitive2DReference xRef(new BitmapPrimitive2D(BitmapEx(getFillBitmap().getBitmap()), aObjectTransform)); + aRetval = Primitive2DSequence(&xRef, 1L); + } + } + + return aRetval; + } + + FillBitmapPrimitive2D::FillBitmapPrimitive2D( + const basegfx::B2DHomMatrix& rTransformation, + const attribute::FillBitmapAttribute& rFillBitmap) + : BasePrimitive2D(), + maTransformation(rTransformation), + maFillBitmap(rFillBitmap) + { + } + + bool FillBitmapPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const FillBitmapPrimitive2D& rCompare = static_cast< const FillBitmapPrimitive2D& >(rPrimitive); + + return (getTransformation() == rCompare.getTransformation() + && getFillBitmap() == rCompare.getFillBitmap()); + } + + return false; + } + + basegfx::B2DRange FillBitmapPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return range of it + basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aPolygon.transform(getTransformation()); + return basegfx::tools::getRange(aPolygon); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(FillBitmapPrimitive2D, PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx new file mode 100644 index 000000000000..ff0c031b38a1 --- /dev/null +++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fillgradientprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/fillgradientprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/texture/texture.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence FillGradientPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const attribute::GradientStyle aGradientStyle(maFillGradient.getStyle()); + ::std::vector< basegfx::B2DHomMatrix > aMatrices; + ::std::vector< basegfx::BColor > aColors; + basegfx::B2DPolygon aUnitPolygon; + sal_uInt32 nSteps(maFillGradient.getSteps()); + + if(attribute::GRADIENTSTYLE_RADIAL == aGradientStyle || attribute::GRADIENTSTYLE_ELLIPTICAL == aGradientStyle) + { + const basegfx::B2DPoint aCircleCenter(0.5, 0.5); + aUnitPolygon = basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5); + } + else + { + aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)); + } + + // make sure steps is not too high/low + const basegfx::BColor aStart(maFillGradient.getStartColor()); + const basegfx::BColor aEnd(maFillGradient.getEndColor()); + const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5)); + + if(nSteps == 0L) + { + nSteps = nMaxSteps; + } + + if(nSteps < 2L) + { + nSteps = 2L; + } + + if(nSteps > nMaxSteps) + { + nSteps = nMaxSteps; + } + + switch(aGradientStyle) + { + case attribute::GRADIENTSTYLE_LINEAR: + { + texture::GeoTexSvxGradientLinear aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), -maFillGradient.getAngle()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + case attribute::GRADIENTSTYLE_AXIAL: + { + texture::GeoTexSvxGradientAxial aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), -maFillGradient.getAngle()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + case attribute::GRADIENTSTYLE_RADIAL: + { + texture::GeoTexSvxGradientRadial aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), maFillGradient.getOffsetX(), maFillGradient.getOffsetY()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + case attribute::GRADIENTSTYLE_ELLIPTICAL: + { + texture::GeoTexSvxGradientElliptical aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), maFillGradient.getOffsetX(), maFillGradient.getOffsetY(), -maFillGradient.getAngle()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + case attribute::GRADIENTSTYLE_SQUARE: + { + texture::GeoTexSvxGradientSquare aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), maFillGradient.getOffsetX(), maFillGradient.getOffsetY(), -maFillGradient.getAngle()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + case attribute::GRADIENTSTYLE_RECT: + { + texture::GeoTexSvxGradientRect aGradient(getObjectRange(), aStart, aEnd, nSteps, maFillGradient.getBorder(), maFillGradient.getOffsetX(), maFillGradient.getOffsetY(), -maFillGradient.getAngle()); + aGradient.appendTransformations(aMatrices); + aGradient.appendColors(aColors); + break; + } + } + + // prepare return value + Primitive2DSequence aRetval(aColors.size() ? aMatrices.size() + 1L : aMatrices.size()); + + // create solid fill with start color + if(aColors.size()) + { + // create primitive + const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(getObjectRange())), aColors[0L])); + aRetval[0L] = xRef; + } + + // create solid fill steps + for(sal_uInt32 a(0L); a < aMatrices.size(); a++) + { + // create part polygon + basegfx::B2DPolygon aNewPoly(aUnitPolygon); + aNewPoly.transform(aMatrices[a]); + + // create solid fill + const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aNewPoly), aColors[a + 1L])); + aRetval[a + 1L] = xRef; + } + + return aRetval; + } + + FillGradientPrimitive2D::FillGradientPrimitive2D( + const basegfx::B2DRange& rObjectRange, + const attribute::FillGradientAttribute& rFillGradient) + : BasePrimitive2D(), + maObjectRange(rObjectRange), + maFillGradient(rFillGradient) + { + } + + bool FillGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const FillGradientPrimitive2D& rCompare = (FillGradientPrimitive2D&)rPrimitive; + + return (getObjectRange() == rCompare.getObjectRange() + && maFillGradient == rCompare.maFillGradient); + } + + return false; + } + + basegfx::B2DRange FillGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return ObjectRange + return getObjectRange(); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(FillGradientPrimitive2D, PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx new file mode 100644 index 000000000000..06d04111686d --- /dev/null +++ b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx @@ -0,0 +1,162 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fillhatchprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/fillhatchprimitive2d.hxx> +#include <drawinglayer/texture/texture.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence FillHatchPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // create hatch + const basegfx::BColor aHatchColor(maFillHatch.getColor()); + const double fAngle(-maFillHatch.getAngle()); + ::std::vector< basegfx::B2DHomMatrix > aMatrices; + + // get hatch transformations + switch(maFillHatch.getStyle()) + { + case attribute::HATCHSTYLE_TRIPLE: + { + // rotated 45 degrees + texture::GeoTexSvxHatch aHatch(getObjectRange(), maFillHatch.getDistance(), fAngle + F_PI4); + aHatch.appendTransformations(aMatrices); + + // fall-through by purpose + } + case attribute::HATCHSTYLE_DOUBLE: + { + // rotated 90 degrees + texture::GeoTexSvxHatch aHatch(getObjectRange(), maFillHatch.getDistance(), fAngle + F_PI2); + aHatch.appendTransformations(aMatrices); + + // fall-through by purpose + } + case attribute::HATCHSTYLE_SINGLE: + { + // angle as given + texture::GeoTexSvxHatch aHatch(getObjectRange(), maFillHatch.getDistance(), fAngle); + aHatch.appendTransformations(aMatrices); + } + } + + // prepare return value + const bool bFillBackground(maFillHatch.isFillBackground()); + Primitive2DSequence aRetval(bFillBackground ? aMatrices.size() + 1L : aMatrices.size()); + + // evtl. create filled background + if(bFillBackground) + { + // create primitive for background + const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(getObjectRange())), maBColor)); + aRetval[0L] = xRef; + } + + // create primitives + const basegfx::B2DPoint aStart(0.0, 0.0); + const basegfx::B2DPoint aEnd(1.0, 0.0); + + for(sal_uInt32 a(0L); a < aMatrices.size(); a++) + { + const basegfx::B2DHomMatrix& rMatrix = aMatrices[a]; + basegfx::B2DPolygon aNewLine; + + aNewLine.append(rMatrix * aStart); + aNewLine.append(rMatrix * aEnd); + + // create hairline + const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(aNewLine, aHatchColor)); + aRetval[bFillBackground ? (a + 1L) : a] = xRef; + } + + return aRetval; + } + + FillHatchPrimitive2D::FillHatchPrimitive2D( + const basegfx::B2DRange& rObjectRange, + const basegfx::BColor& rBColor, + const attribute::FillHatchAttribute& rFillHatch) + : BasePrimitive2D(), + maObjectRange(rObjectRange), + maFillHatch(rFillHatch), + maBColor(rBColor) + { + } + + bool FillHatchPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const FillHatchPrimitive2D& rCompare = (FillHatchPrimitive2D&)rPrimitive; + + return (getObjectRange() == rCompare.getObjectRange() + && maFillHatch == rCompare.maFillHatch + && maBColor == rCompare.maBColor); + } + + return false; + } + + basegfx::B2DRange FillHatchPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return ObjectRange + return getObjectRange(); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(FillHatchPrimitive2D, PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx new file mode 100644 index 000000000000..1ed826dab562 --- /dev/null +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -0,0 +1,458 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: graphicprimitive2d.cxx,v $ + * + * $Revision: 1.3 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/graphicprimitive2d.hxx> +#include <drawinglayer/animation/animationtiming.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/animatedprimitive2d.hxx> +#include <drawinglayer/primitive2d/metafileprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// +// helper class for animated graphics + +#include <vcl/animate.hxx> +#include <vcl/graph.hxx> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + struct animationStep + { + BitmapEx maBitmapEx; + sal_uInt32 mnTime; + }; + + class animatedBitmapExPreparator + { + ::Animation maAnimation; + ::std::vector< animationStep > maSteps; + + sal_uInt32 generateStepTime(sal_uInt32 nIndex) const; + + public: + animatedBitmapExPreparator(const Graphic& rGraphic); + + sal_uInt32 count() const { return maSteps.size(); } + sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); } + sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; } + const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; } + }; + + sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const + { + const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex)); + sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10); + + // #115934# + // Take care of special value for MultiPage TIFFs. ATM these shall just + // show their first page. Later we will offer some switching when object + // is selected. + if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait) + { + // ATM the huge value would block the timer, so + // use a long time to show first page (whole day) + nWaitTime = 100 * 60 * 60 * 24; + } + + // Bad trap: There are animated gifs with no set WaitTime (!). + // In that case use a default value. + if(0L == nWaitTime) + { + nWaitTime = 100L; + } + + return nWaitTime; + } + + animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic) + : maAnimation(rGraphic.GetAnimation()) + { + OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)"); + + // #128539# secure access to Animation, looks like there exist animated GIFs out there + // with a step count of zero + if(maAnimation.Count()) + { + VirtualDevice aVirtualDevice(*Application::GetDefaultDevice()); + VirtualDevice aVirtualDeviceMask(*Application::GetDefaultDevice(), 1L); + + // Prepare VirtualDevices and their states + aVirtualDevice.EnableMapMode(sal_False); + aVirtualDeviceMask.EnableMapMode(sal_False); + aVirtualDevice.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); + aVirtualDeviceMask.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); + aVirtualDevice.Erase(); + aVirtualDeviceMask.Erase(); + + for(sal_uInt16 a(0L); a < maAnimation.Count(); a++) + { + animationStep aNextStep; + aNextStep.mnTime = generateStepTime(a); + + // prepare step + const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a)); + + switch(rAnimBitmap.eDisposal) + { + case DISPOSE_NOT: + { + aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); + Bitmap aMask = rAnimBitmap.aBmpEx.GetMask(); + + if(aMask.IsEmpty()) + { + const Point aEmpty; + const Rectangle aRect(aEmpty, aVirtualDeviceMask.GetOutputSizePixel()); + const Wallpaper aWallpaper(COL_BLACK); + aVirtualDeviceMask.DrawWallpaper(aRect, aWallpaper); + } + else + { + BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask); + aVirtualDeviceMask.DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask); + } + + break; + } + case DISPOSE_BACK: + { + // #i70772# react on no mask, for primitives, too. + const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask()); + const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap()); + + aVirtualDeviceMask.Erase(); + aVirtualDevice.DrawBitmap(rAnimBitmap.aPosPix, aContent); + + if(aMask.IsEmpty()) + { + const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel()); + aVirtualDeviceMask.SetFillColor(COL_BLACK); + aVirtualDeviceMask.SetLineColor(); + aVirtualDeviceMask.DrawRect(aRect); + } + else + { + aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, aMask); + } + + break; + } + case DISPOSE_FULL: + { + aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); + break; + } + case DISPOSE_PREVIOUS : + { + aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); + aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask()); + break; + } + } + + // create BitmapEx + Bitmap aMainBitmap = aVirtualDevice.GetBitmap(Point(), aVirtualDevice.GetOutputSizePixel()); + Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap(Point(), aVirtualDeviceMask.GetOutputSizePixel()); + aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap); + + // add to vector + maSteps.push_back(aNextStep); + } + } + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence GraphicPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence aRetval; + + if(255L != getGraphicAttr().GetTransparency()) + { + // get transformed graphic. Suppress rotation and cropping, only filtering is needed + // here (and may be replaced later on). Cropping is handled below as mask primitive (if set) + GraphicAttr aSuppressGraphicAttr(getGraphicAttr()); + aSuppressGraphicAttr.SetCrop(0L, 0L, 0L, 0L); + aSuppressGraphicAttr.SetRotation(0); + Graphic aTransformedGraphic(getGraphicObject().GetTransformedGraphic(&aSuppressGraphicAttr)); + Primitive2DReference xPrimitive; + + switch(aTransformedGraphic.GetType()) + { + case GRAPHIC_BITMAP : + { + if(aTransformedGraphic.IsAnimated()) + { + // prepare animation data + animatedBitmapExPreparator aData(aTransformedGraphic); + + if(aData.count()) + { + // create sub-primitives for animated bitmap and the needed animation loop + animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff); + Primitive2DSequence aBitmapPrimitives(aData.count()); + + for(sal_uInt32 a(0L); a < aData.count(); a++) + { + animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count()); + aAnimationLoop.append(aTime); + const Primitive2DReference xRef(new BitmapPrimitive2D(aData.stepBitmapEx(a), getTransform())); + aBitmapPrimitives[a] = xRef; + } + + // prepare animation list + animation::AnimationEntryList aAnimationList; + aAnimationList.append(aAnimationLoop); + + // create and add animated switch primitive + xPrimitive = Primitive2DReference(new AnimatedSwitchPrimitive2D(aAnimationList, aBitmapPrimitives, false)); + } + } + else + { + xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), getTransform())); + } + + break; + } + + case GRAPHIC_GDIMETAFILE : + { + // create MetafilePrimitive2D + const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); + + xPrimitive = Primitive2DReference( + new MetafilePrimitive2D( + getTransform(), + rMetafile)); + + // #i100357# find out if clipping is needed for this primitive. Unfortunately, + // there exist Metafiles who's content is bigger than the proposed PrefSize set + // at them. This is an error, but we need to work around this + const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); + const Size aMetaFileRealSize( + const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( + *Application::GetDefaultDevice()).GetSize()); + + if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() + || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) + { + // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon + const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); + basegfx::B2DPolygon aMaskPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aMaskPolygon.transform(getTransform()); + + xPrimitive = Primitive2DReference( + new MaskPrimitive2D( + basegfx::B2DPolyPolygon(aMaskPolygon), + aChildContent)); + } + + break; + } + + default: + { + // nothing to create + break; + } + } + + if(xPrimitive.is()) + { + // check for cropping + if(getGraphicAttr().IsCropped()) + { + // decompose to get current pos and size + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // create ranges. The current object range is just scale and translate + const basegfx::B2DRange aCurrent(aTranslate.getX(), aTranslate.getY(), aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); + + // calculate scalings between real image size and logic object size. This + // is necessary since the crop values are relative to original bitmap size + double fFactorX(1.0); + double fFactorY(1.0); + + { + const MapMode aMapMode100thmm(MAP_100TH_MM); + Size aBitmapSize(getGraphicObject().GetPrefSize()); + + // #i95968# better support PrefMapMode; special for MAP_PIXEL was missing + if(MAP_PIXEL == getGraphicObject().GetPrefMapMode().GetMapUnit()) + { + aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm); + } + else + { + aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, getGraphicObject().GetPrefMapMode(), aMapMode100thmm); + } + + const double fDivX(aBitmapSize.Width() - getGraphicAttr().GetLeftCrop() - getGraphicAttr().GetRightCrop()); + const double fDivY(aBitmapSize.Height() - getGraphicAttr().GetTopCrop() - getGraphicAttr().GetBottomCrop()); + + if(!basegfx::fTools::equalZero(fDivX)) + { + fFactorX = aScale.getX() / fDivX; + } + + if(!basegfx::fTools::equalZero(fDivY)) + { + fFactorY = aScale.getY() / fDivY; + } + } + + // Create cropped range, describes the bounds of the original graphic + basegfx::B2DRange aCropped; + aCropped.expand(aCurrent.getMinimum() - basegfx::B2DPoint(getGraphicAttr().GetLeftCrop() * fFactorX, getGraphicAttr().GetTopCrop() * fFactorY)); + aCropped.expand(aCurrent.getMaximum() + basegfx::B2DPoint(getGraphicAttr().GetRightCrop() * fFactorX, getGraphicAttr().GetBottomCrop() * fFactorY)); + + if(aCropped.isEmpty()) + { + // nothing to add since cropped bitmap is completely empty + // xPrimitive will not be used + } + else + { + // build new object transformation for transform primitive which contains xPrimitive + basegfx::B2DHomMatrix aNewObjectTransform(getTransform()); + aNewObjectTransform.invert(); + aNewObjectTransform.scale(aCropped.getWidth(), aCropped.getHeight()); + aNewObjectTransform.translate(aCropped.getMinX() - aCurrent.getMinX(), aCropped.getMinY() - aCurrent.getMinY()); + aNewObjectTransform.shearX(fShearX); + aNewObjectTransform.rotate(fRotate); + aNewObjectTransform.translate(aTranslate.getX(), aTranslate.getY()); + + // prepare TransformPrimitive2D with xPrimitive + const Primitive2DReference xTransformPrimitive(new TransformPrimitive2D(aNewObjectTransform, Primitive2DSequence(&xPrimitive, 1L))); + + if(aCurrent.isInside(aCropped)) + { + // cropped just got smaller, no need to really use a mask. Add to destination directly + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xTransformPrimitive); + } + else + { + // cropped got bigger, mask it with original object's bounds + basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aMaskPolyPolygon.transform(getTransform()); + + // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector + const Primitive2DReference xRefB(new MaskPrimitive2D(aMaskPolyPolygon, Primitive2DSequence(&xTransformPrimitive, 1L))); + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRefB); + } + } + } + else + { + // add to decomposition + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive); + } + } + } + + return aRetval; + } + + GraphicPrimitive2D::GraphicPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const GraphicObject& rGraphicObject, + const GraphicAttr& rGraphicAttr) + : BasePrimitive2D(), + maTransform(rTransform), + maGraphicObject(rGraphicObject), + maGraphicAttr(rGraphicAttr) + { + } + + GraphicPrimitive2D::GraphicPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const GraphicObject& rGraphicObject) + : BasePrimitive2D(), + maTransform(rTransform), + maGraphicObject(rGraphicObject), + maGraphicAttr() + { + } + + bool GraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const GraphicPrimitive2D& rCompare = (GraphicPrimitive2D&)rPrimitive; + + return (getTransform() == rCompare.getTransform() + && getGraphicObject() == rCompare.getGraphicObject() + && getGraphicAttr() == rCompare.getGraphicAttr()); + } + + return false; + } + + basegfx::B2DRange GraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(GraphicPrimitive2D, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx b/drawinglayer/source/primitive2d/gridprimitive2d.cxx new file mode 100644 index 000000000000..df4171309389 --- /dev/null +++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx @@ -0,0 +1,329 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: gridprimitive2d.cxx,v $ + * + * $Revision: 1.10 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/gridprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> +#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence GridPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + if(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0) + { + // decompose grid matrix to get logic size + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // create grid matrix which transforms from scaled logic to view + basegfx::B2DHomMatrix aRST; + aRST.shearX(fShearX); + aRST.rotate(fRotate); + aRST.translate(aTranslate.getX(), aTranslate.getY()); + aRST *= rViewInformation.getObjectToViewTransformation(); + + // get step widths + double fStepX(getWidth()); + double fStepY(getHeight()); + const double fMinimalStep(10.0); + + // guarantee a step width of 10.0 + if(basegfx::fTools::less(fStepX, fMinimalStep)) + { + fStepX = fMinimalStep; + } + + if(basegfx::fTools::less(fStepY, fMinimalStep)) + { + fStepY = fMinimalStep; + } + + // get relative distances in view coordinates + double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength()); + double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength()); + double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0); + sal_uInt32 nSmallStepsX(0L), nSmallStepsY(0L); + + // setup subdivisions + if(getSubdivisionsX()) + { + fSmallStepX = fStepX / getSubdivisionsX(); + fViewSmallStepX = fViewStepX / getSubdivisionsX(); + } + + if(getSubdivisionsY()) + { + fSmallStepY = fStepY / getSubdivisionsY(); + fViewSmallStepY = fViewStepY / getSubdivisionsY(); + } + + // correct step width + while(fViewStepX < getSmallestViewDistance()) + { + fViewStepX *= 2.0; + fStepX *= 2.0; + } + + while(fViewStepY < getSmallestViewDistance()) + { + fViewStepY *= 2.0; + fStepY *= 2.0; + } + + // correct small step width + if(getSubdivisionsX()) + { + while(fViewSmallStepX < getSmallestSubdivisionViewDistance()) + { + fViewSmallStepX *= 2.0; + fSmallStepX *= 2.0; + } + + nSmallStepsX = (sal_uInt32)(fStepX / fSmallStepX); + } + + if(getSubdivisionsY()) + { + while(fViewSmallStepY < getSmallestSubdivisionViewDistance()) + { + fViewSmallStepY *= 2.0; + fSmallStepY *= 2.0; + } + + nSmallStepsY = (sal_uInt32)(fStepY / fSmallStepY); + } + + // prepare point vectors for point and cross markers + std::vector< basegfx::B2DPoint > aPositionsPoint; + std::vector< basegfx::B2DPoint > aPositionsCross; + + for(double fX(0.0); fX < aScale.getX(); fX += fStepX) + { + const bool bXZero(basegfx::fTools::equalZero(fX)); + + for(double fY(0.0); fY < aScale.getY(); fY += fStepY) + { + const bool bYZero(basegfx::fTools::equalZero(fY)); + + if(!bXZero && !bYZero) + { + // get discrete position and test against 3x3 area surrounding it + // since it's a cross + const double fHalfCrossSize(3.0 * 0.5); + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY)); + const basegfx::B2DRange aDiscreteRangeCross( + aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize, + aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize); + + if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross)) + { + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsCross.push_back(aLogicPos); + } + } + + if(getSubdivisionsX() && !bYZero) + { + double fF(fX + fSmallStepX); + + for(sal_uInt32 a(1L); a < nSmallStepsX && fF < aScale.getX(); a++, fF += fSmallStepX) + { + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY)); + + if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) + { + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsPoint.push_back(aLogicPos); + } + } + } + + if(getSubdivisionsY() && !bXZero) + { + double fF(fY + fSmallStepY); + + for(sal_uInt32 a(1L); a < nSmallStepsY && fF < aScale.getY(); a++, fF += fSmallStepY) + { + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF)); + + if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) + { + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsPoint.push_back(aLogicPos); + } + } + } + } + } + + // prepare return value + const sal_uInt32 nCountPoint(aPositionsPoint.size()); + const sal_uInt32 nCountCross(aPositionsCross.size()); + const sal_uInt32 nRetvalCount((nCountPoint ? 1 : 0) + (nCountCross ? 1 : 0)); + sal_uInt32 nInsertCounter(0); + + aRetval.realloc(nRetvalCount); + + // add PointArrayPrimitive2D if point markers were added + if(nCountPoint) + { + aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor())); + } + + // add MarkerArrayPrimitive2D if cross markers were added + if(nCountCross) + { + if(!getSubdivisionsX() && !getSubdivisionsY()) + { + // no subdivisions, so fall back to points at grid positions, no need to + // visualize a difference between divisions and sub-divisions + aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross, getBColor())); + } + else + { + aRetval[nInsertCounter++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker())); + } + } + } + + return aRetval; + } + + GridPrimitive2D::GridPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + double fWidth, + double fHeight, + double fSmallestViewDistance, + double fSmallestSubdivisionViewDistance, + sal_uInt32 nSubdivisionsX, + sal_uInt32 nSubdivisionsY, + const basegfx::BColor& rBColor, + const BitmapEx& rCrossMarker) + : BasePrimitive2D(), + maTransform(rTransform), + mfWidth(fWidth), + mfHeight(fHeight), + mfSmallestViewDistance(fSmallestViewDistance), + mfSmallestSubdivisionViewDistance(fSmallestSubdivisionViewDistance), + mnSubdivisionsX(nSubdivisionsX), + mnSubdivisionsY(nSubdivisionsY), + maBColor(rBColor), + maCrossMarker(rCrossMarker), + maLastObjectToViewTransformation(), + maLastViewport() + { + } + + bool GridPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const GridPrimitive2D& rCompare = (GridPrimitive2D&)rPrimitive; + + return (getTransform() == rCompare.getTransform() + && getWidth() == rCompare.getWidth() + && getHeight() == rCompare.getHeight() + && getSmallestViewDistance() == rCompare.getSmallestViewDistance() + && getSmallestSubdivisionViewDistance() == rCompare.getSmallestSubdivisionViewDistance() + && getSubdivisionsX() == rCompare.getSubdivisionsX() + && getSubdivisionsY() == rCompare.getSubdivisionsY() + && getBColor() == rCompare.getBColor() + && getCrossMarker() == rCompare.getCrossMarker()); + } + + return false; + } + + basegfx::B2DRange GridPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // get object's range + basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + aUnitRange.transform(getTransform()); + + // intersect with visible part + aUnitRange.intersect(rViewInformation.getViewport()); + + return aUnitRange; + } + + Primitive2DSequence GridPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements()) + { + if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation()) + { + // conditions of last local decomposition have changed, delete + const_cast< GridPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewRange and ViewTransformation + const_cast< GridPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation(); + const_cast< GridPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(GridPrimitive2D, PRIMITIVE2D_ID_GRIDPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/groupprimitive2d.cxx b/drawinglayer/source/primitive2d/groupprimitive2d.cxx new file mode 100644 index 000000000000..ae899af6e84d --- /dev/null +++ b/drawinglayer/source/primitive2d/groupprimitive2d.cxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: groupprimitive2d.cxx,v $ + * + * $Revision: 1.7 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/groupprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + /// default: just return children, so all renderers not supporting group will use it's content + Primitive2DSequence GroupPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + return getChildren(); + } + + GroupPrimitive2D::GroupPrimitive2D( const Primitive2DSequence& rChildren ) + : BasePrimitive2D(), + 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 GroupPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const GroupPrimitive2D& rCompare = static_cast< const GroupPrimitive2D& >(rPrimitive); + + return (arePrimitive2DSequencesEqual(getChildren(), rCompare.getChildren())); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(GroupPrimitive2D, PRIMITIVE2D_ID_GROUPPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/helplineprimitive2d.cxx b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx new file mode 100644 index 000000000000..3232e635b561 --- /dev/null +++ b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx @@ -0,0 +1,230 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: helplineprimitive2d.cxx,v $ + * + * $Revision: 1.7 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/helplineprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygonclipper.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence HelplinePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + std::vector< BasePrimitive2D* > aTempPrimitiveTarget; + + if(!rViewInformation.getViewport().isEmpty() && !getDirection().equalZero()) + { + // position to view coordinates, DashLen and DashLen in logic + const basegfx::B2DPoint aViewPosition(rViewInformation.getObjectToViewTransformation() * getPosition()); + + switch(getStyle()) + { + default : // HELPLINESTYLE2D_POINT + { + const double fViewFixValue(15.0); + basegfx::B2DVector aNormalizedDirection(getDirection()); + aNormalizedDirection.normalize(); + aNormalizedDirection *= fViewFixValue; + const basegfx::B2DPoint aStartA(aViewPosition - aNormalizedDirection); + const basegfx::B2DPoint aEndA(aViewPosition + aNormalizedDirection); + basegfx::B2DPolygon aLineA; + aLineA.append(aStartA); + aLineA.append(aEndA); + aLineA.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNewA = new PolygonMarkerPrimitive2D(aLineA, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + aTempPrimitiveTarget.push_back(pNewA); + + const basegfx::B2DVector aPerpendicularNormalizedDirection(basegfx::getPerpendicular(aNormalizedDirection)); + const basegfx::B2DPoint aStartB(aViewPosition - aPerpendicularNormalizedDirection); + const basegfx::B2DPoint aEndB(aViewPosition + aPerpendicularNormalizedDirection); + basegfx::B2DPolygon aLineB; + aLineB.append(aStartB); + aLineB.append(aEndB); + aLineB.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNewB = new PolygonMarkerPrimitive2D(aLineB, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + aTempPrimitiveTarget.push_back(pNewB); + + break; + } + case HELPLINESTYLE2D_LINE : + { + basegfx::B2DPolygon aLine; + + if(basegfx::areParallel(getDirection(), basegfx::B2DVector(1.0, 0.0))) + { + // parallel to X-Axis, get cuts with Y-Axes + const double fCutA((rViewInformation.getDiscreteViewport().getMinX() - aViewPosition.getX()) / getDirection().getX()); + const double fCutB((rViewInformation.getDiscreteViewport().getMaxX() - aViewPosition.getX()) / getDirection().getX()); + const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); + const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); + const bool bBothLeft(aPosA.getX() < rViewInformation.getDiscreteViewport().getMinX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMinX()); + const bool bBothRight(aPosA.getX() > rViewInformation.getDiscreteViewport().getMaxX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMaxX()); + + if(!bBothLeft && !bBothRight) + { + aLine.append(aPosA); + aLine.append(aPosB); + } + } + else + { + // get cuts with X-Axes + const double fCutA((rViewInformation.getDiscreteViewport().getMinY() - aViewPosition.getY()) / getDirection().getY()); + const double fCutB((rViewInformation.getDiscreteViewport().getMaxY() - aViewPosition.getY()) / getDirection().getY()); + const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); + const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); + const bool bBothAbove(aPosA.getY() < rViewInformation.getDiscreteViewport().getMinY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMinY()); + const bool bBothBelow(aPosA.getY() > rViewInformation.getDiscreteViewport().getMaxY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMaxY()); + + if(!bBothAbove && !bBothBelow) + { + aLine.append(aPosA); + aLine.append(aPosB); + } + } + + if(aLine.count()) + { + // clip against visible area + const basegfx::B2DPolyPolygon aResult(basegfx::tools::clipPolygonOnRange(aLine, rViewInformation.getDiscreteViewport(), true, true)); + + for(sal_uInt32 a(0L); a < aResult.count(); a++) + { + basegfx::B2DPolygon aPart(aResult.getB2DPolygon(a)); + aPart.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNew = new PolygonMarkerPrimitive2D(aPart, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + aTempPrimitiveTarget.push_back(pNew); + } + } + + break; + } + } + } + + // prepare return value + Primitive2DSequence aRetval(aTempPrimitiveTarget.size()); + + for(sal_uInt32 a(0L); a < aTempPrimitiveTarget.size(); a++) + { + const Primitive2DReference xRef(aTempPrimitiveTarget[a]); + aRetval[a] = xRef; + } + + return aRetval; + } + + HelplinePrimitive2D::HelplinePrimitive2D( + const basegfx::B2DPoint& rPosition, + const basegfx::B2DVector& rDirection, + HelplineStyle2D eStyle, + const basegfx::BColor& rRGBColA, + const basegfx::BColor& rRGBColB, + double fDiscreteDashLength) + : BasePrimitive2D(), + maPosition(rPosition), + maDirection(rDirection), + meStyle(eStyle), + maRGBColA(rRGBColA), + maRGBColB(rRGBColB), + mfDiscreteDashLength(fDiscreteDashLength), + maLastObjectToViewTransformation(), + maLastViewport() + { + } + + bool HelplinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const HelplinePrimitive2D& rCompare = (HelplinePrimitive2D&)rPrimitive; + + return (getPosition() == rCompare.getPosition() + && getDirection() == rCompare.getDirection() + && getStyle() == rCompare.getStyle() + && getRGBColA() == rCompare.getRGBColA() + && getRGBColB() == rCompare.getRGBColB() + && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); + } + + return false; + } + + Primitive2DSequence HelplinePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements()) + { + if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation()) + { + // conditions of last local decomposition have changed, delete + const_cast< HelplinePrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewRange and ViewTransformation + const_cast< HelplinePrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation(); + const_cast< HelplinePrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(HelplinePrimitive2D, PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/hittestprimitive2d.cxx b/drawinglayer/source/primitive2d/hittestprimitive2d.cxx new file mode 100644 index 000000000000..daf65abd81d4 --- /dev/null +++ b/drawinglayer/source/primitive2d/hittestprimitive2d.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/primitive2d/hittestprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence HitTestPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return empty sequence + return Primitive2DSequence(); + } + + HitTestPrimitive2D::HitTestPrimitive2D( + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + basegfx::B2DRange HitTestPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + return getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(HitTestPrimitive2D, PRIMITIVE2D_ID_HITTESTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/invertprimitive2d.cxx b/drawinglayer/source/primitive2d/invertprimitive2d.cxx new file mode 100644 index 000000000000..374ec578113d --- /dev/null +++ b/drawinglayer/source/primitive2d/invertprimitive2d.cxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unifiedalphaprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/invertprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + InvertPrimitive2D::InvertPrimitive2D( + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(InvertPrimitive2D, PRIMITIVE2D_ID_INVERTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/makefile.mk b/drawinglayer/source/primitive2d/makefile.mk new file mode 100644 index 000000000000..e10d1ddbcc71 --- /dev/null +++ b/drawinglayer/source/primitive2d/makefile.mk @@ -0,0 +1,90 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.13 $ +# +# last change: $Author: aw $ $Date: 2008-04-04 06:00:23 $ +# +# 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 +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=drawinglayer +TARGET=primitive2d +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/alphaprimitive2d.obj \ + $(SLO)$/animatedprimitive2d.obj \ + $(SLO)$/baseprimitive2d.obj \ + $(SLO)$/backgroundcolorprimitive2d.obj \ + $(SLO)$/bitmapprimitive2d.obj \ + $(SLO)$/borderlineprimitive2d.obj \ + $(SLO)$/chartprimitive2d.obj \ + $(SLO)$/controlprimitive2d.obj \ + $(SLO)$/embedded3dprimitive2d.obj \ + $(SLO)$/fillbitmapprimitive2d.obj \ + $(SLO)$/fillgradientprimitive2d.obj \ + $(SLO)$/fillhatchprimitive2d.obj \ + $(SLO)$/graphicprimitive2d.obj \ + $(SLO)$/gridprimitive2d.obj \ + $(SLO)$/groupprimitive2d.obj \ + $(SLO)$/helplineprimitive2d.obj \ + $(SLO)$/hittestprimitive2d.obj \ + $(SLO)$/invertprimitive2d.obj \ + $(SLO)$/markerarrayprimitive2d.obj \ + $(SLO)$/pointarrayprimitive2d.obj \ + $(SLO)$/maskprimitive2d.obj \ + $(SLO)$/mediaprimitive2d.obj \ + $(SLO)$/metafileprimitive2d.obj \ + $(SLO)$/modifiedcolorprimitive2d.obj \ + $(SLO)$/pagepreviewprimitive2d.obj \ + $(SLO)$/polypolygonprimitive2d.obj \ + $(SLO)$/polygonprimitive2d.obj \ + $(SLO)$/primitivetools2d.obj \ + $(SLO)$/sceneprimitive2d.obj \ + $(SLO)$/shadowprimitive2d.obj \ + $(SLO)$/structuretagprimitive2d.obj \ + $(SLO)$/texteffectprimitive2d.obj \ + $(SLO)$/textlayoutdevice.obj \ + $(SLO)$/textprimitive2d.obj \ + $(SLO)$/textdecoratedprimitive2d.obj \ + $(SLO)$/texthierarchyprimitive2d.obj \ + $(SLO)$/transformprimitive2d.obj \ + $(SLO)$/unifiedalphaprimitive2d.obj \ + $(SLO)$/wrongspellprimitive2d.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk diff --git a/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx new file mode 100644 index 000000000000..5737b9ef6cec --- /dev/null +++ b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: markerarrayprimitive2d.cxx,v $ + * + * $Revision: 1.7 $ + * + * last change: $Author: aw $ $Date: 2008-07-21 17:41:18 $ + * + * 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/primitive2d/markerarrayprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence MarkerArrayPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence xRetval; + const std::vector< basegfx::B2DPoint >& rPositions = getPositions(); + const sal_uInt32 nMarkerCount(rPositions.size()); + + if(nMarkerCount && !getMarker().IsEmpty()) + { + // get pixel size + Size aBitmapSize(getMarker().GetSizePixel()); + + if(aBitmapSize.Width() && aBitmapSize.Height()) + { + // get logic half pixel size + basegfx::B2DVector aLogicHalfSize(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(aBitmapSize.getWidth() - 1.0, aBitmapSize.getHeight() - 1.0)); + + // use half size for expand + aLogicHalfSize *= 0.5; + + // number of primitives is known; realloc accordingly + xRetval.realloc(nMarkerCount); + + for(sal_uInt32 a(0); a < nMarkerCount; a++) + { + const basegfx::B2DPoint& rPosition(rPositions[a]); + const basegfx::B2DRange aRange(rPosition - aLogicHalfSize, rPosition + aLogicHalfSize); + basegfx::B2DHomMatrix aTransform; + + aTransform.set(0, 0, aRange.getWidth()); + aTransform.set(1, 1, aRange.getHeight()); + aTransform.set(0, 2, aRange.getMinX()); + aTransform.set(1, 2, aRange.getMinY()); + + xRetval[a] = Primitive2DReference(new BitmapPrimitive2D(getMarker(), aTransform)); + } + } + } + + return xRetval; + } + + MarkerArrayPrimitive2D::MarkerArrayPrimitive2D( + const std::vector< basegfx::B2DPoint >& rPositions, + const BitmapEx& rMarker) + : BasePrimitive2D(), + maPositions(rPositions), + maMarker(rMarker) + { + } + + bool MarkerArrayPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const MarkerArrayPrimitive2D& rCompare = (MarkerArrayPrimitive2D&)rPrimitive; + + return (getPositions() == rCompare.getPositions() + && getMarker() == rCompare.getMarker()); + } + + return false; + } + + basegfx::B2DRange MarkerArrayPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval; + + if(getPositions().size()) + { + // get the basic range from the position vector + for(std::vector< basegfx::B2DPoint >::const_iterator aIter(getPositions().begin()); aIter != getPositions().end(); aIter++) + { + aRetval.expand(*aIter); + } + + if(!getMarker().IsEmpty()) + { + // get pixel size + const Size aBitmapSize(getMarker().GetSizePixel()); + + if(aBitmapSize.Width() && aBitmapSize.Height()) + { + // get logic half size + basegfx::B2DVector aLogicHalfSize(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(aBitmapSize.getWidth(), aBitmapSize.getHeight())); + + // use half size for expand + aLogicHalfSize *= 0.5; + + // apply aLogicHalfSize + aRetval.expand(aRetval.getMinimum() - aLogicHalfSize); + aRetval.expand(aRetval.getMaximum() + aLogicHalfSize); + } + } + } + + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(MarkerArrayPrimitive2D, PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/maskprimitive2d.cxx b/drawinglayer/source/primitive2d/maskprimitive2d.cxx new file mode 100644 index 000000000000..20a4c98db67d --- /dev/null +++ b/drawinglayer/source/primitive2d/maskprimitive2d.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: maskprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + MaskPrimitive2D::MaskPrimitive2D( + const basegfx::B2DPolyPolygon& rMask, + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren), + maMask(rMask) + { + } + + bool MaskPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const MaskPrimitive2D& rCompare = static_cast< const MaskPrimitive2D& >(rPrimitive); + + return (getMask() == rCompare.getMask()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(MaskPrimitive2D, PRIMITIVE2D_ID_MASKPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/mediaprimitive2d.cxx b/drawinglayer/source/primitive2d/mediaprimitive2d.cxx new file mode 100644 index 000000000000..7799b8e66d0e --- /dev/null +++ b/drawinglayer/source/primitive2d/mediaprimitive2d.cxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: mediaprimitive2d.cxx,v $ + * + * $Revision: 1.4 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/mediaprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <avmedia/mediawindow.hxx> +#include <goodies/grfmgr.hxx> +#include <drawinglayer/primitive2d/graphicprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence MediaPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence xRetval(1); + + // create background object + basegfx::B2DPolygon aBackgroundPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aBackgroundPolygon.transform(getTransform()); + const Primitive2DReference xRefBackground(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aBackgroundPolygon), getBackgroundColor())); + xRetval[0] = xRefBackground; + + // try to get graphic snapshot + const Graphic aGraphic(avmedia::MediaWindow::grabFrame(getURL(), true)); + + if(GRAPHIC_BITMAP == aGraphic.GetType() || GRAPHIC_GDIMETAFILE == aGraphic.GetType()) + { + const GraphicObject aGraphicObject(aGraphic); + const GraphicAttr aGraphicAttr; + xRetval.realloc(2); + xRetval[0] = xRefBackground; + xRetval[1] = Primitive2DReference(new GraphicPrimitive2D(getTransform(), aGraphicObject, aGraphicAttr)); + } + + if(getDiscreteBorder()) + { + const basegfx::B2DVector aDiscreteInLogic(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector((double)getDiscreteBorder(), (double)getDiscreteBorder())); + const double fDiscreteSize(aDiscreteInLogic.getX() + aDiscreteInLogic.getY()); + + basegfx::B2DRange aSourceRange(0.0, 0.0, 1.0, 1.0); + aSourceRange.transform(getTransform()); + + basegfx::B2DRange aDestRange(aSourceRange); + aDestRange.grow(-0.5 * fDiscreteSize); + + if(::basegfx::fTools::equalZero(aDestRange.getWidth()) || ::basegfx::fTools::equalZero(aDestRange.getHeight())) + { + // shrunk primitive has no content (zero size in X or Y), nothing to display, nothing to return + xRetval = Primitive2DSequence(); + } + else + { + // create transformation matrix from original range to shrunk range + basegfx::B2DHomMatrix aTransform; + aTransform.translate(-aSourceRange.getMinX(), -aSourceRange.getMinY()); + aTransform.scale(aDestRange.getWidth() / aSourceRange.getWidth(), aDestRange.getHeight() / aSourceRange.getHeight()); + aTransform.translate(aDestRange.getMinX(), aDestRange.getMinY()); + + // add transform primitive + const Primitive2DReference aScaled(new TransformPrimitive2D(aTransform, xRetval)); + xRetval = Primitive2DSequence(&aScaled, 1L); + } + } + + return xRetval; + } + + MediaPrimitive2D::MediaPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const rtl::OUString& rURL, + const basegfx::BColor& rBackgroundColor, + sal_uInt32 nDiscreteBorder) + : BasePrimitive2D(), + maTransform(rTransform), + maURL(rURL), + maBackgroundColor(rBackgroundColor), + mnDiscreteBorder(nDiscreteBorder) + { + } + + bool MediaPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const MediaPrimitive2D& rCompare = (MediaPrimitive2D&)rPrimitive; + + return (getTransform() == rCompare.getTransform() + && getURL() == rCompare.getURL() + && getBackgroundColor() == rCompare.getBackgroundColor() + && getDiscreteBorder() == rCompare.getDiscreteBorder()); + } + + return false; + } + + basegfx::B2DRange MediaPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + + if(getDiscreteBorder()) + { + const basegfx::B2DVector aDiscreteInLogic(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector((double)getDiscreteBorder(), (double)getDiscreteBorder())); + const double fDiscreteSize(aDiscreteInLogic.getX() + aDiscreteInLogic.getY()); + + aRetval.grow(-0.5 * fDiscreteSize); + } + + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(MediaPrimitive2D, PRIMITIVE2D_ID_MEDIAPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx new file mode 100644 index 000000000000..2d1c0428a6a3 --- /dev/null +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: metafileprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/metafileprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + MetafilePrimitive2D::MetafilePrimitive2D( + const basegfx::B2DHomMatrix& rMetaFileTransform, + const GDIMetaFile& rMetaFile) + : BasePrimitive2D(), + maMetaFileTransform(rMetaFileTransform), + maMetaFile(rMetaFile) + { + } + + bool MetafilePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const MetafilePrimitive2D& rCompare = (MetafilePrimitive2D&)rPrimitive; + + return (getTransform() == rCompare.getTransform() + && getMetaFile() == rCompare.getMetaFile()); + } + + return false; + } + + basegfx::B2DRange MetafilePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(MetafilePrimitive2D, PRIMITIVE2D_ID_METAFILEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx new file mode 100644 index 000000000000..184cf2535911 --- /dev/null +++ b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: modifiedcolorprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + ModifiedColorPrimitive2D::ModifiedColorPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::BColorModifier& rColorModifier) + : GroupPrimitive2D(rChildren), + maColorModifier(rColorModifier) + { + } + + bool ModifiedColorPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const ModifiedColorPrimitive2D& rCompare = (ModifiedColorPrimitive2D&)rPrimitive; + + return (getColorModifier() == rCompare.getColorModifier()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(ModifiedColorPrimitive2D, PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx new file mode 100644 index 000000000000..01a82299682d --- /dev/null +++ b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pagepreviewprimitive2d.cxx,v $ + * + * $Revision: 1.3 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/pagepreviewprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PagePreviewPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence xRetval; + Primitive2DSequence aContent(getChildren()); + + if(aContent.hasElements() + && basegfx::fTools::more(getContentWidth(), 0.0) + && basegfx::fTools::more(getContentHeight(), 0.0)) + { + // the decomposed matrix will be needed + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0)) + { + // check if content overlaps with tageted size and needs to be embedded with a + // clipping primitive + const basegfx::B2DRange aRealContentRange(getB2DRangeFromPrimitive2DSequence(aContent, rViewInformation)); + const basegfx::B2DRange aAllowedContentRange(0.0, 0.0, getContentWidth(), getContentHeight()); + + if(!aAllowedContentRange.isInside(aRealContentRange)) + { + const Primitive2DReference xReferenceA(new MaskPrimitive2D(basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aAllowedContentRange)), aContent)); + aContent = Primitive2DSequence(&xReferenceA, 1); + } + + // create a mapping from content to object. + basegfx::B2DHomMatrix aPageTrans; + + if(getKeepAspectRatio()) + { + // #i101075# when keeping the aspect ratio is wanted, it is necessary to calculate + // an equidistant scaling in X and Y and a corresponding translation to + // center the output. Calculate needed scale factors + const double fScaleX(aScale.getX() / getContentWidth()); + const double fScaleY(aScale.getY() / getContentHeight()); + + // to keep the aspect, use the smaller scale and adapt missing size by translation + if(fScaleX < fScaleY) + { + // height needs to be adapted + const double fNeededHeight(aScale.getY() / fScaleX); + const double fSpaceToAdd(fNeededHeight - getContentHeight()); + + aPageTrans.translate(0.0, fSpaceToAdd * 0.5); + aPageTrans.scale(fScaleX, aScale.getY() / fNeededHeight); + } + else + { + // width needs to be adapted + const double fNeededWidth(aScale.getX() / fScaleY); + const double fSpaceToAdd(fNeededWidth - getContentWidth()); + + aPageTrans.translate(fSpaceToAdd * 0.5, 0.0); + aPageTrans.scale(aScale.getX() / fNeededWidth, fScaleY); + } + + // add the missing object transformation aspects + aPageTrans.shearX(fShearX); + aPageTrans.rotate(fRotate); + aPageTrans.translate(aTranslate.getX(), aTranslate.getY()); + } + else + { + // completely scale to PageObject size. Scale to unit size. + aPageTrans.scale(1.0/ getContentWidth(), 1.0 / getContentHeight()); + + // apply object matrix + aPageTrans *= getTransform(); + } + + // embed in necessary transformation to map from SdrPage to SdrPageObject + const Primitive2DReference xReferenceB(new TransformPrimitive2D(aPageTrans, aContent)); + xRetval = Primitive2DSequence(&xReferenceB, 1); + } + } + + return xRetval; + } + + PagePreviewPrimitive2D::PagePreviewPrimitive2D( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxDrawPage, + const basegfx::B2DHomMatrix& rTransform, + double fContentWidth, + double fContentHeight, + const Primitive2DSequence& rChildren, + bool bKeepAspectRatio) + : GroupPrimitive2D(rChildren), + mxDrawPage(rxDrawPage), + maTransform(rTransform), + mfContentWidth(fContentWidth), + mfContentHeight(fContentHeight), + mbKeepAspectRatio(bKeepAspectRatio) + { + } + + bool PagePreviewPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const PagePreviewPrimitive2D& rCompare = static_cast< const PagePreviewPrimitive2D& >(rPrimitive); + + return (getXDrawPage() == rCompare.getXDrawPage() + && getTransform() == rCompare.getTransform() + && getContentWidth() == rCompare.getContentWidth() + && getContentHeight() == rCompare.getContentHeight() + && getKeepAspectRatio() == rCompare.getKeepAspectRatio()); + } + + return false; + } + + basegfx::B2DRange PagePreviewPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation`*/) const + { + // nothing is allowed to stick out of a PagePreviewPrimitive, thus we + // can quickly deliver our range here + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PagePreviewPrimitive2D, PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx b/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx new file mode 100644 index 000000000000..d144fd7030e6 --- /dev/null +++ b/drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pointarrayprimitive2d.cxx,v $ + * + * $Revision: 1.3 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/pointarrayprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + PointArrayPrimitive2D::PointArrayPrimitive2D( + const std::vector< basegfx::B2DPoint >& rPositions, + const basegfx::BColor& rRGBColor) + : BasePrimitive2D(), + maPositions(rPositions), + maRGBColor(rRGBColor), + maB2DRange() + { + } + + bool PointArrayPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PointArrayPrimitive2D& rCompare = (PointArrayPrimitive2D&)rPrimitive; + + return (getPositions() == rCompare.getPositions() + && getRGBColor() == rCompare.getRGBColor()); + } + + return false; + } + + basegfx::B2DRange PointArrayPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + if(maB2DRange.isEmpty()) + { + basegfx::B2DRange aNewRange; + + // get the basic range from the position vector + for(std::vector< basegfx::B2DPoint >::const_iterator aIter(getPositions().begin()); aIter != getPositions().end(); aIter++) + { + aNewRange.expand(*aIter); + } + + // assign to buffered value + const_cast< PointArrayPrimitive2D* >(this)->maB2DRange = aNewRange; + } + + return maB2DRange; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PointArrayPrimitive2D, PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx new file mode 100644 index 000000000000..b5212da54688 --- /dev/null +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -0,0 +1,633 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: polygonprimitive2d.cxx,v $ + * + * $Revision: 1.12 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/polygonprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + PolygonHairlinePrimitive2D::PolygonHairlinePrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const basegfx::BColor& rBColor) + : BasePrimitive2D(), + maPolygon(rPolygon), + maBColor(rBColor) + { + } + + bool PolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolygonHairlinePrimitive2D& rCompare = (PolygonHairlinePrimitive2D&)rPrimitive; + + return (getB2DPolygon() == rCompare.getB2DPolygon() + && getBColor() == rCompare.getBColor()); + } + + return false; + } + + basegfx::B2DRange PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // this is a hairline, thus the line width is view-dependent. Get range of polygon + // as base size + basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange()); + + if(!aRetval.isEmpty()) + { + // Calculate view-dependent hairline width + const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)); + const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5); + + if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0)) + { + aRetval.grow(fDiscreteHalfLineWidth); + } + } + + // return range + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolygonMarkerPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + // calculate logic DashLength + const basegfx::B2DVector aDashVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(getDiscreteDashLength(), 0.0)); + const double fLogicDashLength(aDashVector.getX()); + + if(fLogicDashLength > 0.0 && !getRGBColorA().equal(getRGBColorB())) + { + // apply dashing; get line and gap snippets + ::std::vector< double > aDash; + basegfx::B2DPolyPolygon aDashedPolyPolyA; + basegfx::B2DPolyPolygon aDashedPolyPolyB; + + aDash.push_back(fLogicDashLength); + aDash.push_back(fLogicDashLength); + basegfx::tools::applyLineDashing(getB2DPolygon(), aDash, &aDashedPolyPolyA, &aDashedPolyPolyB, 2.0 * fLogicDashLength); + + // prepare return value + Primitive2DSequence aRetval(2); + + aRetval[0] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyA, getRGBColorA())); + aRetval[1] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyB, getRGBColorB())); + + return aRetval; + } + else + { + const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(getB2DPolygon(), getRGBColorA())); + return Primitive2DSequence(&xRef, 1L); + } + } + + PolygonMarkerPrimitive2D::PolygonMarkerPrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const basegfx::BColor& rRGBColorA, + const basegfx::BColor& rRGBColorB, + double fDiscreteDashLength) + : BasePrimitive2D(), + maPolygon(rPolygon), + maRGBColorA(rRGBColorA), + maRGBColorB(rRGBColorB), + mfDiscreteDashLength(fDiscreteDashLength), + maLastInverseObjectToViewTransformation() + { + } + + bool PolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolygonMarkerPrimitive2D& rCompare = (PolygonMarkerPrimitive2D&)rPrimitive; + + return (getB2DPolygon() == rCompare.getB2DPolygon() + && getRGBColorA() == rCompare.getRGBColorA() + && getRGBColorB() == rCompare.getRGBColorB() + && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); + } + + return false; + } + + basegfx::B2DRange PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // this is a hairline, thus the line width is view-dependent. Get range of polygon + // as base size + basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange()); + + if(!aRetval.isEmpty()) + { + // Calculate view-dependent hairline width + const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)); + const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5); + + if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0)) + { + aRetval.grow(fDiscreteHalfLineWidth); + } + } + + // return range + return aRetval; + } + + Primitive2DSequence PolygonMarkerPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + bool bNeedNewDecomposition(false); + + if(getLocalDecomposition().hasElements()) + { + if(rViewInformation.getInverseObjectToViewTransformation() != maLastInverseObjectToViewTransformation) + { + bNeedNewDecomposition = true; + } + } + + if(bNeedNewDecomposition) + { + // conditions of last local decomposition have changed, delete + const_cast< PolygonMarkerPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + // remember last used InverseObjectToViewTransformation + PolygonMarkerPrimitive2D* pThat = const_cast< PolygonMarkerPrimitive2D* >(this); + pThat->maLastInverseObjectToViewTransformation = rViewInformation.getInverseObjectToViewTransformation(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolygonStrokePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + if(getB2DPolygon().count()) + { + // #i102241# try to simplify before usage + const basegfx::B2DPolygon aB2DPolygon(basegfx::tools::simplifyCurveSegments(getB2DPolygon())); + basegfx::B2DPolyPolygon aHairLinePolyPolygon; + + if(0.0 == getStrokeAttribute().getFullDotDashLen()) + { + // no line dashing, just copy + aHairLinePolyPolygon.append(aB2DPolygon); + } + else + { + // apply LineStyle + basegfx::tools::applyLineDashing(aB2DPolygon, getStrokeAttribute().getDotDashArray(), &aHairLinePolyPolygon, 0, getStrokeAttribute().getFullDotDashLen()); + } + + const sal_uInt32 nCount(aHairLinePolyPolygon.count()); + + if(getLineAttribute().getWidth()) + { + // create fat line data + const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0); + const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin()); + basegfx::B2DPolyPolygon aAreaPolyPolygon; + + for(sal_uInt32 a(0L); a < nCount; a++) + { + // New version of createAreaGeometry; now creates bezier polygons + aAreaPolyPolygon.append(basegfx::tools::createAreaGeometry( + aHairLinePolyPolygon.getB2DPolygon(a), fHalfLineWidth, aLineJoin)); + } + + // prepare return value + Primitive2DSequence aRetval(aAreaPolyPolygon.count()); + + // create primitive + for(sal_uInt32 b(0L); b < aAreaPolyPolygon.count(); b++) + { + // put into single polyPolygon primitives to make clear that this is NOT meant + // to be painted as a single PolyPolygon (XORed as fill rule). Alternatively, a + // melting process may be used here one day. + const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b)); + static bool bTestByUsingRandomColor(false); + const basegfx::BColor aColor(bTestByUsingRandomColor + ? basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0) + : getLineAttribute().getColor()); + const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor)); + aRetval[b] = xRef; + } + + return aRetval; + } + else + { + // prepare return value + const Primitive2DReference xRef(new PolyPolygonHairlinePrimitive2D(aHairLinePolyPolygon, getLineAttribute().getColor())); + return Primitive2DSequence(&xRef, 1); + } + } + else + { + return Primitive2DSequence(); + } + } + + PolygonStrokePrimitive2D::PolygonStrokePrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::StrokeAttribute& rStrokeAttribute) + : BasePrimitive2D(), + maPolygon(rPolygon), + maLineAttribute(rLineAttribute), + maStrokeAttribute(rStrokeAttribute) + { + } + + PolygonStrokePrimitive2D::PolygonStrokePrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute) + : BasePrimitive2D(), + maPolygon(rPolygon), + maLineAttribute(rLineAttribute), + maStrokeAttribute() + { + } + + bool PolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolygonStrokePrimitive2D& rCompare = (PolygonStrokePrimitive2D&)rPrimitive; + + return (getB2DPolygon() == rCompare.getB2DPolygon() + && getLineAttribute() == rCompare.getLineAttribute() + && getStrokeAttribute() == rCompare.getStrokeAttribute()); + } + + return false; + } + + basegfx::B2DRange PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval; + + if(getLineAttribute().getWidth()) + { + if(basegfx::B2DLINEJOIN_MITER == getLineAttribute().getLineJoin()) + { + // if line is mitered, use parent call since mitered line + // geometry may use more space than the geometry grown by half line width + aRetval = BasePrimitive2D::getB2DRange(rViewInformation); + } + else + { + // for all other B2DLINEJOIN_* get the range from the base geometry + // and expand by half the line width + aRetval = getB2DPolygon().getB2DRange(); + aRetval.grow(getLineAttribute().getWidth() * 0.5); + } + } + else + { + // this is a hairline, thus the line width is view-dependent. Get range of polygon + // as base size + aRetval = getB2DPolygon().getB2DRange(); + + if(!aRetval.isEmpty()) + { + // Calculate view-dependent hairline width + const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)); + const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5); + + if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0)) + { + aRetval.grow(fDiscreteHalfLineWidth); + } + } + } + + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolygonWavePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence aRetval; + + if(getB2DPolygon().count()) + { + const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth())); + const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight())); + + if(bHasWidth && bHasHeight) + { + // create waveline curve + const basegfx::B2DPolygon aWaveline(basegfx::tools::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight())); + const Primitive2DReference xRef(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute())); + aRetval = Primitive2DSequence(&xRef, 1); + } + else + { + // flat waveline, decompose to simple line primitive + const Primitive2DReference xRef(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute())); + aRetval = Primitive2DSequence(&xRef, 1); + } + } + + return aRetval; + } + + PolygonWavePrimitive2D::PolygonWavePrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::StrokeAttribute& rStrokeAttribute, + double fWaveWidth, + double fWaveHeight) + : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute), + mfWaveWidth(fWaveWidth), + mfWaveHeight(fWaveHeight) + { + if(mfWaveWidth < 0.0) + { + mfWaveWidth = 0.0; + } + + if(mfWaveHeight < 0.0) + { + mfWaveHeight = 0.0; + } + } + + PolygonWavePrimitive2D::PolygonWavePrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute, + double fWaveWidth, + double fWaveHeight) + : PolygonStrokePrimitive2D(rPolygon, rLineAttribute), + mfWaveWidth(fWaveWidth), + mfWaveHeight(fWaveHeight) + { + if(mfWaveWidth < 0.0) + { + mfWaveWidth = 0.0; + } + + if(mfWaveHeight < 0.0) + { + mfWaveHeight = 0.0; + } + } + + bool PolygonWavePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolygonStrokePrimitive2D::operator==(rPrimitive)) + { + const PolygonWavePrimitive2D& rCompare = (PolygonWavePrimitive2D&)rPrimitive; + + return (getWaveWidth() == rCompare.getWaveWidth() + && getWaveHeight() == rCompare.getWaveHeight()); + } + + return false; + } + + basegfx::B2DRange PolygonWavePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // get range of parent + basegfx::B2DRange aRetval(PolygonStrokePrimitive2D::getB2DRange(rViewInformation)); + + // if WaveHeight, grow by it + if(basegfx::fTools::more(getWaveHeight(), 0.0)) + { + aRetval.grow(getWaveHeight()); + } + + // if line width, grow by it + if(basegfx::fTools::more(getLineAttribute().getWidth(), 0.0)) + { + aRetval.grow(getLineAttribute().getWidth() * 0.5); + } + + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolygonWavePrimitive2D, PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolygonStrokeArrowPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // copy local polygon, it may be changed + basegfx::B2DPolygon aLocalPolygon(getB2DPolygon()); + basegfx::B2DPolyPolygon aArrowA; + basegfx::B2DPolyPolygon aArrowB; + + if(!aLocalPolygon.isClosed()) + { + // apply arrows + const double fPolyLength(basegfx::tools::getLength(aLocalPolygon)); + double fStart(0.0); + double fEnd(0.0); + + if(getStart().isActive()) + { + // create start arrow primitive and consume + aArrowA = basegfx::tools::createAreaGeometryForLineStartEnd( + aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(), + fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart); + + // create some overlapping + fStart *= 0.8; + } + + if(getEnd().isActive()) + { + // create end arrow primitive and consume + aArrowB = basegfx::tools::createAreaGeometryForLineStartEnd( + aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(), + fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd); + + // create some overlapping + fEnd *= 0.8; + } + + if(0.0 != fStart || 0.0 != fEnd) + { + // build new poly, consume something from old poly + aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength); + } + } + + // prepare return value + Primitive2DSequence aRetval(1L + (aArrowA.count() ? 1L : 0L) + (aArrowB.count() ? 1L : 0L)); + sal_uInt32 nInd(0L); + + // add shaft + const Primitive2DReference xRefShaft(new PolygonStrokePrimitive2D(aLocalPolygon, getLineAttribute(), getStrokeAttribute())); + aRetval[nInd++] = xRefShaft; + + if(aArrowA.count()) + { + const Primitive2DReference xRefA(new PolyPolygonColorPrimitive2D(aArrowA, getLineAttribute().getColor())); + aRetval[nInd++] = xRefA; + } + + if(aArrowB.count()) + { + const Primitive2DReference xRefB(new PolyPolygonColorPrimitive2D(aArrowB, getLineAttribute().getColor())); + aRetval[nInd++] = xRefB; + } + + return aRetval; + } + + PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::StrokeAttribute& rStrokeAttribute, + const attribute::LineStartEndAttribute& rStart, + const attribute::LineStartEndAttribute& rEnd) + : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute), + maStart(rStart), + maEnd(rEnd) + { + } + + PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D( + const basegfx::B2DPolygon& rPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::LineStartEndAttribute& rStart, + const attribute::LineStartEndAttribute& rEnd) + : PolygonStrokePrimitive2D(rPolygon, rLineAttribute), + maStart(rStart), + maEnd(rEnd) + { + } + + bool PolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolygonStrokePrimitive2D::operator==(rPrimitive)) + { + const PolygonStrokeArrowPrimitive2D& rCompare = (PolygonStrokeArrowPrimitive2D&)rPrimitive; + + return (getStart() == rCompare.getStart() + && getEnd() == rCompare.getEnd()); + } + + return false; + } + + basegfx::B2DRange PolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval; + + if(getStart().isActive() || getEnd().isActive()) + { + // use decomposition when line start/end is used + return BasePrimitive2D::getB2DRange(rViewInformation); + } + else + { + // get range from parent + return PolygonStrokePrimitive2D::getB2DRange(rViewInformation); + } + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx new file mode 100644 index 000000000000..9dd14aeb11e3 --- /dev/null +++ b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx @@ -0,0 +1,548 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: polypolygonprimitive2d.cxx,v $ + * + * $Revision: 1.8 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/polypolygonprimitive2d.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonHairlinePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + if(nCount) + { + Primitive2DSequence aRetval(nCount); + + for(sal_uInt32 a(0L); a < nCount; a++) + { + aRetval[a] = Primitive2DReference(new PolygonHairlinePrimitive2D(aPolyPolygon.getB2DPolygon(a), getBColor())); + } + + return aRetval; + } + else + { + return Primitive2DSequence(); + } + } + + PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor) + : BasePrimitive2D(), + maPolyPolygon(rPolyPolygon), + maBColor(rBColor) + { + } + + bool PolyPolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonHairlinePrimitive2D& rCompare = (PolyPolygonHairlinePrimitive2D&)rPrimitive; + + return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon() + && getBColor() == rCompare.getBColor()); + } + + return false; + } + + basegfx::B2DRange PolyPolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return range + return basegfx::tools::getRange(getB2DPolyPolygon()); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonMarkerPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + if(nCount) + { + Primitive2DSequence aRetval(nCount); + + for(sal_uInt32 a(0L); a < nCount; a++) + { + aRetval[a] = Primitive2DReference(new PolygonMarkerPrimitive2D(aPolyPolygon.getB2DPolygon(a), getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); + } + + return aRetval; + } + else + { + return Primitive2DSequence(); + } + } + + PolyPolygonMarkerPrimitive2D::PolyPolygonMarkerPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rRGBColorA, + const basegfx::BColor& rRGBColorB, + double fDiscreteDashLength) + : BasePrimitive2D(), + maPolyPolygon(rPolyPolygon), + maRGBColorA(rRGBColorA), + maRGBColorB(rRGBColorB), + mfDiscreteDashLength(fDiscreteDashLength) + { + } + + bool PolyPolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonMarkerPrimitive2D& rCompare = (PolyPolygonMarkerPrimitive2D&)rPrimitive; + + return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon() + && getRGBColorA() == rCompare.getRGBColorA() + && getRGBColorB() == rCompare.getRGBColorB() + && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); + } + + return false; + } + + basegfx::B2DRange PolyPolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return range + return basegfx::tools::getRange(getB2DPolyPolygon()); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonStrokePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + if(nCount) + { + Primitive2DSequence aRetval(nCount); + + for(sal_uInt32 a(0L); a < nCount; a++) + { + aRetval[a] = Primitive2DReference(new PolygonStrokePrimitive2D(aPolyPolygon.getB2DPolygon(a), getLineAttribute(), getStrokeAttribute())); + } + + return aRetval; + } + else + { + return Primitive2DSequence(); + } + } + + PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::StrokeAttribute& rStrokeAttribute) + : BasePrimitive2D(), + maPolyPolygon(rPolyPolygon), + maLineAttribute(rLineAttribute), + maStrokeAttribute(rStrokeAttribute) + { + } + + PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::LineAttribute& rLineAttribute) + : BasePrimitive2D(), + maPolyPolygon(rPolyPolygon), + maLineAttribute(rLineAttribute), + maStrokeAttribute() + { + } + + bool PolyPolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonStrokePrimitive2D& rCompare = (PolyPolygonStrokePrimitive2D&)rPrimitive; + + return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon() + && getLineAttribute() == rCompare.getLineAttribute() + && getStrokeAttribute() == rCompare.getStrokeAttribute()); + } + + return false; + } + + basegfx::B2DRange PolyPolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // get range of it (subdivided) + basegfx::B2DRange aRetval(basegfx::tools::getRange(getB2DPolyPolygon())); + + // if width, grow by line width + if(getLineAttribute().getWidth()) + { + aRetval.grow(getLineAttribute().getWidth() / 2.0); + } + + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonStrokeArrowPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon()); + const sal_uInt32 nCount(aPolyPolygon.count()); + + if(nCount) + { + Primitive2DSequence aRetval(nCount); + + for(sal_uInt32 a(0L); a < nCount; a++) + { + const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a)); + + if(aPolygon.isClosed()) + { + // no need for PolygonStrokeArrowPrimitive2D when polygon is closed + aRetval[a] = Primitive2DReference(new PolygonStrokePrimitive2D(aPolygon, getLineAttribute(), getStrokeAttribute())); + } + else + { + aRetval[a] = Primitive2DReference(new PolygonStrokeArrowPrimitive2D(aPolygon, getLineAttribute(), getStrokeAttribute(), getStart(), getEnd())); + } + } + + return aRetval; + } + else + { + return Primitive2DSequence(); + } + } + + PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::StrokeAttribute& rStrokeAttribute, + const attribute::LineStartEndAttribute& rStart, + const attribute::LineStartEndAttribute& rEnd) + : PolyPolygonStrokePrimitive2D(rPolyPolygon, rLineAttribute, rStrokeAttribute), + maStart(rStart), + maEnd(rEnd) + { + } + + PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::LineAttribute& rLineAttribute, + const attribute::LineStartEndAttribute& rStart, + const attribute::LineStartEndAttribute& rEnd) + : PolyPolygonStrokePrimitive2D(rPolyPolygon, rLineAttribute), + maStart(rStart), + maEnd(rEnd) + { + } + + bool PolyPolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolyPolygonStrokePrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonStrokeArrowPrimitive2D& rCompare = (PolyPolygonStrokeArrowPrimitive2D&)rPrimitive; + + return (getStart() == rCompare.getStart() + && getEnd() == rCompare.getEnd()); + } + + return false; + } + + basegfx::B2DRange PolyPolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval; + + if(getStart().isActive() || getEnd().isActive()) + { + // use decomposition when line start/end is used + return BasePrimitive2D::getB2DRange(rViewInformation); + } + else + { + // get range from parent + return PolyPolygonStrokePrimitive2D::getB2DRange(rViewInformation); + } + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSTROKEARROWPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rBColor) + : BasePrimitive2D(), + maPolyPolygon(rPolyPolygon), + maBColor(rBColor) + { + } + + bool PolyPolygonColorPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonColorPrimitive2D& rCompare = (PolyPolygonColorPrimitive2D&)rPrimitive; + + return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon() + && getBColor() == rCompare.getBColor()); + } + + return false; + } + + basegfx::B2DRange PolyPolygonColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // return range + return basegfx::tools::getRange(getB2DPolyPolygon()); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonColorPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonGradientPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // create SubSequence with FillGradientPrimitive2D + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(aPolyPolygonRange, getFillGradient()); + const Primitive2DReference xSubRef(pNewGradient); + const Primitive2DSequence aSubSequence(&xSubRef, 1L); + + // create mask primitive + MaskPrimitive2D* pNewMask = new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence); + const Primitive2DReference xRef(pNewMask); + return Primitive2DSequence(&xRef, 1L); + } + + PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rBColor, + const attribute::FillGradientAttribute& rFillGradient) + : PolyPolygonColorPrimitive2D(rPolyPolygon, rBColor), + maFillGradient(rFillGradient) + { + } + + bool PolyPolygonGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolyPolygonColorPrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonGradientPrimitive2D& rCompare = (PolyPolygonGradientPrimitive2D&)rPrimitive; + + return (getFillGradient() == rCompare.getFillGradient()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonGradientPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonHatchPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // create SubSequence with FillHatchPrimitive2D + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(aPolyPolygonRange, getBColor(), getFillHatch()); + const Primitive2DReference xSubRef(pNewHatch); + const Primitive2DSequence aSubSequence(&xSubRef, 1L); + + // create mask primitive + MaskPrimitive2D* pNewMask = new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence); + const Primitive2DReference xRef(pNewMask); + return Primitive2DSequence(&xRef, 1L); + } + + PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rBColor, + const attribute::FillHatchAttribute& rFillHatch) + : PolyPolygonColorPrimitive2D(rPolyPolygon, rBColor), + maFillHatch(rFillHatch) + { + } + + bool PolyPolygonHatchPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolyPolygonColorPrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonHatchPrimitive2D& rCompare = (PolyPolygonHatchPrimitive2D&)rPrimitive; + + return (getFillHatch() == rCompare.getFillHatch()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonHatchPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence PolyPolygonBitmapPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // create SubSequence with FillBitmapPrimitive2D + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + basegfx::B2DHomMatrix aNewObjectTransform; + aNewObjectTransform.set(0, 0, aPolyPolygonRange.getWidth()); + aNewObjectTransform.set(1, 1, aPolyPolygonRange.getHeight()); + aNewObjectTransform.set(0, 2, aPolyPolygonRange.getMinX()); + aNewObjectTransform.set(1, 2, aPolyPolygonRange.getMinY()); + FillBitmapPrimitive2D* pNewBitmap = new FillBitmapPrimitive2D(aNewObjectTransform, getFillBitmap()); + const Primitive2DReference xSubRef(pNewBitmap); + const Primitive2DSequence aSubSequence(&xSubRef, 1L); + + // create mask primitive + MaskPrimitive2D* pNewMask = new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence); + const Primitive2DReference xRef(pNewMask); + return Primitive2DSequence(&xRef, 1L); + } + + PolyPolygonBitmapPrimitive2D::PolyPolygonBitmapPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rBColor, + const attribute::FillBitmapAttribute& rFillBitmap) + : PolyPolygonColorPrimitive2D(rPolyPolygon, rBColor), + maFillBitmap(rFillBitmap) + { + } + + bool PolyPolygonBitmapPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(PolyPolygonColorPrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonBitmapPrimitive2D& rCompare = (PolyPolygonBitmapPrimitive2D&)rPrimitive; + + return (getFillBitmap() == rCompare.getFillBitmap()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(PolyPolygonBitmapPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/primitivetools2d.cxx b/drawinglayer/source/primitive2d/primitivetools2d.cxx new file mode 100644 index 000000000000..d288a697d729 --- /dev/null +++ b/drawinglayer/source/primitive2d/primitivetools2d.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: baseprimitive2d.cxx,v $ + * + * $Revision: 1.6 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/primitivetools2d.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence DiscreteMetricDependentPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // get the current DiscreteUnit + const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength()); + + if(getLocalDecomposition().hasElements() && !basegfx::fTools::equal(fDiscreteUnit, getDiscreteUnit())) + { + // conditions of last local decomposition have changed, delete + const_cast< DiscreteMetricDependentPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + // remember new valid DiscreteUnit + const_cast< DiscreteMetricDependentPrimitive2D* >(this)->mfDiscreteUnit = fDiscreteUnit; + } + + // call base implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence ViewportDependentPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // get the current Viewport + const basegfx::B2DRange& rViewport = rViewInformation.getViewport(); + + if(getLocalDecomposition().hasElements() && !rViewport.equal(getViewport())) + { + // conditions of last local decomposition have changed, delete + const_cast< ViewportDependentPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + // remember new valid DiscreteUnit + const_cast< ViewportDependentPrimitive2D* >(this)->maViewport = rViewport; + } + + // call base implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx new file mode 100644 index 000000000000..ad36a40ea996 --- /dev/null +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -0,0 +1,484 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sceneprimitive2d.cxx,v $ + * + * $Revision: 1.16 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/sceneprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygonclipper.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <drawinglayer/processor3d/zbufferprocessor3d.hxx> +#include <drawinglayer/processor3d/shadow3dextractor.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <svtools/optionsdrawinglayer.hxx> +#include <drawinglayer/processor3d/geometry2dextractor.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + bool ScenePrimitive2D::impGetShadow3D(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // create on demand + if(!mbShadow3DChecked && getChildren3D().hasElements()) + { + basegfx::B3DVector aLightNormal; + const double fShadowSlant(getSdrSceneAttribute().getShadowSlant()); + const basegfx::B3DRange aScene3DRange(primitive3d::getB3DRangeFromPrimitive3DSequence(getChildren3D(), getViewInformation3D())); + + if(maSdrLightingAttribute.getLightVector().size()) + { + // get light normal from first light and normalize + aLightNormal = maSdrLightingAttribute.getLightVector()[0].getDirection(); + aLightNormal.normalize(); + } + + // create shadow extraction processor + processor3d::Shadow3DExtractingProcessor aShadowProcessor( + getViewInformation3D(), + getObjectTransformation(), + aLightNormal, + fShadowSlant, + aScene3DRange); + + // process local primitives + aShadowProcessor.process(getChildren3D()); + + // fetch result and set checked flag + const_cast< ScenePrimitive2D* >(this)->maShadowPrimitives = aShadowProcessor.getPrimitive2DSequence(); + const_cast< ScenePrimitive2D* >(this)->mbShadow3DChecked = true; + } + + // return if there are shadow primitives + return maShadowPrimitives.hasElements(); + } + + void ScenePrimitive2D::calculateDiscreteSizes( + const geometry::ViewInformation2D& rViewInformation, + basegfx::B2DRange& rDiscreteRange, + basegfx::B2DRange& rVisibleDiscreteRange, + basegfx::B2DRange& rUnitVisibleRange) const + { + // use unit range and transform to discrete coordinates + rDiscreteRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); + rDiscreteRange.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); + + // clip it against discrete Viewport (if set) + rVisibleDiscreteRange = rDiscreteRange; + + if(!rViewInformation.getViewport().isEmpty()) + { + rVisibleDiscreteRange.intersect(rViewInformation.getDiscreteViewport()); + } + + if(rVisibleDiscreteRange.isEmpty()) + { + rUnitVisibleRange = rVisibleDiscreteRange; + } + else + { + // create UnitVisibleRange containing unit range values [0.0 .. 1.0] describing + // the relative position of rVisibleDiscreteRange inside rDiscreteRange + const double fDiscreteScaleFactorX(basegfx::fTools::equalZero(rDiscreteRange.getWidth()) ? 1.0 : 1.0 / rDiscreteRange.getWidth()); + const double fDiscreteScaleFactorY(basegfx::fTools::equalZero(rDiscreteRange.getHeight()) ? 1.0 : 1.0 / rDiscreteRange.getHeight()); + + const double fMinX(basegfx::fTools::equal(rVisibleDiscreteRange.getMinX(), rDiscreteRange.getMinX()) + ? 0.0 + : (rVisibleDiscreteRange.getMinX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX); + const double fMinY(basegfx::fTools::equal(rVisibleDiscreteRange.getMinY(), rDiscreteRange.getMinY()) + ? 0.0 + : (rVisibleDiscreteRange.getMinY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY); + + const double fMaxX(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxX(), rDiscreteRange.getMaxX()) + ? 1.0 + : (rVisibleDiscreteRange.getMaxX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX); + const double fMaxY(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxY(), rDiscreteRange.getMaxY()) + ? 1.0 + : (rVisibleDiscreteRange.getMaxY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY); + + rUnitVisibleRange = basegfx::B2DRange(fMinX, fMinY, fMaxX, fMaxY); + } + } + + Primitive2DSequence ScenePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + // create 2D shadows from contained 3D primitives. This creates the shadow primitives on demand and tells if + // there are some or not. Do this at start, the shadow might still be visible even when the scene is not + if(impGetShadow3D(rViewInformation)) + { + // test visibility + const basegfx::B2DRange aShadow2DRange(getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation)); + const basegfx::B2DRange aViewRange(rViewInformation.getViewport()); + + if(aViewRange.isEmpty() || aShadow2DRange.overlaps(aViewRange)) + { + // add extracted 2d shadows (before 3d scene creations itself) + aRetval = maShadowPrimitives; + } + } + + // get the involved ranges (see helper method calculateDiscreteSizes for details) + basegfx::B2DRange aDiscreteRange; + basegfx::B2DRange aVisibleDiscreteRange; + basegfx::B2DRange aUnitVisibleRange; + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + + if(!aVisibleDiscreteRange.isEmpty()) + { + // test if discrete view size (pixel) maybe too big and limit it + double fViewSizeX(aVisibleDiscreteRange.getWidth()); + double fViewSizeY(aVisibleDiscreteRange.getHeight()); + const double fViewVisibleArea(fViewSizeX * fViewSizeY); + const SvtOptionsDrawinglayer aDrawinglayerOpt; + const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit()); + double fReduceFactor(1.0); + + if(fViewVisibleArea > fMaximumVisibleArea) + { + fReduceFactor = sqrt(fMaximumVisibleArea / fViewVisibleArea); + fViewSizeX *= fReduceFactor; + fViewSizeY *= fReduceFactor; + } + + if(rViewInformation.getReducedDisplayQuality()) + { + // when reducing the visualisation is allowed (e.g. an OverlayObject + // only needed for dragging), reduce resolution extra + // to speed up dragging interactions + const double fArea(fViewSizeX * fViewSizeY); + double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0))); + + if(fReducedVisualisationFactor > 1.0) + { + fReducedVisualisationFactor = 1.0; + } + else if(fReducedVisualisationFactor < 0.20) + { + fReducedVisualisationFactor = 0.20; + } + + if(fReducedVisualisationFactor != 1.0) + { + fReduceFactor *= fReducedVisualisationFactor; + fViewSizeX *= fReducedVisualisationFactor; + fViewSizeY *= fReducedVisualisationFactor; + } + } + + // calculate logic render size in world coordinates for usage in renderer + basegfx::B2DVector aLogicRenderSize( + aDiscreteRange.getWidth() * fReduceFactor, + aDiscreteRange.getHeight() * fReduceFactor); + aLogicRenderSize *= rViewInformation.getInverseObjectToViewTransformation(); + + // determine the oversample value + static sal_uInt16 nDefaultOversampleValue(3); + const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); + + // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process + processor3d::ZBufferProcessor3D aZBufferProcessor3D( + getViewInformation3D(), + rViewInformation, + getSdrSceneAttribute(), + getSdrLightingAttribute(), + aLogicRenderSize.getX(), + aLogicRenderSize.getY(), + aUnitVisibleRange, + nOversampleValue); + + aZBufferProcessor3D.processNonTransparent(getChildren3D()); + aZBufferProcessor3D.processTransparent(getChildren3D()); + const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx(); + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); + + if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) + { + // create transform for the created bitmap in discrete coordinates first. + basegfx::B2DHomMatrix aNew2DTransform; + + aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); + aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); + aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); + aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); + + // transform back to world coordinates for usage in primitive creation + aNew2DTransform *= rViewInformation.getInverseObjectToViewTransformation(); + + // create bitmap primitive and add + const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef); + + // test: Allow to add an outline in the debugger when tests are needed + static bool bAddOutlineToCreated3DSceneRepresentation(false); + + if(bAddOutlineToCreated3DSceneRepresentation) + { + basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aOutline.transform(aNew2DTransform); + const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); + appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef2); + } + } + } + + return aRetval; + } + + Primitive2DSequence ScenePrimitive2D::getGeometry2D() const + { + Primitive2DSequence aRetval; + + // create 2D projected geometry from 3D geometry + if(getChildren3D().hasElements()) + { + // create 2D geometry extraction processor + processor3d::Geometry2DExtractingProcessor aGeometryProcessor( + getViewInformation3D(), + getObjectTransformation()); + + // process local primitives + aGeometryProcessor.process(getChildren3D()); + + // fetch result + aRetval = aGeometryProcessor.getPrimitive2DSequence(); + } + + return aRetval; + } + + Primitive2DSequence ScenePrimitive2D::getShadow2D(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + // create 2D shadows from contained 3D primitives + if(impGetShadow3D(rViewInformation)) + { + // add extracted 2d shadows (before 3d scene creations itself) + aRetval = maShadowPrimitives; + } + + return aRetval; + } + + bool ScenePrimitive2D::tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const + { + if(!maOldRenderedBitmap.IsEmpty() && !maOldUnitVisiblePart.isEmpty()) + { + basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation()); + aInverseSceneTransform.invert(); + const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint); + + if(maOldUnitVisiblePart.isInside(aRelativePoint)) + { + // calculate coordinates relative to visualized part + double fDivisorX(maOldUnitVisiblePart.getWidth()); + double fDivisorY(maOldUnitVisiblePart.getHeight()); + + if(basegfx::fTools::equalZero(fDivisorX)) + { + fDivisorX = 1.0; + } + + if(basegfx::fTools::equalZero(fDivisorY)) + { + fDivisorY = 1.0; + } + + const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX); + const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY); + + // combine with real BitmapSizePixel to get bitmap coordinates + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); + const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width())); + const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height())); + + // try to get a statement about transparency in that pixel + o_rResult = (0xff != maOldRenderedBitmap.GetTransparency(nX, nY)); + return true; + } + } + + return false; + } + + ScenePrimitive2D::ScenePrimitive2D( + const primitive3d::Primitive3DSequence& rxChildren3D, + const attribute::SdrSceneAttribute& rSdrSceneAttribute, + const attribute::SdrLightingAttribute& rSdrLightingAttribute, + const basegfx::B2DHomMatrix& rObjectTransformation, + const geometry::ViewInformation3D& rViewInformation3D) + : BasePrimitive2D(), + mxChildren3D(rxChildren3D), + maSdrSceneAttribute(rSdrSceneAttribute), + maSdrLightingAttribute(rSdrLightingAttribute), + maObjectTransformation(rObjectTransformation), + maViewInformation3D(rViewInformation3D), + maShadowPrimitives(), + mbShadow3DChecked(false), + mfOldDiscreteSizeX(0.0), + mfOldDiscreteSizeY(0.0), + maOldUnitVisiblePart(), + maOldRenderedBitmap() + { + } + + bool ScenePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const ScenePrimitive2D& rCompare = (ScenePrimitive2D&)rPrimitive; + + return (primitive3d::arePrimitive3DSequencesEqual(getChildren3D(), rCompare.getChildren3D()) + && getSdrSceneAttribute() == rCompare.getSdrSceneAttribute() + && getSdrLightingAttribute() == rCompare.getSdrLightingAttribute() + && getObjectTransformation() == rCompare.getObjectTransformation() + && getViewInformation3D() == rCompare.getViewInformation3D()); + } + + return false; + } + + basegfx::B2DRange ScenePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // transform unit range to discrete coordinate range + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); + + // force to discrete expanded bounds (it grows, so expanding works perfectly well) + aRetval.expand(basegfx::B2DTuple(floor(aRetval.getMinX()), floor(aRetval.getMinY()))); + aRetval.expand(basegfx::B2DTuple(ceil(aRetval.getMaxX()), ceil(aRetval.getMaxY()))); + + // transform back from discrete (view) to world coordinates + aRetval.transform(rViewInformation.getInverseObjectToViewTransformation()); + + // expand by evtl. existing shadow primitives + if(impGetShadow3D(rViewInformation)) + { + const basegfx::B2DRange aShadow2DRange(getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation)); + + if(!aShadow2DRange.isEmpty()) + { + aRetval.expand(aShadow2DRange); + } + } + + return aRetval; + } + + Primitive2DSequence ScenePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // get the involved ranges (see helper method calculateDiscreteSizes for details) + basegfx::B2DRange aDiscreteRange; + basegfx::B2DRange aUnitVisibleRange; + bool bNeedNewDecomposition(false); + bool bDiscreteSizesAreCalculated(false); + + if(getLocalDecomposition().hasElements()) + { + basegfx::B2DRange aVisibleDiscreteRange; + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + bDiscreteSizesAreCalculated = true; + + // needs to be painted when the new part is not part of the last + // decomposition + if(!maOldUnitVisiblePart.isInside(aUnitVisibleRange)) + { + bNeedNewDecomposition = true; + } + + // display has changed and cannot be reused when resolution got bigger. It + // can be reused when resolution got smaller, though. + if(!bNeedNewDecomposition) + { + if(basegfx::fTools::more(aDiscreteRange.getWidth(), mfOldDiscreteSizeX) || + basegfx::fTools::more(aDiscreteRange.getHeight(), mfOldDiscreteSizeY)) + { + bNeedNewDecomposition = true; + } + } + } + + if(bNeedNewDecomposition) + { + // conditions of last local decomposition have changed, delete + const_cast< ScenePrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + + if(!getLocalDecomposition().hasElements()) + { + if(!bDiscreteSizesAreCalculated) + { + basegfx::B2DRange aVisibleDiscreteRange; + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + } + + // remember last used NewDiscreteSize and NewUnitVisiblePart + ScenePrimitive2D* pThat = const_cast< ScenePrimitive2D* >(this); + pThat->mfOldDiscreteSizeX = aDiscreteRange.getWidth(); + pThat->mfOldDiscreteSizeY = aDiscreteRange.getHeight(); + pThat->maOldUnitVisiblePart = aUnitVisibleRange; + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(ScenePrimitive2D, PRIMITIVE2D_ID_SCENEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx new file mode 100644 index 000000000000..5681f7f98d7e --- /dev/null +++ b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shadowprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/shadowprimitive2d.hxx> +#include <basegfx/color/bcolormodifier.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/alphaprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence ShadowPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence aRetval; + + if(getChildren().hasElements()) + { + // create a modifiedColorPrimitive containing the shadow color and the content + const basegfx::BColorModifier aBColorModifier(getShadowColor()); + const Primitive2DReference xRefA(new ModifiedColorPrimitive2D(getChildren(), aBColorModifier)); + const Primitive2DSequence aSequenceB(&xRefA, 1L); + + // build transformed primitiveVector with shadow offset and add to target + const Primitive2DReference xRefB(new TransformPrimitive2D(getShadowTransform(), aSequenceB)); + aRetval = Primitive2DSequence(&xRefB, 1L); + } + + return aRetval; + } + + ShadowPrimitive2D::ShadowPrimitive2D( + const basegfx::B2DHomMatrix& rShadowTransform, + const basegfx::BColor& rShadowColor, + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren), + maShadowTransform(rShadowTransform), + maShadowColor(rShadowColor) + { + } + + bool ShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const ShadowPrimitive2D& rCompare = static_cast< const ShadowPrimitive2D& >(rPrimitive); + + return (getShadowTransform() == rCompare.getShadowTransform() + && getShadowColor() == rCompare.getShadowColor()); + } + + return false; + } + + basegfx::B2DRange ShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + aRetval.transform(getShadowTransform()); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(ShadowPrimitive2D, PRIMITIVE2D_ID_SHADOWPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx new file mode 100644 index 000000000000..191b24dfcbf9 --- /dev/null +++ b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: structuretagprimitive2d.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/structuretagprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + StructureTagPrimitive2D::StructureTagPrimitive2D( + const vcl::PDFWriter::StructElement& rStructureElement, + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren), + maStructureElement(rStructureElement) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(StructureTagPrimitive2D, PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx new file mode 100644 index 000000000000..d337950c6c6b --- /dev/null +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -0,0 +1,888 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textdecoratedprimitive2d.cxx,v $ + * + * $Revision: 1.12 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/textdecoratedprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/attribute/strokeattribute.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/i18n/WordType.hpp> +#include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> +#include <drawinglayer/primitive2d/shadowprimitive2d.hxx> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + void TextDecoratedPortionPrimitive2D::impCreateTextLine( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans, + const basegfx::B2DHomMatrix &rUnscaledTransform, + FontUnderline eLineStyle, + double fLineOffset, + double fLineHeight, + double fLineWidth, + const basegfx::BColor& rLineColor) const + { + bool bDoubleLine(false); + bool bWaveLine(false); + bool bBoldLine(false); + const int* pDotDashArray(0); + basegfx::B2DLineJoin eLineJoin(basegfx::B2DLINEJOIN_NONE); + + static const int aDottedArray[] = { 1, 1, 0}; // DOTTED LINE + static const int aDotDashArray[] = { 1, 1, 4, 1, 0}; // DASHDOT + static const int aDashDotDotArray[] = { 1, 1, 1, 1, 4, 1, 0}; // DASHDOTDOT + static const int aDashedArray[] = { 5, 2, 0}; // DASHED LINE + static const int aLongDashArray[] = { 7, 2, 0}; // LONGDASH + + switch(eLineStyle) + { + default: // case FONT_UNDERLINE_SINGLE: + { + break; + } + case FONT_UNDERLINE_DOUBLE: + { + bDoubleLine = true; + break; + } + case FONT_UNDERLINE_DOTTED: + { + pDotDashArray = aDottedArray; + break; + } + case FONT_UNDERLINE_DASH: + { + pDotDashArray = aDashedArray; + break; + } + case FONT_UNDERLINE_LONGDASH: + { + pDotDashArray = aLongDashArray; + break; + } + case FONT_UNDERLINE_DASHDOT: + { + pDotDashArray = aDotDashArray; + break; + } + case FONT_UNDERLINE_DASHDOTDOT: + { + pDotDashArray = aDashDotDotArray; + break; + } + case FONT_UNDERLINE_SMALLWAVE: + { + bWaveLine = true; + break; + } + case FONT_UNDERLINE_WAVE: + { + bWaveLine = true; + break; + } + case FONT_UNDERLINE_DOUBLEWAVE: + { + bDoubleLine = true; + bWaveLine = true; + break; + } + case FONT_UNDERLINE_BOLD: + { + bBoldLine = true; + break; + } + case FONT_UNDERLINE_BOLDDOTTED: + { + bBoldLine = true; + pDotDashArray = aDottedArray; + break; + } + case FONT_UNDERLINE_BOLDDASH: + { + bBoldLine = true; + pDotDashArray = aDashedArray; + break; + } + case FONT_UNDERLINE_BOLDLONGDASH: + { + bBoldLine = true; + pDotDashArray = aLongDashArray; + break; + } + case FONT_UNDERLINE_BOLDDASHDOT: + { + bBoldLine = true; + pDotDashArray = aDotDashArray; + break; + } + case FONT_UNDERLINE_BOLDDASHDOTDOT: + { + bBoldLine = true; + pDotDashArray = aDashDotDotArray; + break; + } + case FONT_UNDERLINE_BOLDWAVE: + { + bWaveLine = true; + bBoldLine = true; + break; + } + } + + if(bBoldLine) + { + fLineHeight *= 2.0; + } + + if(bDoubleLine) + { + fLineOffset -= 0.50 * fLineHeight; + fLineHeight *= 0.64; + } + + if(bWaveLine) + { + eLineJoin = basegfx::B2DLINEJOIN_ROUND; + fLineHeight *= 0.25; + } + + // prepare Line and Stroke Attributes + const attribute::LineAttribute aLineAttribute(rLineColor, fLineHeight, eLineJoin); + attribute::StrokeAttribute aStrokeAttribute; + + if(pDotDashArray) + { + ::std::vector< double > aDoubleArray; + + for(const int* p = pDotDashArray; *p; ++p) + { + aDoubleArray.push_back((double)(*p) * fLineHeight); + } + + aStrokeAttribute = attribute::StrokeAttribute(aDoubleArray); + } + + // create base polygon and new primitive + basegfx::B2DPolygon aLine; + Primitive2DReference aNewPrimitive; + + aLine.append(basegfx::B2DPoint(0.0, fLineOffset)); + aLine.append(basegfx::B2DPoint(fLineWidth, fLineOffset)); + aLine.transform(rUnscaledTransform); + + if(bWaveLine) + { + double fWaveWidth(10.6 * fLineHeight); + + if(FONT_UNDERLINE_SMALLWAVE == eLineStyle) + { + fWaveWidth *= 0.7; + } + else if(FONT_UNDERLINE_WAVE == eLineStyle) + { + // extra multiply to get the same WaveWidth as with the bold version + fWaveWidth *= 2.0; + } + + aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5)); + } + else + { + aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aLine, aLineAttribute, aStrokeAttribute)); + } + + // add primitive + rTarget.push_back(aNewPrimitive); + + if(bDoubleLine) + { + // double line, create 2nd primitive with offset using TransformPrimitive based on + // already created NewPrimitive + double fLineDist(2.3 * fLineHeight); + + if(bWaveLine) + { + fLineDist = 6.3 * fLineHeight; + } + + basegfx::B2DHomMatrix aTransform; + + // move base point of text to 0.0 and de-rotate + aTransform.translate(-rDecTrans.getTranslate().getX(), -rDecTrans.getTranslate().getY()); + aTransform.rotate(-rDecTrans.getRotate()); + + // translate in Y by offset + aTransform.translate(0.0, fLineDist); + + // move back and rotate + aTransform.rotate(rDecTrans.getRotate()); + aTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); + + // add transform primitive + const Primitive2DSequence aContent(&aNewPrimitive, 1); + rTarget.push_back(Primitive2DReference(new TransformPrimitive2D(aTransform, aContent))); + } + } + + void TextDecoratedPortionPrimitive2D::impCreateGeometryContent( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans, + const String& rText, + xub_StrLen aTextPosition, + xub_StrLen aTextLength, + const ::std::vector< double >& rDXArray, + const FontAttributes& rFontAttributes) const + { + // create the SimpleTextPrimitive needed in any case + rTarget.push_back(Primitive2DReference( + new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + rText, + aTextPosition, + aTextLength, + rDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); + + // see if something else needs to be done + const bool bOverlineUsed(FONT_UNDERLINE_NONE != getFontOverline()); + const bool bUnderlineUsed(FONT_UNDERLINE_NONE != getFontUnderline()); + const bool bStrikeoutUsed(FONT_STRIKEOUT_NONE != getFontStrikeout()); + + if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed) + { + // common preparations + basegfx::B2DHomMatrix aUnscaledTransform; + TextLayouterDevice aTextLayouter; + + // unscaled is needed since scale contains already the font size + aUnscaledTransform.shearX(rDecTrans.getShearX()); + aUnscaledTransform.rotate(rDecTrans.getRotate()); + aUnscaledTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); + + // TextLayouterDevice is needed to get metrics for text decorations like + // underline/strikeout/emphasis marks from it. For setup, the font size is needed + aTextLayouter.setFontAttributes( + getFontAttributes(), + rDecTrans.getScale().getX(), + rDecTrans.getScale().getY(), + getLocale()); + + // get text width + double fTextWidth(0.0); + + if(rDXArray.empty()) + { + fTextWidth = aTextLayouter.getTextWidth(rText, aTextPosition, aTextLength); + } + else + { + fTextWidth = rDXArray.back() * rDecTrans.getScale().getX(); + const double fFontScaleX(rDecTrans.getScale().getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + // need to take FontScaling out of the DXArray + fTextWidth /= fFontScaleX; + } + } + + if(bOverlineUsed) + { + // create primitive geometry for overline + impCreateTextLine(rTarget, rDecTrans, aUnscaledTransform, getFontOverline(), aTextLayouter.getOverlineOffset(), + aTextLayouter.getOverlineHeight(), fTextWidth, getOverlineColor()); + } + + if(bUnderlineUsed) + { + // create primitive geometry for underline + impCreateTextLine(rTarget, rDecTrans, aUnscaledTransform, getFontUnderline(), aTextLayouter.getUnderlineOffset(), + aTextLayouter.getUnderlineHeight(), fTextWidth, getTextlineColor()); + } + + if(bStrikeoutUsed) + { + // create primitive geometry for strikeout + if(FONT_STRIKEOUT_SLASH == getFontStrikeout() || FONT_STRIKEOUT_X == getFontStrikeout()) + { + // strikeout with character + const sal_Unicode aStrikeoutChar(FONT_STRIKEOUT_SLASH == getFontStrikeout() ? '/' : 'X'); + const String aSingleCharString(aStrikeoutChar); + const double fStrikeCharWidth(aTextLayouter.getTextWidth(aSingleCharString, 0, 1)); + const double fStrikeCharCount(fabs(fTextWidth/fStrikeCharWidth)); + const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.5)); + std::vector<double> aDXArray(nStrikeCharCount); + String aStrikeoutString; + + for(sal_uInt32 a(0); a < nStrikeCharCount; a++) + { + aStrikeoutString += aSingleCharString; + aDXArray[a] = (a + 1) * fStrikeCharWidth; + } + + rTarget.push_back(Primitive2DReference( + new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + aStrikeoutString, + 0, + aStrikeoutString.Len(), + aDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); + } + else + { + // strikeout with geometry + double fStrikeoutHeight(aTextLayouter.getUnderlineHeight()); + double fStrikeoutOffset(aTextLayouter.getStrikeoutOffset()); + bool bDoubleLine(false); + + // set line attribute + switch(getFontStrikeout()) + { + default : // case primitive2d::FONT_STRIKEOUT_SINGLE: + { + break; + } + case primitive2d::FONT_STRIKEOUT_DOUBLE: + { + bDoubleLine = true; + break; + } + case primitive2d::FONT_STRIKEOUT_BOLD: + { + fStrikeoutHeight *= 2.0; + break; + } + } + + if(bDoubleLine) + { + fStrikeoutOffset -= 0.50 * fStrikeoutHeight; + fStrikeoutHeight *= 0.64; + } + + // create base polygon and new primitive + basegfx::B2DPolygon aStrikeoutLine; + + aStrikeoutLine.append(basegfx::B2DPoint(0.0, -fStrikeoutOffset)); + aStrikeoutLine.append(basegfx::B2DPoint(fTextWidth, -fStrikeoutOffset)); + aStrikeoutLine.transform(aUnscaledTransform); + + const attribute::LineAttribute aLineAttribute(getFontColor(), fStrikeoutHeight, basegfx::B2DLINEJOIN_NONE); + Primitive2DReference aNewPrimitive(new PolygonStrokePrimitive2D(aStrikeoutLine, aLineAttribute)); + + // add primitive + rTarget.push_back(aNewPrimitive); + + if(bDoubleLine) + { + // double line, create 2nd primitive with offset using TransformPrimitive based on + // already created NewPrimitive + const double fLineDist(2.0 * fStrikeoutHeight); + basegfx::B2DHomMatrix aTransform; + + // move base point of text to 0.0 and de-rotate + aTransform.translate(-rDecTrans.getTranslate().getX(), -rDecTrans.getTranslate().getY()); + aTransform.rotate(-rDecTrans.getRotate()); + + // translate in Y by offset + aTransform.translate(0.0, -fLineDist); + + // move back and rotate + aTransform.rotate(rDecTrans.getRotate()); + aTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); + + // add transform primitive + const Primitive2DSequence aContent(&aNewPrimitive, 1); + rTarget.push_back(Primitive2DReference(new TransformPrimitive2D(aTransform, aContent))); + } + } + } + } + + // TODO: Handle Font Emphasis Above/Below + } + + void TextDecoratedPortionPrimitive2D::impCorrectTextBoundary(::com::sun::star::i18n::Boundary& rNextWordBoundary) const + { + // truncate aNextWordBoundary to min/max possible values. This is necessary since the word start may be + // before/after getTextPosition() when a long string is the content and getTextPosition() + // is right inside a word. Same for end. + const sal_Int32 aMinPos(static_cast< sal_Int32 >(getTextPosition())); + const sal_Int32 aMaxPos(aMinPos + static_cast< sal_Int32 >(getTextLength())); + + if(rNextWordBoundary.startPos < aMinPos) + { + rNextWordBoundary.startPos = aMinPos; + } + else if(rNextWordBoundary.startPos > aMaxPos) + { + rNextWordBoundary.startPos = aMaxPos; + } + + if(rNextWordBoundary.endPos < aMinPos) + { + rNextWordBoundary.endPos = aMinPos; + } + else if(rNextWordBoundary.endPos > aMaxPos) + { + rNextWordBoundary.endPos = aMaxPos; + } + } + + void TextDecoratedPortionPrimitive2D::impSplitSingleWords( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans) const + { + // break iterator support + // made static so it only needs to be fetched once, even with many single + // constructed VclMetafileProcessor2D. It's still incarnated on demand, + // but exists for OOo runtime now by purpose. + static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xLocalBreakIterator; + + if(!xLocalBreakIterator.is()) + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); + xLocalBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY); + } + + if(xLocalBreakIterator.is() && getTextLength()) + { + // init word iterator, get first word and truncate to possibilities + ::com::sun::star::i18n::Boundary aNextWordBoundary(xLocalBreakIterator->getWordBoundary( + getText(), getTextPosition(), getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True)); + + if(aNextWordBoundary.endPos == getTextPosition()) + { + // backward hit, force next word + aNextWordBoundary = xLocalBreakIterator->getWordBoundary( + getText(), getTextPosition() + 1, getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); + } + + impCorrectTextBoundary(aNextWordBoundary); + + // prepare new font attributes WITHOUT outline + const FontAttributes aNewFontAttributes( + getFontAttributes().getFamilyName(), + getFontAttributes().getStyleName(), + getFontAttributes().getWeight(), + getFontAttributes().getSymbol(), + getFontAttributes().getVertical(), + getFontAttributes().getItalic(), + false, // no outline anymore, handled locally + getFontAttributes().getRTL(), + getFontAttributes().getBiDiStrong()); + + if(aNextWordBoundary.startPos == getTextPosition() && aNextWordBoundary.endPos == getTextLength()) + { + // it IS only a single word, handle as one word + impCreateGeometryContent(rTarget, rDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttributes); + } + else + { + // prepare TextLayouter + const bool bNoDXArray(getDXArray().empty()); + TextLayouterDevice aTextLayouter; + + if(bNoDXArray) + { + // ..but only completely when no DXArray + aTextLayouter.setFontAttributes( + getFontAttributes(), + rDecTrans.getScale().getX(), + rDecTrans.getScale().getY(), + getLocale()); + } + + // do iterate over single words + while(aNextWordBoundary.startPos != aNextWordBoundary.endPos) + { + // prepare values for new portion + const xub_StrLen nNewTextStart(static_cast< xub_StrLen >(aNextWordBoundary.startPos)); + const xub_StrLen nNewTextEnd(static_cast< xub_StrLen >(aNextWordBoundary.endPos)); + + // prepare transform for the single word + basegfx::B2DHomMatrix aNewTransform; + ::std::vector< double > aNewDXArray; + const bool bNewStartIsNotOldStart(nNewTextStart > getTextPosition()); + + if(!bNoDXArray) + { + // prepare new DXArray for the single word + aNewDXArray = ::std::vector< double >( + getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextStart - getTextPosition()), + getDXArray().begin() + static_cast< sal_uInt32 >(nNewTextEnd - getTextPosition())); + } + + if(bNewStartIsNotOldStart) + { + // needs to be moved to a new start position + double fOffset(0.0); + + if(bNoDXArray) + { + // evaluate using TextLayouter + fOffset = aTextLayouter.getTextWidth(getText(), getTextPosition(), nNewTextStart); + } + else + { + // get from DXArray + const sal_uInt32 nIndex(static_cast< sal_uInt32 >(nNewTextStart - getTextPosition())); + fOffset = getDXArray()[nIndex - 1]; + } + + // need offset without FontScale for building the new transformation. The + // new transformation will be multiplied with the current text transformation + // so FontScale would be double + double fOffsetNoScale(fOffset); + const double fFontScaleX(rDecTrans.getScale().getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + fOffsetNoScale /= fFontScaleX; + } + + // apply needed offset to transformation + aNewTransform.translate(fOffsetNoScale, 0.0); + + if(!bNoDXArray) + { + // DXArray values need to be corrected with the offset, too. Here, + // take the scaled offset since the DXArray is scaled + const sal_uInt32 nArraySize(aNewDXArray.size()); + + for(sal_uInt32 a(0); a < nArraySize; a++) + { + aNewDXArray[a] -= fOffset; + } + } + } + + // add text transformation to new transformation + aNewTransform *= rDecTrans.getB2DHomMatrix(); + + // create geometry content for the single word. Do not forget + // to use the new transformation + basegfx::DecomposedB2DHomMatrixContainer aDecTrans(aNewTransform); + + impCreateGeometryContent(rTarget, aDecTrans, getText(), nNewTextStart, + nNewTextEnd - nNewTextStart, aNewDXArray, aNewFontAttributes); + + if(aNextWordBoundary.endPos >= getTextPosition() + getTextLength()) + { + // end reached + aNextWordBoundary.startPos = aNextWordBoundary.endPos; + } + else + { + // get new word portion + const sal_Int32 nLastEndPos(aNextWordBoundary.endPos); + + aNextWordBoundary = xLocalBreakIterator->getWordBoundary( + getText(), aNextWordBoundary.endPos, getLocale(), + ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); + + if(nLastEndPos == aNextWordBoundary.endPos) + { + // backward hit, force next word + aNextWordBoundary = xLocalBreakIterator->getWordBoundary( + getText(), nLastEndPos + 1, getLocale(), + ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); + } + + impCorrectTextBoundary(aNextWordBoundary); + } + } + } + } + } + + Primitive2DSequence TextDecoratedPortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + std::vector< Primitive2DReference > aNewPrimitives; + basegfx::DecomposedB2DHomMatrixContainer aDecTrans(getTextTransform()); + Primitive2DSequence aRetval; + + // create basic geometry such as SimpleTextPrimitive, Overline, Underline, + // Strikeout, etc... + if(getWordLineMode()) + { + // support for single word mode + impSplitSingleWords(aNewPrimitives, aDecTrans); + } + else + { + // prepare new font attributes WITHOUT outline + const FontAttributes aNewFontAttributes( + getFontAttributes().getFamilyName(), + getFontAttributes().getStyleName(), + getFontAttributes().getWeight(), + getFontAttributes().getSymbol(), + getFontAttributes().getVertical(), + getFontAttributes().getItalic(), + false, // no outline anymore, handled locally + getFontAttributes().getRTL(), + getFontAttributes().getBiDiStrong()); + + // handle as one word + impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttributes); + } + + // convert to Primitive2DSequence + const sal_uInt32 nMemberCount(aNewPrimitives.size()); + + if(nMemberCount) + { + aRetval.realloc(nMemberCount); + + for(sal_uInt32 a(0); a < nMemberCount; a++) + { + aRetval[a] = aNewPrimitives[a]; + } + } + + // Handle Shadow, Outline and FontRelief + if(aRetval.hasElements()) + { + // outline AND shadow depend on NO FontRelief (see dialog) + const bool bHasFontRelief(FONT_RELIEF_NONE != getFontRelief()); + const bool bHasShadow(!bHasFontRelief && getShadow()); + const bool bHasOutline(!bHasFontRelief && getFontAttributes().getOutline()); + + if(bHasShadow || bHasFontRelief || bHasOutline) + { + Primitive2DReference aShadow; + + if(bHasShadow) + { + // create shadow with current content (in aRetval). Text shadow + // is constant, relative to font size, rotated with the text and has a + // constant color. + // shadow parameter values + static double fFactor(1.0 / 24.0); + const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor); + static basegfx::BColor aShadowColor(0.3, 0.3, 0.3); + + // preapare shadow transform matrix + basegfx::B2DHomMatrix aShadowTransform; + aShadowTransform.translate(fTextShadowOffset, fTextShadowOffset); + + // create shadow primitive + aShadow = Primitive2DReference(new ShadowPrimitive2D( + aShadowTransform, + aShadowColor, + aRetval)); + } + + if(bHasFontRelief) + { + // create emboss using an own helper primitive since this will + // be view-dependent + const basegfx::BColor aBBlack(0.0, 0.0, 0.0); + const bool bDefaultTextColor(aBBlack == getFontColor()); + TextEffectStyle2D aTextEffectStyle2D(TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED); + + if(bDefaultTextColor) + { + if(FONT_RELIEF_ENGRAVED == getFontRelief()) + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT; + } + else + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT; + } + } + else + { + if(FONT_RELIEF_ENGRAVED == getFontRelief()) + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED; + } + else + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED; + } + } + + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aDecTrans.getTranslate(), + aDecTrans.getRotate(), + aTextEffectStyle2D)); + aRetval = Primitive2DSequence(&aNewTextEffect, 1); + } + else if(bHasOutline) + { + // create outline using an own helper primitive since this will + // be view-dependent + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aDecTrans.getTranslate(), + aDecTrans.getRotate(), + TEXTEFFECTSTYLE2D_OUTLINE)); + aRetval = Primitive2DSequence(&aNewTextEffect, 1); + } + + if(aShadow.is()) + { + // put shadow in front if there is one to paint timely before + // but placed behind content + const Primitive2DSequence aContent(aRetval); + aRetval = Primitive2DSequence(&aShadow, 1); + appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aContent); + } + } + } + + return aRetval; + } + + TextDecoratedPortionPrimitive2D::TextDecoratedPortionPrimitive2D( + + // TextSimplePortionPrimitive2D parameters + const basegfx::B2DHomMatrix& rNewTransform, + const String& rText, + xub_StrLen aTextPosition, + xub_StrLen aTextLength, + const ::std::vector< double >& rDXArray, + const FontAttributes& rFontAttributes, + const ::com::sun::star::lang::Locale& rLocale, + const basegfx::BColor& rFontColor, + + // local parameters + const basegfx::BColor& rOverlineColor, + const basegfx::BColor& rTextlineColor, + FontUnderline eFontOverline, + FontUnderline eFontUnderline, + bool bUnderlineAbove, + FontStrikeout eFontStrikeout, + bool bWordLineMode, + FontEmphasisMark eFontEmphasisMark, + bool bEmphasisMarkAbove, + bool bEmphasisMarkBelow, + FontRelief eFontRelief, + bool bShadow) + : TextSimplePortionPrimitive2D(rNewTransform, rText, aTextPosition, aTextLength, rDXArray, rFontAttributes, rLocale, rFontColor), + maOverlineColor(rOverlineColor), + maTextlineColor(rTextlineColor), + meFontOverline(eFontOverline), + meFontUnderline(eFontUnderline), + meFontStrikeout(eFontStrikeout), + meFontEmphasisMark(eFontEmphasisMark), + meFontRelief(eFontRelief), + mbUnderlineAbove(bUnderlineAbove), + mbWordLineMode(bWordLineMode), + mbEmphasisMarkAbove(bEmphasisMarkAbove), + mbEmphasisMarkBelow(bEmphasisMarkBelow), + mbShadow(bShadow) + { + } + + bool TextDecoratedPortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(TextSimplePortionPrimitive2D::operator==(rPrimitive)) + { + const TextDecoratedPortionPrimitive2D& rCompare = (TextDecoratedPortionPrimitive2D&)rPrimitive; + + return (getOverlineColor() == rCompare.getOverlineColor() + && getTextlineColor() == rCompare.getTextlineColor() + && getFontOverline() == rCompare.getFontOverline() + && getFontUnderline() == rCompare.getFontUnderline() + && getFontStrikeout() == rCompare.getFontStrikeout() + && getFontEmphasisMark() == rCompare.getFontEmphasisMark() + && getFontRelief() == rCompare.getFontRelief() + && getUnderlineAbove() == rCompare.getUnderlineAbove() + && getWordLineMode() == rCompare.getWordLineMode() + && getEmphasisMarkAbove() == rCompare.getEmphasisMarkAbove() + && getEmphasisMarkBelow() == rCompare.getEmphasisMarkBelow() + && getShadow() == rCompare.getShadow()); + } + + return false; + } + + // #i96475# + // Added missing implementation. Decorations may (will) stick out of the text's + // inking area, so add them if needed + basegfx::B2DRange TextDecoratedPortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + const bool bDecoratedIsNeeded( + FONT_UNDERLINE_NONE != getFontOverline() + || FONT_UNDERLINE_NONE != getFontUnderline() + || FONT_STRIKEOUT_NONE != getFontStrikeout() + || FONT_EMPHASISMARK_NONE != getFontEmphasisMark() + || FONT_RELIEF_NONE != getFontRelief() + || getShadow()); + + if(bDecoratedIsNeeded) + { + // decoration is used, fallback to BasePrimitive2D::getB2DRange which uses + // the own local decomposition for computation and thus creates all necessary + // geometric objects + return BasePrimitive2D::getB2DRange(rViewInformation); + } + else + { + // no relevant decoration used, fallback to TextSimplePortionPrimitive2D::getB2DRange + return TextSimplePortionPrimitive2D::getB2DRange(rViewInformation); + } + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextDecoratedPortionPrimitive2D, PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx new file mode 100644 index 000000000000..c1963f4ba2a4 --- /dev/null +++ b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texteffectprimitive2d.cxx,v $ + * + * $Revision: 1.4 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $ + * + * 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/primitive2d/texteffectprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + static double fDiscreteSize(1.1); + + Primitive2DSequence TextEffectPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to + // have good results on rotated objects, too + const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(fDiscreteSize, fDiscreteSize)); + const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44)); + + switch(getTextEffectStyle2D()) + { + case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED: + case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED: + case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT: + case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT: + { + // prepare transform of sub-group back to (0,0) and align to X-Axis + basegfx::B2DHomMatrix aBackTransform; + aBackTransform.translate(-getRotationCenter().getX(), -getRotationCenter().getY()); + aBackTransform.rotate(-getDirection()); + + // prepare transform of sub-group back to it's position and rotation + basegfx::B2DHomMatrix aForwardTransform; + aForwardTransform.rotate(getDirection()); + aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY()); + + // create transformation for one discrete unit + const bool bEmbossed( + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED == getTextEffectStyle2D() + || TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D()); + const bool bDefaultTextColor( + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D() + || TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT == getTextEffectStyle2D()); + basegfx::B2DHomMatrix aTransform(aBackTransform); + aRetval.realloc(2); + + if(bEmbossed) + { + // to bottom-right + aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY()); + } + else + { + // to top-left + aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY()); + } + + aTransform *= aForwardTransform; + + if(bDefaultTextColor) + { + // emboss/engrave in black, original forced to white + const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.0)); + const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToGray)); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1))); + + // add original, too + const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0)); + aRetval[1] = Primitive2DReference(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToWhite)); + } + else + { + // emboss/engrave in gray, keep original's color + const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.75)); // 192 + const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToGray)); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1))); + + // add original, too + aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getChildren())); + } + + break; + } + case TEXTEFFECTSTYLE2D_OUTLINE: + { + // create transform primitives in all directions + basegfx::B2DHomMatrix aTransform; + aRetval.realloc(9); + + aTransform.set(0, 2, aDistance.getX()); + aTransform.set(1, 2, 0.0); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, aDiagonalDistance.getX()); + aTransform.set(1, 2, aDiagonalDistance.getY()); + aRetval[1] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, 0.0); + aTransform.set(1, 2, aDistance.getY()); + aRetval[2] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDiagonalDistance.getX()); + aTransform.set(1, 2, aDiagonalDistance.getY()); + aRetval[3] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDistance.getX()); + aTransform.set(1, 2, 0.0); + aRetval[4] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDiagonalDistance.getX()); + aTransform.set(1, 2, -aDiagonalDistance.getY()); + aRetval[5] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, 0.0); + aTransform.set(1, 2, -aDistance.getY()); + aRetval[6] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, aDiagonalDistance.getX()); + aTransform.set(1, 2, -aDiagonalDistance.getY()); + aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + // at last, place original over it, but force to white + const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0, 1.0, 1.0)); + aRetval[8] = Primitive2DReference(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToWhite)); + + break; + } + } + + return aRetval; + } + + TextEffectPrimitive2D::TextEffectPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::B2DPoint& rRotationCenter, + double fDirection, + TextEffectStyle2D eTextEffectStyle2D) + : GroupPrimitive2D(rChildren), + maRotationCenter(rRotationCenter), + mfDirection(fDirection), + meTextEffectStyle2D(eTextEffectStyle2D) + { + } + + bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const TextEffectPrimitive2D& rCompare = (TextEffectPrimitive2D&)rPrimitive; + + return (getRotationCenter() == rCompare.getRotationCenter() + && getDirection() == rCompare.getDirection() + && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D()); + } + + return false; + } + + basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask + // the whole decomposition for it's ranges (which may be expensive with outline mode which + // then will ask 9 times at nearly the same content. This may even be refined here using the + // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to + // be in two directions + basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + aRetval.grow(fDiscreteSize); + + return aRetval; + } + + Primitive2DSequence TextEffectPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements()) + { + if(maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation()) + { + // conditions of last local decomposition have changed, delete + const_cast< TextEffectPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewRange and ViewTransformation + const_cast< TextEffectPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx new file mode 100644 index 000000000000..72249e673c1b --- /dev/null +++ b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texthierarchyprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/texthierarchyprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyLinePrimitive2D::TextHierarchyLinePrimitive2D(const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyLinePrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyParagraphPrimitive2D::TextHierarchyParagraphPrimitive2D(const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyParagraphPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyBulletPrimitive2D::TextHierarchyBulletPrimitive2D(const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyBulletPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyBlockPrimitive2D::TextHierarchyBlockPrimitive2D(const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyBlockPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyFieldPrimitive2D::TextHierarchyFieldPrimitive2D( + const Primitive2DSequence& rChildren, + const FieldType& rFieldType, + const rtl::OUString& rString) + : GroupPrimitive2D(rChildren), + meType(rFieldType), + maString(rString) + { + } + + bool TextHierarchyFieldPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const TextHierarchyFieldPrimitive2D& rCompare = (TextHierarchyFieldPrimitive2D&)rPrimitive; + + return (getType() == rCompare.getType() + && getString() == rCompare.getString()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyFieldPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D) + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TextHierarchyEditPrimitive2D::TextHierarchyEditPrimitive2D(const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextHierarchyEditPrimitive2D, PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx new file mode 100644 index 000000000000..e321783c8406 --- /dev/null +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -0,0 +1,430 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textlayoutdevice.cxx,v $ + * + * $Revision: 1.10 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/textlayoutdevice.hxx> +#include <vcl/timer.hxx> +#include <vcl/virdev.hxx> +#include <vcl/font.hxx> +#include <vcl/metric.hxx> +#include <i18npool/mslangid.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <vcl/svapp.hxx> + +////////////////////////////////////////////////////////////////////////////// +// VDev RevDevice provider + +namespace +{ + class ImpTimedRefDev : public Timer + { + ImpTimedRefDev** mppStaticPointerOnMe; + VirtualDevice* mpVirDev; + sal_uInt32 mnUseCount; + + public: + ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe); + ~ImpTimedRefDev(); + virtual void Timeout(); + + VirtualDevice& acquireVirtualDevice(); + void releaseVirtualDevice(); + }; + + ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe) + : mppStaticPointerOnMe(ppStaticPointerOnMe), + mpVirDev(0L), + mnUseCount(0L) + { + SetTimeout(3L * 60L * 1000L); // three minutes + Start(); + } + + ImpTimedRefDev::~ImpTimedRefDev() + { + OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)"); + + if(mppStaticPointerOnMe && *mppStaticPointerOnMe) + { + *mppStaticPointerOnMe = 0L; + } + + if(mpVirDev) + { + delete mpVirDev; + } + } + + void ImpTimedRefDev::Timeout() + { + // for obvious reasons, do not call anything after this + delete (this); + } + + VirtualDevice& ImpTimedRefDev::acquireVirtualDevice() + { + if(!mpVirDev) + { + mpVirDev = new VirtualDevice(); + mpVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 ); + } + + if(!mnUseCount) + { + Stop(); + } + + mnUseCount++; + + return *mpVirDev; + } + + void ImpTimedRefDev::releaseVirtualDevice() + { + OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)"); + mnUseCount--; + + if(!mnUseCount) + { + Start(); + } + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// +// access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive + +namespace drawinglayer +{ + namespace primitive2d + { + // static pointer here + static ImpTimedRefDev* pImpGlobalRefDev = 0L; + + // static methods here + VirtualDevice& acquireGlobalVirtualDevice() + { + if(!pImpGlobalRefDev) + { + pImpGlobalRefDev = new ImpTimedRefDev(&pImpGlobalRefDev); + } + + return pImpGlobalRefDev->acquireVirtualDevice(); + } + + void releaseGlobalVirtualDevice() + { + OSL_ENSURE(pImpGlobalRefDev, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)"); + pImpGlobalRefDev->releaseVirtualDevice(); + } + + TextLayouterDevice::TextLayouterDevice() + : mrDevice(acquireGlobalVirtualDevice()) + { + } + + TextLayouterDevice::~TextLayouterDevice() + { + releaseGlobalVirtualDevice(); + } + + void TextLayouterDevice::setFont(const Font& rFont) + { + mrDevice.SetFont( rFont ); + } + + void TextLayouterDevice::setFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + const ::com::sun::star::lang::Locale& rLocale) + { + setFont(getVclFontFromFontAttributes( + rFontAttributes, + fFontScaleX, + fFontScaleY, + 0.0, + rLocale)); + } + + double TextLayouterDevice::getOverlineOffset() const + { + const ::FontMetric& rMetric = mrDevice.GetFontMetric(); + double fRet = (rMetric.GetIntLeading() / 2.0) - rMetric.GetAscent(); + return fRet; + } + + double TextLayouterDevice::getUnderlineOffset() const + { + const ::FontMetric& rMetric = mrDevice.GetFontMetric(); + double fRet = rMetric.GetDescent() / 2.0; + return fRet; + } + + double TextLayouterDevice::getStrikeoutOffset() const + { + const ::FontMetric& rMetric = mrDevice.GetFontMetric(); + double fRet = (rMetric.GetAscent() - rMetric.GetIntLeading()) / 3.0; + return fRet; + } + + double TextLayouterDevice::getOverlineHeight() const + { + const ::FontMetric& rMetric = mrDevice.GetFontMetric(); + double fRet = rMetric.GetIntLeading() / 2.5; + return fRet; + } + + double TextLayouterDevice::getUnderlineHeight() const + { + const ::FontMetric& rMetric = mrDevice.GetFontMetric(); + double fRet = rMetric.GetDescent() / 4.0; + return fRet; + } + + double TextLayouterDevice::getTextHeight() const + { + return mrDevice.GetTextHeight(); + } + + double TextLayouterDevice::getTextWidth( + const String& rText, + xub_StrLen nIndex, + xub_StrLen nLength) const + { + return mrDevice.GetTextWidth(rText, nIndex, nLength); + } + + bool TextLayouterDevice::getTextOutlines( + basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, + const String& rText, + xub_StrLen nIndex, + xub_StrLen nLength, + const ::std::vector< double >& rDXArray) + { + const sal_uInt32 nDXArrayCount(rDXArray.size()); + + if(nDXArrayCount) + { + OSL_ENSURE(nDXArrayCount == nLength, "DXArray size does not correspond to text portion size (!)"); + std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount); + + for(sal_uInt32 a(0); a < nDXArrayCount; a++) + { + aIntegerDXArray[a] = basegfx::fround(rDXArray[a]); + } + + return mrDevice.GetTextOutlines( + rB2DPolyPolyVector, + rText, + nIndex, + nIndex, + nLength, + true, + 0, + &(aIntegerDXArray[0])); + } + else + { + return mrDevice.GetTextOutlines( + rB2DPolyPolyVector, + rText, + nIndex, + nIndex, + nLength, + true, + 0, + 0); + } + } + + basegfx::B2DRange TextLayouterDevice::getTextBoundRect( + const String& rText, + xub_StrLen nIndex, + xub_StrLen nLength) const + { + if(nLength) + { + Rectangle aRect; + + mrDevice.GetTextBoundRect( + aRect, + rText, + nIndex, + nIndex, + nLength); + + // #i104432#, #i102556# take empty results into account + if(!aRect.IsEmpty()) + { + return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); + } + } + + return basegfx::B2DRange(); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// helper methods for vcl font handling + +namespace drawinglayer +{ + namespace primitive2d + { + Font getVclFontFromFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + double fFontRotation, + const ::com::sun::star::lang::Locale& rLocale) + { + // detect FontScaling + const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY))); + const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); + const bool bFontIsScaled(nHeight != nWidth); + +#ifdef WIN32 + // for WIN32 systems, start with creating an unscaled font. If FontScaling + // is wanted, that width needs to be adapted using FontMetric again to get a + // width of the unscaled font + Font aRetval( + rFontAttributes.getFamilyName(), + rFontAttributes.getStyleName(), + Size(0, nHeight)); +#else + // for non-WIN32 systems things are easier since these accept a Font creation + // with initially nWidth != nHeight for FontScaling. Despite that, use zero for + // FontWidth when no scaling is used to explicitely have that zero when e.g. the + // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a + // set FontWidth; import that in a WIN32 system, and trouble is there) + Font aRetval( + rFontAttributes.getFamilyName(), + rFontAttributes.getStyleName(), + Size(bFontIsScaled ? nWidth : 0, nHeight)); +#endif + // define various other FontAttributes + aRetval.SetAlign(ALIGN_BASELINE); + aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); + aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE); + aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.getWeight())); + aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE); + aRetval.SetOutline(rFontAttributes.getOutline()); + aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale)); + +#ifdef WIN32 + // for WIN32 systems, correct the FontWidth if FontScaling is used + if(bFontIsScaled && nHeight > 0) + { + const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval)); + + if(aUnscaledFontMetric.GetWidth() > 0) + { + const double fScaleFactor((double)nWidth / (double)nHeight); + const sal_uInt32 nScaledWidth(basegfx::fround((double)aUnscaledFontMetric.GetWidth() * fScaleFactor)); + aRetval.SetWidth(nScaledWidth); + } + } +#endif + // handle FontRotation (if defined) + if(!basegfx::fTools::equalZero(fFontRotation)) + { + sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI))); + aRetval.SetOrientation(aRotate10th % 3600); + } + + return aRetval; + } + + FontAttributes getFontAttributesFromVclFont( + basegfx::B2DVector& o_rSize, + const Font& rFont, + bool bRTL, + bool bBiDiStrong) + { + const FontAttributes aRetval( + rFont.GetName(), + rFont.GetStyleName(), + static_cast<sal_uInt16>(rFont.GetWeight()), + RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), + rFont.IsVertical(), + ITALIC_NONE != rFont.GetItalic(), + rFont.IsOutline(), + bRTL, + bBiDiStrong); + // TODO: eKerning + + // set FontHeight and init to no FontScaling + o_rSize.setY(rFont.GetSize().getHeight() > 0 ? rFont.GetSize().getHeight() : 0); + o_rSize.setX(o_rSize.getY()); + +#ifdef WIN32 + // for WIN32 systems, the FontScaling at the Font is detected by + // checking that FontWidth != 0. When FontScaling is used, WIN32 + // needs to do extra stuff to detect the correct width (since it's + // zero and not equal the font height) and it's relationship to + // the height + if(rFont.GetSize().getWidth() > 0) + { + Font aUnscaledFont(rFont); + aUnscaledFont.SetWidth(0); + const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont)); + + if(aUnscaledFontMetric.GetWidth() > 0) + { + const double fScaleFactor((double)rFont.GetSize().getWidth() / (double)aUnscaledFontMetric.GetWidth()); + o_rSize.setX(fScaleFactor * o_rSize.getY()); + } + } +#else + // For non-WIN32 systems the detection is the same, but the value + // is easier achieved since width == height is interpreted as no + // scaling. Ergo, Width == 0 means width == height, and width != 0 + // means the scaling is in the direct relation of width to height + if(rFont.GetSize().getWidth() > 0) + { + o_rSize.setX((double)rFont.GetSize().getWidth()); + } +#endif + return aRetval; + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx new file mode 100644 index 000000000000..f8e413da0e8c --- /dev/null +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -0,0 +1,374 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textprimitive2d.cxx,v $ + * + * $Revision: 1.22 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + bool FontAttributes::operator==(const FontAttributes& rCompare) const + { + return (getFamilyName() == rCompare.getFamilyName() + && getStyleName() == rCompare.getStyleName() + && getWeight() == rCompare.getWeight() + && getSymbol() == rCompare.getSymbol() + && getVertical() == rCompare.getVertical() + && getItalic() == rCompare.getItalic() + && getOutline() == rCompare.getOutline() + && getRTL() == rCompare.getRTL() + && getBiDiStrong() == rCompare.getBiDiStrong()); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted + // scale from a text transformation. A copy is modified so that it contains only positive + // scalings and XY-equal scalings to allow to get a non-X-scaled Vcl-Font for TextLayouter. + // rScale is adapted accordingly to contain the corrected scale which would need to be + // applied to e.g. outlines received from TextLayouter under usage of fontScale. This + // includes Y-Scale, X-Scale-correction and mirrorings. + basegfx::B2DVector getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale) + { + // copy input value + basegfx::B2DVector aFontScale(rScale); + + // correct FontHeight settings + if(basegfx::fTools::equalZero(aFontScale.getY())) + { + // no font height; choose one and adapt scale to get back to original scaling + static double fDefaultFontScale(100.0); + rScale.setY(1.0 / fDefaultFontScale); + aFontScale.setY(fDefaultFontScale); + } + else if(basegfx::fTools::less(aFontScale.getY(), 0.0)) + { + // negative font height; invert and adapt scale to get back to original scaling + aFontScale.setY(-aFontScale.getY()); + rScale.setY(-1.0); + } + else + { + // positive font height; adapt scale; scaling will be part of the polygons + rScale.setY(1.0); + } + + // correct FontWidth settings + if(basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY())) + { + // no FontScale, adapt scale + rScale.setX(1.0); + } + else + { + // If FontScale is used, force to no FontScale to get a non-scaled VCL font. + // Adapt scaling in X accordingly. + rScale.setX(aFontScale.getX() / aFontScale.getY()); + aFontScale.setX(aFontScale.getY()); + } + + return aFontScale; + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const + { + if(getTextLength()) + { + // decompose object transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + // if decomposition returns false, create no geometry since e.g. scaling may + // be zero + if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + { + // handle special case: If scale is negative in (x,y) (3rd quadrant), it can + // be expressed as rotation by PI + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale = basegfx::absolute(aScale); + fRotate += F_PI; + } + + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes( + getFontAttributes(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); + + // When getting outlines from stretched text (aScale.getX() != 1.0) it + // is necessary to inverse-scale the DXArray (if used) to not get the + // outlines already aligned to given, but wrong DXArray + if(getDXArray().size() && !basegfx::fTools::equal(aScale.getX(), 1.0)) + { + ::std::vector< double > aScaledDXArray = getDXArray(); + const double fDXArrayScale(1.0 / aScale.getX()); + + for(sal_uInt32 a(0); a < aScaledDXArray.size(); a++) + { + aScaledDXArray[a] *= fDXArrayScale; + } + + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + aScaledDXArray); + } + else + { + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + getDXArray()); + } + + // create primitives for the outlines + const sal_uInt32 nCount(rTarget.size()); + + if(nCount) + { + // prepare object transformation for polygons + rTransformation.identity(); + rTransformation.scale(aScale.getX(), aScale.getY()); + rTransformation.shearX(fShearX); + rTransformation.rotate(fRotate); + rTransformation.translate(aTranslate.getX(), aTranslate.getY()); + } + } + } + } + + Primitive2DSequence TextSimplePortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence aRetval; + + if(getTextLength()) + { + basegfx::B2DPolyPolygonVector aB2DPolyPolyVector; + basegfx::B2DHomMatrix aPolygonTransform; + + // get text outlines and their object transformation + getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform); + + // create primitives for the outlines + const sal_uInt32 nCount(aB2DPolyPolyVector.size()); + + if(nCount) + { + // alloc space for the primitives + aRetval.realloc(nCount); + + // color-filled polypolygons + for(sal_uInt32 a(0L); a < nCount; a++) + { + // prepare polypolygon + basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a]; + rPolyPolygon.transform(aPolygonTransform); + aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor()); + } + + if(getFontAttributes().getOutline()) + { + // decompose polygon transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aPolygonTransform.decompose(aScale, aTranslate, fRotate, fShearX); + + // create outline text effect with current content and replace + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aTranslate, + fRotate, + TEXTEFFECTSTYLE2D_OUTLINE)); + + aRetval = Primitive2DSequence(&aNewTextEffect, 1); + } + } + } + + return aRetval; + } + + TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D( + const basegfx::B2DHomMatrix& rNewTransform, + const String& rText, + xub_StrLen aTextPosition, + xub_StrLen aTextLength, + const ::std::vector< double >& rDXArray, + const FontAttributes& rFontAttributes, + const ::com::sun::star::lang::Locale& rLocale, + const basegfx::BColor& rFontColor) + : BasePrimitive2D(), + maTextTransform(rNewTransform), + maText(rText), + maTextPosition(aTextPosition), + maTextLength(aTextLength), + maDXArray(rDXArray), + maFontAttributes(rFontAttributes), + maLocale(rLocale), + maFontColor(rFontColor), + maB2DRange() + { +#ifdef DBG_UTIL + const xub_StrLen aStringLength(getText().Len()); + OSL_ENSURE(aStringLength >= getTextPosition() && aStringLength >= getTextPosition() + getTextLength(), + "TextSimplePortionPrimitive2D with text out of range (!)"); +#endif + } + + bool impLocalesAreEqual(const ::com::sun::star::lang::Locale& rA, const ::com::sun::star::lang::Locale& rB) + { + return (rA.Language == rB.Language + && rA.Country == rB.Country + && rA.Variant == rB.Variant); + } + + bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const TextSimplePortionPrimitive2D& rCompare = (TextSimplePortionPrimitive2D&)rPrimitive; + + return (getTextTransform() == rCompare.getTextTransform() + && getText() == rCompare.getText() + && getTextPosition() == rCompare.getTextPosition() + && getTextLength() == rCompare.getTextLength() + && getDXArray() == rCompare.getDXArray() + && getFontAttributes() == rCompare.getFontAttributes() + && impLocalesAreEqual(getLocale(), rCompare.getLocale()) + && getFontColor() == rCompare.getFontColor()); + } + + return false; + } + + basegfx::B2DRange TextSimplePortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + if(maB2DRange.isEmpty() && getTextLength()) + { + // get TextBoundRect as base size + // decompose object transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + { + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes( + getFontAttributes(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); + + // get basic text range + basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength())); + + // #i104432#, #i102556# take empty results into account + if(!aNewRange.isEmpty()) + { + // prepare object transformation for range + basegfx::B2DHomMatrix aRangeTransformation; + + aRangeTransformation.scale(aScale.getX(), aScale.getY()); + aRangeTransformation.shearX(fShearX); + aRangeTransformation.rotate(fRotate); + aRangeTransformation.translate(aTranslate.getX(), aTranslate.getY()); + + // apply range transformation to it + aNewRange.transform(aRangeTransformation); + + // assign to buffered value + const_cast< TextSimplePortionPrimitive2D* >(this)->maB2DRange = aNewRange; + } + } + } + + return maB2DRange; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextSimplePortionPrimitive2D, PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/transformprimitive2d.cxx b/drawinglayer/source/primitive2d/transformprimitive2d.cxx new file mode 100644 index 000000000000..7fe8293df854 --- /dev/null +++ b/drawinglayer/source/primitive2d/transformprimitive2d.cxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: transformprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/transformprimitive2d.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + TransformPrimitive2D::TransformPrimitive2D( + const basegfx::B2DHomMatrix& rTransformation, + const Primitive2DSequence& rChildren) + : GroupPrimitive2D(rChildren), + maTransformation(rTransformation) + { + } + + bool TransformPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const TransformPrimitive2D& rCompare = static_cast< const TransformPrimitive2D& >(rPrimitive); + + return (getTransformation() == rCompare.getTransformation()); + } + + return false; + } + + basegfx::B2DRange TransformPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + aRetval.transform(getTransformation()); + return aRetval; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TransformPrimitive2D, PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/unifiedalphaprimitive2d.cxx b/drawinglayer/source/primitive2d/unifiedalphaprimitive2d.cxx new file mode 100644 index 000000000000..49039e1a6e5c --- /dev/null +++ b/drawinglayer/source/primitive2d/unifiedalphaprimitive2d.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unifiedalphaprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/unifiedalphaprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/color/bcolor.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/alphaprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence UnifiedAlphaPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + if(0.0 == getAlpha()) + { + // no transparence used, so just use the content + return getChildren(); + } + else if(getAlpha() > 0.0 && getAlpha() < 1.0) + { + // The idea is to create a AlphaPrimitive2D with alpha content using a fill color + // corresponding to the alpha value. Problem is that in most systems, the right + // and bottom pixel array is not filled when filling polygons, thus this would not + // always produce a complete alpha bitmap. There are some solutions: + // + // - Grow the used polygon range by one discrete unit in X and Y. This + // will make the decomposition view-dependent. + // + // - For all filled polygon renderings, dra wthe polygon outline extra. This + // would lead to unwanted side effects when using concatenated polygons. + // + // - At this decomposition, add a filled polygon and a hairline polygon. This + // solution stays view-independent. + // + // I will take the last one here. The small overhead of two primitives will only be + // used when UnifiedAlphaPrimitive2D is not handled directly. + const basegfx::B2DRange aPolygonRange(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aPolygonRange)); + const basegfx::BColor aGray(getAlpha(), getAlpha(), getAlpha()); + Primitive2DSequence aAlphaContent(2); + + aAlphaContent[0] = Primitive2DReference(new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), aGray)); + aAlphaContent[1] = Primitive2DReference(new PolygonHairlinePrimitive2D(aPolygon, aGray)); + + // create sub-transparence group with a gray-colored rectangular fill polygon + const Primitive2DReference xRefB(new AlphaPrimitive2D(getChildren(), aAlphaContent)); + return Primitive2DSequence(&xRefB, 1L); + } + else + { + // completely transparent or invalid definition, add nothing + return Primitive2DSequence(); + } + } + + UnifiedAlphaPrimitive2D::UnifiedAlphaPrimitive2D( + const Primitive2DSequence& rChildren, + double fAlpha) + : GroupPrimitive2D(rChildren), + mfAlpha(fAlpha) + { + } + + bool UnifiedAlphaPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const UnifiedAlphaPrimitive2D& rCompare = (UnifiedAlphaPrimitive2D&)rPrimitive; + + return (getAlpha() == rCompare.getAlpha()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(UnifiedAlphaPrimitive2D, PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx new file mode 100644 index 000000000000..93a51d5379b3 --- /dev/null +++ b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: wrongspellprimitive2d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $ + * + * 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/primitive2d/wrongspellprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence WrongSpellPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + // ATM this decompose is view-independent, what the original VCL-Display is not. To mimic + // the old behaviour here if wanted it is necessary to add get2DDecomposition and implement + // it similar to the usage in e.g. HelplinePrimitive2D. Remembering the ViewTransformation + // should be enough then. + // The view-independent wavelines work well (if You ask me). Maybe the old VCL-Behaviour is only + // in place because it was not possible/too expensive at that time to scale the wavelines with the + // view... + // With the VCL-PixelRenderer this will not even be used since it implements WrongSpellPrimitive2D + // directly and mimics the old VCL-Display there. If You implemented a new renderer without + // direct WrongSpellPrimitive2D support, You may want to do the described change here. + + // get the font height (part of scale), so decompose the matrix + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + // calculate distances based on a static default (to allow testing in debugger) + static double fDefaultDistance(0.03); + const double fFontHeight(aScale.getY()); + const double fUnderlineDistance(fFontHeight * fDefaultDistance); + const double fWaveWidth(2.0 * fUnderlineDistance); + + // the Y-distance needs to be relativated to FontHeight since the points get + // transformed with the transformation containing that scale already. + const double fRelativeUnderlineDistance(basegfx::fTools::equalZero(aScale.getY()) ? 0.0 : fUnderlineDistance / aScale.getY()); + basegfx::B2DPoint aStart(getStart(), fRelativeUnderlineDistance); + basegfx::B2DPoint aStop(getStop(), fRelativeUnderlineDistance); + basegfx::B2DPolygon aPolygon; + + aPolygon.append(getTransformation() * aStart); + aPolygon.append(getTransformation() * aStop); + + // prepare line attribute + const attribute::LineAttribute aLineAttribute(getColor()); + + // create the waveline primitive + Primitive2DReference xPrimitive(new PolygonWavePrimitive2D(aPolygon, aLineAttribute, fWaveWidth, 0.5 * fWaveWidth)); + Primitive2DSequence xRetval(&xPrimitive, 1); + + return xRetval; + } + + WrongSpellPrimitive2D::WrongSpellPrimitive2D( + const basegfx::B2DHomMatrix& rTransformation, + double fStart, + double fStop, + const basegfx::BColor& rColor) + : BasePrimitive2D(), + maTransformation(rTransformation), + mfStart(fStart), + mfStop(fStop), + maColor(rColor) + { + } + + bool WrongSpellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(BasePrimitive2D::operator==(rPrimitive)) + { + const WrongSpellPrimitive2D& rCompare = (WrongSpellPrimitive2D&)rPrimitive; + + return (getTransformation() == rCompare.getTransformation() + && getStart() == rCompare.getStart() + && getStop() == rCompare.getStop() + && getColor() == rCompare.getColor()); + } + + return false; + } + + // provide unique ID + ImplPrimitrive2DIDBlock(WrongSpellPrimitive2D, PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof |