summaryrefslogtreecommitdiff
path: root/drawinglayer/source
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer/source')
-rw-r--r--drawinglayer/source/animation/animationtiming.cxx378
-rw-r--r--drawinglayer/source/animation/makefile.mk52
-rw-r--r--drawinglayer/source/attribute/fillattribute.cxx102
-rw-r--r--drawinglayer/source/attribute/fillbitmapattribute.cxx66
-rw-r--r--drawinglayer/source/attribute/lineattribute.cxx51
-rw-r--r--drawinglayer/source/attribute/linestartendattribute.cxx58
-rw-r--r--drawinglayer/source/attribute/makefile.mk61
-rw-r--r--drawinglayer/source/attribute/materialattribute3d.cxx192
-rw-r--r--drawinglayer/source/attribute/sdrallattribute3d.cxx200
-rw-r--r--drawinglayer/source/attribute/sdrattribute.cxx293
-rw-r--r--drawinglayer/source/attribute/sdrattribute3d.cxx219
-rw-r--r--drawinglayer/source/attribute/sdrfillbitmapattribute.cxx237
-rw-r--r--drawinglayer/source/attribute/strokeattribute.cxx63
-rw-r--r--drawinglayer/source/geometry/makefile.mk52
-rw-r--r--drawinglayer/source/geometry/viewinformation2d.cxx553
-rw-r--r--drawinglayer/source/geometry/viewinformation3d.cxx562
-rw-r--r--drawinglayer/source/primitive2d/alphaprimitive2d.cxx78
-rw-r--r--drawinglayer/source/primitive2d/animatedprimitive2d.cxx293
-rw-r--r--drawinglayer/source/primitive2d/backgroundcolorprimitive2d.cxx124
-rw-r--r--drawinglayer/source/primitive2d/baseprimitive2d.cxx264
-rw-r--r--drawinglayer/source/primitive2d/bitmapprimitive2d.cxx89
-rw-r--r--drawinglayer/source/primitive2d/borderlineprimitive2d.cxx243
-rw-r--r--drawinglayer/source/primitive2d/chartprimitive2d.cxx90
-rw-r--r--drawinglayer/source/primitive2d/controlprimitive2d.cxx394
-rw-r--r--drawinglayer/source/primitive2d/embedded3dprimitive2d.cxx176
-rw-r--r--drawinglayer/source/primitive2d/fillbitmapprimitive2d.cxx142
-rw-r--r--drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx202
-rw-r--r--drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx162
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitive2d.cxx458
-rw-r--r--drawinglayer/source/primitive2d/gridprimitive2d.cxx329
-rw-r--r--drawinglayer/source/primitive2d/groupprimitive2d.cxx87
-rw-r--r--drawinglayer/source/primitive2d/helplineprimitive2d.cxx230
-rw-r--r--drawinglayer/source/primitive2d/hittestprimitive2d.cxx76
-rw-r--r--drawinglayer/source/primitive2d/invertprimitive2d.cxx65
-rw-r--r--drawinglayer/source/primitive2d/makefile.mk90
-rw-r--r--drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx165
-rw-r--r--drawinglayer/source/primitive2d/maskprimitive2d.cxx79
-rw-r--r--drawinglayer/source/primitive2d/mediaprimitive2d.cxx164
-rw-r--r--drawinglayer/source/primitive2d/metafileprimitive2d.cxx89
-rw-r--r--drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx79
-rw-r--r--drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx185
-rw-r--r--drawinglayer/source/primitive2d/pointarrayprimitive2d.cxx101
-rw-r--r--drawinglayer/source/primitive2d/polygonprimitive2d.cxx633
-rw-r--r--drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx548
-rw-r--r--drawinglayer/source/primitive2d/primitivetools2d.cxx106
-rw-r--r--drawinglayer/source/primitive2d/sceneprimitive2d.cxx484
-rw-r--r--drawinglayer/source/primitive2d/shadowprimitive2d.cxx114
-rw-r--r--drawinglayer/source/primitive2d/structuretagprimitive2d.cxx67
-rw-r--r--drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx888
-rw-r--r--drawinglayer/source/primitive2d/texteffectprimitive2d.cxx245
-rw-r--r--drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx166
-rw-r--r--drawinglayer/source/primitive2d/textlayoutdevice.cxx430
-rw-r--r--drawinglayer/source/primitive2d/textprimitive2d.cxx374
-rw-r--r--drawinglayer/source/primitive2d/transformprimitive2d.cxx87
-rw-r--r--drawinglayer/source/primitive2d/unifiedalphaprimitive2d.cxx129
-rw-r--r--drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx130
-rw-r--r--drawinglayer/source/primitive3d/baseprimitive3d.cxx264
-rw-r--r--drawinglayer/source/primitive3d/groupprimitive3d.cxx87
-rw-r--r--drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx313
-rw-r--r--drawinglayer/source/primitive3d/hittestprimitive3d.cxx76
-rw-r--r--drawinglayer/source/primitive3d/makefile.mk70
-rw-r--r--drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx79
-rw-r--r--drawinglayer/source/primitive3d/polygonprimitive3d.cxx186
-rw-r--r--drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx573
-rw-r--r--drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx91
-rw-r--r--drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx235
-rw-r--r--drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx299
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx999
-rw-r--r--drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx537
-rw-r--r--drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx396
-rw-r--r--drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx206
-rw-r--r--drawinglayer/source/primitive3d/sdrprimitive3d.cxx133
-rw-r--r--drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx236
-rw-r--r--drawinglayer/source/primitive3d/shadowprimitive3d.cxx88
-rw-r--r--drawinglayer/source/primitive3d/textureprimitive3d.cxx237
-rw-r--r--drawinglayer/source/primitive3d/transformprimitive3d.cxx87
-rw-r--r--drawinglayer/source/processor2d/baseprocessor2d.cxx99
-rw-r--r--drawinglayer/source/processor2d/canvasprocessor.cxx2226
-rw-r--r--drawinglayer/source/processor2d/contourextractor2d.cxx211
-rw-r--r--drawinglayer/source/processor2d/helperchartrenderer.cxx163
-rw-r--r--drawinglayer/source/processor2d/helperchartrenderer.hxx68
-rw-r--r--drawinglayer/source/processor2d/helperwrongspellrenderer.cxx104
-rw-r--r--drawinglayer/source/processor2d/helperwrongspellrenderer.hxx73
-rw-r--r--drawinglayer/source/processor2d/hittestprocessor2d.cxx563
-rw-r--r--drawinglayer/source/processor2d/linegeometryextractor2d.cxx152
-rw-r--r--drawinglayer/source/processor2d/makefile.mk66
-rw-r--r--drawinglayer/source/processor2d/textaspolygonextractor2d.cxx255
-rw-r--r--drawinglayer/source/processor2d/vclhelperbitmaprender.cxx278
-rw-r--r--drawinglayer/source/processor2d/vclhelperbitmaprender.hxx74
-rw-r--r--drawinglayer/source/processor2d/vclhelperbitmaptransform.cxx439
-rw-r--r--drawinglayer/source/processor2d/vclhelperbitmaptransform.hxx68
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.cxx190
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.hxx78
-rw-r--r--drawinglayer/source/processor2d/vclhelpergradient.cxx297
-rw-r--r--drawinglayer/source/processor2d/vclhelpergradient.hxx69
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx1769
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx579
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx1413
-rw-r--r--drawinglayer/source/processor3d/baseprocessor3d.cxx122
-rw-r--r--drawinglayer/source/processor3d/cutfindprocessor3d.cxx199
-rw-r--r--drawinglayer/source/processor3d/defaultprocessor3d.cxx578
-rw-r--r--drawinglayer/source/processor3d/geometry2dextractor.cxx178
-rw-r--r--drawinglayer/source/processor3d/makefile.mk58
-rw-r--r--drawinglayer/source/processor3d/shadow3dextractor.cxx306
-rw-r--r--drawinglayer/source/processor3d/zbufferprocessor3d.cxx747
-rw-r--r--drawinglayer/source/texture/makefile.mk53
-rw-r--r--drawinglayer/source/texture/texture.cxx728
-rw-r--r--drawinglayer/source/texture/texture3d.cxx271
108 files changed, 29660 insertions, 0 deletions
diff --git a/drawinglayer/source/animation/animationtiming.cxx b/drawinglayer/source/animation/animationtiming.cxx
new file mode 100644
index 000000000000..ab73d07591b1
--- /dev/null
+++ b/drawinglayer/source/animation/animationtiming.cxx
@@ -0,0 +1,378 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: animationtiming.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/animation/animationtiming.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace animation
+ {
+ //////////////////////////////////////////////////////////////////////////////
+
+ AnimationEntry::AnimationEntry()
+ {
+ }
+
+ AnimationEntry::~AnimationEntry()
+ {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ AnimationEntryFixed::AnimationEntryFixed(double fDuration, double fState)
+ : mfDuration(fDuration),
+ mfState(fState)
+ {
+ }
+
+ AnimationEntryFixed::~AnimationEntryFixed()
+ {
+ }
+
+ AnimationEntry* AnimationEntryFixed::clone() const
+ {
+ return new AnimationEntryFixed(mfDuration, mfState);
+ }
+
+ bool AnimationEntryFixed::operator==(const AnimationEntry& rCandidate) const
+ {
+ const AnimationEntryFixed* pCompare = dynamic_cast< const AnimationEntryFixed* >(&rCandidate);
+
+ return (pCompare
+ && basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
+ && basegfx::fTools::equal(mfState, pCompare->mfState));
+ }
+
+ double AnimationEntryFixed::getDuration() const
+ {
+ return mfDuration;
+ }
+
+ double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const
+ {
+ return mfState;
+ }
+
+ double AnimationEntryFixed::getNextEventTime(double fTime) const
+ {
+ if(basegfx::fTools::less(fTime, mfDuration))
+ {
+ return mfDuration;
+ }
+ else
+ {
+ return 0.0;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ AnimationEntryLinear::AnimationEntryLinear(double fDuration, double fFrequency, double fStart, double fStop)
+ : mfDuration(fDuration),
+ mfFrequency(fFrequency),
+ mfStart(fStart),
+ mfStop(fStop)
+ {
+ }
+
+ AnimationEntryLinear::~AnimationEntryLinear()
+ {
+ }
+
+ AnimationEntry* AnimationEntryLinear::clone() const
+ {
+ return new AnimationEntryLinear(mfDuration, mfFrequency, mfStart, mfStop);
+ }
+
+ bool AnimationEntryLinear::operator==(const AnimationEntry& rCandidate) const
+ {
+ const AnimationEntryLinear* pCompare = dynamic_cast< const AnimationEntryLinear* >(&rCandidate);
+
+ return (pCompare
+ && basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
+ && basegfx::fTools::equal(mfStart, pCompare->mfStart)
+ && basegfx::fTools::equal(mfStop, pCompare->mfStop));
+ }
+
+ double AnimationEntryLinear::getDuration() const
+ {
+ return mfDuration;
+ }
+
+ double AnimationEntryLinear::getStateAtTime(double fTime) const
+ {
+ if(basegfx::fTools::more(mfDuration, 0.0))
+ {
+ const double fFactor(fTime / mfDuration);
+
+ if(fFactor > 1.0)
+ {
+ return mfStop;
+ }
+ else
+ {
+ return mfStart + ((mfStop - mfStart) * fFactor);
+ }
+ }
+ else
+ {
+ return mfStart;
+ }
+ }
+
+ double AnimationEntryLinear::getNextEventTime(double fTime) const
+ {
+ if(basegfx::fTools::less(fTime, mfDuration))
+ {
+ // use the simple solution: just add the frequency. More correct (but also more
+ // complicated) would be to calculate the slice of time we are in and when this
+ // slice will end. For the animations, this makes no quality difference.
+ fTime += mfFrequency;
+
+ if(basegfx::fTools::more(fTime, mfDuration))
+ {
+ fTime = mfDuration;
+ }
+
+ return fTime;
+ }
+ else
+ {
+ return 0.0;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ sal_uInt32 AnimationEntryList::impGetIndexAtTime(double fTime, double &rfAddedTime) const
+ {
+ sal_uInt32 nIndex(0L);
+
+ while(nIndex < maEntries.size() && basegfx::fTools::lessOrEqual(rfAddedTime + maEntries[nIndex]->getDuration(), fTime))
+ {
+ rfAddedTime += maEntries[nIndex++]->getDuration();
+ }
+
+ return nIndex;
+ }
+
+ AnimationEntryList::AnimationEntryList()
+ : mfDuration(0.0)
+ {
+ }
+
+ AnimationEntryList::~AnimationEntryList()
+ {
+ for(sal_uInt32 a(0L); a < maEntries.size(); a++)
+ {
+ delete maEntries[a];
+ }
+ }
+
+ AnimationEntry* AnimationEntryList::clone() const
+ {
+ AnimationEntryList* pNew = new AnimationEntryList();
+
+ for(sal_uInt32 a(0L); a < maEntries.size(); a++)
+ {
+ pNew->append(*maEntries[a]);
+ }
+
+ return pNew;
+ }
+
+ bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const
+ {
+ const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate);
+
+ if(pCompare && mfDuration == pCompare->mfDuration)
+ {
+ for(sal_uInt32 a(0L); a < maEntries.size(); a++)
+ {
+ if(!(*maEntries[a] == *pCompare->maEntries[a]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void AnimationEntryList::append(const AnimationEntry& rCandidate)
+ {
+ const double fDuration(rCandidate.getDuration());
+
+ if(!basegfx::fTools::equalZero(fDuration))
+ {
+ maEntries.push_back(rCandidate.clone());
+ mfDuration += fDuration;
+ }
+ }
+
+ double AnimationEntryList::getDuration() const
+ {
+ return mfDuration;
+ }
+
+ double AnimationEntryList::getStateAtTime(double fTime) const
+ {
+ if(!basegfx::fTools::equalZero(mfDuration))
+ {
+ double fAddedTime(0.0);
+ const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
+
+ if(nIndex < maEntries.size())
+ {
+ return maEntries[nIndex]->getStateAtTime(fTime - fAddedTime);
+ }
+ }
+
+ return 0.0;
+ }
+
+ double AnimationEntryList::getNextEventTime(double fTime) const
+ {
+ double fNewTime(0.0);
+
+ if(!basegfx::fTools::equalZero(mfDuration))
+ {
+ double fAddedTime(0.0);
+ const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
+
+ if(nIndex < maEntries.size())
+ {
+ fNewTime = maEntries[nIndex]->getNextEventTime(fTime - fAddedTime) + fAddedTime;
+ }
+ }
+
+ return fNewTime;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat)
+ : AnimationEntryList(),
+ mnRepeat(nRepeat)
+ {
+ }
+
+ AnimationEntryLoop::~AnimationEntryLoop()
+ {
+ }
+
+ AnimationEntry* AnimationEntryLoop::clone() const
+ {
+ AnimationEntryLoop* pNew = new AnimationEntryLoop(mnRepeat);
+
+ for(sal_uInt32 a(0L); a < maEntries.size(); a++)
+ {
+ pNew->append(*maEntries[a]);
+ }
+
+ return pNew;
+ }
+
+ bool AnimationEntryLoop::operator==(const AnimationEntry& rCandidate) const
+ {
+ const AnimationEntryLoop* pCompare = dynamic_cast< const AnimationEntryLoop* >(&rCandidate);
+
+ return (pCompare
+ && mnRepeat == pCompare->mnRepeat
+ && AnimationEntryList::operator==(rCandidate));
+ }
+
+ double AnimationEntryLoop::getDuration() const
+ {
+ return (mfDuration * (double)mnRepeat);
+ }
+
+ double AnimationEntryLoop::getStateAtTime(double fTime) const
+ {
+ if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
+ {
+ const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
+
+ if(nCurrentLoop > mnRepeat)
+ {
+ return 1.0;
+ }
+ else
+ {
+ const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
+ const double fRelativeTime(fTime - fTimeAtLoopStart);
+ return AnimationEntryList::getStateAtTime(fRelativeTime);
+ }
+ }
+
+ return 0.0;
+ }
+
+ double AnimationEntryLoop::getNextEventTime(double fTime) const
+ {
+ double fNewTime(0.0);
+
+ if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
+ {
+ const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
+
+ if(nCurrentLoop <= mnRepeat)
+ {
+ const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
+ const double fRelativeTime(fTime - fTimeAtLoopStart);
+ const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime));
+
+ if(!basegfx::fTools::equalZero(fNextEventAtLoop))
+ {
+ fNewTime = fNextEventAtLoop + fTimeAtLoopStart;
+ }
+ }
+ }
+
+ return fNewTime;
+ }
+ } // end of namespace animation
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/animation/makefile.mk b/drawinglayer/source/animation/makefile.mk
new file mode 100644
index 000000000000..a72bf10711f4
--- /dev/null
+++ b/drawinglayer/source/animation/makefile.mk
@@ -0,0 +1,52 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# last change: $Author: aw $ $Date: 2006-12-13 16:57:07 $
+#
+# 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=animation
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/animationtiming.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/attribute/fillattribute.cxx b/drawinglayer/source/attribute/fillattribute.cxx
new file mode 100644
index 000000000000..12741e40c5c3
--- /dev/null
+++ b/drawinglayer/source/attribute/fillattribute.cxx
@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: fillattribute.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/fillattribute.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ FillGradientAttribute::FillGradientAttribute(GradientStyle eStyle, double fBorder, double fOffsetX, double fOffsetY, double fAngle,
+ const basegfx::BColor& rStartColor, const basegfx::BColor& rEndColor, sal_uInt16 nSteps)
+ : maStartColor(rStartColor),
+ maEndColor(rEndColor),
+ mfBorder(fBorder),
+ mfOffsetX(fOffsetX),
+ mfOffsetY(fOffsetY),
+ mfAngle(fAngle),
+ meStyle(eStyle),
+ mnSteps(nSteps)
+ {
+ }
+
+ bool FillGradientAttribute::operator==(const FillGradientAttribute& rCandidate) const
+ {
+ return (meStyle == rCandidate.meStyle
+ && maStartColor == rCandidate.maStartColor
+ && maEndColor == rCandidate.maEndColor
+ && mfBorder == rCandidate.mfBorder
+ && mfOffsetX == rCandidate.mfOffsetX
+ && mfOffsetY == rCandidate.mfOffsetY
+ && mfAngle == rCandidate.mfAngle
+ && mnSteps == rCandidate.mnSteps);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ FillHatchAttribute::FillHatchAttribute(HatchStyle eStyle, double fDistance, double fAngle, const basegfx::BColor& rColor, bool bFillBackground)
+ : mfDistance(fDistance),
+ mfAngle(fAngle),
+ maColor(rColor),
+ meStyle(eStyle),
+ mbFillBackground(bFillBackground)
+ {
+ }
+
+ bool FillHatchAttribute::operator==(const FillHatchAttribute& rCandidate) const
+ {
+ return (meStyle == rCandidate.meStyle
+ && mfDistance == rCandidate.mfDistance
+ && mfAngle == rCandidate.mfAngle
+ && maColor == rCandidate.maColor
+ && mbFillBackground == rCandidate.mbFillBackground);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/fillbitmapattribute.cxx b/drawinglayer/source/attribute/fillbitmapattribute.cxx
new file mode 100644
index 000000000000..539e85ab2733
--- /dev/null
+++ b/drawinglayer/source/attribute/fillbitmapattribute.cxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: fillbitmapattribute.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/fillbitmapattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ FillBitmapAttribute::FillBitmapAttribute(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize, bool bTiling)
+ : maBitmap(rBitmap),
+ maTopLeft(rTopLeft),
+ maSize(rSize),
+ mbTiling(bTiling)
+ {
+ }
+
+ bool FillBitmapAttribute::operator==(const FillBitmapAttribute& rCandidate) const
+ {
+ return (maBitmap == rCandidate.maBitmap
+ && maTopLeft == rCandidate.maTopLeft
+ && maSize == rCandidate.maSize
+ && mbTiling == rCandidate.mbTiling);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/lineattribute.cxx b/drawinglayer/source/attribute/lineattribute.cxx
new file mode 100644
index 000000000000..5ab44b73db82
--- /dev/null
+++ b/drawinglayer/source/attribute/lineattribute.cxx
@@ -0,0 +1,51 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lineattribute.cxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/lineattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/linestartendattribute.cxx b/drawinglayer/source/attribute/linestartendattribute.cxx
new file mode 100644
index 000000000000..785819870114
--- /dev/null
+++ b/drawinglayer/source/attribute/linestartendattribute.cxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: linestartendattribute.cxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/linestartendattribute.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ bool LineStartEndAttribute::isActive() const
+ {
+ return (0.0 != getWidth()
+ && 0.0 != getB2DPolyPolygon().count()
+ && 0.0 != getB2DPolyPolygon().getB2DPolygon(0L).count());
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/makefile.mk b/drawinglayer/source/attribute/makefile.mk
new file mode 100644
index 000000000000..fa91224e64b6
--- /dev/null
+++ b/drawinglayer/source/attribute/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# last change: $Author: aw $ $Date: 2007-11-07 14:27:26 $
+#
+# 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=attribute
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/fillattribute.obj \
+ $(SLO)$/fillbitmapattribute.obj \
+ $(SLO)$/materialattribute3d.obj \
+ $(SLO)$/sdrallattribute3d.obj \
+ $(SLO)$/sdrattribute.obj \
+ $(SLO)$/sdrattribute3d.obj \
+ $(SLO)$/sdrfillbitmapattribute.obj \
+ $(SLO)$/lineattribute.obj \
+ $(SLO)$/linestartendattribute.obj \
+ $(SLO)$/strokeattribute.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/attribute/materialattribute3d.cxx b/drawinglayer/source/attribute/materialattribute3d.cxx
new file mode 100644
index 000000000000..bc3e8f3b317b
--- /dev/null
+++ b/drawinglayer/source/attribute/materialattribute3d.cxx
@@ -0,0 +1,192 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: materialattribute3d.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/materialattribute3d.hxx>
+#include <basegfx/color/bcolor.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ class ImpMaterialAttribute3D
+ {
+ public:
+ // materialAttribute3D definitions
+ basegfx::BColor maColor; // object color
+ basegfx::BColor maSpecular; // material specular color
+ basegfx::BColor maEmission; // material emissive color
+ sal_uInt16 mnSpecularIntensity; // material specular intensity [0..128]
+
+ // refcounter
+ sal_uInt32 mnRefCount;
+
+ ImpMaterialAttribute3D(const basegfx::BColor& rColor, const basegfx::BColor& rSpecular, const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity)
+ : maColor(rColor),
+ maSpecular(rSpecular),
+ maEmission(rEmission),
+ mnSpecularIntensity(nSpecularIntensity),
+ mnRefCount(0L)
+ {
+ }
+
+ ImpMaterialAttribute3D(const basegfx::BColor& rColor)
+ : maColor(rColor),
+ maSpecular(1.0, 1.0, 1.0),
+ maEmission(),
+ mnSpecularIntensity(15),
+ mnRefCount(0L)
+ {
+ }
+
+ ImpMaterialAttribute3D()
+ : mnSpecularIntensity(0),
+ mnRefCount(0L)
+ {
+ }
+
+ bool operator==(const ImpMaterialAttribute3D& rCandidate) const
+ {
+ return (maColor == rCandidate.maColor
+ && maSpecular == rCandidate.maSpecular
+ && maEmission == rCandidate.maEmission
+ && mnSpecularIntensity == rCandidate.mnSpecularIntensity);
+ }
+
+ const basegfx::BColor& getColor() const { return maColor; }
+ const basegfx::BColor& getSpecular() const { return maSpecular; }
+ const basegfx::BColor& getEmission() const { return maEmission; }
+ sal_uInt16 getSpecularIntensity() const { return mnSpecularIntensity; }
+ };
+ } // end of anonymous namespace
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ MaterialAttribute3D::MaterialAttribute3D(const basegfx::BColor& rColor, const basegfx::BColor& rSpecular, const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity)
+ : mpMaterialAttribute3D(new ImpMaterialAttribute3D(rColor, rSpecular, rEmission, nSpecularIntensity))
+ {
+ }
+
+ MaterialAttribute3D::MaterialAttribute3D(const basegfx::BColor& rColor)
+ : mpMaterialAttribute3D(new ImpMaterialAttribute3D(rColor))
+ {
+ }
+
+ MaterialAttribute3D::MaterialAttribute3D()
+ : mpMaterialAttribute3D(new ImpMaterialAttribute3D())
+ {
+ }
+
+ MaterialAttribute3D::MaterialAttribute3D(const MaterialAttribute3D& rCandidate)
+ : mpMaterialAttribute3D(rCandidate.mpMaterialAttribute3D)
+ {
+ mpMaterialAttribute3D->mnRefCount++;
+ }
+
+ MaterialAttribute3D::~MaterialAttribute3D()
+ {
+ if(mpMaterialAttribute3D->mnRefCount)
+ {
+ mpMaterialAttribute3D->mnRefCount--;
+ }
+ else
+ {
+ delete mpMaterialAttribute3D;
+ }
+ }
+
+ MaterialAttribute3D& MaterialAttribute3D::operator=(const MaterialAttribute3D& rCandidate)
+ {
+ if(rCandidate.mpMaterialAttribute3D != mpMaterialAttribute3D)
+ {
+ if(mpMaterialAttribute3D->mnRefCount)
+ {
+ mpMaterialAttribute3D->mnRefCount--;
+ }
+ else
+ {
+ delete mpMaterialAttribute3D;
+ }
+
+ mpMaterialAttribute3D = rCandidate.mpMaterialAttribute3D;
+ mpMaterialAttribute3D->mnRefCount++;
+ }
+
+ return *this;
+ }
+
+ bool MaterialAttribute3D::operator==(const MaterialAttribute3D& rCandidate) const
+ {
+ if(rCandidate.mpMaterialAttribute3D == mpMaterialAttribute3D)
+ {
+ return true;
+ }
+
+ return (*rCandidate.mpMaterialAttribute3D == *mpMaterialAttribute3D);
+ }
+
+ const basegfx::BColor& MaterialAttribute3D::getColor() const
+ {
+ return mpMaterialAttribute3D->getColor();
+ }
+
+ const basegfx::BColor& MaterialAttribute3D::getSpecular() const
+ {
+ return mpMaterialAttribute3D->getSpecular();
+ }
+
+ const basegfx::BColor& MaterialAttribute3D::getEmission() const
+ {
+ return mpMaterialAttribute3D->getEmission();
+ }
+
+ sal_uInt16 MaterialAttribute3D::getSpecularIntensity() const
+ {
+ return mpMaterialAttribute3D->getSpecularIntensity();
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/sdrallattribute3d.cxx b/drawinglayer/source/attribute/sdrallattribute3d.cxx
new file mode 100644
index 000000000000..264d8d0432d1
--- /dev/null
+++ b/drawinglayer/source/attribute/sdrallattribute3d.cxx
@@ -0,0 +1,200 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrallattribute3d.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/sdrallattribute3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// pointer compare define
+#define pointerOrContentEqual(p, q) ((p == q) || (p && q && *p == *q))
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrLineFillShadowAttribute::SdrLineFillShadowAttribute(
+ SdrLineAttribute* pLine,
+ SdrFillAttribute* pFill,
+ SdrLineStartEndAttribute* pLineStartEnd,
+ SdrShadowAttribute* pShadow,
+ FillGradientAttribute* pFillFloatTransGradient)
+ : mpShadow(pShadow),
+ mpLine(pLine),
+ mpLineStartEnd(pLineStartEnd),
+ mpFill(pFill),
+ mpFillFloatTransGradient(pFillFloatTransGradient)
+ {
+ }
+
+ SdrLineFillShadowAttribute::SdrLineFillShadowAttribute(
+ const SdrLineFillShadowAttribute& rCandidate)
+ : mpShadow(0),
+ mpLine(0),
+ mpLineStartEnd(0),
+ mpFill(0),
+ mpFillFloatTransGradient(0)
+ {
+ *this = rCandidate;
+ }
+
+ SdrLineFillShadowAttribute::~SdrLineFillShadowAttribute()
+ {
+ delete mpShadow;
+ delete mpLine;
+ delete mpLineStartEnd;
+ delete mpFill;
+ delete mpFillFloatTransGradient;
+ }
+
+ SdrLineFillShadowAttribute& SdrLineFillShadowAttribute::operator=(const SdrLineFillShadowAttribute& rCandidate)
+ {
+ // handle mpShadow
+ {
+ // delete local mpShadow if necessary
+ if(mpShadow)
+ {
+ delete mpShadow;
+ mpShadow = 0;
+ }
+
+ // copy mpShadow if necessary
+ if(rCandidate.mpShadow)
+ {
+ mpShadow = new SdrShadowAttribute(*rCandidate.mpShadow);
+ }
+ }
+
+ // handle mpLine
+ {
+ // delete local mpLine if necessary
+ if(mpLine)
+ {
+ delete mpLine;
+ mpLine = 0;
+ }
+
+ // copy mpLine if necessary
+ if(rCandidate.mpLine)
+ {
+ mpLine = new SdrLineAttribute(*rCandidate.mpLine);
+ }
+ }
+
+ // handle mpLineStartEnd
+ {
+ // delete local mpLineStartEnd if necessary
+ if(mpLineStartEnd)
+ {
+ delete mpLineStartEnd;
+ mpLineStartEnd = 0;
+ }
+
+ // copy mpLineStartEnd if necessary
+ if(rCandidate.mpLineStartEnd)
+ {
+ mpLineStartEnd = new SdrLineStartEndAttribute(*rCandidate.mpLineStartEnd);
+ }
+ }
+
+ // handle mpFill
+ {
+ // delete local mpFill if necessary
+ if(mpFill)
+ {
+ delete mpFill;
+ mpFill = 0;
+ }
+
+ // copy mpFill if necessary
+ if(rCandidate.mpFill)
+ {
+ mpFill = new SdrFillAttribute(*rCandidate.mpFill);
+ }
+ }
+
+ // handle mpFillFloatTransGradient
+ {
+ // delete local mpFillFloatTransGradient if necessary
+ if(mpFillFloatTransGradient)
+ {
+ delete mpFillFloatTransGradient;
+ mpFillFloatTransGradient = 0;
+ }
+
+ // copy mpFillFloatTransGradient if necessary
+ if(rCandidate.mpFillFloatTransGradient)
+ {
+ mpFillFloatTransGradient = new FillGradientAttribute(*rCandidate.mpFillFloatTransGradient);
+ }
+ }
+
+ return *this;
+ }
+
+ bool SdrLineFillShadowAttribute::operator==(const SdrLineFillShadowAttribute& rCandidate) const
+ {
+ // handle mpShadow
+ if(!pointerOrContentEqual(mpShadow, rCandidate.mpShadow))
+ return false;
+
+ // handle mpLine
+ if(!pointerOrContentEqual(mpLine, rCandidate.mpLine))
+ return false;
+
+ // handle mpLineStartEnd
+ if(!pointerOrContentEqual(mpLineStartEnd, rCandidate.mpLineStartEnd))
+ return false;
+
+ // handle mpFill
+ if(!pointerOrContentEqual(mpFill, rCandidate.mpFill))
+ return false;
+
+ // handle mpFillFloatTransGradient
+ if(!pointerOrContentEqual(mpFillFloatTransGradient, rCandidate.mpFillFloatTransGradient))
+ return false;
+
+ return true;
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/sdrattribute.cxx b/drawinglayer/source/attribute/sdrattribute.cxx
new file mode 100644
index 000000000000..8e55afa6751e
--- /dev/null
+++ b/drawinglayer/source/attribute/sdrattribute.cxx
@@ -0,0 +1,293 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrattribute.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/sdrattribute.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrLineAttribute::SdrLineAttribute(
+ basegfx::B2DLineJoin eJoin, double fWidth, double fTransparence, const basegfx::BColor& rColor,
+ const ::std::vector< double >& rDotDashArray, double fFullDotDashLen)
+ : meJoin(eJoin),
+ mfWidth(fWidth),
+ mfTransparence(fTransparence),
+ maColor(rColor),
+ maDotDashArray(rDotDashArray),
+ mfFullDotDashLen(fFullDotDashLen)
+ {
+ }
+
+ SdrLineAttribute::SdrLineAttribute(const basegfx::BColor& rColor)
+ : meJoin(basegfx::B2DLINEJOIN_NONE),
+ mfWidth(0.0),
+ mfTransparence(0.0),
+ maColor(rColor),
+ maDotDashArray(),
+ mfFullDotDashLen(0.0)
+ {
+ }
+
+ SdrLineAttribute::~SdrLineAttribute()
+ {
+ }
+
+ bool SdrLineAttribute::operator==(const SdrLineAttribute& rCandidate) const
+ {
+ return (meJoin == rCandidate.meJoin
+ && mfWidth == rCandidate.mfWidth
+ && mfTransparence == rCandidate.mfTransparence
+ && maColor == rCandidate.maColor
+ && maDotDashArray == rCandidate.maDotDashArray);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrLineStartEndAttribute::SdrLineStartEndAttribute(
+ const basegfx::B2DPolyPolygon& rStartPolyPolygon, const basegfx::B2DPolyPolygon& rEndPolyPolygon,
+ double fStartWidth, double fEndWidth, bool bStartActive, bool bEndActive, bool bStartCentered, bool bEndCentered)
+ : maStartPolyPolygon(rStartPolyPolygon),
+ maEndPolyPolygon(rEndPolyPolygon),
+ mfStartWidth(fStartWidth),
+ mfEndWidth(fEndWidth),
+ mbStartActive(bStartActive),
+ mbEndActive(bEndActive),
+ mbStartCentered(bStartCentered),
+ mbEndCentered(bEndCentered)
+ {
+ }
+
+ SdrLineStartEndAttribute::~SdrLineStartEndAttribute()
+ {
+ }
+
+ bool SdrLineStartEndAttribute::operator==(const SdrLineStartEndAttribute& rCandidate) const
+ {
+ return (mbStartActive == rCandidate.mbStartActive
+ && mbEndActive == rCandidate.mbEndActive
+ && mbStartCentered == rCandidate.mbStartCentered
+ && mbEndCentered == rCandidate.mbEndCentered
+ && mfStartWidth == rCandidate.mfStartWidth
+ && mfEndWidth == rCandidate.mfEndWidth
+ && maStartPolyPolygon == rCandidate.maStartPolyPolygon
+ && maEndPolyPolygon == rCandidate.maEndPolyPolygon);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrShadowAttribute::SdrShadowAttribute(const basegfx::B2DVector& rOffset, double fTransparence, const basegfx::BColor& rColor)
+ : maOffset(rOffset),
+ mfTransparence(fTransparence),
+ maColor(rColor)
+ {
+ }
+
+ SdrShadowAttribute::~SdrShadowAttribute()
+ {
+ }
+
+ bool SdrShadowAttribute::operator==(const SdrShadowAttribute& rCandidate) const
+ {
+ return (mfTransparence == rCandidate.mfTransparence
+ && maColor == rCandidate.maColor
+ && maOffset == rCandidate.maOffset);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrFillAttribute::SdrFillAttribute(
+ double fTransparence,
+ const basegfx::BColor& rColor,
+ FillGradientAttribute* pGradient,
+ FillHatchAttribute* pHatch,
+ SdrFillBitmapAttribute* pBitmap)
+ : mfTransparence(fTransparence),
+ maColor(rColor),
+ mpGradient(pGradient),
+ mpHatch(pHatch),
+ mpBitmap(pBitmap)
+ {
+ }
+
+ SdrFillAttribute::SdrFillAttribute(const SdrFillAttribute& rCandidate)
+ : mfTransparence(1.0),
+ mpGradient(0L),
+ mpHatch(0L),
+ mpBitmap(0L)
+ {
+ if(!(*this == rCandidate))
+ {
+ *this = rCandidate;
+ }
+ }
+
+ SdrFillAttribute::~SdrFillAttribute()
+ {
+ delete mpGradient;
+ delete mpHatch;
+ delete mpBitmap;
+ }
+
+ SdrFillAttribute& SdrFillAttribute::operator=(const SdrFillAttribute& rCandidate)
+ {
+ // copy data
+ mfTransparence = rCandidate.mfTransparence;
+ maColor = rCandidate.maColor;
+
+ // handle mpGradient
+ {
+ // delete local mpGradient if necessary
+ if(mpGradient && ((!rCandidate.mpGradient) || (!(*mpGradient == *rCandidate.mpGradient))))
+ {
+ delete mpGradient;
+ mpGradient = 0L;
+ }
+
+ // copy mpGradient if necessary
+ if(!mpGradient && rCandidate.mpGradient)
+ {
+ mpGradient = new FillGradientAttribute(*rCandidate.mpGradient);
+ }
+ }
+
+ // handle mpHatch
+ {
+ // delete local mpHatch if necessary
+ if(mpHatch && ((!rCandidate.mpHatch) || (!(*mpHatch == *rCandidate.mpHatch))))
+ {
+ delete mpHatch;
+ mpHatch = 0L;
+ }
+
+ // copy mpHatch if necessary
+ if(!mpHatch && rCandidate.mpHatch)
+ {
+ mpHatch = new FillHatchAttribute(*rCandidate.mpHatch);
+ }
+ }
+
+ // handle mpBitmap
+ {
+ // delete local mpBitmap if necessary
+ if(mpBitmap && ((!rCandidate.mpBitmap) || (!(*mpBitmap == *rCandidate.mpBitmap))))
+ {
+ delete mpBitmap;
+ mpBitmap = 0L;
+ }
+
+ // copy mpBitmap if necessary
+ if(!mpBitmap && rCandidate.mpBitmap)
+ {
+ mpBitmap = new SdrFillBitmapAttribute(*rCandidate.mpBitmap);
+ }
+ }
+
+ return *this;
+ }
+
+ bool SdrFillAttribute::operator==(const SdrFillAttribute& rCandidate) const
+ {
+ if(mfTransparence != rCandidate.mfTransparence)
+ return false;
+
+ if(mpGradient)
+ {
+ if(!rCandidate.mpGradient)
+ return false;
+
+ if(!(*mpGradient == *rCandidate.mpGradient))
+ return false;
+ }
+ else if(mpHatch)
+ {
+ if(!rCandidate.mpHatch)
+ return false;
+
+ if(!(*mpHatch == *rCandidate.mpHatch))
+ return false;
+
+ if(mpHatch->isFillBackground() && !(maColor == rCandidate.maColor))
+ return false;
+ }
+ else if(mpBitmap)
+ {
+ if(!rCandidate.mpBitmap)
+ return false;
+
+ if(!(*mpBitmap == *rCandidate.mpBitmap))
+ return false;
+ }
+ else
+ {
+ if(!rCandidate.isColor())
+ return false;
+
+ if(!(maColor == rCandidate.maColor))
+ return false;
+ }
+
+ return true;
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/sdrattribute3d.cxx b/drawinglayer/source/attribute/sdrattribute3d.cxx
new file mode 100644
index 000000000000..c130675b9c97
--- /dev/null
+++ b/drawinglayer/source/attribute/sdrattribute3d.cxx
@@ -0,0 +1,219 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrattribute3d.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/sdrattribute3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ Sdr3DObjectAttribute::Sdr3DObjectAttribute(
+ ::com::sun::star::drawing::NormalsKind aNormalsKind,
+ ::com::sun::star::drawing::TextureProjectionMode aTextureProjectionX,
+ ::com::sun::star::drawing::TextureProjectionMode aTextureProjectionY,
+ ::com::sun::star::drawing::TextureKind2 aTextureKind,
+ ::com::sun::star::drawing::TextureMode aTextureMode,
+ const MaterialAttribute3D& rMaterial,
+ bool bNormalsInvert,
+ bool bDoubleSided,
+ bool bShadow3D,
+ bool bTextureFilter,
+ bool bReducedLineGeometry)
+ : maNormalsKind(aNormalsKind),
+ maTextureProjectionX(aTextureProjectionX),
+ maTextureProjectionY(aTextureProjectionY),
+ maTextureKind(aTextureKind),
+ maTextureMode(aTextureMode),
+ maMaterial(rMaterial),
+ mbNormalsInvert(bNormalsInvert),
+ mbDoubleSided(bDoubleSided),
+ mbShadow3D(bShadow3D),
+ mbTextureFilter(bTextureFilter),
+ mbReducedLineGeometry(bReducedLineGeometry)
+ {
+ }
+
+ bool Sdr3DObjectAttribute::operator==(const Sdr3DObjectAttribute& rCandidate) const
+ {
+ return (maNormalsKind == rCandidate.maNormalsKind
+ && maTextureProjectionX == rCandidate.maTextureProjectionX
+ && maTextureProjectionY == rCandidate.maTextureProjectionY
+ && maTextureKind == rCandidate.maTextureKind
+ && maTextureMode == rCandidate.maTextureMode
+ && maMaterial == rCandidate.maMaterial
+ && mbNormalsInvert == rCandidate.mbNormalsInvert
+ && mbDoubleSided == rCandidate.mbDoubleSided
+ && mbShadow3D == rCandidate.mbShadow3D
+ && mbTextureFilter == rCandidate.mbTextureFilter
+ && mbReducedLineGeometry == rCandidate.mbReducedLineGeometry);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ Sdr3DLightAttribute::Sdr3DLightAttribute(const basegfx::BColor& rColor, const basegfx::B3DVector& rDirection, bool bSpecular)
+ : maColor(rColor),
+ maDirection(rDirection),
+ mbSpecular(bSpecular)
+ {
+ }
+
+ bool Sdr3DLightAttribute::operator==(const Sdr3DLightAttribute& rCandidate) const
+ {
+ return (maColor == rCandidate.maColor
+ && maDirection == rCandidate.maDirection
+ && mbSpecular == rCandidate.mbSpecular);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrLightingAttribute::SdrLightingAttribute(
+ const basegfx::BColor& rAmbientLight,
+ const ::std::vector< Sdr3DLightAttribute >& rLightVector)
+ : maAmbientLight(rAmbientLight),
+ maLightVector(rLightVector)
+ {
+ }
+
+ bool SdrLightingAttribute::operator==(const SdrLightingAttribute& rCandidate) const
+ {
+ return (maAmbientLight == rCandidate.maAmbientLight
+ && maLightVector == rCandidate.maLightVector);
+ }
+
+ // color model solver
+ basegfx::BColor SdrLightingAttribute::solveColorModel(
+ const basegfx::B3DVector& rNormalInEyeCoordinates,
+ const basegfx::BColor& rColor, const basegfx::BColor& rSpecular,
+ const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity) const
+ {
+ // initialize with emissive color
+ basegfx::BColor aRetval(rEmission);
+
+ // take care of global ambient light
+ aRetval += getAmbientLight() * rColor;
+
+ // prepare light access. Is there a light?
+ const sal_uInt32 nLightCount(maLightVector.size());
+
+ if(nLightCount && !rNormalInEyeCoordinates.equalZero())
+ {
+ // prepare normal
+ basegfx::B3DVector aEyeNormal(rNormalInEyeCoordinates);
+ aEyeNormal.normalize();
+
+ for(sal_uInt32 a(0L); a < nLightCount; a++)
+ {
+ const Sdr3DLightAttribute& rLight(maLightVector[a]);
+ const double fCosFac(rLight.getDirection().scalar(aEyeNormal));
+
+ if(basegfx::fTools::more(fCosFac, 0.0))
+ {
+ aRetval += ((rLight.getColor() * rColor) * fCosFac);
+
+ if(rLight.getSpecular())
+ {
+ // expand by (0.0, 0.0, 1.0) in Z
+ basegfx::B3DVector aSpecularNormal(rLight.getDirection().getX(), rLight.getDirection().getY(), rLight.getDirection().getZ() + 1.0);
+ aSpecularNormal.normalize();
+ double fCosFac2(aSpecularNormal.scalar(aEyeNormal));
+
+ if(basegfx::fTools::more(fCosFac2, 0.0))
+ {
+ fCosFac2 = pow(fCosFac2, (double)nSpecularIntensity);
+ aRetval += (rSpecular * fCosFac2);
+ }
+ }
+ }
+ }
+ }
+
+ // clamp to color space before usage
+ aRetval.clamp();
+
+ return aRetval;
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrSceneAttribute::SdrSceneAttribute(
+ double fDistance,
+ double fShadowSlant,
+ ::com::sun::star::drawing::ProjectionMode aProjectionMode,
+ ::com::sun::star::drawing::ShadeMode aShadeMode,
+ bool bTwoSidedLighting)
+ : mfDistance(fDistance),
+ mfShadowSlant(fShadowSlant),
+ maProjectionMode(aProjectionMode),
+ maShadeMode(aShadeMode),
+ mbTwoSidedLighting(bTwoSidedLighting)
+ {
+ }
+
+ bool SdrSceneAttribute::operator==(const SdrSceneAttribute& rCandidate) const
+ {
+ return (mfDistance == rCandidate.mfDistance
+ && mfShadowSlant == rCandidate.mfShadowSlant
+ && maProjectionMode == rCandidate.maProjectionMode
+ && maShadeMode == rCandidate.maShadeMode
+ && mbTwoSidedLighting == rCandidate.mbTwoSidedLighting);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/sdrfillbitmapattribute.cxx b/drawinglayer/source/attribute/sdrfillbitmapattribute.cxx
new file mode 100644
index 000000000000..c35d0ba5c15f
--- /dev/null
+++ b/drawinglayer/source/attribute/sdrfillbitmapattribute.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrfillbitmapattribute.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/sdrfillbitmapattribute.hxx>
+#include <drawinglayer/attribute/fillbitmapattribute.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ SdrFillBitmapAttribute::SdrFillBitmapAttribute(
+ const Bitmap& rBitmap, const basegfx::B2DVector& rSize, const basegfx::B2DVector& rOffset,
+ const basegfx::B2DVector& rOffsetPosition, const basegfx::B2DVector& rRectPoint,
+ bool bTiling, bool bStretch, bool bLogSize)
+ : maBitmap(rBitmap),
+ maSize(rSize),
+ maOffset(rOffset),
+ maOffsetPosition(rOffsetPosition),
+ maRectPoint(rRectPoint),
+ mbTiling(bTiling),
+ mbStretch(bStretch),
+ mbLogSize(bLogSize)
+ {
+ }
+
+ bool SdrFillBitmapAttribute::operator==(const SdrFillBitmapAttribute& rCandidate) const
+ {
+ return (maBitmap == rCandidate.maBitmap
+ && maSize == rCandidate.maSize
+ && maOffset == rCandidate.maOffset
+ && maOffsetPosition == rCandidate.maOffsetPosition
+ && maRectPoint == rCandidate.maRectPoint
+ && mbTiling == rCandidate.mbTiling
+ && mbStretch == rCandidate.mbStretch
+ && mbLogSize == rCandidate.mbLogSize);
+ }
+
+ FillBitmapAttribute SdrFillBitmapAttribute::getFillBitmapAttribute(const basegfx::B2DRange& rRange) const
+ {
+ // get logical size of bitmap (before expanding eventually)
+ Bitmap aBitmap(maBitmap);
+ const basegfx::B2DVector aLogicalSize(aBitmap.GetPrefSize().getWidth(), aBitmap.GetPrefSize().getHeight());
+
+ // get hor/ver shiftings and apply them eventually to the bitmap, but only
+ // when tiling is on
+ bool bExpandWidth(false);
+ bool bExpandHeight(false);
+
+ if(mbTiling)
+ {
+ if(0.0 != maOffset.getX() || 0.0 != maOffset.getY())
+ {
+ const sal_uInt32 nWidth(aBitmap.GetSizePixel().getWidth());
+ const sal_uInt32 nHeight(aBitmap.GetSizePixel().getHeight());
+
+ if(0.0 != maOffset.getX())
+ {
+ bExpandHeight = true;
+ const sal_uInt32 nOffset(basegfx::fround(((double)nWidth * maOffset.getX()) / 100.0));
+ aBitmap.Expand(0L, nHeight);
+
+ const Size aSizeA(nOffset, nHeight);
+ const Rectangle aDstA(Point(0L, nHeight), aSizeA);
+ const Rectangle aSrcA(Point(nWidth - nOffset, 0L), aSizeA);
+ aBitmap.CopyPixel(aDstA, aSrcA);
+
+ const Size aSizeB(nWidth - nOffset, nHeight);
+ const Rectangle aDstB(Point(nOffset, nHeight), aSizeB);
+ const Rectangle aSrcB(Point(0L, 0L), aSizeB);
+ aBitmap.CopyPixel(aDstB, aSrcB);
+ }
+ else
+ {
+ bExpandWidth = true;
+ const sal_uInt32 nOffset(basegfx::fround(((double)nHeight * maOffset.getY()) / 100.0));
+ aBitmap.Expand(nWidth, 0L);
+
+ const Size aSize(nWidth, nHeight);
+ const Rectangle aDst(Point(nWidth, 0L), aSize);
+ const Rectangle aSrc(Point(0L, 0L), aSize);
+ aBitmap.CopyPixel(aDst, aSrc);
+
+ const Size aSizeA(nWidth, nOffset);
+ const Rectangle aDstA(Point(0L, 0L), aSizeA);
+ const Rectangle aSrcA(Point(nWidth, nHeight - nOffset), aSizeA);
+ aBitmap.CopyPixel(aDstA, aSrcA);
+
+ const Size aSizeB(nWidth, nHeight - nOffset);
+ const Rectangle aDstB(Point(0L, nOffset), aSizeB);
+ const Rectangle aSrcB(Point(nWidth, 0L), aSizeB);
+ aBitmap.CopyPixel(aDstB, aSrcB);
+ }
+ }
+ }
+
+ // init values with defaults
+ basegfx::B2DPoint aBitmapSize(1.0, 1.0);
+ basegfx::B2DVector aBitmapTopLeft(0.0, 0.0);
+
+ // are canges needed?
+ if(mbTiling || !mbStretch)
+ {
+ // init values with range sizes
+ const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0);
+ const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0);
+ aBitmapSize = basegfx::B2DPoint(fRangeWidth, fRangeHeight);
+
+ // size changes
+ if(0.0 != maSize.getX())
+ {
+ if(maSize.getX() < 0.0)
+ {
+ aBitmapSize.setX(aBitmapSize.getX() * (maSize.getX() * -0.01));
+ }
+ else
+ {
+ aBitmapSize.setX(maSize.getX());
+ }
+ }
+ else
+ {
+ aBitmapSize.setX(aLogicalSize.getX());
+ }
+
+ if(0.0 != maSize.getY())
+ {
+ if(maSize.getY() < 0.0)
+ {
+ aBitmapSize.setY(aBitmapSize.getY() * (maSize.getY() * -0.01));
+ }
+ else
+ {
+ aBitmapSize.setY(maSize.getY());
+ }
+ }
+ else
+ {
+ aBitmapSize.setY(aLogicalSize.getY());
+ }
+
+ // get values, force to centered if necessary
+ const basegfx::B2DVector aRectPoint(mbTiling ? maRectPoint : basegfx::B2DVector(0.0, 0.0));
+
+ // position changes X
+ if(0.0 == aRectPoint.getX())
+ {
+ aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5);
+ }
+ else if(1.0 == aRectPoint.getX())
+ {
+ aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX());
+ }
+
+ if(mbTiling && 0.0 != maOffsetPosition.getX())
+ {
+ aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (maOffsetPosition.getX() * 0.01)));
+ }
+
+ // position changes Y
+ if(0.0 == aRectPoint.getY())
+ {
+ aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5);
+ }
+ else if(1.0 == aRectPoint.getY())
+ {
+ aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY());
+ }
+
+ if(mbTiling && 0.0 != maOffsetPosition.getY())
+ {
+ aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (maOffsetPosition.getY() * 0.01)));
+ }
+
+ // apply expand
+ if(bExpandWidth)
+ {
+ aBitmapSize.setX(aBitmapSize.getX() * 2.0);
+ }
+
+ if(bExpandHeight)
+ {
+ aBitmapSize.setY(aBitmapSize.getY() * 2.0);
+ }
+
+ // apply bitmap size scaling to unit rectangle
+ aBitmapTopLeft.setX(aBitmapTopLeft.getX() / fRangeWidth);
+ aBitmapTopLeft.setY(aBitmapTopLeft.getY() / fRangeHeight);
+ aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth);
+ aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight);
+ }
+
+ return FillBitmapAttribute(aBitmap, aBitmapTopLeft, aBitmapSize, mbTiling);
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/attribute/strokeattribute.cxx b/drawinglayer/source/attribute/strokeattribute.cxx
new file mode 100644
index 000000000000..f3eb4797b832
--- /dev/null
+++ b/drawinglayer/source/attribute/strokeattribute.cxx
@@ -0,0 +1,63 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: strokeattribute.cxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:19 $
+ *
+ * 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/attribute/strokeattribute.hxx>
+#include <numeric>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace attribute
+ {
+ double StrokeAttribute::getFullDotDashLen() const
+ {
+ if(0.0 == mfFullDotDashLen && maDotDashArray.size())
+ {
+ // calculate length on demand
+ const double fAccumulated(::std::accumulate(maDotDashArray.begin(), maDotDashArray.end(), 0.0));
+ const_cast< StrokeAttribute* >(this)->mfFullDotDashLen = fAccumulated;
+ }
+
+ return mfFullDotDashLen;
+ }
+ } // end of namespace attribute
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/geometry/makefile.mk b/drawinglayer/source/geometry/makefile.mk
new file mode 100644
index 000000000000..38ceeb55a886
--- /dev/null
+++ b/drawinglayer/source/geometry/makefile.mk
@@ -0,0 +1,52 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# last change: $Author: aw $ $Date: 2008-06-10 09:29:32 $
+#
+# 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=geometry
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/viewinformation2d.obj \
+ $(SLO)$/viewinformation3d.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx
new file mode 100644
index 000000000000..706684c5f7d8
--- /dev/null
+++ b/drawinglayer/source/geometry/viewinformation2d.cxx
@@ -0,0 +1,553 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: viewinformation2d.cxx,v $
+ *
+ * $Revision: 1.7 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:07 $
+ *
+ * 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/geometry/viewinformation2d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <osl/mutex.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <com/sun/star/geometry/AffineMatrix2D.hpp>
+#include <com/sun/star/geometry/RealRectangle2D.hpp>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace geometry
+ {
+ class ImpViewInformation2D
+ {
+ private:
+ // ViewInformation2D implementation can change refcount, so we have only
+ // two memory regions for pairs of ViewInformation2D/ImpViewInformation2D
+ friend class ::drawinglayer::geometry::ViewInformation2D;
+
+ // the refcounter. 0 means exclusively used
+ sal_uInt32 mnRefCount;
+
+ protected:
+ // the object transformation
+ basegfx::B2DHomMatrix maObjectTransformation;
+
+ // the view transformation
+ basegfx::B2DHomMatrix maViewTransformation;
+
+ // the ObjectToView and it's inverse, both on demand from ObjectTransformation
+ // and ViewTransformation
+ basegfx::B2DHomMatrix maObjectToViewTransformation;
+ basegfx::B2DHomMatrix maInverseObjectToViewTransformation;
+
+ // the visible range and the on-demand one in ViewCoordinates
+ basegfx::B2DRange maViewport;
+ basegfx::B2DRange maDiscreteViewport;
+
+ // the DrawPage which is target of visualisation. This is needed e.g. for
+ // the view-dependent decomposition of PageNumber TextFields.
+ // This parameter is buffered here, but mainly resides in mxExtendedInformation,
+ // so it will be interpreted, but held there. It will also not be added
+ // to mxExtendedInformation in impFillViewInformationFromContent (it's there already)
+ uno::Reference< drawing::XDrawPage > mxVisualizedPage;
+
+ // the point in time
+ double mfViewTime;
+
+ // bitfield
+ bool mbReducedDisplayQuality : 1;
+
+ // the complete PropertyValue representation (if already created)
+ uno::Sequence< beans::PropertyValue > mxViewInformation;
+
+ // the extra PropertyValues; not represented by ViewTransformation,
+ // Viewport, VisualizedPage or ViewTime
+ uno::Sequence< beans::PropertyValue > mxExtendedInformation;
+
+ // the local UNO API strings
+ const ::rtl::OUString& getNamePropertyObjectTransformation()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyViewTransformation()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ViewTransformation"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyViewport()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Viewport"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyTime()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Time"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyVisualizedPage()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("VisualizedPage"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyReducedDisplayQuality()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality"));
+ return s_sNameProperty;
+ }
+
+ void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ {
+ if(rViewParameters.hasElements())
+ {
+ const sal_Int32 nCount(rViewParameters.getLength());
+ sal_Int32 nExtendedInsert(0);
+
+ // prepare extended information for filtering. Maximum size is nCount
+ mxExtendedInformation.realloc(nCount);
+
+ for(sal_Int32 a(0); a < nCount; a++)
+ {
+ const beans::PropertyValue& rProp = rViewParameters[a];
+
+ if(rProp.Name == getNamePropertyReducedDisplayQuality())
+ {
+ // extra information; add to filtered information
+ mxExtendedInformation[nExtendedInsert++] = rProp;
+
+ // for performance reasons, also cache content locally
+ sal_Bool bSalBool = sal_True;
+ rProp.Value >>= bSalBool;
+ mbReducedDisplayQuality = bSalBool;
+ }
+ else if(rProp.Name == getNamePropertyObjectTransformation())
+ {
+ com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
+ rProp.Value >>= aAffineMatrix2D;
+ basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, aAffineMatrix2D);
+ }
+ else if(rProp.Name == getNamePropertyViewTransformation())
+ {
+ com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
+ rProp.Value >>= aAffineMatrix2D;
+ basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D);
+ }
+ else if(rProp.Name == getNamePropertyViewport())
+ {
+ com::sun::star::geometry::RealRectangle2D aViewport;
+ rProp.Value >>= aViewport;
+ maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport);
+ }
+ else if(rProp.Name == getNamePropertyTime())
+ {
+ rProp.Value >>= mfViewTime;
+ }
+ else if(rProp.Name == getNamePropertyVisualizedPage())
+ {
+ rProp.Value >>= mxVisualizedPage;
+ }
+ else
+ {
+ // extra information; add to filtered information
+ mxExtendedInformation[nExtendedInsert++] = rProp;
+ }
+ }
+
+ // extra information size is now known; realloc to final size
+ mxExtendedInformation.realloc(nExtendedInsert);
+ }
+ }
+
+ void impFillViewInformationFromContent()
+ {
+ uno::Sequence< beans::PropertyValue > xRetval;
+ const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
+ const bool bViewTransformationUsed(!maViewTransformation.isIdentity());
+ const bool bViewportUsed(!maViewport.isEmpty());
+ const bool bTimeUsed(0.0 < mfViewTime);
+ const bool bVisualizedPageUsed(mxVisualizedPage.is());
+ const bool bReducedDisplayQualityUsed(true == mbReducedDisplayQuality);
+ const bool bExtraInformation(mxExtendedInformation.hasElements());
+ sal_uInt32 nIndex(0);
+ const sal_uInt32 nCount(
+ (bObjectTransformationUsed ? 1 : 0) +
+ (bViewTransformationUsed ? 1 : 0) +
+ (bViewportUsed ? 1 : 0) +
+ (bTimeUsed ? 1 : 0) +
+ (bVisualizedPageUsed ? 1 : 0) +
+ (bReducedDisplayQualityUsed ? 1 : 0) +
+ (bExtraInformation ? mxExtendedInformation.getLength() : 0));
+
+ mxViewInformation.realloc(nCount);
+
+ if(bObjectTransformationUsed)
+ {
+ com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
+ basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maObjectTransformation);
+ mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
+ nIndex++;
+ }
+
+ if(bViewTransformationUsed)
+ {
+ com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
+ basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maViewTransformation);
+ mxViewInformation[nIndex].Name = getNamePropertyViewTransformation();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
+ nIndex++;
+ }
+
+ if(bViewportUsed)
+ {
+ const com::sun::star::geometry::RealRectangle2D aViewport(basegfx::unotools::rectangle2DFromB2DRectangle(maViewport));
+ mxViewInformation[nIndex].Name = getNamePropertyViewport();
+ mxViewInformation[nIndex].Value <<= aViewport;
+ nIndex++;
+ }
+
+ if(bTimeUsed)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyTime();
+ mxViewInformation[nIndex].Value <<= mfViewTime;
+ nIndex++;
+ }
+
+ if(bVisualizedPageUsed)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyVisualizedPage();
+ mxViewInformation[nIndex].Value <<= mxVisualizedPage;
+ nIndex++;
+ }
+
+ if(bExtraInformation)
+ {
+ const sal_Int32 nExtra(mxExtendedInformation.getLength());
+
+ for(sal_Int32 a(0); a < nExtra; a++)
+ {
+ mxViewInformation[nIndex++] = mxExtendedInformation[a];
+ }
+ }
+ }
+
+ public:
+ ImpViewInformation2D(
+ const basegfx::B2DHomMatrix& rObjectTransformation,
+ const basegfx::B2DHomMatrix& rViewTransformation,
+ const basegfx::B2DRange& rViewport,
+ const uno::Reference< drawing::XDrawPage >& rxDrawPage,
+ double fViewTime,
+ const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
+ : mnRefCount(0),
+ maObjectTransformation(rObjectTransformation),
+ maViewTransformation(rViewTransformation),
+ maObjectToViewTransformation(),
+ maInverseObjectToViewTransformation(),
+ maViewport(rViewport),
+ maDiscreteViewport(),
+ mxVisualizedPage(rxDrawPage),
+ mfViewTime(fViewTime),
+ mbReducedDisplayQuality(false),
+ mxViewInformation(),
+ mxExtendedInformation()
+ {
+ impInterpretPropertyValues(rExtendedParameters);
+ }
+
+ ImpViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ : mnRefCount(0),
+ maObjectTransformation(),
+ maViewTransformation(),
+ maObjectToViewTransformation(),
+ maInverseObjectToViewTransformation(),
+ maViewport(),
+ maDiscreteViewport(),
+ mxVisualizedPage(),
+ mfViewTime(),
+ mbReducedDisplayQuality(false),
+ mxViewInformation(rViewParameters),
+ mxExtendedInformation()
+ {
+ impInterpretPropertyValues(rViewParameters);
+ }
+
+ const basegfx::B2DHomMatrix& getObjectTransformation() const
+ {
+ return maObjectTransformation;
+ }
+
+ const basegfx::B2DHomMatrix& getViewTransformation() const
+ {
+ return maViewTransformation;
+ }
+
+ const basegfx::B2DRange& getViewport() const
+ {
+ return maViewport;
+ }
+
+ const basegfx::B2DRange& getDiscreteViewport() const
+ {
+ ::osl::Mutex m_mutex;
+
+ if(maDiscreteViewport.isEmpty() && !maViewport.isEmpty())
+ {
+ basegfx::B2DRange aDiscreteViewport(maViewport);
+ aDiscreteViewport.transform(getViewTransformation());
+ const_cast< ImpViewInformation2D* >(this)->maDiscreteViewport = aDiscreteViewport;
+ }
+
+ return maDiscreteViewport;
+ }
+
+ const basegfx::B2DHomMatrix& getObjectToViewTransformation() const
+ {
+ ::osl::Mutex m_mutex;
+
+ if(maObjectToViewTransformation.isIdentity() &&
+ (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
+ {
+ basegfx::B2DHomMatrix aObjectToView(maViewTransformation * maObjectTransformation);
+ const_cast< ImpViewInformation2D* >(this)->maObjectToViewTransformation = aObjectToView;
+ }
+
+ return maObjectToViewTransformation;
+ }
+
+ const basegfx::B2DHomMatrix& getInverseObjectToViewTransformation() const
+ {
+ ::osl::Mutex m_mutex;
+
+ if(maInverseObjectToViewTransformation.isIdentity() &&
+ (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
+ {
+ basegfx::B2DHomMatrix aInverseObjectToView(maViewTransformation * maObjectTransformation);
+ aInverseObjectToView.invert();
+ const_cast< ImpViewInformation2D* >(this)->maInverseObjectToViewTransformation = aInverseObjectToView;
+ }
+
+ return maInverseObjectToViewTransformation;
+ }
+
+ double getViewTime() const
+ {
+ return mfViewTime;
+ }
+
+ const uno::Reference< drawing::XDrawPage >& getVisualizedPage() const
+ {
+ return mxVisualizedPage;
+ }
+
+ bool getReducedDisplayQuality() const
+ {
+ return mbReducedDisplayQuality;
+ }
+
+ const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
+ {
+ if(!mxViewInformation.hasElements())
+ {
+ const_cast< ImpViewInformation2D* >(this)->impFillViewInformationFromContent();
+ }
+
+ return mxViewInformation;
+ }
+
+ const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
+ {
+ return mxExtendedInformation;
+ }
+
+ bool operator==(const ImpViewInformation2D& rCandidate) const
+ {
+ return (maObjectTransformation == rCandidate.maObjectTransformation
+ && maViewTransformation == rCandidate.maViewTransformation
+ && maViewport == rCandidate.maViewport
+ && mxVisualizedPage == rCandidate.mxVisualizedPage
+ && mfViewTime == rCandidate.mfViewTime
+ && mxExtendedInformation == rCandidate.mxExtendedInformation);
+ }
+ };
+ } // end of anonymous namespace
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace geometry
+ {
+ ViewInformation2D::ViewInformation2D(
+ const basegfx::B2DHomMatrix& rObjectTransformation,
+ const basegfx::B2DHomMatrix& rViewTransformation,
+ const basegfx::B2DRange& rViewport,
+ const uno::Reference< drawing::XDrawPage >& rxDrawPage,
+ double fViewTime,
+ const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
+ : mpViewInformation2D(new ImpViewInformation2D(
+ rObjectTransformation,
+ rViewTransformation,
+ rViewport,
+ rxDrawPage,
+ fViewTime,
+ rExtendedParameters))
+ {
+ }
+
+ ViewInformation2D::ViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ : mpViewInformation2D(new ImpViewInformation2D(rViewParameters))
+ {
+ }
+
+ ViewInformation2D::ViewInformation2D(const ViewInformation2D& rCandidate)
+ : mpViewInformation2D(rCandidate.mpViewInformation2D)
+ {
+ ::osl::Mutex m_mutex;
+ mpViewInformation2D->mnRefCount++;
+ }
+
+ ViewInformation2D::~ViewInformation2D()
+ {
+ ::osl::Mutex m_mutex;
+
+ if(mpViewInformation2D->mnRefCount)
+ {
+ mpViewInformation2D->mnRefCount--;
+ }
+ else
+ {
+ delete mpViewInformation2D;
+ }
+ }
+
+ ViewInformation2D& ViewInformation2D::operator=(const ViewInformation2D& rCandidate)
+ {
+ ::osl::Mutex m_mutex;
+
+ if(mpViewInformation2D->mnRefCount)
+ {
+ mpViewInformation2D->mnRefCount--;
+ }
+ else
+ {
+ delete mpViewInformation2D;
+ }
+
+ mpViewInformation2D = rCandidate.mpViewInformation2D;
+ mpViewInformation2D->mnRefCount++;
+
+ return *this;
+ }
+
+ bool ViewInformation2D::operator==(const ViewInformation2D& rCandidate) const
+ {
+ if(rCandidate.mpViewInformation2D == mpViewInformation2D)
+ {
+ return true;
+ }
+
+ return (*rCandidate.mpViewInformation2D == *mpViewInformation2D);
+ }
+
+ const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
+ {
+ return mpViewInformation2D->getObjectTransformation();
+ }
+
+ const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
+ {
+ return mpViewInformation2D->getViewTransformation();
+ }
+
+ const basegfx::B2DRange& ViewInformation2D::getViewport() const
+ {
+ return mpViewInformation2D->getViewport();
+ }
+
+ double ViewInformation2D::getViewTime() const
+ {
+ return mpViewInformation2D->getViewTime();
+ }
+
+ const uno::Reference< drawing::XDrawPage >& ViewInformation2D::getVisualizedPage() const
+ {
+ return mpViewInformation2D->getVisualizedPage();
+ }
+
+ const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const
+ {
+ return mpViewInformation2D->getObjectToViewTransformation();
+ }
+
+ const basegfx::B2DHomMatrix& ViewInformation2D::getInverseObjectToViewTransformation() const
+ {
+ return mpViewInformation2D->getInverseObjectToViewTransformation();
+ }
+
+ const basegfx::B2DRange& ViewInformation2D::getDiscreteViewport() const
+ {
+ return mpViewInformation2D->getDiscreteViewport();
+ }
+
+ bool ViewInformation2D::getReducedDisplayQuality() const
+ {
+ return mpViewInformation2D->getReducedDisplayQuality();
+ }
+
+ const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const
+ {
+ return mpViewInformation2D->getViewInformationSequence();
+ }
+
+ const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getExtendedInformationSequence() const
+ {
+ return mpViewInformation2D->getExtendedInformationSequence();
+ }
+ } // end of namespace geometry
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/geometry/viewinformation3d.cxx b/drawinglayer/source/geometry/viewinformation3d.cxx
new file mode 100644
index 000000000000..a47384485ee7
--- /dev/null
+++ b/drawinglayer/source/geometry/viewinformation3d.cxx
@@ -0,0 +1,562 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: viewinformation3d.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:07 $
+ *
+ * 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/geometry/viewinformation3d.hxx>
+#include <basegfx/range/b3drange.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <com/sun/star/geometry/AffineMatrix3D.hpp>
+#include <com/sun/star/geometry/RealRectangle3D.hpp>
+#include <basegfx/tools/canvastools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace geometry
+ {
+ /** Implementation class for ViewInformation3D
+ */
+ class ImpViewInformation3D
+ {
+ private:
+ // ViewInformation3D implementation can change refcount, so we have only
+ // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D
+ friend class ::drawinglayer::geometry::ViewInformation3D;
+
+ // the refcounter. 0 means exclusively used
+ sal_uInt32 mnRefCount;
+
+ // the 3D transformations
+ // Object to World. This may change and being adapted when entering 3D transformation
+ // groups
+ basegfx::B3DHomMatrix maObjectTransformation;
+
+ // World to Camera. This includes VRP, VPN and VUV camera coordinate system
+ basegfx::B3DHomMatrix maOrientation;
+
+ // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the
+ // 3D to 2D projection which may be parallell or perspective. When it is perspective,
+ // the last line of the homogen matrix will NOT be unused
+ basegfx::B3DHomMatrix maProjection;
+
+ // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates
+ // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays
+ // view-independent. To get discrete coordinates, the 2D transformation of a scene
+ // as 2D object needs to be involved
+ basegfx::B3DHomMatrix maDeviceToView;
+
+ // Object to View is the linear combination of all four transformations. It's
+ // buffered to avoid too much matrix multiplying and created on demand
+ basegfx::B3DHomMatrix maObjectToView;
+
+ // the point in time
+ double mfViewTime;
+
+ // the complete PropertyValue representation (if already created)
+ uno::Sequence< beans::PropertyValue > mxViewInformation;
+
+ // the extra PropertyValues; does not contain the transformations
+ uno::Sequence< beans::PropertyValue > mxExtendedInformation;
+
+ // the local UNO API strings
+ const ::rtl::OUString& getNamePropertyObjectTransformation()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyOrientation()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyProjection()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyProjection_30()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyProjection_31()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyProjection_32()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyProjection_33()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyDeviceToView()
+ {
+ static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView"));
+ return s_sNameProperty;
+ }
+
+ const ::rtl::OUString& getNamePropertyTime()
+ {
+ static ::rtl::OUString s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time"));
+ return s_sNamePropertyTime;
+ }
+
+ // a central PropertyValue parsing method to allow transportatin of
+ // all ViewParameters using UNO API
+ void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ {
+ if(rViewParameters.hasElements())
+ {
+ const sal_Int32 nCount(rViewParameters.getLength());
+ sal_Int32 nExtendedInsert(0);
+
+ // prepare extended information for filtering. Maximum size is nCount
+ mxExtendedInformation.realloc(nCount);
+
+ for(sal_Int32 a(0); a < nCount; a++)
+ {
+ const beans::PropertyValue& rProp = rViewParameters[a];
+
+ if(rProp.Name == getNamePropertyObjectTransformation())
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ rProp.Value >>= aAffineMatrix3D;
+ maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
+ }
+ else if(rProp.Name == getNamePropertyOrientation())
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ rProp.Value >>= aAffineMatrix3D;
+ maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
+ }
+ else if(rProp.Name == getNamePropertyProjection())
+ {
+ // projection may be defined using a frustum in which case the last line of
+ // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
+ // these four values need to be treated extra
+ const double f_30(maProjection.get(3, 0));
+ const double f_31(maProjection.get(3, 1));
+ const double f_32(maProjection.get(3, 2));
+ const double f_33(maProjection.get(3, 3));
+
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ rProp.Value >>= aAffineMatrix3D;
+ maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
+
+ maProjection.set(3, 0, f_30);
+ maProjection.set(3, 1, f_31);
+ maProjection.set(3, 2, f_32);
+ maProjection.set(3, 3, f_33);
+ }
+ else if(rProp.Name == getNamePropertyProjection_30())
+ {
+ double f_30(0.0);
+ rProp.Value >>= f_30;
+ maProjection.set(3, 0, f_30);
+ }
+ else if(rProp.Name == getNamePropertyProjection_31())
+ {
+ double f_31(0.0);
+ rProp.Value >>= f_31;
+ maProjection.set(3, 1, f_31);
+ }
+ else if(rProp.Name == getNamePropertyProjection_32())
+ {
+ double f_32(0.0);
+ rProp.Value >>= f_32;
+ maProjection.set(3, 2, f_32);
+ }
+ else if(rProp.Name == getNamePropertyProjection_33())
+ {
+ double f_33(1.0);
+ rProp.Value >>= f_33;
+ maProjection.set(3, 3, f_33);
+ }
+ else if(rProp.Name == getNamePropertyDeviceToView())
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ rProp.Value >>= aAffineMatrix3D;
+ maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
+ }
+ else if(rProp.Name == getNamePropertyTime())
+ {
+ rProp.Value >>= mfViewTime;
+ }
+ else
+ {
+ // extra information; add to filtered information
+ mxExtendedInformation[nExtendedInsert++] = rProp;
+ }
+ }
+
+ // extra information size is now known; realloc to final size
+ mxExtendedInformation.realloc(nExtendedInsert);
+ }
+ }
+
+ // central method to create a Sequence of PropertyValues containing he complete
+ // data set
+ void impFillViewInformationFromContent()
+ {
+ uno::Sequence< beans::PropertyValue > xRetval;
+ const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
+ const bool bOrientationUsed(!maOrientation.isIdentity());
+ const bool bProjectionUsed(!maProjection.isIdentity());
+ const bool bDeviceToViewUsed(!maDeviceToView.isIdentity());
+ const bool bTimeUsed(0.0 < mfViewTime);
+ const bool bExtraInformation(mxExtendedInformation.hasElements());
+
+ // projection may be defined using a frustum in which case the last line of
+ // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
+ // these four values need to be treated extra
+ const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0)));
+ const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1)));
+ const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2)));
+ const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0));
+
+ sal_uInt32 nIndex(0);
+ const sal_uInt32 nCount(
+ (bObjectTransformationUsed ? 1 : 0) +
+ (bOrientationUsed ? 1 : 0) +
+ (bProjectionUsed ? 1 : 0) +
+ (bProjectionUsed_30 ? 1 : 0) +
+ (bProjectionUsed_31 ? 1 : 0) +
+ (bProjectionUsed_32 ? 1 : 0) +
+ (bProjectionUsed_33 ? 1 : 0) +
+ (bDeviceToViewUsed ? 1 : 0) +
+ (bTimeUsed ? 1 : 0) +
+ (bExtraInformation ? mxExtendedInformation.getLength() : 0));
+
+ mxViewInformation.realloc(nCount);
+
+ if(bObjectTransformationUsed)
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation);
+ mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
+ nIndex++;
+ }
+
+ if(bOrientationUsed)
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation);
+ mxViewInformation[nIndex].Name = getNamePropertyOrientation();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
+ nIndex++;
+ }
+
+ if(bProjectionUsed)
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection);
+ mxViewInformation[nIndex].Name = getNamePropertyProjection();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
+ nIndex++;
+ }
+
+ if(bProjectionUsed_30)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyProjection_30();
+ mxViewInformation[nIndex].Value <<= maProjection.get(3, 0);
+ nIndex++;
+ }
+
+ if(bProjectionUsed_31)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyProjection_31();
+ mxViewInformation[nIndex].Value <<= maProjection.get(3, 1);
+ nIndex++;
+ }
+
+ if(bProjectionUsed_32)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyProjection_32();
+ mxViewInformation[nIndex].Value <<= maProjection.get(3, 2);
+ nIndex++;
+ }
+
+ if(bProjectionUsed_33)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyProjection_33();
+ mxViewInformation[nIndex].Value <<= maProjection.get(3, 3);
+ nIndex++;
+ }
+
+ if(bDeviceToViewUsed)
+ {
+ com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
+ basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView);
+ mxViewInformation[nIndex].Name = getNamePropertyDeviceToView();
+ mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
+ nIndex++;
+ }
+
+ if(bTimeUsed)
+ {
+ mxViewInformation[nIndex].Name = getNamePropertyTime();
+ mxViewInformation[nIndex].Value <<= mfViewTime;
+ nIndex++;
+ }
+
+ if(bExtraInformation)
+ {
+ const sal_Int32 nExtra(mxExtendedInformation.getLength());
+
+ for(sal_Int32 a(0); a < nExtra; a++)
+ {
+ mxViewInformation[nIndex++] = mxExtendedInformation[a];
+ }
+ }
+ }
+
+ public:
+ ImpViewInformation3D(
+ const basegfx::B3DHomMatrix& rObjectTransformation,
+ const basegfx::B3DHomMatrix& rOrientation,
+ const basegfx::B3DHomMatrix& rProjection,
+ const basegfx::B3DHomMatrix& rDeviceToView,
+ double fViewTime,
+ const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
+ : mnRefCount(0),
+ maObjectTransformation(rObjectTransformation),
+ maOrientation(rOrientation),
+ maProjection(rProjection),
+ maDeviceToView(rDeviceToView),
+ mfViewTime(fViewTime),
+ mxViewInformation(),
+ mxExtendedInformation()
+ {
+ impInterpretPropertyValues(rExtendedParameters);
+ }
+
+ ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ : mnRefCount(0),
+ maObjectTransformation(),
+ maOrientation(),
+ maProjection(),
+ maDeviceToView(),
+ mfViewTime(),
+ mxViewInformation(rViewParameters),
+ mxExtendedInformation()
+ {
+ impInterpretPropertyValues(rViewParameters);
+ }
+
+ const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
+ const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; }
+ const basegfx::B3DHomMatrix& getProjection() const { return maProjection; }
+ const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; }
+ double getViewTime() const { return mfViewTime; }
+
+ const basegfx::B3DHomMatrix& getObjectToView() const
+ {
+ // on demand WorldToView creation
+ ::osl::Mutex m_mutex;
+
+ if(maObjectToView.isIdentity())
+ {
+ const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation;
+ }
+
+ return maObjectToView;
+ }
+
+ const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
+ {
+ ::osl::Mutex m_mutex;
+
+ if(!mxViewInformation.hasElements())
+ {
+ const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent();
+ }
+
+ return mxViewInformation;
+ }
+
+ const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
+ {
+ return mxExtendedInformation;
+ }
+
+ bool operator==(const ImpViewInformation3D& rCandidate) const
+ {
+ return (maObjectTransformation == rCandidate.maObjectTransformation
+ && maOrientation == rCandidate.maOrientation
+ && maProjection == rCandidate.maProjection
+ && maDeviceToView == rCandidate.maDeviceToView
+ && mfViewTime == rCandidate.mfViewTime
+ && mxExtendedInformation == rCandidate.mxExtendedInformation);
+ }
+ };
+ } // end of anonymous namespace
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace geometry
+ {
+ ViewInformation3D::ViewInformation3D(
+ const basegfx::B3DHomMatrix& rObjectObjectTransformation,
+ const basegfx::B3DHomMatrix& rOrientation,
+ const basegfx::B3DHomMatrix& rProjection,
+ const basegfx::B3DHomMatrix& rDeviceToView,
+ double fViewTime,
+ const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
+ : mpViewInformation3D(new ImpViewInformation3D(rObjectObjectTransformation, rOrientation, rProjection, rDeviceToView, fViewTime, rExtendedParameters))
+ {
+ }
+
+ ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
+ : mpViewInformation3D(new ImpViewInformation3D(rViewParameters))
+ {
+ }
+
+ ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate)
+ : mpViewInformation3D(rCandidate.mpViewInformation3D)
+ {
+ ::osl::Mutex m_mutex;
+ mpViewInformation3D->mnRefCount++;
+ }
+
+ ViewInformation3D::~ViewInformation3D()
+ {
+ ::osl::Mutex m_mutex;
+
+ if(mpViewInformation3D->mnRefCount)
+ {
+ mpViewInformation3D->mnRefCount--;
+ }
+ else
+ {
+ delete mpViewInformation3D;
+ }
+ }
+
+ ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate)
+ {
+ ::osl::Mutex m_mutex;
+
+ if(mpViewInformation3D->mnRefCount)
+ {
+ mpViewInformation3D->mnRefCount--;
+ }
+ else
+ {
+ delete mpViewInformation3D;
+ }
+
+ mpViewInformation3D = rCandidate.mpViewInformation3D;
+ mpViewInformation3D->mnRefCount++;
+
+ return *this;
+ }
+
+ bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const
+ {
+ if(rCandidate.mpViewInformation3D == mpViewInformation3D)
+ {
+ return true;
+ }
+
+ return (*rCandidate.mpViewInformation3D == *mpViewInformation3D);
+ }
+
+ const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const
+ {
+ return mpViewInformation3D->getObjectTransformation();
+ }
+
+ const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const
+ {
+ return mpViewInformation3D->getOrientation();
+ }
+
+ const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const
+ {
+ return mpViewInformation3D->getProjection();
+ }
+
+ const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const
+ {
+ return mpViewInformation3D->getDeviceToView();
+ }
+
+ const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const
+ {
+ return mpViewInformation3D->getObjectToView();
+ }
+
+ double ViewInformation3D::getViewTime() const
+ {
+ return mpViewInformation3D->getViewTime();
+ }
+
+ const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const
+ {
+ return mpViewInformation3D->getViewInformationSequence();
+ }
+
+ const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const
+ {
+ return mpViewInformation3D->getExtendedInformationSequence();
+ }
+ } // end of namespace geometry
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
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
diff --git a/drawinglayer/source/primitive3d/baseprimitive3d.cxx b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
new file mode 100644
index 000000000000..032ae068003b
--- /dev/null
+++ b/drawinglayer/source/primitive3d/baseprimitive3d.cxx
@@ -0,0 +1,264 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: baseprimitive3d.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/baseprimitive3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence BasePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return Primitive3DSequence();
+ }
+
+ BasePrimitive3D::BasePrimitive3D()
+ : BasePrimitive3DImplBase(m_aMutex),
+ maLocalDecomposition()
+ {
+ }
+
+ bool BasePrimitive3D::operator==( const BasePrimitive3D& rPrimitive ) const
+ {
+ return (getPrimitiveID() == rPrimitive.getPrimitiveID());
+ }
+
+ basegfx::B3DRange BasePrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ return getB3DRangeFromPrimitive3DSequence(get3DDecomposition(rViewInformation), rViewInformation);
+ }
+
+ Primitive3DSequence BasePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if(!getLocalDecomposition().hasElements())
+ {
+ const Primitive3DSequence aNewSequence(createLocalDecomposition(rViewInformation));
+ const_cast< BasePrimitive3D* >(this)->setLocalDecomposition(aNewSequence);
+ }
+
+ return getLocalDecomposition();
+ }
+
+ Primitive3DSequence SAL_CALL BasePrimitive3D::getDecomposition( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException )
+ {
+ const geometry::ViewInformation3D aViewInformation(rViewParameters);
+ return get3DDecomposition(rViewParameters);
+ }
+
+ com::sun::star::geometry::RealRectangle3D SAL_CALL BasePrimitive3D::getRange( const uno::Sequence< beans::PropertyValue >& rViewParameters ) throw ( uno::RuntimeException )
+ {
+ const geometry::ViewInformation3D aViewInformation(rViewParameters);
+ return basegfx::unotools::rectangle3DFromB3DRectangle(getB3DRange(aViewInformation));
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// tooling
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ // get range3D from a given Primitive3DReference
+ basegfx::B3DRange getB3DRangeFromPrimitive3DReference(const Primitive3DReference& rCandidate, const geometry::ViewInformation3D& aViewInformation)
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rCandidate.is())
+ {
+ // try to get C++ implementation base
+ const BasePrimitive3D* pCandidate(dynamic_cast< BasePrimitive3D* >(rCandidate.get()));
+
+ if(pCandidate)
+ {
+ // use it if possible
+ aRetval.expand(pCandidate->getB3DRange(aViewInformation));
+ }
+ else
+ {
+ // use UNO API call instead
+ const uno::Sequence< beans::PropertyValue >& rViewParameters(aViewInformation.getViewInformationSequence());
+ aRetval.expand(basegfx::unotools::b3DRectangleFromRealRectangle3D(rCandidate->getRange(rViewParameters)));
+ }
+ }
+
+ return aRetval;
+ }
+
+ // get range3D from a given Primitive3DSequence
+ basegfx::B3DRange getB3DRangeFromPrimitive3DSequence(const Primitive3DSequence& rCandidate, const geometry::ViewInformation3D& aViewInformation)
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rCandidate.hasElements())
+ {
+ const sal_Int32 nCount(rCandidate.getLength());
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ aRetval.expand(getB3DRangeFromPrimitive3DReference(rCandidate[a], aViewInformation));
+ }
+ }
+
+ return aRetval;
+ }
+
+ bool arePrimitive3DReferencesEqual(const Primitive3DReference& rxA, const Primitive3DReference& rxB)
+ {
+ const sal_Bool bAIs(rxA.is());
+
+ if(bAIs != rxB.is())
+ {
+ return false;
+ }
+
+ if(!bAIs)
+ {
+ return true;
+ }
+
+ const BasePrimitive3D* pA(dynamic_cast< const BasePrimitive3D* >(rxA.get()));
+ const BasePrimitive3D* pB(dynamic_cast< const BasePrimitive3D* >(rxB.get()));
+ const bool bAEqualZero(pA == 0L);
+
+ if(bAEqualZero != (pB == 0L))
+ {
+ return false;
+ }
+
+ if(bAEqualZero)
+ {
+ return false;
+ }
+
+ return (pA->operator==(*pB));
+ }
+
+ bool arePrimitive3DSequencesEqual(const Primitive3DSequence& rA, const Primitive3DSequence& rB)
+ {
+ const sal_Bool bAHasElements(rA.hasElements());
+
+ if(bAHasElements != rB.hasElements())
+ {
+ return false;
+ }
+
+ if(!bAHasElements)
+ {
+ return true;
+ }
+
+ const sal_Int32 nCount(rA.getLength());
+
+ if(nCount != rB.getLength())
+ {
+ return false;
+ }
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ if(!arePrimitive3DReferencesEqual(rA[a], rB[a]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // concatenate sequence
+ void appendPrimitive3DSequenceToPrimitive3DSequence(Primitive3DSequence& rDest, const Primitive3DSequence& rSource)
+ {
+ if(rSource.hasElements())
+ {
+ if(rDest.hasElements())
+ {
+ const sal_Int32 nSourceCount(rSource.getLength());
+ const sal_Int32 nDestCount(rDest.getLength());
+ const sal_Int32 nTargetCount(nSourceCount + nDestCount);
+ sal_Int32 nInsertPos(nDestCount);
+
+ rDest.realloc(nTargetCount);
+
+ for(sal_Int32 a(0L); a < nSourceCount; a++)
+ {
+ if(rSource[a].is())
+ {
+ rDest[nInsertPos++] = rSource[a];
+ }
+ }
+
+ if(nInsertPos != nTargetCount)
+ {
+ rDest.realloc(nInsertPos);
+ }
+ }
+ else
+ {
+ rDest = rSource;
+ }
+ }
+ }
+
+ // concatenate single Primitive3D
+ void appendPrimitive3DReferenceToPrimitive3DSequence(Primitive3DSequence& rDest, const Primitive3DReference& rSource)
+ {
+ if(rSource.is())
+ {
+ const sal_Int32 nDestCount(rDest.getLength());
+ rDest.realloc(nDestCount + 1L);
+ rDest[nDestCount] = rSource;
+ }
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/groupprimitive3d.cxx b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
new file mode 100644
index 000000000000..b8ed86ee952a
--- /dev/null
+++ b/drawinglayer/source/primitive3d/groupprimitive3d.cxx
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: groupprimitive3d.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/groupprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ /// default: just return children, so all renderers not supporting group will use it's content
+ Primitive3DSequence GroupPrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return getChildren();
+ }
+
+ GroupPrimitive3D::GroupPrimitive3D( const Primitive3DSequence& rChildren )
+ : BasePrimitive3D(),
+ maChildren(rChildren)
+ {
+ }
+
+ /** The compare opertator uses the Sequence::==operator, so only checking if
+ the rererences are equal. All non-equal references are interpreted as
+ non-equal.
+ */
+ bool GroupPrimitive3D::operator==( const BasePrimitive3D& rPrimitive ) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const GroupPrimitive3D& rCompare = static_cast< const GroupPrimitive3D& >(rPrimitive);
+
+ return (arePrimitive3DSequencesEqual(getChildren(), rCompare.getChildren()));
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(GroupPrimitive3D, PRIMITIVE3D_ID_GROUPPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
new file mode 100644
index 000000000000..dd49f99b751c
--- /dev/null
+++ b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx
@@ -0,0 +1,313 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: hatchtextureprimitive3d.cxx,v $
+ *
+ * $Revision: 1.11 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <drawinglayer/texture/texture.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence HatchTexturePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getChildren().hasElements())
+ {
+ const Primitive3DSequence aSource(getChildren());
+ const sal_uInt32 nSourceCount(aSource.getLength());
+ std::vector< Primitive3DReference > aDestination;
+
+ for(sal_uInt32 a(0); a < nSourceCount; a++)
+ {
+ // get reference
+ const Primitive3DReference xReference(aSource[a]);
+
+ if(xReference.is())
+ {
+ // try to cast to BasePrimitive2D implementation
+ const BasePrimitive3D* pBasePrimitive = dynamic_cast< const BasePrimitive3D* >(xReference.get());
+
+ if(pBasePrimitive)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ // not all content is needed, remove transparencies and ModifiedColorPrimitives
+ switch(pBasePrimitive->getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // polyPolygonMaterialPrimitive3D, check texturing and hatching
+ const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive);
+ const basegfx::B3DPolyPolygon aFillPolyPolygon(rPrimitive.getB3DPolyPolygon());
+
+ if(maHatch.isFillBackground())
+ {
+ // add original primitive for background
+ aDestination.push_back(xReference);
+ }
+
+ if(aFillPolyPolygon.areTextureCoordinatesUsed())
+ {
+ const sal_uInt32 nPolyCount(aFillPolyPolygon.count());
+ basegfx::B2DPolyPolygon aTexPolyPolygon;
+ basegfx::B2DPoint a2N;
+ basegfx::B2DVector a2X, a2Y;
+ basegfx::B3DPoint a3N;
+ basegfx::B3DVector a3X, a3Y;
+ bool b2N(false), b2X(false), b2Y(false);
+
+ for(sal_uInt32 b(0); b < nPolyCount; b++)
+ {
+ const basegfx::B3DPolygon aPartPoly(aFillPolyPolygon.getB3DPolygon(b));
+ const sal_uInt32 nPointCount(aPartPoly.count());
+ basegfx::B2DPolygon aTexPolygon;
+
+ for(sal_uInt32 c(0); c < nPointCount; c++)
+ {
+ const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c));
+
+ if(!b2N)
+ {
+ a2N = a2Candidate;
+ a3N = aPartPoly.getB3DPoint(c);
+ b2N = true;
+ }
+ else if(!b2X && !a2N.equal(a2Candidate))
+ {
+ a2X = a2Candidate - a2N;
+ a3X = aPartPoly.getB3DPoint(c) - a3N;
+ b2X = true;
+ }
+ else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate))
+ {
+ a2Y = a2Candidate - a2N;
+
+ const double fCross(a2X.cross(a2Y));
+
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ a3Y = aPartPoly.getB3DPoint(c) - a3N;
+ b2Y = true;
+ }
+ }
+
+ aTexPolygon.append(a2Candidate);
+ }
+
+ aTexPolygon.setClosed(true);
+ aTexPolyPolygon.append(aTexPolygon);
+ }
+
+ if(b2N && b2X && b2Y)
+ {
+ // found two linearly independent 2D vectors
+ // get 2d range of texture coordinates
+ const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aTexPolyPolygon));
+ const basegfx::BColor aHatchColor(getHatch().getColor());
+ const double fAngle(-getHatch().getAngle());
+ ::std::vector< basegfx::B2DHomMatrix > aMatrices;
+
+ // get hatch transformations
+ switch(getHatch().getStyle())
+ {
+ case attribute::HATCHSTYLE_TRIPLE:
+ {
+ // rotated 45 degrees
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle + F_PI4);
+ aHatch.appendTransformations(aMatrices);
+ }
+ case attribute::HATCHSTYLE_DOUBLE:
+ {
+ // rotated 90 degrees
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle + F_PI2);
+ aHatch.appendTransformations(aMatrices);
+ }
+ case attribute::HATCHSTYLE_SINGLE:
+ {
+ // angle as given
+ texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle);
+ aHatch.appendTransformations(aMatrices);
+ }
+ }
+
+ // create geometry from unit line
+ basegfx::B2DPolyPolygon a2DHatchLines;
+ basegfx::B2DPolygon a2DUnitLine;
+ a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0));
+ a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0));
+
+ for(sal_uInt32 c(0); c < aMatrices.size(); c++)
+ {
+ const basegfx::B2DHomMatrix& rMatrix = aMatrices[c];
+ basegfx::B2DPolygon aNewLine(a2DUnitLine);
+ aNewLine.transform(rMatrix);
+ a2DHatchLines.append(aNewLine);
+ }
+
+ if(a2DHatchLines.count())
+ {
+ // clip against texture polygon
+ a2DHatchLines = basegfx::tools::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true);
+ }
+
+ if(a2DHatchLines.count())
+ {
+ // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the new coordinate system
+ basegfx::B2DHomMatrix a2D;
+ a2D.set(0, 0, a2X.getX());
+ a2D.set(1, 0, a2X.getY());
+ a2D.set(0, 1, a2Y.getX());
+ a2D.set(1, 1, a2Y.getY());
+ a2D.set(0, 2, a2N.getX());
+ a2D.set(1, 2, a2N.getY());
+
+ // invert that transformation, so we have a back-transformation from texture coordinates
+ // to unit coordinates
+ a2D.invert();
+ a2DHatchLines.transform(a2D);
+
+ // expand back-transformated geometry tpo 3D
+ basegfx::B3DPolyPolygon a3DHatchLines(basegfx::tools::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0));
+
+ // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents
+ // a coordinate system transformation from unit coordinates to the object's 3d coordinate system
+ basegfx::B3DHomMatrix a3D;
+ a3D.set(0, 0, a3X.getX());
+ a3D.set(1, 0, a3X.getY());
+ a3D.set(2, 0, a3X.getZ());
+ a3D.set(0, 1, a3Y.getX());
+ a3D.set(1, 1, a3Y.getY());
+ a3D.set(2, 1, a3Y.getZ());
+ a3D.set(0, 3, a3N.getX());
+ a3D.set(1, 3, a3N.getY());
+ a3D.set(2, 3, a3N.getZ());
+
+ // transform hatch lines to 3D object coordinates
+ a3DHatchLines.transform(a3D);
+
+ // build primitives from this geometry
+ const sal_uInt32 nHatchLines(a3DHatchLines.count());
+
+ for(sal_uInt32 d(0); d < nHatchLines; d++)
+ {
+ const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor));
+ aDestination.push_back(xRef);
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ default :
+ {
+ // add reference to result
+ aDestination.push_back(xReference);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // unknown implementation, add to result
+ aDestination.push_back(xReference);
+ }
+ }
+ }
+
+ // prepare return value
+ const sal_uInt32 nDestSize(aDestination.size());
+ aRetval.realloc(nDestSize);
+
+ for(sal_uInt32 b(0); b < nDestSize; b++)
+ {
+ aRetval[b] = aDestination[b];
+ }
+ }
+
+ return aRetval;
+ }
+
+ HatchTexturePrimitive3D::HatchTexturePrimitive3D(
+ const attribute::FillHatchAttribute& rHatch,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate,
+ bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maHatch(rHatch)
+ {
+ }
+
+ bool HatchTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const HatchTexturePrimitive3D& rCompare = (HatchTexturePrimitive3D&)rPrimitive;
+
+ return (getHatch() == rCompare.getHatch());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(HatchTexturePrimitive3D, PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/hittestprimitive3d.cxx b/drawinglayer/source/primitive3d/hittestprimitive3d.cxx
new file mode 100644
index 000000000000..50616ab1548b
--- /dev/null
+++ b/drawinglayer/source/primitive3d/hittestprimitive3d.cxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: hittestprimitive3d.cxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/25 17:12:14 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence HitTestPrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // return empty sequence
+ return Primitive3DSequence();
+ }
+
+ HitTestPrimitive3D::HitTestPrimitive3D(
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren)
+ {
+ }
+
+ basegfx::B3DRange HitTestPrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ return getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(HitTestPrimitive3D, PRIMITIVE3D_ID_HITTESTPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/makefile.mk b/drawinglayer/source/primitive3d/makefile.mk
new file mode 100644
index 000000000000..fb160fb9bfa7
--- /dev/null
+++ b/drawinglayer/source/primitive3d/makefile.mk
@@ -0,0 +1,70 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.5 $
+#
+# 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
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJNAME=drawinglayer
+TARGET=primitive3d
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/baseprimitive3d.obj \
+ $(SLO)$/groupprimitive3d.obj \
+ $(SLO)$/hatchtextureprimitive3d.obj \
+ $(SLO)$/hittestprimitive3d.obj \
+ $(SLO)$/modifiedcolorprimitive3d.obj \
+ $(SLO)$/polypolygonprimitive3d.obj \
+ $(SLO)$/polygonprimitive3d.obj \
+ $(SLO)$/polygontubeprimitive3d.obj \
+ $(SLO)$/sdrcubeprimitive3d.obj \
+ $(SLO)$/sdrdecompositiontools3d.obj \
+ $(SLO)$/sdrextrudelathetools3d.obj \
+ $(SLO)$/sdrextrudeprimitive3d.obj \
+ $(SLO)$/sdrlatheprimitive3d.obj \
+ $(SLO)$/sdrpolypolygonprimitive3d.obj \
+ $(SLO)$/sdrprimitive3d.obj \
+ $(SLO)$/sdrsphereprimitive3d.obj \
+ $(SLO)$/shadowprimitive3d.obj \
+ $(SLO)$/textureprimitive3d.obj \
+ $(SLO)$/transformprimitive3d.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
new file mode 100644
index 000000000000..b683cef9defa
--- /dev/null
+++ b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: modifiedcolorprimitive3d.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ ModifiedColorPrimitive3D::ModifiedColorPrimitive3D(
+ const Primitive3DSequence& rChildren,
+ const basegfx::BColorModifier& rColorModifier)
+ : GroupPrimitive3D(rChildren),
+ maColorModifier(rColorModifier)
+ {
+ }
+
+ bool ModifiedColorPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const ModifiedColorPrimitive3D& rCompare = (ModifiedColorPrimitive3D&)rPrimitive;
+
+ return (maColorModifier == rCompare.maColorModifier);
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(ModifiedColorPrimitive3D, PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
new file mode 100644
index 000000000000..b89499091dd0
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
@@ -0,0 +1,186 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: polygonprimitive3d.cxx,v $
+ *
+ * $Revision: 1.10 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/polygontubeprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ PolygonHairlinePrimitive3D::PolygonHairlinePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const basegfx::BColor& rBColor)
+ : BasePrimitive3D(),
+ maPolygon(rPolygon),
+ maBColor(rBColor)
+ {
+ }
+
+ bool PolygonHairlinePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonHairlinePrimitive3D& rCompare = (PolygonHairlinePrimitive3D&)rPrimitive;
+
+ return (getB3DPolygon() == rCompare.getB3DPolygon()
+ && getBColor() == rCompare.getBColor());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange PolygonHairlinePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return basegfx::tools::getRange(getB3DPolygon());
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonHairlinePrimitive3D, PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence PolygonStrokePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getB3DPolygon().count())
+ {
+ basegfx::B3DPolyPolygon aHairLinePolyPolygon;
+
+ if(0.0 == getStrokeAttribute().getFullDotDashLen())
+ {
+ aHairLinePolyPolygon = basegfx::B3DPolyPolygon(getB3DPolygon());
+ }
+ else
+ {
+ // apply LineStyle
+ basegfx::tools::applyLineDashing(getB3DPolygon(), getStrokeAttribute().getDotDashArray(), &aHairLinePolyPolygon, 0, getStrokeAttribute().getFullDotDashLen());
+ }
+
+ // prepare result
+ aRetval.realloc(aHairLinePolyPolygon.count());
+
+ if(getLineAttribute().getWidth())
+ {
+ // create fat line data
+ const double fRadius(getLineAttribute().getWidth() / 2.0);
+ const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
+
+ for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
+ {
+ // create tube primitives
+ const Primitive3DReference xRef(new PolygonTubePrimitive3D(aHairLinePolyPolygon.getB3DPolygon(a), getLineAttribute().getColor(), fRadius, aLineJoin));
+ aRetval[a] = xRef;
+ }
+ }
+ else
+ {
+ // create hair line data for all sub polygons
+ for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B3DPolygon aCandidate = aHairLinePolyPolygon.getB3DPolygon(a);
+ const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(aCandidate, getLineAttribute().getColor()));
+ aRetval[a] = xRef;
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ PolygonStrokePrimitive3D::PolygonStrokePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute,
+ const attribute::StrokeAttribute& rStrokeAttribute)
+ : BasePrimitive3D(),
+ maPolygon(rPolygon),
+ maLineAttribute(rLineAttribute),
+ maStrokeAttribute(rStrokeAttribute)
+ {
+ }
+
+ PolygonStrokePrimitive3D::PolygonStrokePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const attribute::LineAttribute& rLineAttribute)
+ : BasePrimitive3D(),
+ maPolygon(rPolygon),
+ maLineAttribute(rLineAttribute),
+ maStrokeAttribute()
+ {
+ }
+
+ bool PolygonStrokePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonStrokePrimitive3D& rCompare = (PolygonStrokePrimitive3D&)rPrimitive;
+
+ return (getB3DPolygon() == rCompare.getB3DPolygon()
+ && getLineAttribute() == rCompare.getLineAttribute()
+ && getStrokeAttribute() == rCompare.getStrokeAttribute());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonStrokePrimitive3D, PRIMITIVE3D_ID_POLYGONSTROKEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
new file mode 100644
index 000000000000..09c4acdcaed5
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
@@ -0,0 +1,573 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: polygontubeprimitive3d.cxx,v $
+ *
+ * $Revision: 1.12 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/polygontubeprimitive3d.hxx>
+#include <drawinglayer/attribute/materialattribute3d.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ namespace // anonymous namespace
+ {
+ Primitive3DSequence getLineTubeSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial)
+ {
+ // static data for buffered tube primitives
+ static Primitive3DSequence aLineTubeList;
+ static sal_uInt32 nLineTubeSegments(0L);
+ static attribute::MaterialAttribute3D aLineMaterial;
+
+ // may exclusively change static data, use mutex
+ ::osl::Mutex m_mutex;
+
+ if(nSegments != nLineTubeSegments || rMaterial != aLineMaterial)
+ {
+ nLineTubeSegments = nSegments;
+ aLineMaterial = rMaterial;
+ aLineTubeList = Primitive3DSequence();
+ }
+
+ if(!aLineTubeList.hasElements() && 0L != nLineTubeSegments)
+ {
+ const basegfx::B3DPoint aLeft(0.0, 0.0, 0.0);
+ const basegfx::B3DPoint aRight(1.0, 0.0, 0.0);
+ basegfx::B3DPoint aLastLeft(0.0, 1.0, 0.0);
+ basegfx::B3DPoint aLastRight(1.0, 1.0, 0.0);
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(F_2PI / (double)nLineTubeSegments, 0.0, 0.0);
+ aLineTubeList.realloc(nLineTubeSegments);
+
+ for(sal_uInt32 a(0L); a < nLineTubeSegments; a++)
+ {
+ const basegfx::B3DPoint aNextLeft(aRot * aLastLeft);
+ const basegfx::B3DPoint aNextRight(aRot * aLastRight);
+ basegfx::B3DPolygon aNewPolygon;
+
+ aNewPolygon.append(aNextLeft);
+ aNewPolygon.setNormal(0L, basegfx::B3DVector(aNextLeft - aLeft));
+
+ aNewPolygon.append(aLastLeft);
+ aNewPolygon.setNormal(1L, basegfx::B3DVector(aLastLeft - aLeft));
+
+ aNewPolygon.append(aLastRight);
+ aNewPolygon.setNormal(2L, basegfx::B3DVector(aLastRight - aRight));
+
+ aNewPolygon.append(aNextRight);
+ aNewPolygon.setNormal(3L, basegfx::B3DVector(aNextRight - aRight));
+
+ aNewPolygon.setClosed(true);
+
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false));
+ aLineTubeList[a] = xRef;
+
+ aLastLeft = aNextLeft;
+ aLastRight = aNextRight;
+ }
+ }
+
+ return aLineTubeList;
+ }
+
+ Primitive3DSequence getLineCapSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial)
+ {
+ // static data for buffered tube primitives
+ static Primitive3DSequence aLineCapList;
+ static sal_uInt32 nLineCapSegments(0L);
+ static attribute::MaterialAttribute3D aLineMaterial;
+
+ // may exclusively change static data, use mutex
+ ::osl::Mutex m_mutex;
+
+ if(nSegments != nLineCapSegments || rMaterial != aLineMaterial)
+ {
+ nLineCapSegments = nSegments;
+ aLineMaterial = rMaterial;
+ aLineCapList = Primitive3DSequence();
+ }
+
+ if(!aLineCapList.hasElements() && 0L != nLineCapSegments)
+ {
+ const basegfx::B3DPoint aNull(0.0, 0.0, 0.0);
+ basegfx::B3DPoint aLast(0.0, 1.0, 0.0);
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(F_2PI / (double)nLineCapSegments, 0.0, 0.0);
+ aLineCapList.realloc(nLineCapSegments);
+
+ for(sal_uInt32 a(0L); a < nLineCapSegments; a++)
+ {
+ const basegfx::B3DPoint aNext(aRot * aLast);
+ basegfx::B3DPolygon aNewPolygon;
+
+ aNewPolygon.append(aLast);
+ aNewPolygon.setNormal(0L, basegfx::B3DVector(aLast - aNull));
+
+ aNewPolygon.append(aNext);
+ aNewPolygon.setNormal(1L, basegfx::B3DVector(aNext - aNull));
+
+ aNewPolygon.append(aNull);
+ aNewPolygon.setNormal(2L, basegfx::B3DVector(-1.0, 0.0, 0.0));
+
+ aNewPolygon.setClosed(true);
+
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false));
+ aLineCapList[a] = xRef;
+
+ aLast = aNext;
+ }
+ }
+
+ return aLineCapList;
+ }
+
+ Primitive3DSequence getLineJoinSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial,
+ double fAngle,
+ double /*fDegreeStepWidth*/,
+ double fMiterMinimumAngle,
+ basegfx::B2DLineJoin aLineJoin)
+ {
+ // nSegments is for whole circle, adapt to half circle
+ const sal_uInt32 nVerSeg(nSegments >> 1L);
+ std::vector< BasePrimitive3D* > aResultVector;
+
+ if(nVerSeg)
+ {
+ if(basegfx::B2DLINEJOIN_ROUND == aLineJoin)
+ {
+ // calculate new horizontal segments
+ const sal_uInt32 nHorSeg((sal_uInt32)((fAngle / F_2PI) * (double)nSegments));
+
+ if(nHorSeg)
+ {
+ // create half-sphere
+ const basegfx::B3DPolyPolygon aSphere(basegfx::tools::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle));
+
+ for(sal_uInt32 a(0L); a < aSphere.count(); a++)
+ {
+ const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a));
+ const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aPartPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+ }
+ else
+ {
+ // fallback to bevel when there is not at least one segment hor and ver
+ aLineJoin = basegfx::B2DLINEJOIN_BEVEL;
+ }
+ }
+
+ if(basegfx::B2DLINEJOIN_MIDDLE == aLineJoin
+ || basegfx::B2DLINEJOIN_BEVEL == aLineJoin
+ || basegfx::B2DLINEJOIN_MITER == aLineJoin)
+ {
+ if(basegfx::B2DLINEJOIN_MITER == aLineJoin)
+ {
+ const double fMiterAngle(fAngle/2.0);
+
+ if(fMiterAngle < fMiterMinimumAngle)
+ {
+ // fallback to bevel when miter's angle is too small
+ aLineJoin = basegfx::B2DLINEJOIN_BEVEL;
+ }
+ }
+
+ const double fInc(F_PI / (double)nVerSeg);
+ const double fSin(sin(-fAngle));
+ const double fCos(cos(-fAngle));
+ const bool bMiter(basegfx::B2DLINEJOIN_MITER == aLineJoin);
+ const double fMiterSin(bMiter ? sin(-(fAngle/2.0)) : 0.0);
+ const double fMiterCos(bMiter ? cos(-(fAngle/2.0)) : 0.0);
+ double fPos(-F_PI2);
+ basegfx::B3DPoint aPointOnXY, aPointRotY, aNextPointOnXY, aNextPointRotY;
+ basegfx::B3DPoint aCurrMiter, aNextMiter;
+ basegfx::B3DPolygon aNewPolygon, aMiterPolygon;
+
+ // close polygon
+ aNewPolygon.setClosed(true);
+ aMiterPolygon.setClosed(true);
+
+ for(sal_uInt32 a(0L); a < nVerSeg; a++)
+ {
+ const bool bFirst(0L == a);
+ const bool bLast(a + 1L == nVerSeg);
+
+ if(bFirst || !bLast)
+ {
+ fPos += fInc;
+
+ aNextPointOnXY = basegfx::B3DPoint(
+ cos(fPos),
+ sin(fPos),
+ 0.0);
+
+ aNextPointRotY = basegfx::B3DPoint(
+ aNextPointOnXY.getX() * fCos,
+ aNextPointOnXY.getY(),
+ aNextPointOnXY.getX() * fSin);
+
+ if(bMiter)
+ {
+ aNextMiter = basegfx::B3DPoint(
+ aNextPointOnXY.getX(),
+ aNextPointOnXY.getY(),
+ fMiterSin * (aNextPointOnXY.getX() / fMiterCos));
+ }
+ }
+
+ if(bFirst)
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextMiter);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aMiterPolygon.append(aNextMiter);
+ aMiterPolygon.append(aNextPointRotY);
+ }
+ else
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0));
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextPointRotY);
+ }
+ }
+ else if(bLast)
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aNewPolygon.append(aCurrMiter);
+ aNewPolygon.append(aPointOnXY);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aMiterPolygon.append(aPointRotY);
+ aMiterPolygon.append(aCurrMiter);
+ }
+ else
+ {
+ aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0));
+ aNewPolygon.append(aPointRotY);
+ aNewPolygon.append(aPointOnXY);
+ }
+ }
+ else
+ {
+ aNewPolygon.clear();
+
+ if(bMiter)
+ {
+ aNewPolygon.append(aPointOnXY);
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextMiter);
+ aNewPolygon.append(aCurrMiter);
+
+ aMiterPolygon.clear();
+ aMiterPolygon.append(aCurrMiter);
+ aMiterPolygon.append(aNextMiter);
+ aMiterPolygon.append(aNextPointRotY);
+ aMiterPolygon.append(aPointRotY);
+ }
+ else
+ {
+ aNewPolygon.append(aPointRotY);
+ aNewPolygon.append(aPointOnXY);
+ aNewPolygon.append(aNextPointOnXY);
+ aNewPolygon.append(aNextPointRotY);
+ }
+ }
+
+ // set normals
+ for(sal_uInt32 b(0L); b < aNewPolygon.count(); b++)
+ {
+ aNewPolygon.setNormal(b, basegfx::B3DVector(aNewPolygon.getB3DPoint(b)));
+ }
+
+ // create primitive
+ if(aNewPolygon.count())
+ {
+ const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+
+ if(bMiter && aMiterPolygon.count())
+ {
+ // set normals
+ for(sal_uInt32 c(0L); c < aMiterPolygon.count(); c++)
+ {
+ aMiterPolygon.setNormal(c, basegfx::B3DVector(aMiterPolygon.getB3DPoint(c)));
+ }
+
+ // create primitive
+ const basegfx::B3DPolyPolygon aMiterPolyPolygon(aMiterPolygon);
+ BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aMiterPolyPolygon, rMaterial, false);
+ aResultVector.push_back(pNew);
+ }
+
+ // prepare next step
+ if(bFirst || !bLast)
+ {
+ aPointOnXY = aNextPointOnXY;
+ aPointRotY = aNextPointRotY;
+
+ if(bMiter)
+ {
+ aCurrMiter = aNextMiter;
+ }
+ }
+ }
+ }
+ }
+
+ Primitive3DSequence aRetval(aResultVector.size());
+
+ for(sal_uInt32 a(0L); a < aResultVector.size(); a++)
+ {
+ aRetval[a] = Primitive3DReference(aResultVector[a]);
+ }
+
+ return aRetval;
+ }
+
+ basegfx::B3DHomMatrix getRotationFromVector(const basegfx::B3DVector& rVector)
+ {
+ // build transformation from unit vector to vector
+ basegfx::B3DHomMatrix aRetval;
+
+ // get applied rotations from angles in XY and in XZ (cartesian)
+ const double fRotInXY(atan2(rVector.getY(), rVector.getXZLength()));
+ const double fRotInXZ(atan2(-rVector.getZ(), rVector.getX()));
+
+ // apply rotations. Rot around Z needs to be done first, so apply in two steps
+ aRetval.rotate(0.0, 0.0, fRotInXY);
+ aRetval.rotate(0.0, fRotInXZ, 0.0);
+
+ return aRetval;
+ }
+ } // end of anonymous namespace
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence PolygonTubePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ const sal_uInt32 nPointCount(getB3DPolygon().count());
+ std::vector< BasePrimitive3D* > aResultVector;
+
+ if(0L != nPointCount)
+ {
+ if(basegfx::fTools::more(getRadius(), 0.0))
+ {
+ const attribute::MaterialAttribute3D aMaterial(getBColor());
+ static sal_uInt32 nSegments(8L); // default for 3d line segments, for more quality just raise this value (in even steps)
+ const bool bClosed(getB3DPolygon().isClosed());
+ const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin());
+ const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1L);
+ basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1L));
+ basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0L));
+
+ for(sal_uInt32 a(0L); a < nLoopCount; a++)
+ {
+ // get next data
+ const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1L) % nPointCount));
+ const basegfx::B3DVector aForw(aNext - aCurr);
+ const double fForwLen(aForw.getLength());
+
+ if(basegfx::fTools::more(fForwLen, 0.0))
+ {
+ // get rotation from vector, this describes rotation from (1, 0, 0) to aForw
+ basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw));
+
+ // create default transformation with scale and rotate
+ basegfx::B3DHomMatrix aVectorTrans;
+ aVectorTrans.scale(fForwLen, getRadius(), getRadius());
+ aVectorTrans *= aRotVector;
+ aVectorTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ if(bNoLineJoin || (!bClosed && !a))
+ {
+ // line start edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aVectorTrans, getLineCapSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedA);
+ }
+ else
+ {
+ const basegfx::B3DVector aBack(aCurr - aLast);
+ const double fCross(basegfx::cross(aBack, aForw).getLength());
+
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ // line connect non-parallel, aBack, aForw, use getLineJoin()
+ const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2
+ Primitive3DSequence aNewList(getLineJoinSegments(nSegments, aMaterial, fAngle, getDegreeStepWidth(), getMiterMinimumAngle(), getLineJoin()));
+
+ // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack
+ basegfx::B3DHomMatrix aInvRotVector(aRotVector);
+ aInvRotVector.invert();
+ basegfx::B3DVector aTransBack(aInvRotVector * aBack);
+ const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ()));
+
+ // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X.
+ // Also apply usual scaling and translation
+ basegfx::B3DHomMatrix aSphereTrans;
+ aSphereTrans.rotate(0.0, F_PI2, 0.0);
+ aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0);
+ aSphereTrans *= aRotVector;
+ aSphereTrans.scale(getRadius(), getRadius(), getRadius());
+ aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // line start edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedB = new TransformPrimitive3D(aSphereTrans, aNewList);
+ aResultVector.push_back(pNewTransformedB);
+ }
+ }
+
+ // create line segments, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedC = new TransformPrimitive3D(aVectorTrans, getLineTubeSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedC);
+
+ if(bNoLineJoin || (!bClosed && ((a + 1L) == nLoopCount)))
+ {
+ // line end edge, first rotate (mirror) and translate, then use use aRotVector
+ basegfx::B3DHomMatrix aBackTrans;
+ aBackTrans.rotate(0.0, F_PI, 0.0);
+ aBackTrans.translate(1.0, 0.0, 0.0);
+ aBackTrans.scale(fForwLen, getRadius(), getRadius());
+ aBackTrans *= aRotVector;
+ aBackTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // line end edge, build transformed primitiveVector3D
+ TransformPrimitive3D* pNewTransformedD = new TransformPrimitive3D(aBackTrans, getLineCapSegments(nSegments, aMaterial));
+ aResultVector.push_back(pNewTransformedD);
+ }
+ }
+
+ // prepare next loop step
+ aLast = aCurr;
+ aCurr = aNext;
+ }
+ }
+ else
+ {
+ // create hairline
+ PolygonHairlinePrimitive3D* pNew = new PolygonHairlinePrimitive3D(getB3DPolygon(), getBColor());
+ aResultVector.push_back(pNew);
+ }
+ }
+
+ // prepare return value
+ Primitive3DSequence aRetval(aResultVector.size());
+
+ for(sal_uInt32 a(0L); a < aResultVector.size(); a++)
+ {
+ aRetval[a] = Primitive3DReference(aResultVector[a]);
+ }
+
+ return aRetval;
+ }
+
+ PolygonTubePrimitive3D::PolygonTubePrimitive3D(
+ const basegfx::B3DPolygon& rPolygon,
+ const basegfx::BColor& rBColor,
+ double fRadius, basegfx::B2DLineJoin aLineJoin,
+ double fDegreeStepWidth,
+ double fMiterMinimumAngle)
+ : PolygonHairlinePrimitive3D(rPolygon, rBColor),
+ mfRadius(fRadius),
+ mfDegreeStepWidth(fDegreeStepWidth),
+ mfMiterMinimumAngle(fMiterMinimumAngle),
+ maLineJoin(aLineJoin)
+ {
+ }
+
+ bool PolygonTubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(PolygonHairlinePrimitive3D::operator==(rPrimitive))
+ {
+ const PolygonTubePrimitive3D& rCompare = (PolygonTubePrimitive3D&)rPrimitive;
+
+ return (getRadius() == rCompare.getRadius()
+ && getDegreeStepWidth() == rCompare.getDegreeStepWidth()
+ && getMiterMinimumAngle() == rCompare.getMiterMinimumAngle()
+ && getLineJoin() == rCompare.getLineJoin());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolygonTubePrimitive3D, PRIMITIVE3D_ID_POLYGONTUBEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
new file mode 100644
index 000000000000..f05a85869cbf
--- /dev/null
+++ b/drawinglayer/source/primitive3d/polypolygonprimitive3d.cxx
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: polypolygonprimitive3d.cxx,v $
+ *
+ * $Revision: 1.9 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ PolyPolygonMaterialPrimitive3D::PolyPolygonMaterialPrimitive3D(
+ const basegfx::B3DPolyPolygon& rPolyPolygon,
+ const attribute::MaterialAttribute3D& rMaterial,
+ bool bDoubleSided)
+ : BasePrimitive3D(),
+ maPolyPolygon(rPolyPolygon),
+ maMaterial(rMaterial),
+ mbDoubleSided(bDoubleSided)
+ {
+ }
+
+ bool PolyPolygonMaterialPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const PolyPolygonMaterialPrimitive3D& rCompare = (PolyPolygonMaterialPrimitive3D&)rPrimitive;
+
+ return (getB3DPolyPolygon() == rCompare.getB3DPolyPolygon()
+ && getMaterial() == rCompare.getMaterial()
+ && getDoubleSided() == rCompare.getDoubleSided());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange PolyPolygonMaterialPrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return basegfx::tools::getRange(getB3DPolyPolygon());
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(PolyPolygonMaterialPrimitive3D, PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx
new file mode 100644
index 000000000000..341d2907a53d
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx
@@ -0,0 +1,235 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrcubeprimitive3d.cxx,v $
+ *
+ * $Revision: 1.11 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/sdrcubeprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrCubePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ Primitive3DSequence aRetval;
+ basegfx::B3DPolyPolygon aFill(basegfx::tools::createCubeFillPolyPolygonFromB3DRange(aUnitRange));
+
+ // normal creation
+ if(getSdrLFSAttribute().getFill())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()
+ || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ // create sphere normals
+ const basegfx::B3DPoint aCenter(basegfx::tools::getRange(aFill).getCenter());
+ aFill = basegfx::tools::applyDefaultNormalsSphere(aFill, aCenter);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ // invert normals
+ aFill = basegfx::tools::invertNormals(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(getSdrLFSAttribute().getFill())
+ {
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX()));
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY()));
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY);
+ }
+
+ if(bSphereX || bSphereY)
+ {
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ const basegfx::B3DPoint aCenter(aRange.getCenter());
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, bSphereX, bSphereY);
+ }
+
+ if(bObjectSpecificX || bObjectSpecificY)
+ {
+ // object-specific
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ basegfx::B3DPolygon aTmpPoly(aFill.getB3DPolygon(a));
+
+ if(aTmpPoly.count() >= 4L)
+ {
+ for(sal_uInt32 b(0L); b < 4L; b++)
+ {
+ basegfx::B2DPoint aPoint(aTmpPoly.getTextureCoordinate(b));
+
+ if(bObjectSpecificX)
+ {
+ aPoint.setX((1L == b || 2L == b) ? 1.0 : 0.0);
+ }
+
+ if(bObjectSpecificY)
+ {
+ aPoint.setY((2L == b || 3L == b) ? 1.0 : 0.0);
+ }
+
+ aTmpPoly.setTextureCoordinate(b, aPoint);
+ }
+
+ aFill.setB3DPolygon(a, aTmpPoly);
+ }
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY());
+ aFill.transformTextureCoordiantes(aTexMatrix);
+ }
+
+ // build vector of PolyPolygons
+ ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector;
+
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a)));
+ }
+
+ if(getSdrLFSAttribute().getFill())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ *getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
+
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ aSimplifiedFillAttribute,
+ 0);
+
+ // encapsulate in HitTestPrimitive3D and add
+ const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ // add line
+ if(getSdrLFSAttribute().getLine())
+ {
+ basegfx::B3DPolyPolygon aLine(basegfx::tools::createCubePolyPolygonFromB3DRange(aUnitRange));
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(aLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(getSdrLFSAttribute().getShadow() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(aRetval, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+
+ return aRetval;
+ }
+
+ SdrCubePrimitive3D::SdrCubePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute)
+ {
+ }
+
+ bool SdrCubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ return SdrPrimitive3D::operator==(rPrimitive);
+ }
+
+ basegfx::B3DRange SdrCubePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2.
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return getStandard3DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrCubePrimitive3D, PRIMITIVE3D_ID_SDRCUBEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
new file mode 100644
index 000000000000..df682ab04e6f
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
@@ -0,0 +1,299 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrdecompositiontools3d.cxx,v $
+ *
+ * $Revision: 1.7 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+#include <drawinglayer/primitive3d/baseprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+#include <vcl/vclenum.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+#include <drawinglayer/attribute/fillbitmapattribute.hxx>
+#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
+#include <vcl/bmpacc.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute3d.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ basegfx::B3DRange getRangeFrom3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ basegfx::B3DRange aRetval;
+
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ aRetval.expand(basegfx::tools::getRange(rFill[a]));
+ }
+
+ return aRetval;
+ }
+
+ void applyNormalsKindSphereTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill, const basegfx::B3DRange& rRange)
+ {
+ // create sphere normals
+ const basegfx::B3DPoint aCenter(rRange.getCenter());
+
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultNormalsSphere(rFill[a], aCenter);
+ }
+ }
+
+ void applyNormalsKindFlatTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a].clearNormals();
+ }
+ }
+
+ void applyNormalsInvertTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
+ {
+ // invert normals
+ for(sal_uInt32 a(0); a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::invertNormals(rFill[a]);
+ }
+ }
+
+ void applyTextureTo3DGeometry(
+ ::com::sun::star::drawing::TextureProjectionMode eModeX,
+ ::com::sun::star::drawing::TextureProjectionMode eModeY,
+ ::std::vector< basegfx::B3DPolyPolygon >& rFill,
+ const basegfx::B3DRange& rRange,
+ const basegfx::B2DVector& rTextureSize)
+ {
+ sal_uInt32 a;
+
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeX);
+ const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeX));
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeY);
+ const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeY));
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(rFill[a], rRange, bParallelX, bParallelY);
+ }
+ }
+
+ if(bSphereX || bSphereY)
+ {
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DPoint aCenter(rRange.getCenter());
+
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(rFill[a], aCenter, bSphereX, bSphereY);
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(rTextureSize.getX(), rTextureSize.getY());
+
+ for(a = 0; a < rFill.size(); a++)
+ {
+ rFill[a].transformTextureCoordiantes(aTexMatrix);
+ }
+ }
+
+ Primitive3DSequence create3DPolyPolygonLinePrimitives(
+ const basegfx::B3DPolyPolygon& rUnitPolyPolygon,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const attribute::SdrLineAttribute& rLine)
+ {
+ // prepare fully scaled polyPolygon
+ basegfx::B3DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon);
+ aScaledPolyPolygon.transform(rObjectTransform);
+
+ // create line and stroke attribute
+ const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin());
+ const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen());
+
+ // create primitives
+ Primitive3DSequence aRetval(aScaledPolyPolygon.count());
+
+ for(sal_uInt32 a(0L); a < aScaledPolyPolygon.count(); a++)
+ {
+ const Primitive3DReference xRef(new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute));
+ aRetval[a] = xRef;
+ }
+
+ if(0.0 != rLine.getTransparence())
+ {
+ // create UnifiedAlphaTexturePrimitive3D, add created primitives and exchange
+ const Primitive3DReference xRef(new UnifiedAlphaTexturePrimitive3D(rLine.getTransparence(), aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ return aRetval;
+ }
+
+ Primitive3DSequence create3DPolyPolygonFillPrimitives(
+ const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute,
+ const attribute::SdrFillAttribute& rFill,
+ const attribute::FillGradientAttribute* pFillGradient)
+ {
+ Primitive3DSequence aRetval;
+
+ if(r3DPolyPolygonVector.size())
+ {
+ // create list of simple fill primitives
+ aRetval.realloc(r3DPolyPolygonVector.size());
+
+ for(sal_uInt32 a(0L); a < r3DPolyPolygonVector.size(); a++)
+ {
+ // get scaled PolyPolygon
+ basegfx::B3DPolyPolygon aScaledPolyPolygon(r3DPolyPolygonVector[a]);
+ aScaledPolyPolygon.transform(rObjectTransform);
+
+ if(aScaledPolyPolygon.areNormalsUsed())
+ {
+ aScaledPolyPolygon.transformNormals(rObjectTransform);
+ }
+
+ const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(
+ aScaledPolyPolygon,
+ aSdr3DObjectAttribute.getMaterial(),
+ aSdr3DObjectAttribute.getDoubleSided()));
+ aRetval[a] = xRef;
+ }
+
+ // look for and evtl. build texture sub-group primitive
+ if(rFill.isGradient() || rFill.isHatch() || rFill.isBitmap())
+ {
+ bool bModulate(::com::sun::star::drawing::TextureMode_MODULATE == aSdr3DObjectAttribute.getTextureMode());
+ bool bFilter(aSdr3DObjectAttribute.getTextureFilter());
+ BasePrimitive3D* pNewTexturePrimitive3D = 0L;
+
+ if(rFill.isGradient())
+ {
+ // create gradientTexture3D with sublist, add to local aRetval
+ pNewTexturePrimitive3D = new GradientTexturePrimitive3D(*rFill.getGradient(), aRetval, rTextureSize, bModulate, bFilter);
+ }
+ else if(rFill.isHatch())
+ {
+ // create hatchTexture3D with sublist, add to local aRetval
+ pNewTexturePrimitive3D = new HatchTexturePrimitive3D(*rFill.getHatch(), aRetval, rTextureSize, bModulate, bFilter);
+ }
+ else // if(rFill.isBitmap())
+ {
+ // create bitmapTexture3D with sublist, add to local aRetval
+ basegfx::B2DRange aTexRange(0.0, 0.0, rTextureSize.getX(), rTextureSize.getY());
+ pNewTexturePrimitive3D = new BitmapTexturePrimitive3D(rFill.getBitmap()->getFillBitmapAttribute(aTexRange), aRetval, rTextureSize, bModulate, bFilter);
+ }
+
+ // exchange aRetval content with texture group
+ const Primitive3DReference xRef(pNewTexturePrimitive3D);
+ aRetval = Primitive3DSequence(&xRef, 1L);
+
+ if(::com::sun::star::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind())
+ {
+ // use modified color primitive to force textures to gray
+ const basegfx::BColorModifier aBColorModifier(basegfx::BColor(), 0.0, basegfx::BCOLORMODIFYMODE_GRAY);
+ const Primitive3DReference xRef2(new ModifiedColorPrimitive3D(aRetval, aBColorModifier));
+ aRetval = Primitive3DSequence(&xRef2, 1L);
+ }
+ }
+
+ if(0.0 != rFill.getTransparence())
+ {
+ // create UnifiedAlphaTexturePrimitive3D with sublist and exchange
+ const Primitive3DReference xRef(new UnifiedAlphaTexturePrimitive3D(rFill.getTransparence(), aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+ else if(pFillGradient)
+ {
+ // create AlphaTexturePrimitive3D with sublist and exchange
+ const Primitive3DReference xRef(new AlphaTexturePrimitive3D(*pFillGradient, aRetval, rTextureSize));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+ }
+
+ return aRetval;
+ }
+
+ Primitive3DSequence createShadowPrimitive3D(
+ const Primitive3DSequence& rSource,
+ const attribute::SdrShadowAttribute& rShadow,
+ bool bShadow3D)
+ {
+ // create Shadow primitives. Uses already created primitives
+ if(rSource.hasElements() && !basegfx::fTools::moreOrEqual(rShadow.getTransparence(), 1.0))
+ {
+ // prepare new list for shadow geometry
+ basegfx::B2DHomMatrix aShadowOffset;
+ aShadowOffset.set(0, 2, rShadow.getOffset().getX());
+ aShadowOffset.set(1, 2, rShadow.getOffset().getY());
+
+ // create shadow primitive and add primitives
+ const Primitive3DReference xRef(new ShadowPrimitive3D(aShadowOffset, rShadow.getColor(), rShadow.getTransparence(), bShadow3D, rSource));
+ return Primitive3DSequence(&xRef, 1L);
+ }
+ else
+ {
+ return Primitive3DSequence();
+ }
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
new file mode 100644
index 000000000000..973a82c8eca4
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx
@@ -0,0 +1,999 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrextrudelathetools3d.cxx,v $
+ *
+ * $Revision: 1.11 $
+ *
+ * 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/primitive3d/sdrextrudelathetools3d.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b3dpoint.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/range/b3drange.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <numeric>
+
+//////////////////////////////////////////////////////////////////////////////
+// decompositon helpers for extrude/lathe (rotation) objects
+
+namespace
+{
+ //////////////////////////////////////////////////////////////////////////////
+ // common helpers
+
+ basegfx::B2DPolyPolygon impScalePolyPolygonOnCenter(
+ const basegfx::B2DPolyPolygon& rSource,
+ double fScale)
+ {
+ basegfx::B2DPolyPolygon aRetval(rSource);
+
+ if(!basegfx::fTools::equalZero(fScale))
+ {
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(rSource));
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
+ basegfx::B2DHomMatrix aTrans;
+
+ aTrans.translate(-aCenter.getX(), -aCenter.getY());
+ aTrans.scale(fScale, fScale);
+ aTrans.translate(aCenter.getX(), aCenter.getY());
+ aRetval.transform(aTrans);
+ }
+
+ return aRetval;
+ }
+
+ void impGetOuterPolyPolygon(
+ basegfx::B2DPolyPolygon& rPolygon,
+ basegfx::B2DPolyPolygon& rOuterPolyPolygon,
+ double fOffset,
+ bool bCharacterMode)
+ {
+ rOuterPolyPolygon = rPolygon;
+
+ if(basegfx::fTools::more(fOffset, 0.0))
+ {
+ if(bCharacterMode)
+ {
+ // grow the outside polygon and scale all polygons to original size. This is done
+ // to avoid a shrink which potentially would lead to self-intersections, but changes
+ // the original polygon -> not a precision step, so e.g. not usable for charts
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(rPolygon));
+ rPolygon = basegfx::tools::growInNormalDirection(rPolygon, fOffset);
+ const basegfx::B2DRange aGrownRange(basegfx::tools::getRange(rPolygon));
+ const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth());
+ const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight());
+ basegfx::B2DHomMatrix aScaleTrans;
+
+ aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY());
+ aScaleTrans.scale(fScaleX, fScaleY);
+ aScaleTrans.translate(aRange.getMinX(), aRange.getMinY());
+ rPolygon.transform(aScaleTrans);
+ rOuterPolyPolygon.transform(aScaleTrans);
+ }
+ else
+ {
+ // use more precision, shrink the outer polygons. Since this may lead to self-intersections,
+ // some kind of correction should be applied here after that step
+ rOuterPolyPolygon = basegfx::tools::growInNormalDirection(rPolygon, -fOffset);
+ basegfx::tools::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon);
+ }
+ }
+ }
+
+ void impAddInBetweenFill(
+ basegfx::B3DPolyPolygon& rTarget,
+ const basegfx::B3DPolyPolygon& rPolA,
+ const basegfx::B3DPolyPolygon& rPolB,
+ double fTexVerStart,
+ double fTexVerStop,
+ bool bCreateNormals,
+ bool bCreateTextureCoordinates)
+ {
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
+ const sal_uInt32 nPolygonCount(rPolA.count());
+
+ for(sal_uInt32 a(0L); a < nPolygonCount; a++)
+ {
+ const basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ if(nPointCount)
+ {
+ const sal_uInt32 nEdgeCount(aSubA.isClosed() ? nPointCount : nPointCount - 1L);
+ double fTexHorMultiplicatorA(0.0), fTexHorMultiplicatorB(0.0);
+ double fPolygonPosA(0.0), fPolygonPosB(0.0);
+
+ if(bCreateTextureCoordinates)
+ {
+ const double fPolygonLengthA(basegfx::tools::getLength(aSubA));
+ fTexHorMultiplicatorA = basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA;
+
+ const double fPolygonLengthB(basegfx::tools::getLength(aSubB));
+ fTexHorMultiplicatorB = basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB;
+ }
+
+ for(sal_uInt32 b(0L); b < nEdgeCount; b++)
+ {
+ const sal_uInt32 nIndexA(b);
+ const sal_uInt32 nIndexB((b + 1L) % nPointCount);
+
+ const basegfx::B3DPoint aStartA(aSubA.getB3DPoint(nIndexA));
+ const basegfx::B3DPoint aEndA(aSubA.getB3DPoint(nIndexB));
+ const basegfx::B3DPoint aStartB(aSubB.getB3DPoint(nIndexA));
+ const basegfx::B3DPoint aEndB(aSubB.getB3DPoint(nIndexB));
+
+ basegfx::B3DPolygon aNew;
+ aNew.setClosed(true);
+
+ aNew.append(aStartA);
+ aNew.append(aStartB);
+ aNew.append(aEndB);
+ aNew.append(aEndA);
+
+ if(bCreateNormals)
+ {
+ aNew.setNormal(0L, aSubA.getNormal(nIndexA));
+ aNew.setNormal(1L, aSubB.getNormal(nIndexA));
+ aNew.setNormal(2L, aSubB.getNormal(nIndexB));
+ aNew.setNormal(3L, aSubA.getNormal(nIndexB));
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ const double fRelTexAL(fPolygonPosA * fTexHorMultiplicatorA);
+ const double fEdgeLengthA(basegfx::B3DVector(aEndA - aStartA).getLength());
+ fPolygonPosA += fEdgeLengthA;
+ const double fRelTexAR(fPolygonPosA * fTexHorMultiplicatorA);
+
+ const double fRelTexBL(fPolygonPosB * fTexHorMultiplicatorB);
+ const double fEdgeLengthB(basegfx::B3DVector(aEndB - aStartB).getLength());
+ fPolygonPosB += fEdgeLengthB;
+ const double fRelTexBR(fPolygonPosB * fTexHorMultiplicatorB);
+
+ aNew.setTextureCoordinate(0L, basegfx::B2DPoint(fRelTexAL, fTexVerStart));
+ aNew.setTextureCoordinate(1L, basegfx::B2DPoint(fRelTexBL, fTexVerStop));
+ aNew.setTextureCoordinate(2L, basegfx::B2DPoint(fRelTexBR, fTexVerStop));
+ aNew.setTextureCoordinate(3L, basegfx::B2DPoint(fRelTexAR, fTexVerStart));
+ }
+
+ rTarget.append(aNew);
+ }
+ }
+ }
+ }
+
+ void impSetNormal(
+ basegfx::B3DPolyPolygon& rCandidate,
+ const basegfx::B3DVector& rNormal)
+ {
+ for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
+ {
+ basegfx::B3DPolygon aSub(rCandidate.getB3DPolygon(a));
+
+ for(sal_uInt32 b(0L); b < aSub.count(); b++)
+ {
+ aSub.setNormal(b, rNormal);
+ }
+
+ rCandidate.setB3DPolygon(a, aSub);
+ }
+ }
+
+ void impCreateInBetweenNormals(
+ basegfx::B3DPolyPolygon& rPolA,
+ basegfx::B3DPolyPolygon& rPolB,
+ bool bSmoothHorizontalNormals)
+ {
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+
+ for(sal_uInt32 a(0L); a < rPolA.count(); a++)
+ {
+ basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ if(nPointCount)
+ {
+ basegfx::B3DPoint aPrevA(aSubA.getB3DPoint(nPointCount - 1L));
+ basegfx::B3DPoint aCurrA(aSubA.getB3DPoint(0L));
+ const bool bClosed(aSubA.isClosed());
+
+ for(sal_uInt32 b(0L); b < nPointCount; b++)
+ {
+ const sal_uInt32 nIndNext((b + 1L) % nPointCount);
+ const basegfx::B3DPoint aNextA(aSubA.getB3DPoint(nIndNext));
+ const basegfx::B3DPoint aCurrB(aSubB.getB3DPoint(b));
+
+ // vector to back
+ basegfx::B3DVector aDepth(aCurrB - aCurrA);
+ aDepth.normalize();
+
+ if(aDepth.equalZero())
+ {
+ // no difference, try to get depth from next point
+ const basegfx::B3DPoint aNextB(aSubB.getB3DPoint(nIndNext));
+ aDepth = aNextB - aNextA;
+ aDepth.normalize();
+ }
+
+ // vector to left (correct for non-closed lines)
+ const bool bFirstAndNotClosed(!bClosed && 0L == b);
+ basegfx::B3DVector aLeft(bFirstAndNotClosed ? aCurrA - aNextA : aPrevA - aCurrA);
+ aLeft.normalize();
+
+ // create left normal
+ const basegfx::B3DVector aNormalLeft(aDepth.getPerpendicular(aLeft));
+
+ if(bSmoothHorizontalNormals)
+ {
+ // vector to right (correct for non-closed lines)
+ const bool bLastAndNotClosed(!bClosed && b + 1L == nPointCount);
+ basegfx::B3DVector aRight(bLastAndNotClosed ? aCurrA - aPrevA : aNextA - aCurrA);
+ aRight.normalize();
+
+ // create right normal
+ const basegfx::B3DVector aNormalRight(aRight.getPerpendicular(aDepth));
+
+ // create smoothed in-between normal
+ basegfx::B3DVector aNewNormal(aNormalLeft + aNormalRight);
+ aNewNormal.normalize();
+
+ // set as new normal at polygons
+ aSubA.setNormal(b, aNewNormal);
+ aSubB.setNormal(b, aNewNormal);
+ }
+ else
+ {
+ // set aNormalLeft as new normal at polygons
+ aSubA.setNormal(b, aNormalLeft);
+ aSubB.setNormal(b, aNormalLeft);
+ }
+
+ // prepare next step
+ aPrevA = aCurrA;
+ aCurrA = aNextA;
+ }
+
+ rPolA.setB3DPolygon(a, aSubA);
+ rPolB.setB3DPolygon(a, aSubB);
+ }
+ }
+ }
+
+ void impMixNormals(
+ basegfx::B3DPolyPolygon& rPolA,
+ const basegfx::B3DPolyPolygon& rPolB,
+ double fWeightA)
+ {
+ const double fWeightB(1.0 - fWeightA);
+ OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+
+ for(sal_uInt32 a(0L); a < rPolA.count(); a++)
+ {
+ basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
+ const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
+ OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
+ const sal_uInt32 nPointCount(aSubA.count());
+
+ for(sal_uInt32 b(0L); b < nPointCount; b++)
+ {
+ const basegfx::B3DVector aVA(aSubA.getNormal(b) * fWeightA);
+ const basegfx::B3DVector aVB(aSubB.getNormal(b) * fWeightB);
+ basegfx::B3DVector aVNew(aVA + aVB);
+ aVNew.normalize();
+ aSubA.setNormal(b, aVNew);
+ }
+
+ rPolA.setB3DPolygon(a, aSubA);
+ }
+ }
+
+ bool impHasCutWith(const basegfx::B2DPolygon& rPoly, const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd)
+ {
+ // polygon is closed, one of the points is a member
+ const sal_uInt32 nPointCount(rPoly.count());
+
+ if(nPointCount)
+ {
+ basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
+ const basegfx::B2DVector aVector(rEnd - rStart);
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
+ const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
+
+ if(basegfx::tools::findCut(
+ rStart, aVector,
+ aCurrent, aEdgeVector))
+ {
+ return true;
+ }
+
+ aCurrent = aNext;
+ }
+ }
+
+ return false;
+ }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ void createLatheSlices(
+ Slice3DVector& rSliceVector,
+ const basegfx::B2DPolyPolygon& rSource,
+ double fBackScale,
+ double fDiagonal,
+ double fRotation,
+ sal_uInt32 nSteps,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ {
+ if(basegfx::fTools::equalZero(fRotation) || 0L == nSteps)
+ {
+ // no rotation or no steps, just one plane
+ rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
+ }
+ else
+ {
+ const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
+ const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, F_2PI));
+ basegfx::B2DPolyPolygon aFront(rSource);
+ basegfx::B2DPolyPolygon aBack(rSource);
+ basegfx::B3DHomMatrix aTransformBack;
+ basegfx::B2DPolyPolygon aOuterBack;
+
+ if(bClosedRotation)
+ {
+ bCloseFront = bCloseBack = false;
+ }
+
+ if(bBackScale)
+ {
+ // avoid null zoom
+ if(basegfx::fTools::equalZero(fBackScale))
+ {
+ fBackScale = 0.000001;
+ }
+
+ // back is scaled compared to front, create scaled version
+ aBack = impScalePolyPolygonOnCenter(aBack, fBackScale);
+ }
+
+ if(bCloseFront || bCloseBack)
+ {
+ const basegfx::B2DRange aBaseRange(basegfx::tools::getRange(aFront));
+ const double fOuterLength(aBaseRange.getMaxX() * fRotation);
+ const double fInnerLength(aBaseRange.getMinX() * fRotation);
+ const double fAverageLength((fOuterLength + fInnerLength) * 0.5);
+
+ if(bCloseFront)
+ {
+ const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
+ basegfx::B2DPolyPolygon aOuterFront;
+ impGetOuterPolyPolygon(aFront, aOuterFront, fOffsetLen, bCharacterMode);
+ basegfx::B3DHomMatrix aTransform;
+ aTransform.translate(0.0, 0.0, fOffsetLen);
+ rSliceVector.push_back(Slice3D(aOuterFront, aTransform, SLICETYPE3D_FRONTCAP));
+ }
+
+ if(bCloseBack)
+ {
+ const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
+ impGetOuterPolyPolygon(aBack, aOuterBack, fOffsetLen, bCharacterMode);
+ aTransformBack.translate(0.0, 0.0, -fOffsetLen);
+ aTransformBack.rotate(0.0, fRotation, 0.0);
+ }
+ }
+
+ // add start polygon (a = 0L)
+ if(!bClosedRotation)
+ {
+ rSliceVector.push_back(Slice3D(aFront, basegfx::B3DHomMatrix()));
+ }
+
+ // create segments (a + 1 .. nSteps)
+ const double fStepSize(1.0 / (double)nSteps);
+
+ for(sal_uInt32 a(0L); a < nSteps; a++)
+ {
+ const double fStep((double)(a + 1L) * fStepSize);
+ basegfx::B2DPolyPolygon aNewPoly(bBackScale ? basegfx::tools::interpolate(aFront, aBack, fStep) : aFront);
+ basegfx::B3DHomMatrix aNewMat;
+ aNewMat.rotate(0.0, fRotation * fStep, 0.0);
+ rSliceVector.push_back(Slice3D(aNewPoly, aNewMat));
+ }
+
+ if(bCloseBack)
+ {
+ rSliceVector.push_back(Slice3D(aOuterBack, aTransformBack, SLICETYPE3D_BACKCAP));
+ }
+ }
+ }
+
+ void createExtrudeSlices(
+ Slice3DVector& rSliceVector,
+ const basegfx::B2DPolyPolygon& rSource,
+ double fBackScale,
+ double fDiagonal,
+ double fDepth,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ {
+ if(basegfx::fTools::equalZero(fDepth))
+ {
+ // no depth, just one plane
+ rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
+ }
+ else
+ {
+ // there is depth, create Polygons for front,back and their default depth positions
+ basegfx::B2DPolyPolygon aFront(rSource);
+ basegfx::B2DPolyPolygon aBack(rSource);
+ const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
+ double fZFront(fDepth); // default depth for aFront
+ double fZBack(0.0); // default depth for aBack
+ basegfx::B2DPolyPolygon aOuterBack;
+
+ if(bBackScale)
+ {
+ // avoid null zoom
+ if(basegfx::fTools::equalZero(fBackScale))
+ {
+ fBackScale = 0.000001;
+ }
+
+ // aFront is scaled compared to aBack, create scaled version
+ aFront = impScalePolyPolygonOnCenter(aFront, fBackScale);
+ }
+
+ if(bCloseFront)
+ {
+ const double fOffset(fDepth * fDiagonal * 0.5);
+ fZFront = fDepth - fOffset;
+ basegfx::B2DPolyPolygon aOuterFront;
+ impGetOuterPolyPolygon(aFront, aOuterFront, fOffset, bCharacterMode);
+ basegfx::B3DHomMatrix aTransformFront;
+ aTransformFront.translate(0.0, 0.0, fDepth);
+ rSliceVector.push_back(Slice3D(aOuterFront, aTransformFront, SLICETYPE3D_FRONTCAP));
+ }
+
+ if(bCloseBack)
+ {
+ const double fOffset(fDepth * fDiagonal * 0.5);
+ fZBack = fOffset;
+ impGetOuterPolyPolygon(aBack, aOuterBack, fOffset, bCharacterMode);
+ }
+
+ // add front and back polygons at evtl. changed depths
+ {
+ basegfx::B3DHomMatrix aTransformA, aTransformB;
+
+ aTransformA.translate(0.0, 0.0, fZFront);
+ rSliceVector.push_back(Slice3D(aFront, aTransformA));
+
+ aTransformB.translate(0.0, 0.0, fZBack);
+ rSliceVector.push_back(Slice3D(aBack, aTransformB));
+ }
+
+ if(bCloseBack)
+ {
+ rSliceVector.push_back(Slice3D(aOuterBack, basegfx::B3DHomMatrix(), SLICETYPE3D_BACKCAP));
+ }
+ }
+ }
+
+ basegfx::B3DPolyPolygon extractHorizontalLinesFromSlice(const Slice3DVector& rSliceVector, bool bCloseHorLines)
+ {
+ basegfx::B3DPolyPolygon aRetval;
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ if(nNumSlices)
+ {
+ const sal_uInt32 nSlideSubPolygonCount(rSliceVector[0].getB3DPolyPolygon().count());
+
+ for(sal_uInt32 b(0); b < nSlideSubPolygonCount; b++)
+ {
+ const sal_uInt32 nSubPolygonPointCount(rSliceVector[0].getB3DPolyPolygon().getB3DPolygon(b).count());
+
+ for(sal_uInt32 c(0); c < nSubPolygonPointCount; c++)
+ {
+ basegfx::B3DPolygon aNew;
+
+ for(sal_uInt32 d(0); d < nNumSlices; d++)
+ {
+ OSL_ENSURE(nSlideSubPolygonCount == rSliceVector[d].getB3DPolyPolygon().count(),
+ "Slice PolyPolygon with different Polygon count (!)");
+ OSL_ENSURE(nSubPolygonPointCount == rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).count(),
+ "Slice Polygon with different point count (!)");
+ aNew.append(rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).getB3DPoint(c));
+ }
+
+ aNew.setClosed(bCloseHorLines);
+ aRetval.append(aNew);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ basegfx::B3DPolyPolygon extractVerticalLinesFromSlice(const Slice3DVector& rSliceVector)
+ {
+ basegfx::B3DPolyPolygon aRetval;
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ for(sal_uInt32 a(0L); a < nNumSlices; a++)
+ {
+ aRetval.append(rSliceVector[a].getB3DPolyPolygon());
+ }
+
+ return aRetval;
+ }
+
+ void extractPlanesFromSlice(
+ ::std::vector< basegfx::B3DPolyPolygon >& rFill,
+ const Slice3DVector& rSliceVector,
+ bool bCreateNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothNormals,
+ bool bSmoothLids,
+ bool bClosed,
+ double fSmoothNormalsMix,
+ double fSmoothLidsMix,
+ bool bCreateTextureCoordinates,
+ const basegfx::B2DHomMatrix& rTexTransform)
+ {
+ const sal_uInt32 nNumSlices(rSliceVector.size());
+
+ if(nNumSlices)
+ {
+ // common parameters
+ const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1L);
+ basegfx::B3DPolyPolygon aEdgeRounding;
+ sal_uInt32 a;
+
+ // tetxture parameters
+ double fInvTexHeight(1.0);
+ double fTexHeightPos(0.0);
+ double fTexStart(0.0);
+ double fTexStop(1.0);
+ ::std::vector<double> aTexHeightArray;
+ basegfx::B3DRange aTexRangeFront;
+ basegfx::B3DRange aTexRangeBack;
+
+ if(bCreateTextureCoordinates)
+ {
+ aTexRangeFront = basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon());
+ aTexRangeBack = basegfx::tools::getRange(rSliceVector[nNumSlices - 1L].getB3DPolyPolygon());
+
+ if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth())
+ {
+ // last polygon is rotated so that depth is bigger than width, exchange X and Z
+ // for making applyDefaultTextureCoordinatesParallel use Z instead of X for
+ // horizontal texture coordinate
+ aTexRangeBack = basegfx::B3DRange(
+ aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(),
+ aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX());
+ }
+
+ basegfx::B3DPoint aCenter(basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()).getCenter());
+
+ for(a = 0L; a < nLoopCount; a++)
+ {
+ const basegfx::B3DPoint aNextCenter(basegfx::tools::getRange(rSliceVector[(a + 1L) % nNumSlices].getB3DPolyPolygon()).getCenter());
+ const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength());
+ aTexHeightArray.push_back(fLength);
+ aCenter = aNextCenter;
+ }
+
+ const double fTexHeight(::std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0));
+
+ if(!basegfx::fTools::equalZero(fTexHeight))
+ {
+ fInvTexHeight = 1.0 / fTexHeight;
+ }
+ }
+
+ if(nLoopCount)
+ {
+ for(a = 0L; a < nLoopCount; a++)
+ {
+ const Slice3D& rSliceA(rSliceVector[a]);
+ const Slice3D& rSliceB(rSliceVector[(a + 1L) % nNumSlices]);
+ const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType());
+ basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon());
+
+ if(bAcceptPair)
+ {
+ if(bCreateNormals)
+ {
+ impCreateInBetweenNormals(aPolB, aPolA, bSmoothHorizontalNormals);
+ }
+
+ {
+ const sal_uInt32 nIndPrev((a + nNumSlices - 1L) % nNumSlices);
+ const Slice3D& rSlicePrev(rSliceVector[nIndPrev]);
+ basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon());
+
+ if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType())
+ {
+ basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon());
+ const bool bHasSlant(aPolAA != aPrev);
+
+ if(bCreateTextureCoordinates)
+ {
+ aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
+ }
+
+ if(bCreateNormals)
+ {
+ basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
+
+ if(aFront.count())
+ {
+ aNormal = -aFront.getB3DPolygon(0L).getNormal();
+ }
+
+ impSetNormal(aFront, aNormal);
+
+ if(bHasSlant)
+ {
+ impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
+
+ if(bSmoothNormals)
+ {
+ // smooth and copy
+ impMixNormals(aPolA, aPolAA, fSmoothNormalsMix);
+ aPolAA = aPolA;
+ }
+ else
+ {
+ // take over from surface
+ aPolAA = aPolA;
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aFront, aPrev, fSmoothLidsMix);
+ aPrev = aFront;
+ }
+ else
+ {
+ // take over from front
+ aPrev = aFront;
+ }
+ }
+ else
+ {
+ if(bSmoothNormals)
+ {
+ // smooth
+ impMixNormals(aPolA, aFront, fSmoothNormalsMix);
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aFront, aPolA, fSmoothLidsMix);
+ aPolA = aFront;
+ }
+ }
+ }
+
+ if(bHasSlant)
+ {
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = fTexHeightPos * fInvTexHeight;
+ fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1L) % nLoopCount]) * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ aFront.flip();
+ rFill.push_back(aFront);
+ }
+ else
+ {
+ if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1L))
+ {
+ impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
+ impMixNormals(aPolA, aPolAA, 0.5);
+ }
+ }
+ }
+
+ {
+ const sal_uInt32 nIndNext((a + 2L) % nNumSlices);
+ const Slice3D& rSliceNext(rSliceVector[nIndNext]);
+ basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon());
+ basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon());
+
+ if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType())
+ {
+ basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon());
+ const bool bHasSlant(aPolBB != aNext);
+
+ if(bCreateTextureCoordinates)
+ {
+ aBack = basegfx::tools::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack);
+ }
+
+ if(bCreateNormals)
+ {
+ const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0L).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0));
+ impSetNormal(aBack, aNormal);
+
+ if(bHasSlant)
+ {
+ impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
+
+ if(bSmoothNormals)
+ {
+ // smooth and copy
+ impMixNormals(aPolB, aPolBB, fSmoothNormalsMix);
+ aPolBB = aPolB;
+ }
+ else
+ {
+ // take over from surface
+ aPolBB = aPolB;
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aBack, aNext, fSmoothLidsMix);
+ aNext = aBack;
+ }
+ else
+ {
+ // take over from back
+ aNext = aBack;
+ }
+ }
+ else
+ {
+ if(bSmoothNormals)
+ {
+ // smooth
+ impMixNormals(aPolB, aBack, fSmoothNormalsMix);
+ }
+
+ if(bSmoothLids)
+ {
+ // smooth and copy
+ impMixNormals(aBack, aPolB, fSmoothLidsMix);
+ aPolB = aBack;
+ }
+ }
+ }
+
+ if(bHasSlant)
+ {
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1L) % nLoopCount]) * fInvTexHeight;
+ fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ rFill.push_back(aBack);
+ }
+ else
+ {
+ if(bCreateNormals && bSmoothNormals && (nIndNext != a))
+ {
+ impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
+ impMixNormals(aPolB, aPolBB, 0.5);
+ }
+ }
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
+ fTexStop = fTexHeightPos * fInvTexHeight;
+ }
+
+ impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ fTexHeightPos += aTexHeightArray[a];
+ }
+ }
+ }
+ else
+ {
+ // no loop, but a single slice (1 == nNumSlices), create a filling from the single
+ // front plane
+ const Slice3D& rSlice(rSliceVector[0]);
+ basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon());
+
+ if(bCreateTextureCoordinates)
+ {
+ aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
+ }
+
+ if(bCreateNormals)
+ {
+ basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
+
+ if(aFront.count())
+ {
+ aNormal = -aFront.getB3DPolygon(0L).getNormal();
+ }
+
+ impSetNormal(aFront, aNormal);
+ }
+
+ aFront.flip();
+ rFill.push_back(aFront);
+ }
+
+ if(bCreateTextureCoordinates)
+ {
+ aEdgeRounding.transformTextureCoordiantes(rTexTransform);
+ }
+
+ for(a = 0L; a < aEdgeRounding.count(); a++)
+ {
+ rFill.push_back(basegfx::B3DPolyPolygon(aEdgeRounding.getB3DPolygon(a)));
+ }
+ }
+ }
+
+ void createReducedOutlines(
+ const geometry::ViewInformation3D& rViewInformation,
+ const basegfx::B3DHomMatrix& rObjectTransform,
+ const basegfx::B3DPolygon& rLoopA,
+ const basegfx::B3DPolygon& rLoopB,
+ basegfx::B3DPolyPolygon& rTarget)
+ {
+ const sal_uInt32 nPointCount(rLoopA.count());
+
+ // with idetic polygons there are no outlines
+ if(rLoopA != rLoopB)
+ {
+ if(nPointCount && nPointCount == rLoopB.count())
+ {
+ const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform);
+ const basegfx::B2DPolygon a2DLoopA(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform));
+ const basegfx::B2DPolygon a2DLoopB(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform));
+ const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter());
+ const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter());
+
+ // without detectable Y-Axis there are no outlines
+ if(!a2DCenterA.equal(a2DCenterB))
+ {
+ // search for outmost left and right inter-loop-edges which do not cut the loops
+ const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB));
+ const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB);
+ double fMaxLeft(0.0);
+ double fMaxRight(0.0);
+ sal_uInt32 nIndexLeft(0);
+ sal_uInt32 nIndexRight(0);
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a));
+ const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a));
+ const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd));
+
+ if(!basegfx::tools::isInside(a2DLoopA, aMiddle))
+ {
+ if(!basegfx::tools::isInside(a2DLoopB, aMiddle))
+ {
+ if(!impHasCutWith(a2DLoopA, aStart, aEnd))
+ {
+ if(!impHasCutWith(a2DLoopB, aStart, aEnd))
+ {
+ const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter);
+ const double fCross(aCandidateVector.cross(aAxisVector));
+ const double fDistance(aCandidateVector.getLength());
+
+ if(fCross > 0.0)
+ {
+ if(fDistance > fMaxLeft)
+ {
+ fMaxLeft = fDistance;
+ nIndexLeft = a;
+ }
+ }
+ else if(fCross < 0.0)
+ {
+ if(fDistance > fMaxRight)
+ {
+ fMaxRight = fDistance;
+ nIndexRight = a;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(fMaxLeft != 0.0)
+ {
+ basegfx::B3DPolygon aToBeAdded;
+ aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft));
+ aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft));
+ rTarget.append(aToBeAdded);
+ }
+
+ if(fMaxRight != 0.0)
+ {
+ basegfx::B3DPolygon aToBeAdded;
+ aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight));
+ aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight));
+ rTarget.append(aToBeAdded);
+ }
+ }
+ }
+ }
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
new file mode 100644
index 000000000000..e9ef154c95f3
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
@@ -0,0 +1,537 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrextrudeprimitive3d.cxx,v $
+ *
+ * $Revision: 1.15 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-26 16:21:48 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/sdrextrudeprimitive3d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrExtrudePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ Primitive3DSequence aRetval;
+
+ // get slices
+ const Slice3DVector& rSliceVector = getSlices();
+
+ if(rSliceVector.size())
+ {
+ sal_uInt32 a;
+
+ // decide what to create
+ const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind);
+ const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ double fRelativeTextureWidth(1.0);
+ basegfx::B2DHomMatrix aTexTransform;
+
+ if(getSdrLFSAttribute().getFill() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY))
+ {
+ const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0L));
+ const double fFrontLength(basegfx::tools::getLength(aFirstPolygon));
+ const double fFrontArea(basegfx::tools::getArea(aFirstPolygon));
+ const double fSqrtFrontArea(sqrt(fFrontArea));
+ fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea;
+ fRelativeTextureWidth = (double)((sal_uInt32)(fRelativeTextureWidth - 0.5));
+
+ if(fRelativeTextureWidth < 1.0)
+ {
+ fRelativeTextureWidth = 1.0;
+ }
+
+ aTexTransform.translate(-0.5, -0.5);
+ aTexTransform.scale(-1.0, -1.0);
+ aTexTransform.translate(0.5, 0.5);
+ aTexTransform.scale(fRelativeTextureWidth, 1.0);
+ }
+
+ // create geometry
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ extractPlanesFromSlice(aFill, rSliceVector,
+ bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), false,
+ 0.5, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform);
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // normal creation
+ if(getSdrLFSAttribute().getFill())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind)
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind)
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(getSdrLFSAttribute().getFill())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(getSdrLFSAttribute().getFill())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ *getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
+
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ aSimplifiedFillAttribute,
+ 0);
+
+ // encapsulate in HitTestPrimitive3D and add
+ const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ // add line
+ if(getSdrLFSAttribute().getLine())
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ // create geometric outlines with reduced line geometry for chart.
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+ const sal_uInt32 nCount(aVerLine.count());
+ basegfx::B3DPolyPolygon aReducedLoops;
+ basegfx::B3DPolyPolygon aNewLineGeometry;
+
+ // sort out doubles (front and back planes when no edge rounding is done). Since
+ // this is a line geometry merged from PolyPolygons, loop over all Polygons
+ for(a = 0; a < nCount; a++)
+ {
+ const sal_uInt32 nReducedCount(aReducedLoops.count());
+ const basegfx::B3DPolygon aCandidate(aVerLine.getB3DPolygon(a));
+ bool bAdd(true);
+
+ if(nReducedCount)
+ {
+ for(sal_uInt32 b(0); bAdd && b < nReducedCount; b++)
+ {
+ if(aCandidate == aReducedLoops.getB3DPolygon(b))
+ {
+ bAdd = false;
+ }
+ }
+ }
+
+ if(bAdd)
+ {
+ aReducedLoops.append(aCandidate);
+ }
+ }
+
+ // from here work with reduced loops and reduced count without changing them
+ const sal_uInt32 nReducedCount(aReducedLoops.count());
+
+ if(nReducedCount > 1)
+ {
+ for(sal_uInt32 b(1); b < nReducedCount; b++)
+ {
+ // get loop pair
+ const basegfx::B3DPolygon aCandA(aReducedLoops.getB3DPolygon(b - 1));
+ const basegfx::B3DPolygon aCandB(aReducedLoops.getB3DPolygon(b));
+
+ // for each loop pair create the connection edges
+ createReducedOutlines(
+ rViewInformation,
+ getTransform(),
+ aCandA,
+ aCandB,
+ aNewLineGeometry);
+ }
+ }
+
+ // add reduced loops themselves
+ aNewLineGeometry.append(aReducedLoops);
+
+ // to create vertical edges at non-C1/C2 steady loops, use maCorrectedPolyPolygon
+ // directly since the 3D Polygons do not suport this.
+ //
+ // Unfortunately there is no bezier polygon provided by the chart module; one reason is
+ // that the API for extrude wants a 3D polygon geometry (for historical reasons, i guess)
+ // and those have no beziers. Another reason is that he chart module uses self-created
+ // stuff to create the 2D geometry (in ShapeFactory::createPieSegment), but this geometry
+ // does not contain bezier infos, either. The only way which is possible for now is to 'detect'
+ // candidates for vertical edges of pie segments by looking for the angles in the polygon.
+ //
+ // This is all not very well designed ATM. Ideally, the ReducedLineGeometry is responsible
+ // for creating the outer geometry edges (createReducedOutlines), but for special edges
+ // like the vertical ones for pie center and both start/end, the incarnation with the
+ // knowledge about that it needs to create those and IS a pie segment -> in this case,
+ // the chart itself.
+ const sal_uInt32 nPolyCount(maCorrectedPolyPolygon.count());
+
+ for(sal_uInt32 c(0); c < nPolyCount; c++)
+ {
+ const basegfx::B2DPolygon aCandidate(maCorrectedPolyPolygon.getB2DPolygon(c));
+ const sal_uInt32 nPointCount(aCandidate.count());
+
+ if(nPointCount > 2)
+ {
+ sal_uInt32 nIndexA(nPointCount);
+ sal_uInt32 nIndexB(nPointCount);
+ sal_uInt32 nIndexC(nPointCount);
+
+ for(sal_uInt32 d(0); d < nPointCount; d++)
+ {
+ const sal_uInt32 nPrevInd((d + nPointCount - 1) % nPointCount);
+ const sal_uInt32 nNextInd((d + 1) % nPointCount);
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(d));
+ const basegfx::B2DVector aPrev(aCandidate.getB2DPoint(nPrevInd) - aPoint);
+ const basegfx::B2DVector aNext(aCandidate.getB2DPoint(nNextInd) - aPoint);
+ const double fAngle(aPrev.angle(aNext));
+
+ // take each angle which deviates more than 10% from going straight as
+ // special edge. This will detect the two outer edges of pie segments,
+ // but not always the center one (think about a near 180 degree pie)
+ if(F_PI - fabs(fAngle) > F_PI * 0.1)
+ {
+ if(nPointCount == nIndexA)
+ {
+ nIndexA = d;
+ }
+ else if(nPointCount == nIndexB)
+ {
+ nIndexB = d;
+ }
+ else if(nPointCount == nIndexC)
+ {
+ nIndexC = d;
+ d = nPointCount;
+ }
+ }
+ }
+
+ const bool bIndexAUsed(nIndexA != nPointCount);
+ const bool bIndexBUsed(nIndexB != nPointCount);
+ bool bIndexCUsed(nIndexC != nPointCount);
+
+ if(bIndexCUsed)
+ {
+ // already three special edges found, so the center one was already detected
+ // and does not need to be searched
+ }
+ else if(bIndexAUsed && bIndexBUsed)
+ {
+ // outer edges detected (they are approx. 90 degrees), but center one not.
+ // Look with the knowledge that it's in-between the two found ones
+ if(((nIndexA + 2) % nPointCount) == nIndexB)
+ {
+ nIndexC = (nIndexA + 1) % nPointCount;
+ }
+ else if(((nIndexA + nPointCount - 2) % nPointCount) == nIndexB)
+ {
+ nIndexC = (nIndexA + nPointCount - 1) % nPointCount;
+ }
+
+ bIndexCUsed = (nIndexC != nPointCount);
+ }
+
+ if(bIndexAUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexA));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+
+ if(bIndexBUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexB));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+
+ if(bIndexCUsed)
+ {
+ const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexC));
+ const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0);
+ const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth());
+ basegfx::B3DPolygon aToBeAdded;
+
+ aToBeAdded.append(aStart);
+ aToBeAdded.append(aEnd);
+ aNewLineGeometry.append(aToBeAdded);
+ }
+ }
+ }
+
+ // append loops themselves
+ aNewLineGeometry.append(aReducedLoops);
+
+ if(aNewLineGeometry.count())
+ {
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(aNewLineGeometry, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+ }
+ else
+ {
+ // extract line geometry from slices
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, false));
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+
+ // add horizontal lines
+ const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives(aHorLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines);
+
+ // add vertical lines
+ const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives(aVerLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines);
+ }
+ }
+
+ // add shadow
+ if(getSdrLFSAttribute().getShadow() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(aRetval, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void SdrExtrudePrimitive3D::impCreateSlices()
+ {
+ // prepare the polygon. No double points, correct orientations and a correct
+ // outmost polygon are needed
+ maCorrectedPolyPolygon = getPolyPolygon();
+ maCorrectedPolyPolygon.removeDoublePoints();
+ maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon);
+ maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon);
+
+ // prepare slices as geometry
+ createExtrudeSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getDepth(), getCharacterMode(), getCloseFront(), getCloseBack());
+ }
+
+ const Slice3DVector& SdrExtrudePrimitive3D::getSlices() const
+ {
+ // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
+ // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
+ if(getPolyPolygon().count() && !maSlices.size())
+ {
+ ::osl::Mutex m_mutex;
+ const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices();
+ }
+
+ return maSlices;
+ }
+
+ SdrExtrudePrimitive3D::SdrExtrudePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fDepth,
+ double fDiagonal,
+ double fBackScale,
+ bool bSmoothNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothLids,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maCorrectedPolyPolygon(),
+ maSlices(),
+ maPolyPolygon(rPolyPolygon),
+ mfDepth(fDepth),
+ mfDiagonal(fDiagonal),
+ mfBackScale(fBackScale),
+ mpLastRLGViewInformation(0),
+ mbSmoothNormals(bSmoothNormals),
+ mbSmoothHorizontalNormals(bSmoothHorizontalNormals),
+ mbSmoothLids(bSmoothLids),
+ mbCharacterMode(bCharacterMode),
+ mbCloseFront(bCloseFront),
+ mbCloseBack(bCloseBack)
+ {
+ // make sure depth is positive
+ if(basegfx::fTools::lessOrEqual(getDepth(), 0.0))
+ {
+ mfDepth = 0.0;
+ }
+
+ // make sure the percentage value getDiagonal() is between 0.0 and 1.0
+ if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ {
+ mfDiagonal = 0.0;
+ }
+ else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
+ {
+ mfDiagonal = 1.0;
+ }
+
+ // no close front/back when polygon is not closed
+ if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
+ {
+ mbCloseFront = mbCloseBack = false;
+ }
+
+ // no edge rounding when not closing
+ if(!getCloseFront() && !getCloseBack())
+ {
+ mfDiagonal = 0.0;
+ }
+ }
+
+ SdrExtrudePrimitive3D::~SdrExtrudePrimitive3D()
+ {
+ if(mpLastRLGViewInformation)
+ {
+ delete mpLastRLGViewInformation;
+ }
+ }
+
+ bool SdrExtrudePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrExtrudePrimitive3D& rCompare = static_cast< const SdrExtrudePrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon() == rCompare.getPolyPolygon()
+ && getDepth() == rCompare.getDepth()
+ && getDiagonal() == rCompare.getDiagonal()
+ && getBackScale() == rCompare.getBackScale()
+ && getSmoothNormals() == rCompare.getSmoothNormals()
+ && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals()
+ && getSmoothLids() == rCompare.getSmoothLids()
+ && getCharacterMode() == rCompare.getCharacterMode()
+ && getCloseFront() == rCompare.getCloseFront()
+ && getCloseBack() == rCompare.getCloseBack());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrExtrudePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return get3DRangeFromSlices(getSlices());
+ }
+
+ Primitive3DSequence SdrExtrudePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ if(!mpLastRLGViewInformation ||
+ (getLocalDecomposition().hasElements()
+ && *mpLastRLGViewInformation != rViewInformation))
+ {
+ // conditions of last local decomposition with reduced lines have changed. Remember
+ // new one and clear current decompositiopn
+ ::osl::Mutex m_mutex;
+ SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this);
+ pThat->setLocalDecomposition(Primitive3DSequence());
+ delete pThat->mpLastRLGViewInformation;
+ pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation);
+ }
+ }
+
+ // no test for buffering needed, call parent
+ return SdrPrimitive3D::get3DDecomposition(rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrExtrudePrimitive3D, PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
new file mode 100644
index 000000000000..33008e762c0a
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx
@@ -0,0 +1,396 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrlatheprimitive3d.cxx,v $
+ *
+ * $Revision: 1.15 $
+ *
+ * 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/primitive3d/sdrlatheprimitive3d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrLathePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ Primitive3DSequence aRetval;
+
+ // get slices
+ const Slice3DVector& rSliceVector = getSlices();
+
+ if(rSliceVector.size())
+ {
+ const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
+ const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI));
+ sal_uInt32 a;
+
+ // decide what to create
+ const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind);
+ const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ basegfx::B2DHomMatrix aTexTransform;
+
+ if(getSdrLFSAttribute().getFill() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY))
+ {
+ aTexTransform.set(0, 0, 0.0);
+ aTexTransform.set(0, 1, 1.0);
+ aTexTransform.set(1, 0, 1.0);
+ aTexTransform.set(1, 1, 0.0);
+
+ aTexTransform.translate(0.0, -0.5);
+ aTexTransform.scale(1.0, -1.0);
+ aTexTransform.translate(0.0, 0.5);
+ }
+
+ // create geometry
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ extractPlanesFromSlice(aFill, rSliceVector,
+ bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation,
+ 0.85, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform);
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // normal creation
+ if(getSdrLFSAttribute().getFill())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind)
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind)
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // texture coordinates
+ if(getSdrLFSAttribute().getFill())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(getSdrLFSAttribute().getFill())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ *getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
+
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ aSimplifiedFillAttribute,
+ 0);
+
+ // encapsulate in HitTestPrimitive3D and add
+ const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ // add line
+ if(getSdrLFSAttribute().getLine())
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ // create geometric outlines with reduced line geometry for chart
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
+ const sal_uInt32 nCount(aHorLine.count());
+ basegfx::B3DPolyPolygon aNewLineGeometry;
+
+ for(a = 1; a < nCount; a++)
+ {
+ // for each loop pair create the connection edges
+ createReducedOutlines(
+ rViewInformation,
+ getTransform(),
+ aHorLine.getB3DPolygon(a - 1),
+ aHorLine.getB3DPolygon(a),
+ aNewLineGeometry);
+ }
+
+ for(a = 0; a < nCount; a++)
+ {
+ // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
+ basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a));
+ aCandidate.removeDoublePoints();
+
+ if(aCandidate.count())
+ {
+ aNewLineGeometry.append(aCandidate);
+ }
+ }
+
+ if(aNewLineGeometry.count())
+ {
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(aNewLineGeometry, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+ }
+ else
+ {
+ // extract line geometry from slices
+ const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
+ const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
+
+ // add horizontal lines
+ const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives(aHorLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines);
+
+ // add vertical lines
+ const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives(aVerLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines);
+ }
+ }
+
+ // add shadow
+ if(getSdrLFSAttribute().getShadow() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(aRetval, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void SdrLathePrimitive3D::impCreateSlices()
+ {
+ // prepare the polygon. No double points, correct orientations and a correct
+ // outmost polygon are needed
+ maCorrectedPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(getPolyPolygon());
+ maCorrectedPolyPolygon.removeDoublePoints();
+ maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon);
+ maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon);
+
+ // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
+ // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0L is different
+ // at all (and not always)
+ const basegfx::B2DPolygon aSubCandidate(maCorrectedPolyPolygon.getB2DPolygon(0));
+ const sal_uInt32 nSubEdgeCount(aSubCandidate.isClosed() ? aSubCandidate.count() : (aSubCandidate.count() ? aSubCandidate.count() - 1L : 0L));
+
+ if(nSubEdgeCount != getVerticalSegments())
+ {
+ maCorrectedPolyPolygon = basegfx::tools::reSegmentPolyPolygon(maCorrectedPolyPolygon, getVerticalSegments());
+ }
+
+ // prepare slices as geometry
+ createLatheSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
+ }
+
+ const Slice3DVector& SdrLathePrimitive3D::getSlices() const
+ {
+ // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
+ // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
+ if(getPolyPolygon().count() && !maSlices.size())
+ {
+ ::osl::Mutex m_mutex;
+ const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
+ }
+
+ return maSlices;
+ }
+
+ SdrLathePrimitive3D::SdrLathePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ sal_uInt32 nHorizontalSegments,
+ sal_uInt32 nVerticalSegments,
+ double fDiagonal,
+ double fBackScale,
+ double fRotation,
+ bool bSmoothNormals,
+ bool bSmoothHorizontalNormals,
+ bool bSmoothLids,
+ bool bCharacterMode,
+ bool bCloseFront,
+ bool bCloseBack)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maCorrectedPolyPolygon(),
+ maSlices(),
+ maPolyPolygon(rPolyPolygon),
+ mnHorizontalSegments(nHorizontalSegments),
+ mnVerticalSegments(nVerticalSegments),
+ mfDiagonal(fDiagonal),
+ mfBackScale(fBackScale),
+ mfRotation(fRotation),
+ mpLastRLGViewInformation(0),
+ mbSmoothNormals(bSmoothNormals),
+ mbSmoothHorizontalNormals(bSmoothHorizontalNormals),
+ mbSmoothLids(bSmoothLids),
+ mbCharacterMode(bCharacterMode),
+ mbCloseFront(bCloseFront),
+ mbCloseBack(bCloseBack)
+ {
+ // make sure Rotation is positive
+ if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
+ {
+ mfRotation = 0.0;
+ }
+
+ // make sure the percentage value getDiagonal() is between 0.0 and 1.0
+ if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
+ {
+ mfDiagonal = 0.0;
+ }
+ else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
+ {
+ mfDiagonal = 1.0;
+ }
+
+ // no close front/back when polygon is not closed
+ if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
+ {
+ mbCloseFront = mbCloseBack = false;
+ }
+
+ // no edge rounding when not closing
+ if(!getCloseFront() && !getCloseBack())
+ {
+ mfDiagonal = 0.0;
+ }
+ }
+
+ SdrLathePrimitive3D::~SdrLathePrimitive3D()
+ {
+ if(mpLastRLGViewInformation)
+ {
+ delete mpLastRLGViewInformation;
+ }
+ }
+
+ bool SdrLathePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrLathePrimitive3D& rCompare = static_cast< const SdrLathePrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon() == rCompare.getPolyPolygon()
+ && getHorizontalSegments() == rCompare.getHorizontalSegments()
+ && getVerticalSegments() == rCompare.getVerticalSegments()
+ && getDiagonal() == rCompare.getDiagonal()
+ && getBackScale() == rCompare.getBackScale()
+ && getRotation() == rCompare.getRotation()
+ && getSmoothNormals() == rCompare.getSmoothNormals()
+ && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals()
+ && getSmoothLids() == rCompare.getSmoothLids()
+ && getCharacterMode() == rCompare.getCharacterMode()
+ && getCloseFront() == rCompare.getCloseFront()
+ && getCloseBack() == rCompare.getCloseBack());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return get3DRangeFromSlices(getSlices());
+ }
+
+ Primitive3DSequence SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ if(getSdr3DObjectAttribute().getReducedLineGeometry())
+ {
+ if(!mpLastRLGViewInformation ||
+ (getLocalDecomposition().hasElements()
+ && *mpLastRLGViewInformation != rViewInformation))
+ {
+ // conditions of last local decomposition with reduced lines have changed. Remember
+ // new one and clear current decompositiopn
+ ::osl::Mutex m_mutex;
+ SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
+ pThat->setLocalDecomposition(Primitive3DSequence());
+ delete pThat->mpLastRLGViewInformation;
+ pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation);
+ }
+ }
+
+ // no test for buffering needed, call parent
+ return SdrPrimitive3D::get3DDecomposition(rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrLathePrimitive3D, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
new file mode 100644
index 000000000000..a0813d3202a8
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx
@@ -0,0 +1,206 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrpolypolygonprimitive3d.cxx,v $
+ *
+ * $Revision: 1.7 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/sdrpolypolygonprimitive3d.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrPolyPolygonPrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+
+ if(getPolyPolygon3D().count())
+ {
+ ::std::vector< basegfx::B3DPolyPolygon > aFill;
+ aFill.push_back(getPolyPolygon3D());
+
+ // get full range
+ const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
+
+ // #i98295# normal creation
+ if(getSdrLFSAttribute().getFill())
+ {
+ if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ applyNormalsKindSphereTo3DGeometry(aFill, aRange);
+ }
+ else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind())
+ {
+ applyNormalsKindFlatTo3DGeometry(aFill);
+ }
+
+ if(getSdr3DObjectAttribute().getNormalsInvert())
+ {
+ applyNormalsInvertTo3DGeometry(aFill);
+ }
+ }
+
+ // #i98314# texture coordinates
+ if(getSdrLFSAttribute().getFill())
+ {
+ applyTextureTo3DGeometry(
+ getSdr3DObjectAttribute().getTextureProjectionX(),
+ getSdr3DObjectAttribute().getTextureProjectionY(),
+ aFill,
+ aRange,
+ getTextureSize());
+ }
+
+ if(getSdrLFSAttribute().getFill())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ *getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
+
+ aRetval = create3DPolyPolygonFillPrimitives(
+ aFill,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ aSimplifiedFillAttribute,
+ 0);
+
+ // encapsulate in HitTestPrimitive3D and add
+ const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ // add line
+ if(getSdrLFSAttribute().getLine())
+ {
+ basegfx::B3DPolyPolygon aLine(getPolyPolygon3D());
+ aLine.clearNormals();
+ aLine.clearTextureCoordinates();
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(aLine, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(getSdrLFSAttribute().getShadow() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(aRetval, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+ }
+
+ return aRetval;
+ }
+
+ SdrPolyPolygonPrimitive3D::SdrPolyPolygonPrimitive3D(
+ const basegfx::B3DPolyPolygon& rPolyPolygon3D,
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ maPolyPolygon3D(rPolyPolygon3D)
+ {
+ }
+
+ bool SdrPolyPolygonPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrPolyPolygonPrimitive3D& rCompare = static_cast< const SdrPolyPolygonPrimitive3D& >(rPrimitive);
+
+ return (getPolyPolygon3D() == rCompare.getPolyPolygon3D());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrPolyPolygonPrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // added this implementation to make sure that non-visible objects of this
+ // kind will deliver their expansion. If not implemented, it would never deliver
+ // the used space for non-visible objects since the decomposition for that
+ // case will be empty (what is correct). To support chart ATM which relies on
+ // non-visible objects occupying space in 3D, this method was added
+ basegfx::B3DRange aRetval;
+
+ if(getPolyPolygon3D().count())
+ {
+ aRetval = basegfx::tools::getRange(getPolyPolygon3D());
+ aRetval.transform(getTransform());
+
+ if(getSdrLFSAttribute().getLine())
+ {
+ const attribute::SdrLineAttribute& rLine = *getSdrLFSAttribute().getLine();
+
+ if(rLine.isVisible() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by half LineWidth as tube radius
+ aRetval.grow(rLine.getWidth() / 2.0);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrPolyPolygonPrimitive3D, PRIMITIVE3D_ID_SDRPOLYPOLYGONPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
new file mode 100644
index 000000000000..dc93d0c0f339
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrprimitive3d.cxx
@@ -0,0 +1,133 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrprimitive3d.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/primitive3d/sdrprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ basegfx::B3DRange SdrPrimitive3D::getStandard3DRange() const
+ {
+ basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ aUnitRange.transform(getTransform());
+
+ if(getSdrLFSAttribute().getLine())
+ {
+ const attribute::SdrLineAttribute& rLine = *getSdrLFSAttribute().getLine();
+
+ if(rLine.isVisible() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by hald LineWidth as tube radius
+ aUnitRange.grow(rLine.getWidth() / 2.0);
+ }
+ }
+
+ return aUnitRange;
+ }
+
+ basegfx::B3DRange SdrPrimitive3D::get3DRangeFromSlices(const Slice3DVector& rSlices) const
+ {
+ basegfx::B3DRange aRetval;
+
+ if(rSlices.size())
+ {
+ for(sal_uInt32 a(0L); a < rSlices.size(); a++)
+ {
+ aRetval.expand(basegfx::tools::getRange(rSlices[a].getB3DPolyPolygon()));
+ }
+
+ aRetval.transform(getTransform());
+
+ if(getSdrLFSAttribute().getLine())
+ {
+ const attribute::SdrLineAttribute& rLine = *getSdrLFSAttribute().getLine();
+
+ if(rLine.isVisible() && !basegfx::fTools::equalZero(rLine.getWidth()))
+ {
+ // expand by half LineWidth as tube radius
+ aRetval.grow(rLine.getWidth() / 2.0);
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ SdrPrimitive3D::SdrPrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute)
+ : BasePrimitive3D(),
+ maTransform(rTransform),
+ maTextureSize(rTextureSize),
+ maSdrLFSAttribute(rSdrLFSAttribute),
+ maSdr3DObjectAttribute(rSdr3DObjectAttribute)
+ {
+ }
+
+ bool SdrPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(BasePrimitive3D::operator==(rPrimitive))
+ {
+ const SdrPrimitive3D& rCompare = static_cast< const SdrPrimitive3D& >(rPrimitive);
+
+ return (getTransform() == rCompare.getTransform()
+ && getTextureSize() == rCompare.getTextureSize()
+ && getSdrLFSAttribute() == rCompare.getSdrLFSAttribute()
+ && getSdr3DObjectAttribute() == rCompare.getSdr3DObjectAttribute());
+ }
+
+ return false;
+ }
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
new file mode 100644
index 000000000000..e7149c611dd9
--- /dev/null
+++ b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sdrsphereprimitive3d.cxx,v $
+ *
+ * $Revision: 1.12 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/sdrsphereprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/attribute/sdrattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence SdrSpherePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ Primitive3DSequence aRetval;
+ const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
+ const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()
+ || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind());
+
+ // create unit geometry
+ basegfx::B3DPolyPolygon aFill(basegfx::tools::createSphereFillPolyPolygonFromB3DRange(aUnitRange,
+ getHorizontalSegments(), getVerticalSegments(), bCreateNormals));
+
+ // normal inversion
+ if(getSdrLFSAttribute().getFill()
+ && bCreateNormals
+ && getSdr3DObjectAttribute().getNormalsInvert()
+ && aFill.areNormalsUsed())
+ {
+ // invert normals
+ aFill = basegfx::tools::invertNormals(aFill);
+ }
+
+ // texture coordinates
+ if(getSdrLFSAttribute().getFill())
+ {
+ // handle texture coordinates X
+ const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
+ const bool bSphereX(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX());
+
+ // handle texture coordinates Y
+ const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
+ const bool bSphereY(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY());
+
+ if(bParallelX || bParallelY)
+ {
+ // apply parallel texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY);
+ }
+
+ if(bSphereX || bObjectSpecificX || bSphereY || bObjectSpecificY)
+ {
+ double fRelativeAngle(0.0);
+
+ if(bObjectSpecificX)
+ {
+ // Since the texture coordinates are (for historical reasons)
+ // different from forced to sphere texture coordinates,
+ // create a old version from it by rotating to old state before applying
+ // the texture coordinates to emulate old behaviour
+ fRelativeAngle = F_2PI * ((double)((getHorizontalSegments() >> 1L) - 1L) / (double)getHorizontalSegments());
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(0.0, fRelativeAngle, 0.0);
+ aFill.transform(aRot);
+ }
+
+ // apply spherical texture coordinates in X and/or Y
+ const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
+ const basegfx::B3DPoint aCenter(aRange.getCenter());
+ aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter,
+ bSphereX || bObjectSpecificX, bSphereY || bObjectSpecificY);
+
+ if(bObjectSpecificX)
+ {
+ // rotate back again
+ basegfx::B3DHomMatrix aRot;
+ aRot.rotate(0.0, -fRelativeAngle, 0.0);
+ aFill.transform(aRot);
+ }
+ }
+
+ // transform texture coordinates to texture size
+ basegfx::B2DHomMatrix aTexMatrix;
+ aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY());
+ aFill.transformTextureCoordiantes(aTexMatrix);
+ }
+
+ // build vector of PolyPolygons
+ ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector;
+
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a)));
+ }
+
+ if(getSdrLFSAttribute().getFill())
+ {
+ // add fill
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ *getSdrLFSAttribute().getFill(),
+ getSdrLFSAttribute().getFillFloatTransGradient());
+ }
+ else
+ {
+ // create simplified 3d hit test geometry
+ const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
+
+ aRetval = create3DPolyPolygonFillPrimitives(
+ a3DPolyPolygonVector,
+ getTransform(),
+ getTextureSize(),
+ getSdr3DObjectAttribute(),
+ aSimplifiedFillAttribute,
+ 0);
+
+ // encapsulate in HitTestPrimitive3D and add
+ const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval));
+ aRetval = Primitive3DSequence(&xRef, 1L);
+ }
+
+ // add line
+ if(getSdrLFSAttribute().getLine())
+ {
+ basegfx::B3DPolyPolygon aSphere(basegfx::tools::createSpherePolyPolygonFromB3DRange(aUnitRange, getHorizontalSegments(), getVerticalSegments()));
+ const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(aSphere, getTransform(), *getSdrLFSAttribute().getLine()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
+ }
+
+ // add shadow
+ if(getSdrLFSAttribute().getShadow() && aRetval.hasElements())
+ {
+ const Primitive3DSequence aShadow(createShadowPrimitive3D(aRetval, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
+ appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
+ }
+
+ return aRetval;
+ }
+
+ SdrSpherePrimitive3D::SdrSpherePrimitive3D(
+ const basegfx::B3DHomMatrix& rTransform,
+ const basegfx::B2DVector& rTextureSize,
+ const attribute::SdrLineFillShadowAttribute& rSdrLFSAttribute,
+ const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
+ sal_uInt32 nHorizontalSegments,
+ sal_uInt32 nVerticalSegments)
+ : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
+ mnHorizontalSegments(nHorizontalSegments),
+ mnVerticalSegments(nVerticalSegments)
+ {
+ }
+
+ bool SdrSpherePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(SdrPrimitive3D::operator==(rPrimitive))
+ {
+ const SdrSpherePrimitive3D& rCompare = static_cast< const SdrSpherePrimitive3D& >(rPrimitive);
+
+ return (getHorizontalSegments() == rCompare.getHorizontalSegments()
+ && getVerticalSegments() == rCompare.getVerticalSegments());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange SdrSpherePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
+ // The parent implementation which uses the ranges of the decomposition would be more
+ // corrcet, but for historical reasons it is necessary to do the old method: To get
+ // the range of the non-transformed geometry and transform it then. This leads to different
+ // ranges where the new method is more correct, but the need to keep the old behaviour
+ // has priority here.
+ return getStandard3DRange();
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(SdrSpherePrimitive3D, PRIMITIVE3D_ID_SDRSPHEREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/shadowprimitive3d.cxx b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
new file mode 100644
index 000000000000..712bee65c7c3
--- /dev/null
+++ b/drawinglayer/source/primitive3d/shadowprimitive3d.cxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: shadowprimitive3d.cxx,v $
+ *
+ * $Revision: 1.8 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ ShadowPrimitive3D::ShadowPrimitive3D(
+ const basegfx::B2DHomMatrix& rShadowTransform,
+ const basegfx::BColor& rShadowColor,
+ double fShadowTransparence,
+ bool bShadow3D,
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren),
+ maShadowTransform(rShadowTransform),
+ maShadowColor(rShadowColor),
+ mfShadowTransparence(fShadowTransparence),
+ mbShadow3D(bShadow3D)
+ {
+ }
+
+ bool ShadowPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const ShadowPrimitive3D& rCompare = (ShadowPrimitive3D&)rPrimitive;
+
+ return (getShadowTransform() == rCompare.getShadowTransform()
+ && getShadowColor() == rCompare.getShadowColor()
+ && getShadowTransparence() == rCompare.getShadowTransparence()
+ && getShadow3D() == rCompare.getShadow3D());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(ShadowPrimitive3D, PRIMITIVE3D_ID_SHADOWPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/textureprimitive3d.cxx b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
new file mode 100644
index 000000000000..3393346d0b2d
--- /dev/null
+++ b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: textureprimitive3d.cxx,v $
+ *
+ * $Revision: 1.9 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ TexturePrimitive3D::TexturePrimitive3D(
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate, bool bFilter)
+ : GroupPrimitive3D(rChildren),
+ maTextureSize(rTextureSize),
+ mbModulate(bModulate),
+ mbFilter(bFilter)
+ {
+ }
+
+ bool TexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const TexturePrimitive3D& rCompare = (TexturePrimitive3D&)rPrimitive;
+
+ return (getModulate() == rCompare.getModulate()
+ && getFilter() == rCompare.getFilter());
+ }
+
+ return false;
+ }
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence UnifiedAlphaTexturePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ if(0.0 == getTransparence())
+ {
+ // no transparence used, so just use content
+ return getChildren();
+ }
+ else if(getTransparence() > 0.0 && getTransparence() < 1.0)
+ {
+ // create AlphaTexturePrimitive3D with fixed transparence as replacement
+ const basegfx::BColor aGray(getTransparence(), getTransparence(), getTransparence());
+ const attribute::FillGradientAttribute aFillGradient(attribute::GRADIENTSTYLE_LINEAR, 0.0, 0.0, 0.0, 0.0, aGray, aGray, 1);
+ const Primitive3DReference xRef(new AlphaTexturePrimitive3D(aFillGradient, getChildren(), getTextureSize()));
+ return Primitive3DSequence(&xRef, 1L);
+ }
+ else
+ {
+ // completely transparent or invalid definition, add nothing
+ return Primitive3DSequence();
+ }
+ }
+
+ UnifiedAlphaTexturePrimitive3D::UnifiedAlphaTexturePrimitive3D(
+ double fTransparence,
+ const Primitive3DSequence& rChildren)
+ : TexturePrimitive3D(rChildren, basegfx::B2DVector(), false, false),
+ mfTransparence(fTransparence)
+ {
+ }
+
+ bool UnifiedAlphaTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const UnifiedAlphaTexturePrimitive3D& rCompare = (UnifiedAlphaTexturePrimitive3D&)rPrimitive;
+
+ return (getTransparence() == rCompare.getTransparence());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(UnifiedAlphaTexturePrimitive3D, PRIMITIVE3D_ID_UNIFIEDALPHATEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence GradientTexturePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return getChildren();
+ }
+
+ GradientTexturePrimitive3D::GradientTexturePrimitive3D(
+ const attribute::FillGradientAttribute& rGradient,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate,
+ bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maGradient(rGradient)
+ {
+ }
+
+ bool GradientTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const GradientTexturePrimitive3D& rCompare = (GradientTexturePrimitive3D&)rPrimitive;
+
+ return (getGradient() == rCompare.getGradient());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(GradientTexturePrimitive3D, PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ Primitive3DSequence BitmapTexturePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ return getChildren();
+ }
+
+ BitmapTexturePrimitive3D::BitmapTexturePrimitive3D(
+ const attribute::FillBitmapAttribute& rBitmap,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize,
+ bool bModulate, bool bFilter)
+ : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter),
+ maBitmap(rBitmap)
+ {
+ }
+
+ bool BitmapTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(TexturePrimitive3D::operator==(rPrimitive))
+ {
+ const BitmapTexturePrimitive3D& rCompare = (BitmapTexturePrimitive3D&)rPrimitive;
+
+ return (getBitmap() == rCompare.getBitmap());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(BitmapTexturePrimitive3D, PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ AlphaTexturePrimitive3D::AlphaTexturePrimitive3D(
+ const attribute::FillGradientAttribute& rGradient,
+ const Primitive3DSequence& rChildren,
+ const basegfx::B2DVector& rTextureSize)
+ : GradientTexturePrimitive3D(rGradient, rChildren, rTextureSize, false, false)
+ {
+ }
+
+ bool AlphaTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ return (GradientTexturePrimitive3D::operator==(rPrimitive));
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(AlphaTexturePrimitive3D, PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/primitive3d/transformprimitive3d.cxx b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
new file mode 100644
index 000000000000..cc96a9ecbc8d
--- /dev/null
+++ b/drawinglayer/source/primitive3d/transformprimitive3d.cxx
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: transformprimitive3d.cxx,v $
+ *
+ * $Revision: 1.8 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-10 09:29:33 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive3d
+ {
+ TransformPrimitive3D::TransformPrimitive3D(
+ const basegfx::B3DHomMatrix& rTransformation,
+ const Primitive3DSequence& rChildren)
+ : GroupPrimitive3D(rChildren),
+ maTransformation(rTransformation)
+ {
+ }
+
+ bool TransformPrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
+ {
+ if(GroupPrimitive3D::operator==(rPrimitive))
+ {
+ const TransformPrimitive3D& rCompare = static_cast< const TransformPrimitive3D& >(rPrimitive);
+
+ return (getTransformation() == rCompare.getTransformation());
+ }
+
+ return false;
+ }
+
+ basegfx::B3DRange TransformPrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const
+ {
+ basegfx::B3DRange aRetval(getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation));
+ aRetval.transform(getTransformation());
+ return aRetval;
+ }
+
+ // provide unique ID
+ ImplPrimitrive3DIDBlock(TransformPrimitive3D, PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D)
+
+ } // end of namespace primitive3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/baseprocessor2d.cxx b/drawinglayer/source/processor2d/baseprocessor2d.cxx
new file mode 100644
index 000000000000..76f66b85c9fa
--- /dev/null
+++ b/drawinglayer/source/processor2d/baseprocessor2d.cxx
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: baseprocessor2d.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * 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/processor2d/baseprocessor2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ void BaseProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& /*rCandidate*/)
+ {
+ }
+
+ BaseProcessor2D::BaseProcessor2D(const geometry::ViewInformation2D& rViewInformation)
+ : maViewInformation2D(rViewInformation)
+ {
+ }
+
+ BaseProcessor2D::~BaseProcessor2D()
+ {
+ }
+
+ void BaseProcessor2D::process(const primitive2d::Primitive2DSequence& rSource)
+ {
+ if(rSource.hasElements())
+ {
+ const sal_Int32 nCount(rSource.getLength());
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ // get reference
+ const primitive2d::Primitive2DReference xReference(rSource[a]);
+
+ if(xReference.is())
+ {
+ // try to cast to BasePrimitive2D implementation
+ const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
+
+ if(pBasePrimitive)
+ {
+ // it is a BasePrimitive2D implementation, use local processor
+ processBasePrimitive2D(*pBasePrimitive);
+ }
+ else
+ {
+ // unknown implementation, use UNO API call instead and process recursively
+ const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation2D().getViewInformationSequence());
+ process(xReference->getDecomposition(rViewParameters));
+ }
+ }
+ }
+ }
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/canvasprocessor.cxx b/drawinglayer/source/processor2d/canvasprocessor.cxx
new file mode 100644
index 000000000000..a60162de6ee0
--- /dev/null
+++ b/drawinglayer/source/processor2d/canvasprocessor.cxx
@@ -0,0 +1,2226 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: canvasprocessor.cxx,v $
+ *
+ * $Revision: 1.8 $
+ *
+ * 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/processor2d/canvasprocessor.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <vcl/canvastools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <canvas/canvastools.hxx>
+#include <svtools/ctloptions.hxx>
+#include <vcl/svapp.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
+#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <cppcanvas/vclfactory.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <vclhelperbitmaptransform.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <basegfx/tuple/b2i64tuple.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/StrokeAttributes.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
+#include <vclhelperbufferdevice.hxx>
+#include <drawinglayer/primitive2d/chartprimitive2d.hxx>
+#include <helperchartrenderer.hxx>
+#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
+#include <helperwrongspellrenderer.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+// AW: Adding the canvas example from THB here to extract stuff later
+/*
+ // TODO(Q3): share impCreateEmptyBitmapWithPattern() and other
+ // helper methods with vclprocessor.cxx
+ Bitmap impCreateEmptyBitmapWithPattern(Bitmap aSource, const Size& aTargetSizePixel)
+ {
+ Bitmap aRetval;
+ BitmapReadAccess* pReadAccess = aSource.AcquireReadAccess();
+
+ if(pReadAccess)
+ {
+ if(aSource.GetBitCount() <= 8)
+ {
+ BitmapPalette aPalette(pReadAccess->GetPalette());
+ aRetval = Bitmap(aTargetSizePixel, aSource.GetBitCount(), &aPalette);
+ }
+ else
+ {
+ aRetval = Bitmap(aTargetSizePixel, aSource.GetBitCount());
+ }
+
+ delete pReadAccess;
+ }
+
+ return aRetval;
+ }
+
+ Bitmap impModifyBitmap(const basegfx::BColorModifier& rModifier, const Bitmap& rSource)
+ {
+ Bitmap aRetval(rSource);
+
+ switch(rModifier.getMode())
+ {
+ case basegfx::BCOLORMODIFYMODE_REPLACE :
+ {
+ aRetval = impCreateEmptyBitmapWithPattern(aRetval, Size(1L, 1L));
+ aRetval.Erase(Color(rModifier.getBColor()));
+ break;
+ }
+
+ default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
+ {
+ BitmapWriteAccess* pContent = aRetval.AcquireWriteAccess();
+
+ if(pContent)
+ {
+ for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+ {
+ for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
+ {
+ const Color aColor = pContent->GetPixel(y, x);
+ const basegfx::BColor aBColor(rModifier.getModifiedColor(aColor.getBColor()));
+ pContent->SetPixel(y, x, BitmapColor(Color(aBColor)));
+ }
+ }
+
+ delete pContent;
+ }
+
+ break;
+ }
+ }
+
+ return aRetval;
+ }
+
+ Bitmap impModifyBitmap(const basegfx::BColorModifierStack& rBColorModifierStack, const Bitmap& rSource)
+ {
+ Bitmap aRetval(rSource);
+
+ for(sal_uInt32 a(rBColorModifierStack.count()); a; )
+ {
+ const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
+ aRetval = impModifyBitmap(rModifier, aRetval);
+ }
+
+ return aRetval;
+ }
+
+ sal_uInt32 impCalcGradientSteps(sal_uInt32 nSteps, const basegfx::B2DRange& rRange, sal_uInt32 nMaxDist)
+ {
+ if(nSteps == 0L)
+ nSteps = (sal_uInt32)(rRange.getWidth() + rRange.getHeight()) / 8;
+
+ if(nSteps < 2L)
+ {
+ nSteps = 2L;
+ }
+
+ if(nSteps > nMaxDist)
+ {
+ nSteps = nMaxDist;
+ }
+
+ return nSteps;
+ }
+
+ void canvasProcessor::impDrawGradientSimple(
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< basegfx::BColor >& rColors,
+ const basegfx::B2DPolygon& rUnitPolygon)
+ {
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rUnitPolygon));
+ uno::Reference< rendering::XPolyPolygon2D > xTargetPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm));
+
+ for(sal_uInt32 a(0L); a < rColors.size(); a++)
+ {
+ // set correct color
+ const basegfx::BColor aFillColor(rColors[a]);
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aFillColor);
+
+ if(a)
+ {
+ if(a - 1L < rMatrices.size())
+ {
+ canvas::tools::setRenderStateTransform( maRenderState,
+ rMatrices[a - 1L] );
+ mxCanvas->fillPolyPolygon(xPoly,maViewState,maRenderState);
+ }
+ }
+ else
+ {
+ canvas::tools::setRenderStateTransform( maRenderState,
+ basegfx::B2DHomMatrix() );
+ mxCanvas->fillPolyPolygon(xTargetPoly,maViewState,maRenderState);
+ }
+ }
+ }
+
+ void canvasProcessor::impDrawGradientComplex(
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< basegfx::BColor >& rColors,
+ const basegfx::B2DPolygon& rUnitPolygon)
+ {
+ uno::Reference< rendering::XPolyPolygon2D > xPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rUnitPolygon));
+ uno::Reference< rendering::XPolyPolygon2D > xTargetPoly(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm));
+
+ maRenderState.Clip = xTargetPoly;
+
+ // draw gradient PolyPolygons
+ for(std::size_t a = 0L; a < rMatrices.size(); a++)
+ {
+ // set correct color
+ if(rColors.size() > a)
+ {
+ const basegfx::BColor aFillColor(rColors[a]);
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aFillColor);
+ }
+
+ canvas::tools::setRenderStateTransform( maRenderState,
+ rMatrices[a] );
+
+ if(a)
+ mxCanvas->fillPolyPolygon(xPoly,maViewState,maRenderState);
+ else
+ mxCanvas->fillPolyPolygon(xTargetPoly,maViewState,maRenderState);
+ }
+
+ maRenderState.Clip.clear();
+ }
+
+ void canvasProcessor::impDrawGradient(
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ ::drawinglayer::primitive::GradientStyle eGradientStyle,
+ sal_uInt32 nSteps,
+ const basegfx::BColor& rStart,
+ const basegfx::BColor& rEnd,
+ double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple)
+ {
+ fprintf(stderr,"impDrawGradient\n");
+
+ basegfx::B2DPolyPolygon aTmp(rTargetForm);
+ aTmp.transform( maWorldToView );
+ const basegfx::B2DRange aOutlineRangePixel(basegfx::tools::getRange(aTmp));
+ const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(rTargetForm));
+
+ fprintf(stderr,"impDrawGradient: #%d\n",nSteps);
+
+ if( // step count is infinite, can use native canvas
+ // gradients here
+ nSteps == 0 ||
+ // step count is sufficiently high, such that no
+ // discernible difference should be visible.
+ nSteps > 64 )
+ {
+ uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory(
+ mxCanvas->getDevice()->getParametricPolyPolygonFactory() );
+
+ if( xFactory.is() )
+ {
+ fprintf(stderr,"native gradient #1\n");
+
+ basegfx::B2DHomMatrix aTextureTransformation;
+ rendering::Texture aTexture;
+
+ aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
+ aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
+ aTexture.Alpha = 1.0;
+
+
+ // setup start/end color values
+ // ----------------------------
+
+ const uno::Sequence< double > aStartColor(
+ basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(),
+ rStart ));
+ const uno::Sequence< double > aEndColor(
+ basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(),
+ rEnd ));
+
+ // Setup texture transformation
+ // ----------------------------
+
+ const basegfx::B2DRange& rBounds(
+ basegfx::tools::getRange( rTargetForm ));
+
+ // setup rotation angle. VCL rotates
+ // counter-clockwise, while canvas transformation
+ // rotates clockwise
+ //fAngle = -fAngle;
+
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ {
+ // standard orientation for VCL linear
+ // gradient is vertical, thus, rotate 90
+ // degrees
+ fAngle += M_PI/2.0;
+
+ // shrink texture, to account for border
+ // (only in x direction, linear gradient
+ // is constant in y direction, anyway)
+ aTextureTransformation.scale(
+ basegfx::pruneScaleValue(1.0 - fBorder),
+ 1.0 );
+
+ double fBorderX(0.0);
+
+ // determine type of gradient (and necessary
+ // transformation matrix, should it be emulated by a
+ // generic gradient)
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ // linear gradients don't respect
+ // offsets (they are implicitely
+ // assumed to be 50%). linear
+ // gradients don't have border on
+ // both sides, only on the
+ // startColor side. Gradient is
+ // invariant in y direction: leave
+ // y offset alone.
+ fBorderX = fBorder;
+ aTexture.Gradient = xFactory->createLinearHorizontalGradient( aStartColor,
+ aEndColor );
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ // axial gradients have border on
+ // both sides. Gradient is
+ // invariant in y direction: leave
+ // y offset alone.
+ fBorderX = fBorder * .5;
+ aTexture.Gradient = xFactory->createAxialHorizontalGradient( aStartColor,
+ aEndColor );
+ break;
+ }
+
+ // apply border offset values
+ aTextureTransformation.translate( fBorderX,
+ 0.0 );
+
+ // rotate texture according to gradient rotation
+ aTextureTransformation.translate( -0.5, -0.5 );
+ aTextureTransformation.rotate( fAngle );
+
+ // to let the first strip of a rotated
+ // gradient start at the _edge_ of the
+ // bound rect (and not, due to rotation,
+ // slightly inside), slightly enlarge the
+ // gradient:
+ //
+ // y/2 sin(alpha) + x/2 cos(alpha)
+ //
+ // (values to change are not actual
+ // gradient scales, but original bound
+ // rect dimensions. Since we still want
+ // the border setting to apply after that,
+ // we multiply with that as above for
+ // nScaleX)
+ const double nScale(
+ basegfx::pruneScaleValue(
+ fabs( rBounds.getHeight()*sin(fAngle) ) +
+ fabs( rBounds.getWidth()*cos(fAngle) )));
+
+ aTextureTransformation.scale( nScale, nScale );
+
+ // translate back origin to center of
+ // primitive
+ aTextureTransformation.translate( 0.5*rBounds.getWidth(),
+ 0.5*rBounds.getHeight() );
+ break;
+ }
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ // FALLTHROUGH intended
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ fprintf(stderr,"native gradient #2\n");
+
+ // determine scale factors for the gradient (must
+ // be scaled up from [0,1]x[0,1] rect to object
+ // bounds). Will potentially changed in switch
+ // statement below.
+ // Respect border value, while doing so, the VCL
+ // gradient's border will effectively shrink the
+ // resulting gradient.
+ double nScaleX( rBounds.getWidth() * (1.0 - fBorder) );
+ double nScaleY( rBounds.getHeight()* (1.0 - fBorder) );
+
+ // determine offset values. Since the
+ // border is divided half-by-half to both
+ // sides of the gradient, divide
+ // translation offset by an additional
+ // factor of 2. Also respect offset here,
+ // but since VCL gradients have their
+ // center at [0,0] for zero offset, but
+ // canvas gradients have their top, left
+ // edge aligned with the primitive, and
+ // offset of 50% effectively must yield
+ // zero shift. Both values will
+ // potentially be adapted in switch
+ // statement below.
+ double nOffsetX( rBounds.getWidth() *
+ (2.0 * fOffsetX - 1.0 + fBorder)*.5 );
+ double nOffsetY( rBounds.getHeight() *
+ (2.0 * fOffsetY - 1.0 + fBorder)*.5 );
+
+ // determine type of gradient (and necessary
+ // transformation matrix, should it be emulated by a
+ // generic gradient)
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ {
+ // create isotrophic scaling
+ if( nScaleX > nScaleY )
+ {
+ nOffsetY -= (nScaleX - nScaleY) * 0.5;
+ nScaleY = nScaleX;
+ }
+ else
+ {
+ nOffsetX -= (nScaleY - nScaleX) * 0.5;
+ nScaleX = nScaleY;
+ }
+
+ // enlarge gradient to match bound rect diagonal
+ aTextureTransformation.translate( -0.5, -0.5 );
+ const double nScale( hypot(rBounds.getWidth(),
+ rBounds.getHeight()) / nScaleX );
+ aTextureTransformation.scale( nScale, nScale );
+ aTextureTransformation.translate( 0.5, 0.5 );
+
+ aTexture.Gradient = xFactory->createEllipticalGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D(0.0,0.0,
+ 1.0,1.0) );
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ // enlarge gradient slightly
+ aTextureTransformation.translate( -0.5, -0.5 );
+ const double nSqrt2( sqrt(2.0) );
+ aTextureTransformation.scale( nSqrt2,nSqrt2 );
+ aTextureTransformation.translate( 0.5, 0.5 );
+
+ aTexture.Gradient = xFactory->createEllipticalGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D( rBounds.getMinX(),
+ rBounds.getMinY(),
+ rBounds.getMaxX(),
+ rBounds.getMaxY() ));
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ {
+ // create isotrophic scaling
+ if( nScaleX > nScaleY )
+ {
+ nOffsetY -= (nScaleX - nScaleY) * 0.5;
+ nScaleY = nScaleX;
+ }
+ else
+ {
+ nOffsetX -= (nScaleY - nScaleX) * 0.5;
+ nScaleX = nScaleY;
+ }
+
+ aTexture.Gradient = xFactory->createRectangularGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D(0.0,0.0,
+ 1.0,1.0));
+ }
+ break;
+
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ aTexture.Gradient = xFactory->createRectangularGradient(
+ aEndColor,
+ aStartColor,
+ cssgeom::RealRectangle2D( rBounds.getMinX(),
+ rBounds.getMinY(),
+ rBounds.getMaxX(),
+ rBounds.getMaxY() ));
+ }
+ break;
+ }
+
+ nScaleX = basegfx::pruneScaleValue( nScaleX );
+ nScaleY = basegfx::pruneScaleValue( nScaleY );
+
+ aTextureTransformation.scale( nScaleX, nScaleY );
+
+ // rotate texture according to gradient rotation
+ aTextureTransformation.translate( -0.5*nScaleX, -0.5*nScaleY );
+ aTextureTransformation.rotate( fAngle );
+ aTextureTransformation.translate( 0.5*nScaleX, 0.5*nScaleY );
+
+ aTextureTransformation.translate( nOffsetX, nOffsetY );
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false,
+ "canvasProcessor::impDrawGradient(): Unexpected gradient type" );
+ break;
+ }
+
+ // As the texture coordinate space is relative to
+ // the polygon coordinate space (NOT to the
+ // polygon itself), move gradient to the start of
+ // the actual polygon. If we skip this, the
+ // gradient will always display at the origin, and
+ // not within the polygon bound (which might be
+ // miles away from the origin).
+ aTextureTransformation.translate( rBounds.getMinX(),
+ rBounds.getMinY() );
+
+ basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
+ aTextureTransformation );
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = aTexture;
+
+ mxCanvas->fillTexturedPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rTargetForm),
+ maViewState,
+ maRenderState,
+ aSeq );
+
+ // done, using native gradients
+ return;
+ }
+ }
+ else
+ {
+ // make sure steps is not too high/low
+ nSteps = impCalcGradientSteps(nSteps,
+ aOutlineRangePixel,
+ sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5));
+
+
+ ::std::vector< basegfx::B2DHomMatrix > aMatrices;
+ ::std::vector< basegfx::BColor > aColors;
+ basegfx::B2DPolygon aUnitPolygon;
+
+ if( drawinglayer::primitive::GRADIENTSTYLE_RADIAL == eGradientStyle ||
+ drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL == eGradientStyle)
+ {
+ const basegfx::B2DPoint aCircleCenter(0.5, 0.5);
+ aUnitPolygon = basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5);
+ aUnitPolygon = basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon);
+ }
+ else
+ {
+ aUnitPolygon = basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(0.0, 0.0, 1.0, 1.0));
+ }
+
+ // create geometries
+ switch(eGradientStyle)
+ {
+ case ::drawinglayer::primitive::GRADIENTSTYLE_LINEAR:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientLinear aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_AXIAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientAxial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RADIAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientRadial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetY);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientElliptical aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_SQUARE:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientSquare aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case ::drawinglayer::primitive::GRADIENTSTYLE_RECT:
+ {
+ ::drawinglayer::primitive::geoTexSvxGradientRect aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ }
+
+ // paint them with mask using the XOR method
+ if(aMatrices.size())
+ {
+ if(bSimple)
+ {
+ impDrawGradientSimple(rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ else
+ {
+ impDrawGradientComplex(rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ }
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+ // rendering support
+
+ // directdraw of text simple portion
+ void canvasProcessor::impRender_STXP(const textSimplePortionPrimitive& rTextCandidate)
+ {
+ const fontAttributes& rFontAttrs( rTextCandidate.getFontAttributes() );
+ rendering::FontRequest aFontRequest;
+
+ aFontRequest.FontDescription.FamilyName = rFontAttrs.maFamilyName;
+ aFontRequest.FontDescription.StyleName = rFontAttrs.maStyleName;
+ aFontRequest.FontDescription.IsSymbolFont = rFontAttrs.mbSymbol ? util::TriState_YES : util::TriState_NO;
+ aFontRequest.FontDescription.IsVertical = rFontAttrs.mbVertical ? util::TriState_YES : util::TriState_NO;
+
+ // TODO(F2): improve vclenum->panose conversion
+ aFontRequest.FontDescription.FontDescription.Weight =
+ rFontAttrs.mnWeight;
+ aFontRequest.FontDescription.FontDescription.Letterform =
+ rFontAttrs.mbItalic ? 9 : 0;
+
+ // font matrix should only be used for glyph rotations etc.
+ css::geometry::Matrix2D aFontMatrix;
+ canvas::tools::setIdentityMatrix2D( aFontMatrix );
+
+ uno::Reference<rendering::XCanvasFont> xFont(
+ mxCanvas->createFont( aFontRequest,
+ uno::Sequence< beans::PropertyValue >(),
+ aFontMatrix ));
+
+ if( !xFont.is() )
+ return;
+
+ uno::Reference<rendering::XTextLayout> xLayout(
+ xFont->createTextLayout(
+ rendering::StringContext( rTextCandidate.getText(),
+ 0,
+ rTextCandidate.getText().Len() ),
+ // TODO(F3): Is this sufficient?
+ rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
+ 0 ));
+ if( !xLayout.is() )
+ return;
+
+ xLayout->applyLogicalAdvancements(
+ uno::Sequence<double>(&rTextCandidate.getDXArray()[0],
+ rTextCandidate.getDXArray().size() ));
+
+ const basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rTextCandidate.getFontColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ // get render parameters and paint
+ mxCanvas->drawTextLayout( xLayout,
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of hairline
+ void canvasProcessor::impRender_POHL(const polygonHairlinePrimitive& rPolygonCandidate)
+ {
+ const basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ mxCanvas->drawPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolygon(
+ mxCanvas->getDevice(),
+ rPolygonCandidate.getB2DPolygon()),
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of transformed BitmapEx primitive
+ void canvasProcessor::impRender_BMPR(const bitmapPrimitive& rBitmapCandidate)
+ {
+ BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
+
+ if(maBColorModifierStack.count())
+ {
+ // TODO(Q3): Share common bmp modification code with
+ // vclprocessor.cxx
+ Bitmap aChangedBitmap(impModifyBitmap(maBColorModifierStack, aBitmapEx.GetBitmap()));
+
+ if(aBitmapEx.IsTransparent())
+ {
+ if(aBitmapEx.IsAlpha())
+ aBitmapEx = BitmapEx(aChangedBitmap, aBitmapEx.GetAlpha());
+ else
+ aBitmapEx = BitmapEx(aChangedBitmap, aBitmapEx.GetMask());
+ }
+ else
+ aBitmapEx = BitmapEx(aChangedBitmap);
+ }
+
+ mxCanvas->drawBitmap(
+ vcl::unotools::xBitmapFromBitmapEx( mxCanvas->getDevice(),
+ aBitmapEx ),
+ maViewState,
+ maRenderState);
+ }
+
+ void canvasProcessor::impRender_PPLB(const polyPolygonBitmapPrimitive& rPolyBitmapCandidate )
+ {
+ const fillBitmapAttribute& rFillBmpAttr( rPolyBitmapCandidate.getFillBitmap() );
+ const basegfx::B2DPolyPolygon& rPoly( rPolyBitmapCandidate.getB2DPolyPolygon() );
+
+ // TODO(Q3): Share common bmp modification code with
+ // vclprocessor.cxx
+ Bitmap aChangedBitmap(
+ impModifyBitmap(maBColorModifierStack,
+ rFillBmpAttr.getBitmap()));
+
+ rendering::Texture aTexture;
+ const basegfx::B2DVector aBmpSize( rFillBmpAttr.getSize() );
+
+ const basegfx::B2DRange& rBounds(
+ basegfx::tools::getRange( rPoly ));
+
+ basegfx::B2DHomMatrix aScale;
+ aScale.scale( aBmpSize.getX() * rBounds.getWidth(),
+ aBmpSize.getY() * rBounds.getHeight() );
+
+ basegfx::unotools::affineMatrixFromHomMatrix(
+ aTexture.AffineTransform,
+ aScale );
+
+ aTexture.Alpha = 1.0;
+ aTexture.Bitmap =
+ ::vcl::unotools::xBitmapFromBitmapEx(
+ mxCanvas->getDevice(),
+ aChangedBitmap );
+ aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
+ aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
+
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = aTexture;
+
+ mxCanvas->fillTexturedPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rPoly),
+ maViewState,
+ maRenderState,
+ aSeq );
+ }
+
+ // direct draw of gradient
+ void canvasProcessor::impRender_PPLG(const polyPolygonGradientPrimitive& rPolygonCandidate)
+ {
+ const fillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
+ basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
+ basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+
+ if(aStartColor == aEndColor)
+ {
+ // no gradient at all, draw as polygon
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aStartColor);
+
+ mxCanvas->drawPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aLocalPolyPolygon),
+ maViewState,
+ maRenderState );
+ }
+ else
+ {
+ // TODO(F3): if rGradient.getSteps() > 0, render
+ // gradient manually!
+ impDrawGradient(
+ aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(),
+ aStartColor, aEndColor, rGradient.getBorder(),
+ -rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), false);
+ }
+ }
+
+ // direct draw of PolyPolygon with color
+ void canvasProcessor::impRender_PPLC(const polyPolygonColorPrimitive& rPolygonCandidate)
+ {
+ const basegfx::BColor aRGBColor(
+ maBColorModifierStack.getModifiedColor(
+ rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ mxCanvas->fillPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rPolygonCandidate.getB2DPolyPolygon()),
+ maViewState,
+ maRenderState );
+ }
+
+ // direct draw of MetaFile
+ void canvasProcessor::impRender_META(const metafilePrimitive& rMetaCandidate)
+ {
+ // get metafile (copy it)
+ GDIMetaFile aMetaFile;
+
+ // TODO(Q3): Share common metafile modification code with
+ // vclprocessor.cxx
+ if(maBColorModifierStack.count())
+ {
+ const basegfx::BColor aRGBBaseColor(0, 0, 0);
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
+ aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
+ }
+ else
+ {
+ aMetaFile = rMetaCandidate.getMetaFile();
+ }
+
+ cppcanvas::BitmapCanvasSharedPtr pCanvas(
+ cppcanvas::VCLFactory::getInstance().createCanvas(
+ uno::Reference<rendering::XBitmapCanvas>(
+ mxCanvas,
+ uno::UNO_QUERY_THROW) ));
+ cppcanvas::RendererSharedPtr pMtfRenderer(
+ cppcanvas::VCLFactory::getInstance().createRenderer(
+ pCanvas,
+ aMetaFile,
+ cppcanvas::Renderer::Parameters() ));
+ if( pMtfRenderer )
+ {
+ pCanvas->setTransformation(maWorldToView);
+ pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
+ pMtfRenderer->draw();
+ }
+ }
+
+ // mask group. Set mask polygon as clip
+ void canvasProcessor::impRender_MASK(const maskPrimitive& rMaskCandidate)
+ {
+ const primitiveVector& rSubList = rMaskCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ // TODO(F3): cannot use state-global renderstate, when recursing!
+ maRenderState.Clip =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ rMaskCandidate.getMask());
+
+ // paint to it
+ process(rSubList);
+
+ maRenderState.Clip.clear();
+ }
+ }
+
+ // modified color group. Force output to unified color.
+ void canvasProcessor::impRender_MCOL(const modifiedColorPrimitive& rModifiedCandidate)
+ {
+ const primitiveVector& rSubList = rModifiedCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getPrimitiveVector());
+ maBColorModifierStack.pop();
+ }
+ }
+
+ // sub-transparence group. Draw to bitmap device first.
+ void canvasProcessor::impRender_TRPR(const transparencePrimitive& rTransCandidate)
+ {
+ const primitiveVector& rSubList = rTransCandidate.getPrimitiveVector();
+
+ if(!rSubList.empty())
+ {
+ basegfx::B2DRange aRange(
+ get2DRangeFromVector(rSubList,
+ getViewInformation()));
+ aRange.transform(maWorldToView);
+ const basegfx::B2I64Tuple& rSize(
+ canvas::tools::spritePixelAreaFromB2DRange(aRange).getRange());
+ uno::Reference< rendering::XCanvas > xBitmap(
+ mxCanvas->getDevice()->createCompatibleAlphaBitmap(
+ css::geometry::IntegerSize2D(rSize.getX(),
+ rSize.getY())),
+ uno::UNO_QUERY_THROW);
+
+ // remember last worldToView and add pixel offset
+ basegfx::B2DHomMatrix aLastWorldToView(maWorldToView);
+ basegfx::B2DHomMatrix aPixelOffset;
+ aPixelOffset.translate(aRange.getMinX(),
+ aRange.getMinY());
+ setWorldToView(aPixelOffset * maWorldToView);
+
+ // remember last canvas, set bitmap as target
+ uno::Reference< rendering::XCanvas > xLastCanvas( mxCanvas );
+ mxCanvas = xBitmap;
+
+ // paint content to it
+ process(rSubList);
+
+ // TODO(F3): render transparent list to alpha
+ // channel. Note that the OutDev implementation has a
+ // shortcoming, in that nested transparency groups
+ // don't work - alpha is not combined properly.
+
+ // process(rTransCandidate.getTransparenceList());
+
+ // back to old OutDev and worldToView
+ mxCanvas = xLastCanvas;
+ setWorldToView(aLastWorldToView);
+
+ // DUMMY: add alpha modulation value to DeviceColor
+ // TODO(F3): color management
+ canvas::tools::setDeviceColor( maRenderState,
+ 1.0, 1.0, 1.0, 0.5 );
+ // finally, draw bitmap
+ mxCanvas->drawBitmapModulated(
+ uno::Reference< rendering::XBitmap >(
+ xBitmap,
+ uno::UNO_QUERY_THROW),
+ maViewState,
+ maRenderState );
+ }
+ }
+
+ // transform group.
+ void canvasProcessor::impRender_TRN2(const transformPrimitive& rTransformCandidate)
+ {
+ // remember current transformation
+ basegfx::B2DHomMatrix aLastWorldToView(maWorldToView);
+
+ // create new transformations
+ setWorldToView(maWorldToView * rTransformCandidate.getTransformation());
+
+ // let break down
+ process(rTransformCandidate.getPrimitiveVector());
+
+ // restore transformations
+ setWorldToView(aLastWorldToView);
+ }
+
+ // marker
+ void canvasProcessor::impRender_MARK(const markerPrimitive& rMarkCandidate)
+ {
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rMarkCandidate.getRGBColor()));
+
+ canvas::tools::initRenderState(maMarkerRenderState);
+ maMarkerRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence(
+ mxCanvas->getDevice(),
+ aRGBColor);
+
+ // Markers are special objects - their position is
+ // determined by the view transformation, but their size
+ // is always the same
+ const basegfx::B2DPoint aViewPos(maWorldToView * rMarkCandidate.getPosition());
+
+ uno::Reference< rendering::XPolyPolygon2D > xMarkerPoly;
+ uno::Reference< rendering::XPolyPolygon2D > xHighlightMarkerPoly;
+ switch(rMarkCandidate.getStyle())
+ {
+ default:
+ case MARKERSTYLE_POINT:
+ mxCanvas->drawPoint( basegfx::unotools::point2DFromB2DPoint(aViewPos),
+ maMarkerViewState,
+ maMarkerRenderState );
+ return;
+
+ case MARKERSTYLE_CROSS:
+ if( !mxCrossMarkerPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-1 0 h2 m0 -1 v2" ));
+ mxCrossMarkerPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ xMarkerPoly = mxCrossMarkerPoly;
+ break;
+
+ case MARKERSTYLE_GLUEPOINT :
+ if( !mxGluePointPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-2 -3 l5 5 m-3 -2 l5 5 m-3 2 l5 -5 m-2 3 l5 -5" ));
+ mxGluePointPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ if( !mxGluePointHighlightPoly.is() )
+ {
+ basegfx::B2DPolyPolygon aPoly;
+ basegfx::tools::importFromSvgD(
+ aPoly,
+ rtl::OUString::createFromAscii(
+ "m-2 -2 l4 4 m-2 2 l4 -4" ));
+ mxGluePointHighlightPoly =
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(),
+ aPoly );
+ }
+ xMarkerPoly = mxGluePointPoly;
+ xHighlightMarkerPoly = mxGluePointHighlightPoly;
+ break;
+ }
+
+ basegfx::B2DRange aRange;
+ rMarkCandidate.getRealtiveViewRange(aRange);
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
+
+ basegfx::B2DHomMatrix aTranslate;
+ aTranslate.translate(aViewPos.getX()+aCenter.getX(),
+ aViewPos.getY()+aCenter.getY());
+
+ canvas::tools::setRenderStateTransform( maMarkerRenderState,
+ aTranslate );
+
+
+ mxCanvas->drawPolyPolygon( xMarkerPoly,
+ maMarkerViewState,
+ maMarkerRenderState );
+ if( xHighlightMarkerPoly.is() )
+ {
+ // TODO(F3): color management
+ canvas::tools::setDeviceColor(maMarkerRenderState,
+ 0.0, 0.0, 1.0, 1.0);
+ mxCanvas->drawPolyPolygon( xMarkerPoly,
+ maMarkerViewState,
+ maMarkerRenderState );
+ }
+ }
+
+ void canvasProcessor::setWorldToView(const basegfx::B2DHomMatrix& rMat)
+ {
+ maWorldToView = rMat;
+ canvas::tools::setViewStateTransform(maViewState,
+ maWorldToView);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // internal processing support
+
+ void canvasProcessor::process(const primitiveVector& rSource)
+ {
+ primitiveVector::const_iterator aCurr = rSource.begin();
+ const primitiveVector::const_iterator aEnd = rSource.end();
+ while( aCurr != aEnd )
+ {
+ const referencedPrimitive& rCandidate = *aCurr;
+
+ switch(rCandidate.getID())
+ {
+ case CreatePrimitiveID('S', 'T', 'X', 'P'):
+ {
+ // directdraw of text simple portion
+ impRender_STXP(static_cast< const textSimplePortionPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'O', 'H', 'L'):
+ {
+ // direct draw of hairline
+ impRender_POHL(static_cast< const polygonHairlinePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('B', 'M', 'P', 'R'):
+ {
+ // direct draw of transformed BitmapEx primitive
+ impRender_BMPR(static_cast< const bitmapPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('F', 'B', 'M', 'P'):
+ {
+ OSL_ENSURE(false,"fillBitmapPrimitive not yet implemented");
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'B'):
+ {
+ // direct draw of polygon with bitmap fill
+ impRender_PPLB(static_cast< const polyPolygonBitmapPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'G'):
+ {
+ // direct draw of gradient
+ impRender_PPLG(static_cast< const polyPolygonGradientPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('P', 'P', 'L', 'C'):
+ {
+ // direct draw of PolyPolygon with color
+ impRender_PPLC(static_cast< const polyPolygonColorPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'E', 'T', 'A'):
+ {
+ // direct draw of MetaFile
+ impRender_META(static_cast< const metafilePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'A', 'S', 'K'):
+ {
+ // mask group. Force output to VDev and create mask from given mask
+ impRender_MASK(static_cast< const maskPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'C', 'O', 'L'):
+ {
+ // modified color group. Force output to unified color.
+ impRender_MCOL(static_cast< const modifiedColorPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('T', 'R', 'P', 'R'):
+ {
+ // sub-transparence group. Draw to VDev first.
+ impRender_TRPR(static_cast< const transparencePrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('T', 'R', 'N', '2'):
+ {
+ // transform group.
+ impRender_TRN2(static_cast< const transformPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('M', 'A', 'R', 'K'):
+ {
+ // marker
+ impRender_MARK(static_cast< const markerPrimitive& >(rCandidate.getBasePrimitive()));
+ break;
+ }
+
+ case CreatePrimitiveID('A', 'N', 'S', 'W'):
+ case CreatePrimitiveID('A', 'N', 'B', 'L'):
+ case CreatePrimitiveID('A', 'N', 'I', 'N'):
+ {
+ // check timing, but do not accept
+ const animatedSwitchPrimitive& rAnimatedCandidate(static_cast< const animatedSwitchPrimitive& >(rCandidate.getBasePrimitive()));
+ const ::drawinglayer::animation::animationEntryList& rAnimationList = rAnimatedCandidate.getAnimationList();
+ const double fNewTime(rAnimationList.getNextEventTime(getViewInformation().getViewTime()));
+
+ // let break down
+ process(rAnimatedCandidate.getDecomposition(getViewInformation()));
+
+ break;
+ }
+
+ default:
+ {
+ // let break down
+ process(rCandidate.getBasePrimitive().getDecomposition(getViewInformation()));
+ }
+ }
+
+ ++aCurr;
+ }
+ }
+
+ canvasProcessor::canvasProcessor( const ::drawinglayer::geometry::viewInformation& rViewInformation,
+ const uno::Reference<rendering::XCanvas>& rCanvas ) :
+ processor(rViewInformation),
+ mxCanvas( rCanvas ),
+ mxCrossMarkerPoly(),
+ mxGluePointPoly(),
+ mxGluePointHighlightPoly(),
+ maBColorModifierStack(),
+ maWorldToView(),
+ maViewState(),
+ maRenderState(),
+ maMarkerViewState(),
+ maMarkerRenderState()
+ {
+ canvas::tools::initViewState(maViewState);
+ canvas::tools::initRenderState(maRenderState);
+ canvas::tools::initViewState(maMarkerViewState);
+ canvas::tools::initRenderState(maMarkerRenderState);
+
+ maWorldToView = maViewInformation.getViewTransformation();
+
+ canvas::tools::setViewStateTransform(maViewState,
+ maWorldToView);
+ }
+
+ canvasProcessor::~canvasProcessor()
+ {}
+*/
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ //////////////////////////////////////////////////////////////////////////////
+ // single primitive renderers
+
+ void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
+ {
+ const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
+ static bool bUseMaskBitmapMethod(true);
+
+ if(rChildren.hasElements())
+ {
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+ if(!aMask.count())
+ {
+ // no mask, no clipping. recursively paint content
+ process(rChildren);
+ }
+ else
+ {
+ // there are principally two methods for implementing the mask primitive. One
+ // is to set a clip polygon at the canvas, the other is to create and use a
+ // alpha-using XBitmap for content and draw the mask as alpha. Both have their
+ // advantages and disadvantages, so here are both with a bool allowing simple
+ // change
+ if(bUseMaskBitmapMethod)
+ {
+ // get logic range of transparent part, clip with ViewRange
+ basegfx::B2DRange aLogicRange(aMask.getB2DRange());
+
+ if(!getViewInformation2D().getViewport().isEmpty())
+ {
+ aLogicRange.intersect(getViewInformation2D().getViewport());
+ }
+
+ if(!aLogicRange.isEmpty())
+ {
+ // get discrete range of transparent part
+ basegfx::B2DRange aDiscreteRange(aLogicRange);
+ aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // expand to next covering discrete values (pixel bounds)
+ aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
+ aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
+
+ // use VCL-based buffer device
+ impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
+
+ if(aBufferDevice.isVisible())
+ {
+ // remember current OutDev, Canvas and ViewInformation
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
+ // may be truncated to discrete visible pixels
+ basegfx::B2DHomMatrix aDiscreteOffset;
+ aDiscreteOffset.translate(
+ aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
+ aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0);
+
+ // create new local ViewInformation2D with new transformation
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation(),
+ aDiscreteOffset * getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // set OutDev and Canvas to content target
+ mpOutputDevice = &aBufferDevice.getContent();
+ mxCanvas = mpOutputDevice->GetCanvas();
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // if ViewState transform is changed, the clipping polygon needs to be adapted, too
+ const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
+
+ if(maClipPolyPolygon.count())
+ {
+ maClipPolyPolygon.transform(aDiscreteOffset);
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+
+ // paint content
+ process(rChildren);
+
+ // draw mask
+ const basegfx::BColor aBlack(0.0, 0.0, 0.0);
+ maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice());
+
+ if(getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // with AA, use 8bit AlphaMask to get nice borders
+ VirtualDevice& rAlpha = aBufferDevice.getAlpha();
+ rAlpha.GetCanvas()->fillPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
+ maViewState, maRenderState);
+ }
+ else
+ {
+ // No AA, use 1bit mask
+ VirtualDevice& rMask = aBufferDevice.getMask();
+ rMask.GetCanvas()->fillPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
+ maViewState, maRenderState);
+ }
+
+ // back to old color stack, OutDev, Canvas and ViewTransform
+ mpOutputDevice = pLastOutputDevice;
+ mxCanvas = xLastCanvas;
+ updateViewInformation(aLastViewInformation2D);
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // restore clipping polygon
+ maClipPolyPolygon = aOldClipPolyPolygon;
+
+ if(maClipPolyPolygon.count())
+ {
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
+ }
+ }
+ }
+ else
+ {
+ // transform new mask polygon to view coordinates for processing. All masks
+ // are processed in view coordinates and clipped against each other evtl. to
+ // create multi-clips
+ aMask.transform(getViewInformation2D().getObjectTransformation());
+
+ // remember last current clip polygon
+ const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
+
+ if(maClipPolyPolygon.count())
+ {
+ // there is already a clip polygon set; build clipped union of
+ // current mask polygon and new one
+ maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
+ }
+ else
+ {
+ // use mask directly
+ maClipPolyPolygon = aMask;
+ }
+
+ // set at ViewState
+ if(maClipPolyPolygon.count())
+ {
+ // set new as clip polygon
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+ else
+ {
+ // empty, reset
+ maViewState.Clip.clear();
+ }
+
+ // paint content
+ process(rChildren);
+
+ // restore local current to rescued clip polygon
+ maClipPolyPolygon = aLastClipPolyPolygon;
+
+ // set at ViewState
+ if(maClipPolyPolygon.count())
+ {
+ // set new as clip polygon
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+ else
+ {
+ // empty, reset
+ maViewState.Clip.clear();
+ }
+ }
+ }
+ }
+ }
+
+ void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
+ {
+ GDIMetaFile aMetaFile;
+
+ if(maBColorModifierStack.count())
+ {
+ const basegfx::BColor aRGBBaseColor(0, 0, 0);
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
+ aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
+ }
+ else
+ {
+ aMetaFile = rMetaCandidate.getMetaFile();
+ }
+
+ cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas(
+ uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW)));
+ cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer(
+ pCanvas, aMetaFile, cppcanvas::Renderer::Parameters()));
+
+ if(pMtfRenderer)
+ {
+ pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation());
+ pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
+ pMtfRenderer->draw();
+ }
+ }
+
+ void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+ {
+ if(rTextCandidate.getTextLength())
+ {
+ double fShearX(0.0);
+ {
+ const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform());
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+ }
+
+ if(!basegfx::fTools::equalZero(fShearX))
+ {
+ // text is sheared. As long as the canvas renderers do not support this,
+ // use the decomposed primitive
+ process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ else
+ {
+ const primitive2d::FontAttributes& rFontAttrs(rTextCandidate.getFontAttributes());
+ rendering::FontRequest aFontRequest;
+
+ aFontRequest.FontDescription.FamilyName = rFontAttrs.getFamilyName();
+ aFontRequest.FontDescription.StyleName = rFontAttrs.getStyleName();
+ aFontRequest.FontDescription.IsSymbolFont = rFontAttrs.getSymbol() ? util::TriState_YES : util::TriState_NO;
+ aFontRequest.FontDescription.IsVertical = rFontAttrs.getVertical() ? util::TriState_YES : util::TriState_NO;
+ // TODO(F2): improve vclenum->panose conversion
+ aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttrs.getWeight());
+ aFontRequest.FontDescription.FontDescription.Letterform = rFontAttrs.getItalic() ? 9 : 0;
+
+ // init CellSize to 1.0, else a default font height will be used
+ aFontRequest.CellSize = 1.0;
+ aFontRequest.Locale = rTextCandidate.getLocale();
+
+ // font matrix should only be used for glyph rotations etc.
+ com::sun::star::geometry::Matrix2D aFontMatrix;
+ canvas::tools::setIdentityMatrix2D(aFontMatrix);
+
+ uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont(
+ aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix));
+
+ if(xFont.is())
+ {
+ // got a font, now try to get a TextLayout
+ const rendering::StringContext aStringContext(
+ rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength());
+ uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout(
+ aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
+
+ if(xLayout.is())
+ {
+ // got a text layout, apply DXArray if given
+ const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray();
+ const sal_uInt32 nDXCount(rDXArray.size());
+
+ if(nDXCount)
+ {
+ // DXArray does not need to be adapted to getTextPosition/getTextLength,
+ // it is already provided correctly
+ const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount);
+ xLayout->applyLogicalAdvancements(aDXSequence);
+ }
+
+ // set text color
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
+ maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
+
+ // set text transformation
+ canvas::tools::setRenderStateTransform(maRenderState,
+ getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
+
+ // paint
+ mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState);
+ }
+ }
+ }
+ }
+ }
+
+ void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+ {
+ // apply possible color modification to BitmapEx
+ BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx()));
+
+ if(aModifiedBitmapEx.IsEmpty())
+ {
+ // replace with color filled polygon
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+
+ maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState,
+ getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
+
+ mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
+ }
+ else
+ {
+ // adapt object's transformation to the correct scale
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ basegfx::B2DHomMatrix aNewMatrix;
+ const Size aSizePixel(aModifiedBitmapEx.GetSizePixel());
+
+ if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
+ {
+ rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
+ aNewMatrix.scale(aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height());
+ aNewMatrix.shearX(fShearX);
+ aNewMatrix.rotate(fRotate);
+ aNewMatrix.translate(aTranslate.getX(), aTranslate.getY());
+
+ canvas::tools::setRenderStateTransform(maRenderState,
+ getViewInformation2D().getObjectTransformation() * aNewMatrix);
+
+ mxCanvas->drawBitmap(
+ vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx),
+ maViewState, maRenderState);
+ }
+ }
+ }
+
+ void canvasProcessor2D::impRenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D& rAlphaCandidate)
+ {
+ const primitive2d::Primitive2DSequence& rChildren = rAlphaCandidate.getChildren();
+ const primitive2d::Primitive2DSequence& rAlpha = rAlphaCandidate.getAlpha();
+
+ if(rChildren.hasElements() && rAlpha.hasElements())
+ {
+ // get logic range of transparent part and clip with ViewRange
+ basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D()));
+
+ if(!getViewInformation2D().getViewport().isEmpty())
+ {
+ aLogicRange.intersect(getViewInformation2D().getViewport());
+ }
+
+ if(!aLogicRange.isEmpty())
+ {
+ // get discrete range of transparent part
+ basegfx::B2DRange aDiscreteRange(aLogicRange);
+ aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // expand to next covering discrete values (pixel bounds)
+ aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
+ aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
+
+ // use VCL-based buffer device
+ impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
+
+ if(aBufferDevice.isVisible())
+ {
+ // remember current OutDev, Canvas and ViewInformation
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
+ // may be truncated to discrete visible pixels
+ basegfx::B2DHomMatrix aDiscreteOffset;
+ aDiscreteOffset.translate(
+ aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
+ aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0);
+
+ // create new local ViewInformation2D with new transformation
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation(),
+ aDiscreteOffset * getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // set OutDev and Canvas to content target
+ mpOutputDevice = &aBufferDevice.getContent();
+ mxCanvas = mpOutputDevice->GetCanvas();
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // if ViewState transform is changed, the clipping polygon needs to be adapted, too
+ const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
+
+ if(maClipPolyPolygon.count())
+ {
+ maClipPolyPolygon.transform(aDiscreteOffset);
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+
+ // paint content
+ process(rChildren);
+
+ // set to mask
+ mpOutputDevice = &aBufferDevice.getAlpha();
+ mxCanvas = mpOutputDevice->GetCanvas();
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // when painting alpha masks, reset the color stack
+ basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
+ maBColorModifierStack = basegfx::BColorModifierStack();
+
+ // paint mask to it (always with alpha intensities, evtl. with AA)
+ process(rAlpha);
+
+ // back to old color stack, OutDev, Canvas and ViewTransform
+ maBColorModifierStack = aLastBColorModifierStack;
+ mpOutputDevice = pLastOutputDevice;
+ mxCanvas = xLastCanvas;
+ updateViewInformation(aLastViewInformation2D);
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // restore clipping polygon
+ maClipPolyPolygon = aOldClipPolyPolygon;
+
+ if(maClipPolyPolygon.count())
+ {
+ maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
+ }
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
+ }
+ }
+ }
+ }
+
+ void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
+ {
+ // support direct fat line geometry. This moves the decomposition to the canvas.
+ // As long as our canvases are used (which also use basegfx tooling) this makes
+ // no difference, but potentially canvases may better support this
+ static bool bSupportFatLineDirectly(true);
+ bool bOutputDone(false);
+
+ if(bSupportFatLineDirectly)
+ {
+ const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute();
+ const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute();
+
+ if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size())
+ {
+ rendering::StrokeAttributes aStrokeAttribute;
+
+ aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth();
+ aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation
+ const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray();
+
+ if(rDotDashArray.size())
+ {
+ aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size());
+ }
+
+ switch(rLineAttribute.getLineJoin())
+ {
+ default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
+ aStrokeAttribute.JoinType = rendering::PathJoinType::NONE;
+ break;
+ case basegfx::B2DLINEJOIN_BEVEL:
+ aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL;
+ break;
+ case basegfx::B2DLINEJOIN_MITER:
+ aStrokeAttribute.JoinType = rendering::PathJoinType::MITER;
+ break;
+ case basegfx::B2DLINEJOIN_ROUND:
+ aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND;
+ break;
+ }
+
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
+ maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+
+ mxCanvas->strokePolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()),
+ maViewState, maRenderState, aStrokeAttribute);
+
+ bOutputDone = true;
+ }
+ }
+
+ if(!bOutputDone)
+ {
+ // process decomposition
+ process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D)
+ {
+ // support tiled fills directly when tiling is on
+ static bool bSupportFillBitmapDirectly(true);
+ bool bOutputDone(false);
+
+ if(bSupportFillBitmapDirectly)
+ {
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap();
+
+ if(rFillBitmapAttribute.getTiling())
+ {
+ // apply possible color modification to Bitmap
+ const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, BitmapEx(rFillBitmapAttribute.getBitmap())));
+
+ if(aChangedBitmapEx.IsEmpty())
+ {
+ // replace with color filled polygon
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+
+ maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState,
+ getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
+
+ mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
+ }
+ else
+ {
+ const Size aSizePixel(aChangedBitmapEx.GetSizePixel());
+
+ if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
+ {
+ // create texture matrix from texture to object (where object is unit square here),
+ // so use values directly
+ basegfx::B2DHomMatrix aTextureMatrix;
+ aTextureMatrix.scale(
+ rFillBitmapAttribute.getSize().getX(),
+ rFillBitmapAttribute.getSize().getY());
+ aTextureMatrix.translate(
+ rFillBitmapAttribute.getTopLeft().getX(),
+ rFillBitmapAttribute.getTopLeft().getY());
+
+ // create and fill texture
+ rendering::Texture aTexture;
+
+ basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix);
+ aTexture.Alpha = 1.0;
+ aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx);
+ aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
+ aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
+
+ // canvas needs a polygon to fill, create unit rectangle polygon
+ const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+
+ // set primitive's transformation as render state transform
+ canvas::tools::setRenderStateTransform(maRenderState,
+ getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
+
+ // put texture into a uno sequence for handover
+ uno::Sequence< rendering::Texture > aSeq(1);
+ aSeq[0] = aTexture;
+
+ // draw textured rectangle
+ mxCanvas->fillTexturedPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)),
+ maViewState, maRenderState, aSeq);
+ }
+ }
+
+ bOutputDone = true;
+ }
+ }
+
+ if(!bOutputDone)
+ {
+ // process decomposition
+ process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ void canvasProcessor2D::impRenderUnifiedAlphaPrimitive2D(const primitive2d::UnifiedAlphaPrimitive2D& rUniAlphaCandidate)
+ {
+ const primitive2d::Primitive2DSequence rChildren = rUniAlphaCandidate.getChildren();
+
+ if(rChildren.hasElements())
+ {
+ bool bOutputDone(false);
+
+ // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
+ // use the fillPolyPolygon method with correctly set alpha. This is a often used
+ // case, so detectiong it is valuable
+ if(1 == rChildren.getLength())
+ {
+ const primitive2d::Primitive2DReference xReference(rChildren[0]);
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
+
+ if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitiveID())
+ {
+ // direct draw of PolyPolygon with color and transparence
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
+
+ // add alpha modulation value to DeviceColor
+ uno::Sequence< double > aColor(4);
+
+ aColor[0] = aPolygonColor.getRed();
+ aColor[1] = aPolygonColor.getGreen();
+ aColor[2] = aPolygonColor.getBlue();
+ aColor[3] = 1.0 - rUniAlphaCandidate.getAlpha();
+ maRenderState.DeviceColor = aColor;
+
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+ mxCanvas->fillPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()),
+ maViewState, maRenderState);
+ bOutputDone = true;
+ }
+ }
+
+ if(!bOutputDone)
+ {
+ // process decomposition. This will be decomposed to an AlphaPrimitive2D
+ // with the same child context and a single polygon for alpha context. This could be
+ // directly handled here with known VCL-buffer technology, but would only
+ // make a small difference compared to directly rendering the AlphaPrimitive2D
+ // using impRenderAlphaPrimitive2D above.
+ process(rUniAlphaCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // internal processing support
+
+ void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ // direct draw of hairline
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+ mxCanvas->drawPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()),
+ maViewState, maRenderState);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ // direct draw of PolyPolygon with color
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+
+ maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+ mxCanvas->fillPolyPolygon(
+ basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()),
+ maViewState, maRenderState);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ // modified color group. Force output to unified color.
+ const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
+
+ if(rModifiedCandidate.getChildren().hasElements())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // mask group
+ impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // transform group. Remember current ViewInformation2D
+ const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new local ViewInformation2D with new transformation
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // set at canvas
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+
+ // restore at canvas
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ {
+ // new XDrawPage for ViewInformation2D
+ const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate = static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate);
+
+ // remember current transformation and ViewInformation
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new local ViewInformation2D
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ rPagePreviewCandidate.getXDrawPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess decomposed content
+ process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+ break;
+ }
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ {
+ // MetaFile primitive
+ impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ // PointArray primitive
+ const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate = static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate);
+
+ // set point color
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
+ maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
+ canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
+
+ const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions();
+ const sal_uInt32 nPointCount(rPointVector.size());
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const basegfx::B2DPoint& rPoint = rPointVector[a];
+ mxCanvas->drawPoint(basegfx::unotools::point2DFromB2DPoint(rPoint), maViewState, maRenderState);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ {
+ // TextSimplePortion primitive
+ impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // Bitmap primitive
+ impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D :
+ {
+ // Alpha primitive
+ impRenderAlphaPrimitive2D(static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ // PolygonStrokePrimitive
+ impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
+ {
+ // FillBitmapPrimitive2D
+ impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D :
+ {
+ // UnifiedAlphaPrimitive2D
+ impRenderUnifiedAlphaPrimitive2D(static_cast< const primitive2d::UnifiedAlphaPrimitive2D& >(rCandidate));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
+ {
+ // chart primitive in canvas renderer; restore original DrawMode during call
+ // since the evtl. used ChartPrettyPainter will use the MapMode
+ const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
+ mpOutputDevice->Push(PUSH_MAPMODE);
+ mpOutputDevice->SetMapMode(maOriginalMapMode);
+
+ if(!renderChartPrimitive2D(
+ rChartPrimitive,
+ *mpOutputDevice,
+ getViewInformation2D()))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+
+ mpOutputDevice->Pop();
+ break;
+ }
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ {
+ // wrong spell primitive. Handled directly here using VCL since VCL has a nice and
+ // very direct waveline painting which is needed for this. If VCL is to be avoided,
+ // this can be removed anytime and the decomposition may be used
+ const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
+
+ if(!renderWrongSpellPrimitive2D(
+ rWrongSpellPrimitive,
+ *mpOutputDevice,
+ getViewInformation2D().getObjectToViewTransformation(),
+ maBColorModifierStack))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+
+ break;
+ }
+
+ // nice to have:
+ //
+ // case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+ // - support FormControls more direct eventually, not sure if this is needed
+ // with the canvas renderer. The decomposition provides a bitmap representation
+ // of the control which will work
+ //
+
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ break;
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // process support
+
+ canvasProcessor2D::canvasProcessor2D(
+ const geometry::ViewInformation2D& rViewInformation,
+ OutputDevice& rOutDev)
+ : BaseProcessor2D(rViewInformation),
+ maOriginalMapMode(rOutDev.GetMapMode()),
+ mpOutputDevice(&rOutDev),
+ mxCanvas(rOutDev.GetCanvas()),
+ maViewState(),
+ maRenderState(),
+ maBColorModifierStack(),
+ maDrawinglayerOpt(),
+ maClipPolyPolygon(),
+ meLang(LANGUAGE_SYSTEM)
+ {
+ const SvtCTLOptions aSvtCTLOptions;
+
+ canvas::tools::initViewState(maViewState);
+ canvas::tools::initRenderState(maRenderState);
+ canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
+
+ // set digit language, derived from SvtCTLOptions to have the correct
+ // number display for arabic/hindi numerals
+ if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ meLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ }
+ else if(SvtCTLOptions::NUMERALS_ARABIC == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ meLang = LANGUAGE_ENGLISH;
+ }
+ else
+ {
+ meLang = (LanguageType)Application::GetSettings().GetLanguage();
+ }
+
+ rOutDev.SetDigitLanguage(meLang);
+
+ // prepare output directly to pixels
+ mpOutputDevice->Push(PUSH_MAPMODE);
+ mpOutputDevice->SetMapMode();
+
+ // react on AntiAliasing settings
+ if(getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ else
+ {
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ }
+
+ canvasProcessor2D::~canvasProcessor2D()
+ {
+ // restore MapMode
+ mpOutputDevice->Pop();
+
+ // restore AntiAliasing
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/contourextractor2d.cxx b/drawinglayer/source/processor2d/contourextractor2d.cxx
new file mode 100644
index 000000000000..1f629cb25c9c
--- /dev/null
+++ b/drawinglayer/source/processor2d/contourextractor2d.cxx
@@ -0,0 +1,211 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: contourextractor2d.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/processor2d/contourextractor2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ ContourExtractor2D::ContourExtractor2D(const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation),
+ maExtractedContour()
+ {
+ }
+
+ ContourExtractor2D::~ContourExtractor2D()
+ {
+ }
+
+ void ContourExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ // extract hairline in world coordinates
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate));
+ basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
+ aLocalPolygon.transform(getViewInformation2D().getObjectTransformation());
+
+ if(aLocalPolygon.isClosed())
+ {
+ // line polygons need to be represented as open polygons to differentiate them
+ // from filled polygons
+ basegfx::tools::openWithGeometryChange(aLocalPolygon);
+ }
+
+ maExtractedContour.push_back(basegfx::B2DPolyPolygon(aLocalPolygon));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ // extract fill in world coordinates
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(getViewInformation2D().getObjectTransformation());
+ maExtractedContour.push_back(aLocalPolyPolygon);
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // extract BoundRect from bitmaps in world coordinates
+ const primitive2d::BitmapPrimitive2D& rBitmapCandidate(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+ basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
+ basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+ aPolygon.transform(aLocalTransform);
+ maExtractedContour.push_back(basegfx::B2DPolyPolygon(aPolygon));
+ break;
+ }
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ {
+ // extract BoundRect from MetaFiles in world coordinates
+ const primitive2d::MetafilePrimitive2D& rMetaCandidate(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
+ basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectTransformation() * rMetaCandidate.getTransform());
+ basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+ aPolygon.transform(aLocalTransform);
+ maExtractedContour.push_back(basegfx::B2DPolyPolygon(aPolygon));
+ break;
+ }
+ case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D :
+ {
+ // sub-transparence group. Look at children
+ const primitive2d::AlphaPrimitive2D& rTransCandidate(static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate));
+ process(rTransCandidate.getChildren());
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // extract mask in world coordinates, ignore content
+ const primitive2d::MaskPrimitive2D& rMaskCandidate(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+ aMask.transform(getViewInformation2D().getObjectTransformation());
+ maExtractedContour.push_back(basegfx::B2DPolyPolygon(aMask));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // remember current ViewInformation2D
+ const primitive2d::TransformPrimitive2D& rTransformCandidate(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new local ViewInformation2D
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D :
+ {
+ // 2D Scene primitive containing 3D stuff; extract 2D contour in world coordinates
+ const primitive2d::ScenePrimitive2D& rScenePrimitive2DCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate));
+ const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D());
+ const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rScenePrimitive2DCandidate.getShadow2D(getViewInformation2D()));
+
+ // proccess content
+ if(xExtracted2DSceneGeometry.hasElements())
+ {
+ process(xExtracted2DSceneGeometry);
+ }
+
+ // proccess content
+ if(xExtracted2DSceneShadow.hasElements())
+ {
+ process(xExtracted2DSceneShadow);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ // ignorable primitives
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+ {
+ // primitives who's BoundRect will be added in world coordinates
+ basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+ aRange.transform(getViewInformation2D().getObjectTransformation());
+ maExtractedContour.push_back(basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aRange)));
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ break;
+ }
+ }
+ }
+
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/helperchartrenderer.cxx b/drawinglayer/source/processor2d/helperchartrenderer.cxx
new file mode 100644
index 000000000000..ffa8917ddec8
--- /dev/null
+++ b/drawinglayer/source/processor2d/helperchartrenderer.cxx
@@ -0,0 +1,163 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helperchartrenderer.cxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/24 14:28:34 $
+ *
+ * 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 <helperchartrenderer.hxx>
+#include <drawinglayer/primitive2d/chartprimitive2d.hxx>
+#include <svtools/chartprettypainter.hxx>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ bool renderChartPrimitive2D(
+ const primitive2d::ChartPrimitive2D& rChartCandidate,
+ OutputDevice& rOutputDevice,
+ const geometry::ViewInformation2D& rViewInformation2D)
+ {
+ bool bChartRendered(false);
+
+ // code from chart PrettyPrinter
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFact( rChartCandidate.getChartModel(), uno::UNO_QUERY );
+ OSL_ENSURE( xFact.is(), "Chart cannot be painted pretty!\n" );
+
+ if( xFact.is() )
+ {
+ uno::Reference< lang::XUnoTunnel > xChartRenderer( xFact->createInstance(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ChartRenderer" ) ) ), uno::UNO_QUERY );
+ OSL_ENSURE( xChartRenderer.is(), "Chart cannot be painted pretty!\n" );
+
+ if( xChartRenderer.is() )
+ {
+ ChartPrettyPainter* pPrettyPainter = reinterpret_cast<ChartPrettyPainter*>(
+ xChartRenderer->getSomething( ChartPrettyPainter::getUnoTunnelId() ));
+
+ if( pPrettyPainter )
+ {
+ // create logic object range; do NOT use ObjectTransformation for this
+ // (rViewInformation2D.getObjectTransformation()), only the logic object
+ // size is wanted
+ basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
+ aObjectRange.transform(rChartCandidate.getTransformation());
+ const Rectangle aRectangle(
+ (sal_Int32)aObjectRange.getMinX(), (sal_Int32)aObjectRange.getMinY(),
+ (sal_Int32)aObjectRange.getMaxX(), (sal_Int32)aObjectRange.getMaxY());
+
+ // #i101811#
+ if(rViewInformation2D.getObjectTransformation().isIdentity())
+ {
+ // no embedding in another transfromation, just paint with existing
+ // MapMode. This is just a shortcut; using the below code will also
+ // work; it has just a neutral ObjectTransformation
+ bChartRendered = pPrettyPainter->DoPaint(&rOutputDevice, aRectangle);
+ }
+ else
+ {
+ // rViewInformation2D.getObjectTransformation() is used and
+ // needs to be expressed in the MapMode for the PrettyPainter;
+ // else it would call ChartModelHelper::setPageSize(...) with the
+ // changed size what really will change the chart model and leads
+ // to re-layouts and re-formattings
+ const MapMode aOldMapMode(rOutputDevice.GetMapMode());
+ basegfx::B2DVector aVTScale, aScale, aTranslate;
+ double fRotate, fShearX;
+
+ // get basic scaling with current MapMode (aVTScale), containing
+ // mapping for set MapUnit (e.g. for 100th mm, the basic scale is
+ // not 1.0, 1.0). This is needed since this scale is included in
+ // the ObjectToView Transformation and needs to be removed (see
+ // correction below) to re-create a MapMode
+ rOutputDevice.SetMapMode(aOldMapMode.GetMapUnit());
+ rOutputDevice.GetViewTransformation().decompose(aVTScale, aTranslate, fRotate, fShearX);
+
+ // get complete ObjectToView Transformation scale and translate from current
+ // transformation chain (combined view and object transform)
+ rViewInformation2D.getObjectToViewTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // assert when shear and/or rotation is used
+ OSL_ENSURE(basegfx::fTools::equalZero(fRotate), "Chart PrettyPrinting with unsupportable rotation (!)");
+ OSL_ENSURE(basegfx::fTools::equalZero(fShearX), "Chart PrettyPrinting with unsupportable shear (!)");
+
+ // clean scale and translate from basic scaling (DPI, etc...)
+ // since this will implicitely be part of the to-be-created MapMode
+ const basegfx::B2DTuple aBasicCleaner(
+ basegfx::fTools::equalZero(aVTScale.getX()) ? 1.0 : 1.0 / aVTScale.getX(),
+ basegfx::fTools::equalZero(aVTScale.getY()) ? 1.0 : 1.0 / aVTScale.getY());
+ aScale *= aBasicCleaner;
+ aTranslate *= aBasicCleaner;
+
+ // for MapMode, take scale out of translation
+ const basegfx::B2DTuple aScaleRemover(
+ basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(),
+ basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY());
+ aTranslate *= aScaleRemover;
+
+ // build new MapMode
+ const MapMode aNewMapMode(aOldMapMode.GetMapUnit(),
+ Point(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY())),
+ Fraction(aScale.getX()), Fraction(aScale.getY()));
+
+ // use, paint, restore
+ rOutputDevice.SetMapMode(aNewMapMode);
+ bChartRendered = pPrettyPainter->DoPaint(&rOutputDevice, aRectangle);
+ rOutputDevice.SetMapMode(aOldMapMode);
+ }
+ }
+ }
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ (void)e;
+ DBG_ERROR( "Chart cannot be painted pretty!" );
+ }
+
+ return bChartRendered;
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/helperchartrenderer.hxx b/drawinglayer/source/processor2d/helperchartrenderer.hxx
new file mode 100644
index 000000000000..4677698129c2
--- /dev/null
+++ b/drawinglayer/source/processor2d/helperchartrenderer.hxx
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helperchartrenderer.hxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/24 14:28:43 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERCHARTRENDER_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERCHARTRENDER_HXX
+
+#include <sal/types.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+class OutputDevice;
+
+namespace drawinglayer { namespace primitive2d { class ChartPrimitive2D; }}
+namespace drawinglayer { namespace geometry { class ViewInformation2D; }}
+
+//////////////////////////////////////////////////////////////////////////////
+// support chart PrettyPrinter usage from primitives
+
+namespace drawinglayer
+{
+ // #i101811#
+ // Added current ViewInformation2D to take evtl. changed
+ // ObjectTransformation into account
+ bool renderChartPrimitive2D(
+ const primitive2d::ChartPrimitive2D& rChartCandidate,
+ OutputDevice& rOutputDevice,
+ const geometry::ViewInformation2D& rViewInformation2D);
+
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERCHARTRENDER_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
new file mode 100644
index 000000000000..44524f9c3fef
--- /dev/null
+++ b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
@@ -0,0 +1,104 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helperwrongspellrenderer.cxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/24 14:28:52 $
+ *
+ * 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 <helperwrongspellrenderer.hxx>
+#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
+#include <tools/gen.hxx>
+#include <vcl/outdev.hxx>
+#include <basegfx/color/bcolormodifier.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ bool renderWrongSpellPrimitive2D(
+ const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate,
+ OutputDevice& rOutputDevice,
+ const basegfx::B2DHomMatrix& rObjectToViewTransformation,
+ const basegfx::BColorModifierStack& rBColorModifierStack)
+ {
+ const basegfx::B2DHomMatrix aLocalTransform(rObjectToViewTransformation * rWrongSpellCandidate.getTransformation());
+ const basegfx::B2DVector aFontVectorPixel(aLocalTransform * basegfx::B2DVector(0.0, 1.0));
+ const sal_uInt32 nFontPixelHeight(basegfx::fround(aFontVectorPixel.getLength()));
+
+ static const sal_uInt32 nMinimumFontHeight(5); // #define WRONG_SHOW_MIN 5
+ static const sal_uInt32 nSmallFontHeight(11); // #define WRONG_SHOW_SMALL 11
+ static const sal_uInt32 nMediumFontHeight(15); // #define WRONG_SHOW_MEDIUM 15
+
+ if(nFontPixelHeight > nMinimumFontHeight)
+ {
+ const basegfx::B2DPoint aStart(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStart(), 0.0));
+ const basegfx::B2DPoint aStop(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStop(), 0.0));
+ const Point aVclStart(basegfx::fround(aStart.getX()), basegfx::fround(aStart.getY()));
+ const Point aVclStop(basegfx::fround(aStop.getX()), basegfx::fround(aStop.getY()));
+ sal_uInt16 nWaveStyle(WAVE_FLAT);
+
+ if(nFontPixelHeight > nMediumFontHeight)
+ {
+ nWaveStyle = WAVE_NORMAL;
+ }
+ else if(nFontPixelHeight > nSmallFontHeight)
+ {
+ nWaveStyle = WAVE_SMALL;
+ }
+
+ // #i101075# draw it. Do not forget to use the evtl. offsetted origin of the target device,
+ // e.g. when used with mask/transparence buffer device
+ const Point aOrigin(rOutputDevice.GetMapMode().GetOrigin());
+
+ const basegfx::BColor aProcessedColor(rBColorModifierStack.getModifiedColor(rWrongSpellCandidate.getColor()));
+ const bool bMapModeEnabledState(rOutputDevice.IsMapModeEnabled());
+
+ rOutputDevice.EnableMapMode(false);
+ rOutputDevice.SetLineColor(Color(aProcessedColor));
+ rOutputDevice.SetFillColor();
+ rOutputDevice.DrawWaveLine(aOrigin + aVclStart, aOrigin + aVclStop, nWaveStyle);
+ rOutputDevice.EnableMapMode(bMapModeEnabledState);
+ }
+
+ // cannot really go wrong
+ return true;
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx b/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx
new file mode 100644
index 000000000000..6d9938a72f4e
--- /dev/null
+++ b/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helperwrongspellrenderer.hxx,v $
+ *
+ * $Revision: 1.1.2.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008/09/24 14:29:02 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX
+
+#include <sal/types.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+class OutputDevice;
+
+namespace drawinglayer { namespace primitive2d {
+ class WrongSpellPrimitive2D;
+}}
+
+namespace basegfx {
+ class B2DHomMatrix;
+ class BColorModifierStack;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// support WrongSpell rendreing using VCL from primitives due to VCLs nice
+// and fast solution with wavelines
+
+namespace drawinglayer
+{
+ bool renderWrongSpellPrimitive2D(
+ const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate,
+ OutputDevice& rOutputDevice,
+ const basegfx::B2DHomMatrix& rObjectToViewTransformation,
+ const basegfx::BColorModifierStack& rBColorModifierStack);
+
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
new file mode 100644
index 000000000000..4ffef7515389
--- /dev/null
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -0,0 +1,563 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: contourextractor2d.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/processor2d/hittestprocessor2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
+#include <drawinglayer/primitive2d/hittestprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <drawinglayer/processor3d/cutfindprocessor3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ HitTestProcessor2D::HitTestProcessor2D(const geometry::ViewInformation2D& rViewInformation,
+ const basegfx::B2DPoint& rLogicHitPosition,
+ double fLogicHitTolerance,
+ bool bHitTextOnly)
+ : BaseProcessor2D(rViewInformation),
+ maDiscreteHitPosition(),
+ mfDiscreteHitTolerance(0.0),
+ mbHit(false),
+ mbHitToleranceUsed(false),
+ mbUseHitTestPrimitiveContent(true),
+ mbHitTextOnly(bHitTextOnly)
+ {
+ // init hit tolerance
+ mfDiscreteHitTolerance = fLogicHitTolerance;
+
+ if(basegfx::fTools::less(mfDiscreteHitTolerance, 0.0))
+ {
+ // ensure input parameter for hit tolerance is >= 0.0
+ mfDiscreteHitTolerance = 0.0;
+ }
+ else if(basegfx::fTools::more(mfDiscreteHitTolerance, 0.0))
+ {
+ // generate discrete hit tolerance
+ mfDiscreteHitTolerance = (getViewInformation2D().getObjectToViewTransformation()
+ * basegfx::B2DVector(mfDiscreteHitTolerance, 0.0)).getLength();
+ }
+
+ // gererate discrete hit position
+ maDiscreteHitPosition = getViewInformation2D().getObjectToViewTransformation() * rLogicHitPosition;
+
+ // check if HitTolerance is used
+ mbHitToleranceUsed = basegfx::fTools::more(getDiscreteHitTolerance(), 0.0);
+ }
+
+ HitTestProcessor2D::~HitTestProcessor2D()
+ {
+ }
+
+ bool HitTestProcessor2D::checkHairlineHitWithTolerance(
+ const basegfx::B2DPolygon& rPolygon,
+ double fDiscreteHitTolerance)
+ {
+ basegfx::B2DPolygon aLocalPolygon(rPolygon);
+ aLocalPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // get discrete range
+ basegfx::B2DRange aPolygonRange(aLocalPolygon.getB2DRange());
+
+ if(basegfx::fTools::more(fDiscreteHitTolerance, 0.0))
+ {
+ aPolygonRange.grow(fDiscreteHitTolerance);
+ }
+
+ // do rough range test first
+ if(aPolygonRange.isInside(getDiscreteHitPosition()))
+ {
+ // check if a polygon edge is hit
+ return basegfx::tools::isInEpsilonRange(
+ aLocalPolygon,
+ getDiscreteHitPosition(),
+ fDiscreteHitTolerance);
+ }
+
+ return false;
+ }
+
+ bool HitTestProcessor2D::checkFillHitWithTolerance(
+ const basegfx::B2DPolyPolygon& rPolyPolygon,
+ double fDiscreteHitTolerance)
+ {
+ bool bRetval(false);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
+ aLocalPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // get discrete range
+ basegfx::B2DRange aPolygonRange(aLocalPolyPolygon.getB2DRange());
+ const bool bDiscreteHitToleranceUsed(basegfx::fTools::more(fDiscreteHitTolerance, 0.0));
+
+ if(bDiscreteHitToleranceUsed)
+ {
+ aPolygonRange.grow(fDiscreteHitTolerance);
+ }
+
+ // do rough range test first
+ if(aPolygonRange.isInside(getDiscreteHitPosition()))
+ {
+ // if a HitTolerance is given, check for polygon edge hit in epsilon first
+ if(bDiscreteHitToleranceUsed &&
+ basegfx::tools::isInEpsilonRange(
+ aLocalPolyPolygon,
+ getDiscreteHitPosition(),
+ fDiscreteHitTolerance))
+ {
+ bRetval = true;
+ }
+
+ // check for hit in filled polyPolygon
+ if(!bRetval && basegfx::tools::isInside(
+ aLocalPolyPolygon,
+ getDiscreteHitPosition(),
+ true))
+ {
+ bRetval = true;
+ }
+ }
+
+ return bRetval;
+ }
+
+ void HitTestProcessor2D::check3DHit(const primitive2d::ScenePrimitive2D& rCandidate)
+ {
+ // calculate relative point in unified 2D scene
+ const basegfx::B2DPoint aLogicHitPosition(getViewInformation2D().getInverseObjectToViewTransformation() * getDiscreteHitPosition());
+
+ // use bitmap check in ScenePrimitive2D
+ bool bTryFastResult(false);
+
+ if(rCandidate.tryToCheckLastVisualisationDirectHit(aLogicHitPosition, bTryFastResult))
+ {
+ mbHit = bTryFastResult;
+ }
+ else
+ {
+ basegfx::B2DHomMatrix aInverseSceneTransform(rCandidate.getObjectTransformation());
+ aInverseSceneTransform.invert();
+ const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * aLogicHitPosition);
+
+ // check if test point is inside scene's unified area at all
+ if(aRelativePoint.getX() >= 0.0 && aRelativePoint.getX() <= 1.0
+ && aRelativePoint.getY() >= 0.0 && aRelativePoint.getY() <= 1.0)
+ {
+ // get 3D view information
+ const geometry::ViewInformation3D& rObjectViewInformation3D = rCandidate.getViewInformation3D();
+
+ // create HitPoint Front and Back, transform to object coordinates
+ basegfx::B3DHomMatrix aViewToObject(rObjectViewInformation3D.getObjectToView());
+ aViewToObject.invert();
+ const basegfx::B3DPoint aFront(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 0.0));
+ const basegfx::B3DPoint aBack(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 1.0));
+
+ if(!aFront.equal(aBack))
+ {
+ const primitive3d::Primitive3DSequence& rPrimitives = rCandidate.getChildren3D();
+
+ if(rPrimitives.hasElements())
+ {
+ // make BoundVolume empty and overlapping test for speedup
+ const basegfx::B3DRange aObjectRange(
+ drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
+ rPrimitives, rObjectViewInformation3D));
+
+ if(!aObjectRange.isEmpty())
+ {
+ const basegfx::B3DRange aFrontBackRange(aFront, aBack);
+
+ if(aObjectRange.overlaps(aFrontBackRange))
+ {
+ // bound volumes hit, geometric cut tests needed
+ drawinglayer::processor3d::CutFindProcessor aCutFindProcessor(
+ rObjectViewInformation3D,
+ aFront,
+ aBack,
+ true);
+ aCutFindProcessor.process(rPrimitives);
+
+ mbHit = (0 != aCutFindProcessor.getCutPoints().size());
+ }
+ }
+ }
+ }
+ }
+
+ // This is needed to check hit with 3D shadows, too. HitTest is without shadow
+ // to keep compatible with previous versions. Keeping here as reference
+ //
+ // if(!getHit())
+ // {
+ // // if scene has shadow, check hit with shadow, too
+ // const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rCandidate.getShadow2D(getViewInformation2D()));
+ //
+ // if(xExtracted2DSceneShadow.hasElements())
+ // {
+ // // proccess extracted 2D content
+ // process(xExtracted2DSceneShadow);
+ // }
+ // }
+
+ if(!getHit())
+ {
+ // empty 3D scene; Check for border hit
+ basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+ aOutline.transform(rCandidate.getObjectTransformation());
+
+ mbHit = checkHairlineHitWithTolerance(aOutline, getDiscreteHitTolerance());
+ }
+
+ // This is what the previous version did. Keeping it here for reference
+ //
+ // // 2D Scene primitive containing 3D stuff; extract 2D contour in world coordinates
+ // // This may be refined later to an own 3D HitTest renderer which processes the 3D
+ // // geometry directly
+ // const primitive2d::ScenePrimitive2D& rScenePrimitive2DCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate));
+ // const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D());
+ // const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rScenePrimitive2DCandidate.getShadow2D(getViewInformation2D()));
+ //
+ // if(xExtracted2DSceneGeometry.hasElements() || xExtracted2DSceneShadow.hasElements())
+ // {
+ // // proccess extracted 2D content
+ // process(xExtracted2DSceneGeometry);
+ // process(xExtracted2DSceneShadow);
+ // }
+ // else
+ // {
+ // // empty 3D scene; Check for border hit
+ // const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+ // if(!aRange.isEmpty())
+ // {
+ // const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange));
+ // mbHit = checkHairlineHitWithTolerance(aOutline, getDiscreteHitTolerance());
+ // }
+ // }
+ }
+ }
+
+ void HitTestProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ if(getHit())
+ {
+ // stop processing as soon as a hit was recognized
+ return;
+ }
+
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // remember current ViewInformation2D
+ const primitive2d::TransformPrimitive2D& rTransformCandidate(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new local ViewInformation2D containing transformation
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess child content recursively
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // create hairline in discrete coordinates
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate));
+
+ // use hairline test
+ mbHit = checkHairlineHitWithTolerance(rPolygonCandidate.getB2DPolygon(), getDiscreteHitTolerance());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // handle marker like hairline; no need to decompose in dashes
+ const primitive2d::PolygonMarkerPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonMarkerPrimitive2D& >(rCandidate));
+
+ // use hairline test
+ mbHit = checkHairlineHitWithTolerance(rPolygonCandidate.getB2DPolygon(), getDiscreteHitTolerance());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // handle stroke evtl. directly; no need to decompose to filled polygon outlines
+ const primitive2d::PolygonStrokePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
+ const attribute::LineAttribute& rLineAttribute = rPolygonCandidate.getLineAttribute();
+
+ if(basegfx::fTools::more(rLineAttribute.getWidth(), 0.0))
+ {
+ if(basegfx::B2DLINEJOIN_MITER == rLineAttribute.getLineJoin())
+ {
+ // if line is mitered, use decomposition since mitered line
+ // geometry may use more space than the geometry grown by half line width
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ else
+ {
+ // for all other B2DLINEJOIN_* do a hairline HitTest with expanded tolerance
+ const basegfx::B2DVector aDiscreteHalfLineVector(getViewInformation2D().getObjectToViewTransformation()
+ * basegfx::B2DVector(rLineAttribute.getWidth() * 0.5, 0.0));
+ mbHit = checkHairlineHitWithTolerance(
+ rPolygonCandidate.getB2DPolygon(),
+ getDiscreteHitTolerance() + aDiscreteHalfLineVector.getLength());
+ }
+ }
+ else
+ {
+ // hairline; fallback to hairline test. Do not decompose
+ // since this may decompose the hairline to dashes
+ mbHit = checkHairlineHitWithTolerance(rPolygonCandidate.getB2DPolygon(), getDiscreteHitTolerance());
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // do not use decompose; just handle like a line with width
+ const primitive2d::PolygonWavePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonWavePrimitive2D& >(rCandidate));
+ double fLogicHitTolerance(0.0);
+
+ // if WaveHeight, grow by it
+ if(basegfx::fTools::more(rPolygonCandidate.getWaveHeight(), 0.0))
+ {
+ fLogicHitTolerance += rPolygonCandidate.getWaveHeight();
+ }
+
+ // if line width, grow by it
+ if(basegfx::fTools::more(rPolygonCandidate.getLineAttribute().getWidth(), 0.0))
+ {
+ fLogicHitTolerance += rPolygonCandidate.getLineAttribute().getWidth() * 0.5;
+ }
+
+ const basegfx::B2DVector aDiscreteHalfLineVector(getViewInformation2D().getObjectToViewTransformation()
+ * basegfx::B2DVector(fLogicHitTolerance, 0.0));
+
+ mbHit = checkHairlineHitWithTolerance(
+ rPolygonCandidate.getB2DPolygon(),
+ getDiscreteHitTolerance() + aDiscreteHalfLineVector.getLength());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // create filled polyPolygon in discrete coordinates
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+
+ // use fill hit test
+ mbHit = checkFillHitWithTolerance(rPolygonCandidate.getB2DPolyPolygon(), getDiscreteHitTolerance());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D :
+ {
+ // sub-transparence group
+ const primitive2d::AlphaPrimitive2D& rTransCandidate(static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate));
+
+ // Currently the transparence content is not taken into account; only
+ // the children are recursively checked for hit. This may be refined for
+ // parts where the content is completely transparent if needed.
+ process(rTransCandidate.getChildren());
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // create mask in discrete coordinates; only recursively continue
+ // with content when HitTest position is inside the mask
+ const primitive2d::MaskPrimitive2D& rMaskCandidate(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
+
+ // use fill hit test
+ if(checkFillHitWithTolerance(rMaskCandidate.getMask(), getDiscreteHitTolerance()))
+ {
+ // recursively HitTest children
+ process(rMaskCandidate.getChildren());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ const primitive2d::ScenePrimitive2D& rSceneCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate));
+ check3DHit(rSceneCandidate);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_GRIDPRIMITIVE2D :
+ case PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D :
+ {
+ // ignorable primitives
+ break;
+ }
+ case PRIMITIVE2D_ID_SHADOWPRIMITIVE2D :
+ {
+ // Ignore shadows; we do not want to have shadows hittable.
+ // Remove this one to make shadows hittable on demand.
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+ {
+ // for text use the BoundRect of the primitive itself
+ const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+
+ if(!aRange.isEmpty())
+ {
+ const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange));
+ mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+ case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D :
+ case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D :
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ // Class of primitives for which just the BoundRect of the primitive itself
+ // will be used for HitTest currently.
+ //
+ // This may be refined in the future, e.g:
+ // - For Bitamps, the mask and/or alpha information may be used
+ // - For MetaFiles, the MetaFile content may be used
+ const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+
+ if(!aRange.isEmpty())
+ {
+ const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange));
+ mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance());
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_HITTESTPRIMITIVE2D :
+ {
+ // HitTest primitive; the default decomposition would return an empty seqence,
+ // so force this primitive to process it's children directly if the switch is set
+ // (which is the default). Else, ignore invisible content
+ if(getUseHitTestPrimitiveContent())
+ {
+ const primitive2d::HitTestPrimitive2D& rHitTestCandidate(static_cast< const primitive2d::HitTestPrimitive2D& >(rCandidate));
+ process(rHitTestCandidate.getChildren());
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ if(!getHitTextOnly())
+ {
+ const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+ const std::vector< basegfx::B2DPoint >& rPositions = rPointArrayCandidate.getPositions();
+ const sal_uInt32 nCount(rPositions.size());
+
+ for(sal_uInt32 a(0); !getHit() && a < nCount; a++)
+ {
+ const basegfx::B2DPoint aPosition(getViewInformation2D().getObjectToViewTransformation() * rPositions[a]);
+ const basegfx::B2DVector aDistance(aPosition - getDiscreteHitPosition());
+
+ if(aDistance.getLength() <= getDiscreteHitTolerance())
+ {
+ mbHit = true;
+ }
+ }
+ }
+
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ break;
+ }
+ }
+ }
+
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/linegeometryextractor2d.cxx b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
new file mode 100644
index 000000000000..5f0ab63ee1b3
--- /dev/null
+++ b/drawinglayer/source/processor2d/linegeometryextractor2d.cxx
@@ -0,0 +1,152 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: linegeometryextractor2d.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:44:27 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_drawinglayer.hxx"
+
+#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ LineGeometryExtractor2D::LineGeometryExtractor2D(const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation),
+ maExtractedHairlines(),
+ maExtractedLineFills(),
+ mbInLineGeometry(false)
+ {
+ }
+
+ LineGeometryExtractor2D::~LineGeometryExtractor2D()
+ {
+ }
+
+ void LineGeometryExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
+ {
+ // enter a line geometry group (with or without LineEnds)
+ bool bOldState(mbInLineGeometry);
+ mbInLineGeometry = true;
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ mbInLineGeometry = bOldState;
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ if(mbInLineGeometry)
+ {
+ // extract hairline line geometry in world coordinates
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate));
+ basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
+ aLocalPolygon.transform(getViewInformation2D().getObjectTransformation());
+ maExtractedHairlines.push_back(aLocalPolygon);
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ if(mbInLineGeometry)
+ {
+ // extract filled line geometry (line with width)
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(getViewInformation2D().getObjectTransformation());
+ maExtractedLineFills.push_back(aLocalPolyPolygon);
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // remember current transformation and ViewInformation
+ const primitive2d::TransformPrimitive2D& rTransformCandidate(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for CurrentTransformation and for local ViewInformation2D
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // ignorable primitives
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ break;
+ }
+ }
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/makefile.mk b/drawinglayer/source/processor2d/makefile.mk
new file mode 100644
index 000000000000..fcbf2413b61f
--- /dev/null
+++ b/drawinglayer/source/processor2d/makefile.mk
@@ -0,0 +1,66 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,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
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJNAME=drawinglayer
+TARGET=processor2d
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/baseprocessor2d.obj \
+ $(SLO)$/vclhelpergradient.obj \
+ $(SLO)$/vclhelperbitmaptransform.obj \
+ $(SLO)$/vclhelperbitmaprender.obj \
+ $(SLO)$/vclhelperbufferdevice.obj \
+ $(SLO)$/vclprocessor2d.obj \
+ $(SLO)$/helperchartrenderer.obj \
+ $(SLO)$/helperwrongspellrenderer.obj \
+ $(SLO)$/vclpixelprocessor2d.obj \
+ $(SLO)$/vclmetafileprocessor2d.obj \
+ $(SLO)$/contourextractor2d.obj \
+ $(SLO)$/linegeometryextractor2d.obj \
+ $(SLO)$/canvasprocessor.obj \
+ $(SLO)$/hittestprocessor2d.obj \
+ $(SLO)$/textaspolygonextractor2d.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
new file mode 100644
index 000000000000..9358c7f39c57
--- /dev/null
+++ b/drawinglayer/source/processor2d/textaspolygonextractor2d.cxx
@@ -0,0 +1,255 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: contourextractor2d.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/processor2d/textaspolygonextractor2d.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ void TextAsPolygonExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+ {
+ // TextDecoratedPortionPrimitive2D can produce the following primitives
+ // when being decomposed:
+ //
+ // - TextSimplePortionPrimitive2D
+ // - PolygonWavePrimitive2D
+ // - PolygonStrokePrimitive2D
+ // - PolygonStrokePrimitive2D
+ // - PolyPolygonColorPrimitive2D
+ // - PolyPolygonHairlinePrimitive2D
+ // - PolygonHairlinePrimitive2D
+ // - ShadowPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - TextEffectPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - GroupPrimitive2D
+
+ // encapsulate with flag and use decomposition
+ mnInText++;
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ mnInText--;
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ {
+ // TextSimplePortionPrimitive2D can produce the following primitives
+ // when being decomposed:
+ //
+ // - PolyPolygonColorPrimitive2D
+ // - TextEffectPrimitive2D
+ // - ModifiedColorPrimitive2D
+ // - TransformPrimitive2D
+ // - GroupPrimitive2D
+
+ // encapsulate with flag and use decomposition
+ mnInText++;
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ mnInText--;
+
+ break;
+ }
+
+ // as can be seen from the TextSimplePortionPrimitive2D and the
+ // TextDecoratedPortionPrimitive2D, inside of the mnInText marks
+ // the following primitives can occurr containing geometry data
+ // from text decomposition:
+ //
+ // - PolyPolygonColorPrimitive2D
+ // - PolygonHairlinePrimitive2D
+ // - PolyPolygonHairlinePrimitive2D (for convenience)
+ //
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ if(mnInText)
+ {
+ const primitive2d::PolyPolygonColorPrimitive2D& rPoPoCoCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+ basegfx::B2DPolyPolygon aPolyPolygon(rPoPoCoCandidate.getB2DPolyPolygon());
+
+ if(aPolyPolygon.count())
+ {
+ // transform the PolyPolygon
+ aPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // get evtl. corrected color
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rPoPoCoCandidate.getBColor()));
+
+ // add to result vector
+ maTarget.push_back(TextAsPolygonDataNode(aPolyPolygon, aColor, true));
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ if(mnInText)
+ {
+ const primitive2d::PolygonHairlinePrimitive2D& rPoHaCandidate(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate));
+ basegfx::B2DPolygon aPolygon(rPoHaCandidate.getB2DPolygon());
+
+ if(aPolygon.count())
+ {
+ // transform the Polygon
+ aPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // get evtl. corrected color
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rPoHaCandidate.getBColor()));
+
+ // add to result vector
+ maTarget.push_back(TextAsPolygonDataNode(basegfx::B2DPolyPolygon(aPolygon), aColor, false));
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D :
+ {
+ if(mnInText)
+ {
+ const primitive2d::PolyPolygonHairlinePrimitive2D& rPoPoHaCandidate(static_cast< const primitive2d::PolyPolygonHairlinePrimitive2D& >(rCandidate));
+ basegfx::B2DPolyPolygon aPolyPolygon(rPoPoHaCandidate.getB2DPolyPolygon());
+
+ if(aPolyPolygon.count())
+ {
+ // transform the Polygon
+ aPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation());
+
+ // get evtl. corrected color
+ const basegfx::BColor aColor(maBColorModifierStack.getModifiedColor(rPoPoHaCandidate.getBColor()));
+
+ // add to result vector
+ maTarget.push_back(TextAsPolygonDataNode(aPolyPolygon, aColor, false));
+ }
+ }
+
+ break;
+ }
+
+ // usage of color modification stack is needed
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ const primitive2d::ModifiedColorPrimitive2D& rModifiedColorCandidate(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
+
+ if(rModifiedColorCandidate.getChildren().hasElements())
+ {
+ maBColorModifierStack.push(rModifiedColorCandidate.getColorModifier());
+ process(rModifiedColorCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+
+ break;
+ }
+
+ // usage of transformation stack is needed
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // remember current transformation and ViewInformation
+ const primitive2d::TransformPrimitive2D& rTransformCandidate(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for CurrentTransformation and for local ViewInformation2D
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+
+ break;
+ }
+
+ // ignorable primitives
+ case PRIMITIVE2D_ID_SCENEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ break;
+ }
+
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ break;
+ }
+ }
+ }
+
+ TextAsPolygonExtractor2D::TextAsPolygonExtractor2D(const geometry::ViewInformation2D& rViewInformation)
+ : BaseProcessor2D(rViewInformation),
+ maTarget(),
+ maBColorModifierStack(),
+ mnInText(0)
+ {
+ }
+
+ TextAsPolygonExtractor2D::~TextAsPolygonExtractor2D()
+ {
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx b/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx
new file mode 100644
index 000000000000..1488cd4fd054
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx
@@ -0,0 +1,278 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbitmaprender.cxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * 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 <vclhelperbitmaprender.hxx>
+#include <goodies/grfmgr.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <vcl/outdev.hxx>
+#include <vclhelperbitmaptransform.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// support for different kinds of bitmap rendering using vcl
+
+namespace drawinglayer
+{
+ void RenderBitmapPrimitive2D_GraphicManager(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform)
+ {
+ // prepare attributes
+ GraphicAttr aAttributes;
+
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // mirror flags
+ aAttributes.SetMirrorFlags(
+ (basegfx::fTools::less(aScale.getX(), 0.0) ? BMP_MIRROR_HORZ : 0)|
+ (basegfx::fTools::less(aScale.getY(), 0.0) ? BMP_MIRROR_VERT : 0));
+
+ // rotation
+ if(!basegfx::fTools::equalZero(fRotate))
+ {
+ double fRotation(fmod(3600.0 - (fRotate * (10.0 / F_PI180)), 3600.0));
+ aAttributes.SetRotation((sal_uInt16)(fRotation));
+ }
+
+ // prepare Bitmap
+ basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
+
+ if(basegfx::fTools::equalZero(fRotate))
+ {
+ aOutlineRange.transform(rTransform);
+ }
+ else
+ {
+ // if rotated, create the unrotated output rectangle for the GraphicManager paint
+ basegfx::B2DHomMatrix aSimpleObjectMatrix;
+
+ aSimpleObjectMatrix.scale(fabs(aScale.getX()), fabs(aScale.getY()));
+ aSimpleObjectMatrix.translate(aTranslate.getX(), aTranslate.getY());
+
+ aOutlineRange.transform(aSimpleObjectMatrix);
+ }
+
+ // prepare dest coor
+ const Rectangle aDestRectPixel(
+ basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
+ basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
+
+ // paint it using GraphicManager
+ Graphic aGraphic(rBitmapEx);
+ GraphicObject aGraphicObject(aGraphic);
+ aGraphicObject.Draw(&rOutDev, aDestRectPixel.TopLeft(), aDestRectPixel.GetSize(), &aAttributes);
+ }
+
+ void RenderBitmapPrimitive2D_BitmapEx(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform)
+ {
+ // only translate and scale, use vcl's DrawBitmapEx().
+ BitmapEx aContent(rBitmapEx);
+
+ // prepare dest coor. Necessary to expand since vcl's DrawBitmapEx draws one pix less
+ basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
+ aOutlineRange.transform(rTransform);
+ const Rectangle aDestRectPixel(
+ basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
+ basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
+
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // Check mirroring.
+ sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
+
+ if(basegfx::fTools::less(aScale.getX(), 0.0))
+ {
+ nMirrorFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if(basegfx::fTools::less(aScale.getY(), 0.0))
+ {
+ nMirrorFlags |= BMP_MIRROR_VERT;
+ }
+
+ if(BMP_MIRROR_NONE != nMirrorFlags)
+ {
+ aContent.Mirror(nMirrorFlags);
+ }
+
+ // draw bitmap
+ rOutDev.DrawBitmapEx(aDestRectPixel.TopLeft(), aDestRectPixel.GetSize(), aContent);
+ }
+
+ void RenderBitmapPrimitive2D_self(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform)
+ {
+ // process self with free transformation (containing shear and rotate). Get dest rect in pixels.
+ basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
+ aOutlineRange.transform(rTransform);
+ const Rectangle aDestRectLogic(
+ basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
+ basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
+ const Rectangle aDestRectPixel(rOutDev.LogicToPixel(aDestRectLogic));
+
+ // #i96708# check if Metafile is recorded
+ const GDIMetaFile* pMetaFile = rOutDev.GetConnectMetaFile();
+ const bool bRecordToMetaFile(pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
+
+ // intersect with output pixel size, but only
+ // when not recording to metafile
+ const Rectangle aOutputRectPixel(Point(), rOutDev.GetOutputSizePixel());
+ Rectangle aCroppedRectPixel(bRecordToMetaFile ? aDestRectPixel : aDestRectPixel.GetIntersection(aOutputRectPixel));
+
+ if(!aCroppedRectPixel.IsEmpty())
+ {
+ // as maximum for destination, orientate at SourceSizePixel, but
+ // take a rotation of 45 degrees (sqrt(2)) as maximum expansion into account
+ const Size aSourceSizePixel(rBitmapEx.GetSizePixel());
+ const double fMaximumArea(
+ (double)aSourceSizePixel.getWidth() *
+ (double)aSourceSizePixel.getHeight() *
+ 1.4142136); // 1.4142136 taken as sqrt(2.0)
+
+ // test if discrete view size (pixel) maybe too big and limit it
+ const double fArea(aCroppedRectPixel.getWidth() * aCroppedRectPixel.getHeight());
+ const bool bNeedToReduce(fArea > fMaximumArea);
+ double fReduceFactor(1.0);
+
+ if(bNeedToReduce)
+ {
+ fReduceFactor = sqrt(fMaximumArea / fArea);
+ aCroppedRectPixel.setWidth(basegfx::fround(aCroppedRectPixel.getWidth() * fReduceFactor));
+ aCroppedRectPixel.setHeight(basegfx::fround(aCroppedRectPixel.getHeight() * fReduceFactor));
+ }
+
+ // build transform from pixel in aDestination to pixel in rBitmapEx
+ basegfx::B2DHomMatrix aTransform;
+
+ // from relative in aCroppedRectPixel to relative in aDestRectPixel
+ // No need to take bNeedToReduce into account, TopLeft is unchanged
+ aTransform.translate(aCroppedRectPixel.Left() - aDestRectPixel.Left(), aCroppedRectPixel.Top() - aDestRectPixel.Top());
+
+ // from relative in aDestRectPixel to absolute Logic. Here it
+ // is essential to adapt to reduce factor (if used)
+ double fAdaptedDRPWidth((double)aDestRectPixel.getWidth());
+ double fAdaptedDRPHeight((double)aDestRectPixel.getHeight());
+
+ if(bNeedToReduce)
+ {
+ fAdaptedDRPWidth *= fReduceFactor;
+ fAdaptedDRPHeight *= fReduceFactor;
+ }
+
+ aTransform.scale(aDestRectLogic.getWidth() / fAdaptedDRPWidth, aDestRectLogic.getHeight() / fAdaptedDRPHeight);
+ aTransform.translate(aDestRectLogic.Left(), aDestRectLogic.Top());
+
+ // from absolute in Logic to unified object coordinates (0.0 .. 1.0 in x and y)
+ basegfx::B2DHomMatrix aInvBitmapTransform(rTransform);
+ aInvBitmapTransform.invert();
+ aTransform = aInvBitmapTransform * aTransform;
+
+ // from unit object coordinates to rBitmapEx pixel coordintes
+ aTransform.scale(aSourceSizePixel.getWidth() - 1L, aSourceSizePixel.getHeight() - 1L);
+
+ // create bitmap using source, destination and linear back-transformation
+ BitmapEx aDestination = impTransformBitmapEx(rBitmapEx, aCroppedRectPixel, aTransform);
+
+ // paint
+ if(bNeedToReduce)
+ {
+ // paint in target size
+ const double fFactor(1.0 / fReduceFactor);
+ const Size aDestSizePixel(
+ basegfx::fround(aCroppedRectPixel.getWidth() * fFactor),
+ basegfx::fround(aCroppedRectPixel.getHeight() * fFactor));
+
+ if(bRecordToMetaFile)
+ {
+ rOutDev.DrawBitmapEx(
+ rOutDev.PixelToLogic(aCroppedRectPixel.TopLeft()),
+ rOutDev.PixelToLogic(aDestSizePixel),
+ aDestination);
+ }
+ else
+ {
+ const bool bWasEnabled(rOutDev.IsMapModeEnabled());
+ rOutDev.EnableMapMode(false);
+
+ rOutDev.DrawBitmapEx(
+ aCroppedRectPixel.TopLeft(),
+ aDestSizePixel,
+ aDestination);
+
+ rOutDev.EnableMapMode(bWasEnabled);
+ }
+ }
+ else
+ {
+ if(bRecordToMetaFile)
+ {
+ rOutDev.DrawBitmapEx(
+ rOutDev.PixelToLogic(aCroppedRectPixel.TopLeft()),
+ aDestination);
+ }
+ else
+ {
+ const bool bWasEnabled(rOutDev.IsMapModeEnabled());
+ rOutDev.EnableMapMode(false);
+
+ rOutDev.DrawBitmapEx(
+ aCroppedRectPixel.TopLeft(),
+ aDestination);
+
+ rOutDev.EnableMapMode(bWasEnabled);
+ }
+ }
+ }
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbitmaprender.hxx b/drawinglayer/source/processor2d/vclhelperbitmaprender.hxx
new file mode 100644
index 000000000000..6dccdd72a813
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbitmaprender.hxx
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbitmaprender.hxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPRENDER_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPRENDER_HXX
+
+#include <sal/types.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+class OutputDevice;
+class BitmapEx;
+namespace basegfx { class B2DHomMatrix; }
+
+//////////////////////////////////////////////////////////////////////////////
+// support methods for vcl direct gradient renderering
+
+namespace drawinglayer
+{
+ void RenderBitmapPrimitive2D_GraphicManager(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform);
+
+ void RenderBitmapPrimitive2D_BitmapEx(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform);
+
+ void RenderBitmapPrimitive2D_self(
+ OutputDevice& rOutDev,
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DHomMatrix& rTransform);
+
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPRENDER_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbitmaptransform.cxx b/drawinglayer/source/processor2d/vclhelperbitmaptransform.cxx
new file mode 100644
index 000000000000..15be4047c35a
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbitmaptransform.cxx
@@ -0,0 +1,439 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbitmaptransform.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
+ *
+ * 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 <vclhelperbitmaptransform.hxx>
+#include <vcl/bmpacc.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/color/bcolormodifier.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// support for rendering Bitmap and BitmapEx contents
+
+namespace drawinglayer
+{
+ namespace
+ {
+ void impSmoothPoint(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
+ {
+ double fDeltaX(rSource.getX() - nIntX);
+ double fDeltaY(rSource.getY() - nIntY);
+ sal_Int32 nIndX(0L);
+ sal_Int32 nIndY(0L);
+
+ if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
+ {
+ nIndX++;
+ }
+ else if(fDeltaX < 0.0 && nIntX >= 1L)
+ {
+ fDeltaX = -fDeltaX;
+ nIndX--;
+ }
+
+ if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
+ {
+ nIndY++;
+ }
+ else if(fDeltaY < 0.0 && nIntY >= 1L)
+ {
+ fDeltaY = -fDeltaY;
+ nIndY--;
+ }
+
+ if(nIndX || nIndY)
+ {
+ const double fColorToReal(1.0 / 255.0);
+ double fR(rValue.GetRed() * fColorToReal);
+ double fG(rValue.GetGreen() * fColorToReal);
+ double fB(rValue.GetBlue() * fColorToReal);
+ double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
+
+ if(nIndX)
+ {
+ const double fMulA(fDeltaX * fColorToReal);
+ double fMulB(1.0 - fDeltaX);
+ const BitmapColor aTopPartner(rRead.GetColor(nIntY, nIntX + nIndX));
+
+ fR = (fR * fMulB) + (aTopPartner.GetRed() * fMulA);
+ fG = (fG * fMulB) + (aTopPartner.GetGreen() * fMulA);
+ fB = (fB * fMulB) + (aTopPartner.GetBlue() * fMulA);
+
+ if(nIndY)
+ {
+ fMulB *= fColorToReal;
+ const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
+ const BitmapColor aBottomPartner(rRead.GetColor(nIntY + nIndY, nIntX + nIndX));
+
+ fRBottom = (aBottom.GetRed() * fMulB) + (aBottomPartner.GetRed() * fMulA);
+ fGBottom = (aBottom.GetGreen() * fMulB) + (aBottomPartner.GetGreen() * fMulA);
+ fBBottom = (aBottom.GetBlue() * fMulB) + (aBottomPartner.GetBlue() * fMulA);
+ }
+ }
+
+ if(nIndY)
+ {
+ if(!nIndX)
+ {
+ const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
+
+ fRBottom = aBottom.GetRed() * fColorToReal;
+ fGBottom = aBottom.GetGreen() * fColorToReal;
+ fBBottom = aBottom.GetBlue() * fColorToReal;
+ }
+
+ const double fMulB(1.0 - fDeltaY);
+
+ fR = (fR * fMulB) + (fRBottom * fDeltaY);
+ fG = (fG * fMulB) + (fGBottom * fDeltaY);
+ fB = (fB * fMulB) + (fBBottom * fDeltaY);
+ }
+
+ rValue.SetRed((sal_uInt8)(fR * 255.0));
+ rValue.SetGreen((sal_uInt8)(fG * 255.0));
+ rValue.SetBlue((sal_uInt8)(fB * 255.0));
+ }
+ }
+
+ void impSmoothIndex(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
+ {
+ double fDeltaX(rSource.getX() - nIntX);
+ double fDeltaY(rSource.getY() - nIntY);
+ sal_Int32 nIndX(0L);
+ sal_Int32 nIndY(0L);
+
+ if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
+ {
+ nIndX++;
+ }
+ else if(fDeltaX < 0.0 && nIntX >= 1L)
+ {
+ fDeltaX = -fDeltaX;
+ nIndX--;
+ }
+
+ if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
+ {
+ nIndY++;
+ }
+ else if(fDeltaY < 0.0 && nIntY >= 1L)
+ {
+ fDeltaY = -fDeltaY;
+ nIndY--;
+ }
+
+ if(nIndX || nIndY)
+ {
+ const double fColorToReal(1.0 / 255.0);
+ double fVal(rValue.GetIndex() * fColorToReal);
+ double fValBottom(0.0);
+
+ if(nIndX)
+ {
+ const double fMulA(fDeltaX * fColorToReal);
+ double fMulB(1.0 - fDeltaX);
+ const BitmapColor aTopPartner(rRead.GetPixel(nIntY, nIntX + nIndX));
+
+ fVal = (fVal * fMulB) + (aTopPartner.GetIndex() * fMulA);
+
+ if(nIndY)
+ {
+ fMulB *= fColorToReal;
+ const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
+ const BitmapColor aBottomPartner(rRead.GetPixel(nIntY + nIndY, nIntX + nIndX));
+
+ fValBottom = (aBottom.GetIndex() * fMulB) + (aBottomPartner.GetIndex() * fMulA);
+ }
+ }
+
+ if(nIndY)
+ {
+ if(!nIndX)
+ {
+ const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
+
+ fValBottom = aBottom.GetIndex() * fColorToReal;
+ }
+
+ const double fMulB(1.0 - fDeltaY);
+
+ fVal = (fVal * fMulB) + (fValBottom * fDeltaY);
+ }
+
+ rValue.SetIndex((sal_uInt8)(fVal * 255.0));
+ }
+ }
+
+ void impTransformBitmap(const Bitmap& rSource, Bitmap& rDestination, const basegfx::B2DHomMatrix& rTransform, bool bSmooth)
+ {
+ BitmapWriteAccess* pWrite = rDestination.AcquireWriteAccess();
+
+ if(pWrite)
+ {
+ const Size aContentSizePixel(rSource.GetSizePixel());
+ BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
+
+ if(pRead)
+ {
+ const Size aDestinationSizePixel(rDestination.GetSizePixel());
+ bool bWorkWithIndex(rDestination.GetBitCount() <= 8);
+ BitmapColor aOutside(pRead->GetBestMatchingColor(BitmapColor(0xff, 0xff, 0xff)));
+
+ for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
+ {
+ for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
+ {
+ const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
+ const sal_Int32 nIntX(basegfx::fround(aSourceCoor.getX()));
+
+ if(nIntX >= 0L && nIntX < aContentSizePixel.getWidth())
+ {
+ const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY()));
+
+ if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight())
+ {
+ if(bWorkWithIndex)
+ {
+ BitmapColor aValue(pRead->GetPixel(nIntY, nIntX));
+
+ if(bSmooth)
+ {
+ impSmoothIndex(aValue, aSourceCoor, nIntX, nIntY, *pRead);
+ }
+
+ pWrite->SetPixel(y, x, aValue);
+ }
+ else
+ {
+ BitmapColor aValue(pRead->GetColor(nIntY, nIntX));
+
+ if(bSmooth)
+ {
+ impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead);
+ }
+
+ pWrite->SetPixel(y, x, aValue.IsIndex() ? aValue : pWrite->GetBestMatchingColor(aValue));
+ }
+
+ continue;
+ }
+ }
+
+ // here are outside pixels. Complete mask
+ if(bWorkWithIndex)
+ {
+ pWrite->SetPixel(y, x, aOutside);
+ }
+ }
+ }
+
+ delete pRead;
+ }
+
+ delete pWrite;
+ }
+ }
+
+ Bitmap impCreateEmptyBitmapWithPattern(const Bitmap& rSource, const Size& aTargetSizePixel)
+ {
+ Bitmap aRetval;
+ BitmapReadAccess* pReadAccess = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
+
+ if(pReadAccess)
+ {
+ if(rSource.GetBitCount() <= 8)
+ {
+ BitmapPalette aPalette(pReadAccess->GetPalette());
+ aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount(), &aPalette);
+ }
+ else
+ {
+ aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount());
+ }
+
+ delete pReadAccess;
+ }
+
+ return aRetval;
+ }
+ } // end of anonymous namespace
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+ BitmapEx impTransformBitmapEx(
+ const BitmapEx& rSource,
+ const Rectangle& rCroppedRectPixel,
+ const basegfx::B2DHomMatrix& rTransform)
+ {
+ // force destination to 24 bit, we want to smooth output
+ const Size aDestinationSize(rCroppedRectPixel.GetSize());
+ Bitmap aDestination(impCreateEmptyBitmapWithPattern(rSource.GetBitmap(), aDestinationSize));
+ static bool bDoSmoothAtAll(true);
+ impTransformBitmap(rSource.GetBitmap(), aDestination, rTransform, bDoSmoothAtAll);
+
+ // create mask
+ if(rSource.IsTransparent())
+ {
+ if(rSource.IsAlpha())
+ {
+ Bitmap aAlpha(impCreateEmptyBitmapWithPattern(rSource.GetAlpha().GetBitmap(), aDestinationSize));
+ impTransformBitmap(rSource.GetAlpha().GetBitmap(), aAlpha, rTransform, bDoSmoothAtAll);
+ return BitmapEx(aDestination, AlphaMask(aAlpha));
+ }
+ else
+ {
+ Bitmap aMask(impCreateEmptyBitmapWithPattern(rSource.GetMask(), aDestinationSize));
+ impTransformBitmap(rSource.GetMask(), aMask, rTransform, false);
+ return BitmapEx(aDestination, aMask);
+ }
+ }
+
+ return BitmapEx(aDestination);
+ }
+
+ BitmapEx impModifyBitmapEx(
+ const basegfx::BColorModifierStack& rBColorModifierStack,
+ const BitmapEx& rSource)
+ {
+ Bitmap aChangedBitmap(rSource.GetBitmap());
+ bool bDone(false);
+
+ for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
+ {
+ const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
+
+ switch(rModifier.getMode())
+ {
+ case basegfx::BCOLORMODIFYMODE_REPLACE :
+ {
+ // complete replace
+ if(rSource.IsTransparent())
+ {
+ // clear bitmap with dest color
+ if(aChangedBitmap.GetBitCount() <= 8)
+ {
+ // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
+ // erase color is determined and used -> this may be different from what is
+ // wanted here. Better create a new bitmap with the needed color explicitely
+ BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
+ OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
+
+ if(pReadAccess)
+ {
+ BitmapPalette aNewPalette(pReadAccess->GetPalette());
+ aNewPalette[0] = BitmapColor(Color(rModifier.getBColor()));
+ aChangedBitmap = Bitmap(
+ aChangedBitmap.GetSizePixel(),
+ aChangedBitmap.GetBitCount(),
+ &aNewPalette);
+ delete pReadAccess;
+ }
+ }
+ else
+ {
+ aChangedBitmap.Erase(Color(rModifier.getBColor()));
+ }
+ }
+ else
+ {
+ // erase bitmap, caller will know to paint direct
+ aChangedBitmap.SetEmpty();
+ }
+
+ bDone = true;
+ break;
+ }
+
+ default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
+ {
+ BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
+
+ if(pContent)
+ {
+ const double fConvertColor(1.0 / 255.0);
+
+ for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+ {
+ for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
+ {
+ const BitmapColor aBMCol(pContent->GetColor(y, x));
+ const basegfx::BColor aBSource(
+ (double)aBMCol.GetRed() * fConvertColor,
+ (double)aBMCol.GetGreen() * fConvertColor,
+ (double)aBMCol.GetBlue() * fConvertColor);
+ const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
+
+ pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
+ }
+ }
+
+ delete pContent;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if(aChangedBitmap.IsEmpty())
+ {
+ return BitmapEx();
+ }
+ else
+ {
+ if(rSource.IsTransparent())
+ {
+ if(rSource.IsAlpha())
+ {
+ return BitmapEx(aChangedBitmap, rSource.GetAlpha());
+ }
+ else
+ {
+ return BitmapEx(aChangedBitmap, rSource.GetMask());
+ }
+ }
+ else
+ {
+ return BitmapEx(aChangedBitmap);
+ }
+ }
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbitmaptransform.hxx b/drawinglayer/source/processor2d/vclhelperbitmaptransform.hxx
new file mode 100644
index 000000000000..5fa0e66eea2f
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbitmaptransform.hxx
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbitmaptransform.hxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPTRANSFORM_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPTRANSFORM_HXX
+
+#include <vcl/bitmapex.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+namespace basegfx {
+ class B2DHomMatrix;
+ class BColorModifierStack;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// support methods for vcl direct gradient renderering
+
+namespace drawinglayer
+{
+ BitmapEx impTransformBitmapEx(
+ const BitmapEx& rSource,
+ const Rectangle& rCroppedRectPixel,
+ const basegfx::B2DHomMatrix& rTransform);
+
+ BitmapEx impModifyBitmapEx(
+ const basegfx::BColorModifierStack& rBColorModifierStack,
+ const BitmapEx& rSource);
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBITMAPTRANSFORM_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
new file mode 100644
index 000000000000..9d63bd5c7df6
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -0,0 +1,190 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbufferdevice.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
+ *
+ * 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 <vclhelperbufferdevice.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <vcl/bitmapex.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <tools/stream.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// support for rendering Bitmap and BitmapEx contents
+
+namespace drawinglayer
+{
+ impBufferDevice::impBufferDevice(
+ OutputDevice& rOutDev,
+ const basegfx::B2DRange& rRange,
+ bool bAddOffsetToMapping)
+ : mrOutDev(rOutDev),
+ maContent(rOutDev),
+ mpMask(0L),
+ mpAlpha(0L)
+ {
+ basegfx::B2DRange aRangePixel(rRange);
+ aRangePixel.transform(rOutDev.GetViewTransformation());
+ const Rectangle aRectPixel(
+ (sal_Int32)floor(aRangePixel.getMinX()), (sal_Int32)floor(aRangePixel.getMinY()),
+ (sal_Int32)ceil(aRangePixel.getMaxX()), (sal_Int32)ceil(aRangePixel.getMaxY()));
+ const Point aEmptyPoint;
+ maDestPixel = Rectangle(aEmptyPoint, rOutDev.GetOutputSizePixel());
+ maDestPixel.Intersection(aRectPixel);
+
+ if(isVisible())
+ {
+ maContent.SetOutputSizePixel(maDestPixel.GetSize(), false);
+
+ // #i93485# assert when copying from window to VDev is used
+ OSL_ENSURE(rOutDev.GetOutDevType() != OUTDEV_WINDOW,
+ "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)");
+
+ const bool bWasEnabledSrc(rOutDev.IsMapModeEnabled());
+ rOutDev.EnableMapMode(false);
+ maContent.DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), rOutDev);
+ rOutDev.EnableMapMode(bWasEnabledSrc);
+
+ MapMode aNewMapMode(rOutDev.GetMapMode());
+
+ if(bAddOffsetToMapping)
+ {
+ const Point aLogicTopLeft(rOutDev.PixelToLogic(maDestPixel.TopLeft()));
+ aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y()));
+ }
+
+ maContent.SetMapMode(aNewMapMode);
+
+ // copy AA flag for new target
+ maContent.SetAntialiasing(mrOutDev.GetAntialiasing());
+ }
+ }
+
+ impBufferDevice::~impBufferDevice()
+ {
+ delete mpMask;
+ delete mpAlpha;
+ }
+
+ void impBufferDevice::paint(double fTrans)
+ {
+ const Point aEmptyPoint;
+ const Size aSizePixel(maContent.GetOutputSizePixel());
+ const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled());
+ static bool bDoSaveForVisualControl(false);
+
+ mrOutDev.EnableMapMode(false);
+ maContent.EnableMapMode(false);
+ Bitmap aContent(maContent.GetBitmap(aEmptyPoint, aSizePixel));
+
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew((const String&)String(ByteString( "c:\\content.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
+ aNew << aContent;
+ }
+
+ if(mpAlpha)
+ {
+ mpAlpha->EnableMapMode(false);
+ const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
+
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew((const String&)String(ByteString( "c:\\alpha.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
+ aNew << aAlphaMask.GetBitmap();
+ }
+
+ mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
+ }
+ else if(mpMask)
+ {
+ mpMask->EnableMapMode(false);
+ const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel));
+
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew((const String&)String(ByteString( "c:\\mask.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
+ aNew << aMask;
+ }
+
+ mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask));
+ }
+ else if(0.0 != fTrans)
+ {
+ sal_uInt8 nMaskValue((sal_uInt8)basegfx::fround(fTrans * 255.0));
+ const AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
+ mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
+ }
+ else
+ {
+ mrOutDev.DrawBitmap(maDestPixel.TopLeft(), aContent);
+ }
+
+ mrOutDev.EnableMapMode(bWasEnabledDst);
+ }
+
+ VirtualDevice& impBufferDevice::getMask()
+ {
+ if(!mpMask)
+ {
+ mpMask = new VirtualDevice(mrOutDev, 1);
+ mpMask->SetOutputSizePixel(maDestPixel.GetSize(), true);
+ mpMask->SetMapMode(maContent.GetMapMode());
+
+ // do NOT copy AA flag for mask!
+ }
+
+ return *mpMask;
+ }
+
+ VirtualDevice& impBufferDevice::getAlpha()
+ {
+ if(!mpAlpha)
+ {
+ mpAlpha = new VirtualDevice();
+ mpAlpha->SetOutputSizePixel(maDestPixel.GetSize(), true);
+ mpAlpha->SetMapMode(maContent.GetMapMode());
+
+ // copy AA flag for new target; masking needs to be smooth
+ mpAlpha->SetAntialiasing(maContent.GetAntialiasing());
+ }
+
+ return *mpAlpha;
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
new file mode 100644
index 000000000000..f987585249ad
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelperbufferdevice.hxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBUFFERDEVICE_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBUFFERDEVICE_HXX
+
+#include <vcl/virdev.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+namespace basegfx { class B2DRange; }
+
+//////////////////////////////////////////////////////////////////////////////
+// support methods for vcl direct gradient renderering
+
+namespace drawinglayer
+{
+ class impBufferDevice
+ {
+ OutputDevice& mrOutDev;
+ VirtualDevice maContent;
+ VirtualDevice* mpMask;
+ VirtualDevice* mpAlpha;
+ Rectangle maDestPixel;
+
+ public:
+ impBufferDevice(
+ OutputDevice& rOutDev,
+ const basegfx::B2DRange& rRange,
+ bool bAddOffsetToMapping);
+ ~impBufferDevice();
+
+ void paint(double fTrans = 0.0);
+ bool isVisible() const { return !maDestPixel.IsEmpty(); }
+ VirtualDevice& getContent() { return maContent; }
+ VirtualDevice& getMask();
+ VirtualDevice& getAlpha();
+ };
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERBUFFERDEVICE_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelpergradient.cxx b/drawinglayer/source/processor2d/vclhelpergradient.cxx
new file mode 100644
index 000000000000..25d7513006fa
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelpergradient.cxx
@@ -0,0 +1,297 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelpergradient.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
+ *
+ * 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 <vclhelpergradient.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <vcl/outdev.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/texture/texture.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// support methods for vcl direct gradient renderering
+
+namespace drawinglayer
+{
+ namespace
+ {
+ sal_uInt32 impCalcGradientSteps(OutputDevice& rOutDev, sal_uInt32 nSteps, const basegfx::B2DRange& rRange, sal_uInt32 nMaxDist)
+ {
+ if(nSteps == 0L)
+ {
+ const Size aSize(rOutDev.LogicToPixel(Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight()))));
+ nSteps = (aSize.getWidth() + aSize.getHeight()) >> 3L;
+ }
+
+ if(nSteps < 2L)
+ {
+ nSteps = 2L;
+ }
+
+ if(nSteps > nMaxDist)
+ {
+ nSteps = nMaxDist;
+ }
+
+ return nSteps;
+ }
+
+ void impDrawGradientToOutDevSimple(
+ OutputDevice& rOutDev,
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< basegfx::BColor >& rColors,
+ const basegfx::B2DPolygon& rUnitPolygon)
+ {
+ rOutDev.SetLineColor();
+
+ for(sal_uInt32 a(0L); a < rColors.size(); a++)
+ {
+ // set correct color
+ const basegfx::BColor aFillColor(rColors[a]);
+ rOutDev.SetFillColor(Color(aFillColor));
+
+ if(a)
+ {
+ if(a - 1L < static_cast< sal_uInt32 >(rMatrices.size()))
+ {
+ basegfx::B2DPolygon aNewPoly(rUnitPolygon);
+ aNewPoly.transform(rMatrices[a - 1L]);
+ rOutDev.DrawPolygon(aNewPoly);
+ }
+ }
+ else
+ {
+ rOutDev.DrawPolyPolygon(rTargetForm);
+ }
+ }
+ }
+
+ void impDrawGradientToOutDevComplex(
+ OutputDevice& rOutDev,
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
+ const ::std::vector< basegfx::BColor >& rColors,
+ const basegfx::B2DPolygon& rUnitPolygon)
+ {
+ PolyPolygon aVclTargetForm(rTargetForm);
+ ::std::vector< Polygon > aVclPolygons;
+ sal_uInt32 a;
+
+ // remember and set to XOR
+ rOutDev.SetLineColor();
+ rOutDev.Push(PUSH_RASTEROP);
+ rOutDev.SetRasterOp(ROP_XOR);
+
+ // draw gradient PolyPolygons
+ for(a = 0L; a < rMatrices.size(); a++)
+ {
+ // create polygon and remember
+ basegfx::B2DPolygon aNewPoly(rUnitPolygon);
+ aNewPoly.transform(rMatrices[a]);
+ aVclPolygons.push_back(Polygon(aNewPoly));
+
+ // set correct color
+ if(rColors.size() > a)
+ {
+ const basegfx::BColor aFillColor(rColors[a]);
+ rOutDev.SetFillColor(Color(aFillColor));
+ }
+
+ // create vcl PolyPolygon and draw it
+ if(a)
+ {
+ PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
+ aVclPolyPoly.Insert(aVclPolygons[a]);
+ rOutDev.DrawPolyPolygon(aVclPolyPoly);
+ }
+ else
+ {
+ PolyPolygon aVclPolyPoly(aVclTargetForm);
+ aVclPolyPoly.Insert(aVclPolygons[0L]);
+ rOutDev.DrawPolyPolygon(aVclPolyPoly);
+ }
+ }
+
+ // draw last poly in last color
+ if(rColors.size())
+ {
+ const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
+ rOutDev.SetFillColor(Color(aFillColor));
+ rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
+ }
+
+ // draw object form in black and go back to XOR
+ rOutDev.SetFillColor(COL_BLACK);
+ rOutDev.SetRasterOp(ROP_0);
+ rOutDev.DrawPolyPolygon(aVclTargetForm);
+ rOutDev.SetRasterOp(ROP_XOR);
+
+ // draw gradient PolyPolygons again
+ for(a = 0L; a < rMatrices.size(); a++)
+ {
+ // set correct color
+ if(rColors.size() > a)
+ {
+ const basegfx::BColor aFillColor(rColors[a]);
+ rOutDev.SetFillColor(Color(aFillColor));
+ }
+
+ // create vcl PolyPolygon and draw it
+ if(a)
+ {
+ PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
+ aVclPolyPoly.Insert(aVclPolygons[a]);
+ rOutDev.DrawPolyPolygon(aVclPolyPoly);
+ }
+ else
+ {
+ PolyPolygon aVclPolyPoly(aVclTargetForm);
+ aVclPolyPoly.Insert(aVclPolygons[0L]);
+ rOutDev.DrawPolyPolygon(aVclPolyPoly);
+ }
+ }
+
+ // draw last poly in last color
+ if(rColors.size())
+ {
+ const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
+ rOutDev.SetFillColor(Color(aFillColor));
+ rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
+ }
+
+ // reset drawmode
+ rOutDev.Pop();
+ }
+ } // end of anonymous namespace
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+ void impDrawGradientToOutDev(
+ OutputDevice& rOutDev,
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ attribute::GradientStyle eGradientStyle,
+ sal_uInt32 nSteps,
+ const basegfx::BColor& rStart,
+ const basegfx::BColor& rEnd,
+ double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple)
+ {
+ const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(rTargetForm));
+ ::std::vector< basegfx::B2DHomMatrix > aMatrices;
+ ::std::vector< basegfx::BColor > aColors;
+ basegfx::B2DPolygon aUnitPolygon;
+
+ if(attribute::GRADIENTSTYLE_RADIAL == eGradientStyle || attribute::GRADIENTSTYLE_ELLIPTICAL == eGradientStyle)
+ {
+ 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
+ nSteps = impCalcGradientSteps(rOutDev, nSteps, aOutlineRange, sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5));
+
+ // create geometries
+ switch(eGradientStyle)
+ {
+ case attribute::GRADIENTSTYLE_LINEAR:
+ {
+ texture::GeoTexSvxGradientLinear aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_AXIAL:
+ {
+ texture::GeoTexSvxGradientAxial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RADIAL:
+ {
+ texture::GeoTexSvxGradientRadial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetY);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ texture::GeoTexSvxGradientElliptical aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_SQUARE:
+ {
+ texture::GeoTexSvxGradientSquare aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RECT:
+ {
+ texture::GeoTexSvxGradientRect aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
+ aGradient.appendTransformations(aMatrices);
+ aGradient.appendColors(aColors);
+ break;
+ }
+ }
+
+ // paint them with mask using the XOR method
+ if(aMatrices.size())
+ {
+ if(bSimple)
+ {
+ impDrawGradientToOutDevSimple(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ else
+ {
+ impDrawGradientToOutDevComplex(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
+ }
+ }
+ }
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclhelpergradient.hxx b/drawinglayer/source/processor2d/vclhelpergradient.hxx
new file mode 100644
index 000000000000..e1671dbb87b2
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclhelpergradient.hxx
@@ -0,0 +1,69 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclhelpergradient.hxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
+#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
+
+#include <drawinglayer/attribute/fillattribute.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// predefines
+
+class OutputDevice;
+namespace basegfx {
+ class B2DPolyPolygon;
+ class BColor;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// support methods for vcl direct gradient renderering
+
+namespace drawinglayer
+{
+ void impDrawGradientToOutDev(
+ OutputDevice& rOutDev,
+ const basegfx::B2DPolyPolygon& rTargetForm,
+ attribute::GradientStyle eGradientStyle,
+ sal_uInt32 nSteps,
+ const basegfx::BColor& rStart,
+ const basegfx::BColor& rEnd,
+ double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple);
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLHELPERGRADIENT_HXX
+
+// eof
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
new file mode 100644
index 000000000000..d1190c2d9179
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -0,0 +1,1769 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclmetafileprocessor2d.cxx,v $
+ *
+ * $Revision: 1.25 $
+ *
+ * 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/processor2d/vclmetafileprocessor2d.hxx>
+#include <tools/gen.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/gradient.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
+#include <tools/stream.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <vcl/graphictools.hxx>
+#include <vcl/metaact.hxx>
+#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <comphelper/processfactory.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
+#include <helperchartrenderer.hxx>
+#include <drawinglayer/primitive2d/hittestprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// for PDFExtOutDevData Graphic support
+
+#include <vcl/graph.hxx>
+#include <vcl/svapp.hxx>
+#include <toolkit/helper/formpdfexport.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// for Control printing
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+//////////////////////////////////////////////////////////////////////////////
+// for current chart PrettyPrinting support
+
+#include <drawinglayer/primitive2d/chartprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// for StructureTagPrimitive support in sd's unomodel.cxx
+
+#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
+ const primitive2d::Primitive2DSequence& rContent,
+ GDIMetaFile& o_rContentMetafile)
+ {
+ // Prepare VDev, MetaFile and connections
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ GDIMetaFile* pLastMetafile = mpMetaFile;
+ basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
+
+ // transform primitive range with current transformation (e.g shadow offset)
+ aPrimitiveRange.transform(maCurrentTransformation);
+
+ const Rectangle aPrimitiveRectangle(
+ basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
+ basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
+ VirtualDevice aContentVDev;
+ MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
+
+ mpOutputDevice = &aContentVDev;
+ mpMetaFile = &o_rContentMetafile;
+ aContentVDev.EnableOutput(false);
+ aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode());
+ o_rContentMetafile.Record(&aContentVDev);
+ aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor());
+ aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor());
+ aContentVDev.SetFont(pLastOutputDevice->GetFont());
+ aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode());
+ aContentVDev.SetSettings(pLastOutputDevice->GetSettings());
+ aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint());
+
+ // dump to MetaFile
+ process(rContent);
+
+ // cleanups
+ o_rContentMetafile.Stop();
+ o_rContentMetafile.WindStart();
+ aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
+ o_rContentMetafile.SetPrefMapMode(aNewMapMode);
+ o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
+ mpOutputDevice = pLastOutputDevice;
+ mpMetaFile = pLastMetafile;
+
+ return aPrimitiveRectangle;
+ }
+
+ void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
+ Gradient& o_rVCLGradient,
+ const attribute::FillGradientAttribute& rFiGrAtt,
+ bool bIsTransparenceGradient)
+ {
+ if(bIsTransparenceGradient)
+ {
+ // it's about alpha channel intensities (black/white), do not use color modifier
+ o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
+ o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
+ }
+ else
+ {
+ // use color modifier to influence start/end color of gradient
+ o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
+ o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
+ }
+
+ o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
+ o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
+ o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
+ o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
+ o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
+
+ // defaults for intensity; those were computed into the start/end colors already
+ o_rVCLGradient.SetStartIntensity(100);
+ o_rVCLGradient.SetEndIntensity(100);
+
+ switch(rFiGrAtt.getStyle())
+ {
+ default : // attribute::GRADIENTSTYLE_LINEAR :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_LINEAR);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_AXIAL :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_AXIAL);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RADIAL :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_RADIAL);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_ELLIPTICAL :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_ELLIPTICAL);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_SQUARE :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_SQUARE);
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RECT :
+ {
+ o_rVCLGradient.SetStyle(GRADIENT_RECT);
+ break;
+ }
+ }
+ }
+
+ void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
+ {
+ if(pSvtGraphicFill && !mnSvtGraphicFillCount)
+ {
+ SvMemoryStream aMemStm;
+
+ aMemStm << *pSvtGraphicFill;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const BYTE* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
+ mnSvtGraphicFillCount++;
+ }
+ }
+
+ void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
+ {
+ if(pSvtGraphicFill && mnSvtGraphicFillCount)
+ {
+ mnSvtGraphicFillCount--;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
+ delete pSvtGraphicFill;
+ }
+ }
+
+ SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
+ const basegfx::B2DPolygon& rB2DPolygon,
+ const basegfx::BColor* pColor,
+ const attribute::LineAttribute* pLineAttribute,
+ const attribute::StrokeAttribute* pStrokeAttribute,
+ const attribute::LineStartEndAttribute* pStart,
+ const attribute::LineStartEndAttribute* pEnd)
+ {
+ SvtGraphicStroke* pRetval = 0;
+
+ if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
+ {
+ basegfx::BColor aStrokeColor;
+ basegfx::B2DPolyPolygon aStartArrow;
+ basegfx::B2DPolyPolygon aEndArrow;
+
+ if(pColor)
+ {
+ aStrokeColor = *pColor;
+ }
+ else if(pLineAttribute)
+ {
+ aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
+ }
+
+ // It IS needed to record the stroke color at all in the metafile,
+ // SvtGraphicStroke has NO entry for stroke color(!)
+ mpOutputDevice->SetLineColor(Color(aStrokeColor));
+
+ if(!rB2DPolygon.isClosed())
+ {
+ double fPolyLength(0.0);
+
+ if(pStart && pStart->isActive())
+ {
+ fPolyLength = basegfx::tools::getLength(rB2DPolygon);
+
+ aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
+ rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
+ fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0);
+ }
+
+ if(pEnd && pEnd->isActive())
+ {
+ if(basegfx::fTools::equalZero(fPolyLength))
+ {
+ fPolyLength = basegfx::tools::getLength(rB2DPolygon);
+ }
+
+ aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
+ rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
+ fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0);
+ }
+ }
+
+ SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
+ double fLineWidth(0.0);
+ double fMiterLength(0.0);
+ SvtGraphicStroke::DashArray aDashArray;
+
+ if(pLineAttribute)
+ {
+ // pre-fill fLineWidth
+ fLineWidth = pLineAttribute->getWidth();
+
+ // pre-fill fMiterLength
+ fMiterLength = fLineWidth;
+
+ // get Join
+ switch(pLineAttribute->getLineJoin())
+ {
+ default : // basegfx::B2DLINEJOIN_NONE :
+ {
+ eJoin = SvtGraphicStroke::joinNone;
+ break;
+ }
+ case basegfx::B2DLINEJOIN_BEVEL :
+ {
+ eJoin = SvtGraphicStroke::joinBevel;
+ break;
+ }
+ case basegfx::B2DLINEJOIN_MIDDLE :
+ case basegfx::B2DLINEJOIN_MITER :
+ {
+ eJoin = SvtGraphicStroke::joinMiter;
+ // ATM 15 degrees is assumed
+ fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0));
+ break;
+ }
+ case basegfx::B2DLINEJOIN_ROUND :
+ {
+ eJoin = SvtGraphicStroke::joinRound;
+ break;
+ }
+ }
+ }
+
+ if(pStrokeAttribute)
+ {
+ // copy dash array
+ aDashArray = pStrokeAttribute->getDotDashArray();
+ }
+
+ // #i101734# apply current object transformation to created geometry.
+ // This is a partial fix. When a object transformation is used which
+ // e.g. contains a scaleX != scaleY, an unproportional scaling would
+ // have to be applied to the evtl. existing fat line. The current
+ // concept of PDF export and SvtGraphicStroke usage does simply not
+ // allow handling such definitions. The only clean way would be to
+ // add the transformation to SvtGraphicStroke and to handle it there
+ basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
+
+ aB2DPolygon.transform(maCurrentTransformation);
+ aStartArrow.transform(maCurrentTransformation);
+ aEndArrow.transform(maCurrentTransformation);
+
+ pRetval = new SvtGraphicStroke(
+ Polygon(aB2DPolygon),
+ PolyPolygon(aStartArrow),
+ PolyPolygon(aEndArrow),
+ mfCurrentUnifiedTransparence,
+ fLineWidth,
+ SvtGraphicStroke::capButt,
+ eJoin,
+ fMiterLength,
+ aDashArray);
+ }
+
+ return pRetval;
+ }
+
+ void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
+ {
+ if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
+ {
+ SvMemoryStream aMemStm;
+
+ aMemStm << *pSvtGraphicStroke;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const BYTE* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
+ mnSvtGraphicStrokeCount++;
+ }
+ }
+
+ void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
+ {
+ if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
+ {
+ mnSvtGraphicStrokeCount--;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
+ delete pSvtGraphicStroke;
+ }
+ }
+
+ // init static break iterator
+ uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
+
+ VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
+ : VclProcessor2D(rViewInformation, rOutDev),
+ mpMetaFile(rOutDev.GetConnectMetaFile()),
+ mnSvtGraphicFillCount(0),
+ mnSvtGraphicStrokeCount(0),
+ mfCurrentUnifiedTransparence(0.0),
+ mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData()))
+ {
+ OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
+ // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
+ // but only to ObjectTransformation. Do not change MapMode of destination.
+ maCurrentTransformation = rViewInformation.getObjectTransformation();
+ }
+
+ VclMetafileProcessor2D::~VclMetafileProcessor2D()
+ {
+ // MapMode was not changed, no restore necessary
+ }
+
+ /***********************************************************************************************
+
+ Support of MetaCommentActions in the VclMetafileProcessor2D
+ Found MetaCommentActions and how they are supported:
+
+ XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
+
+ Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
+ It is used in various exporters/importers to have direct access to the gradient before it
+ is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
+ the Metafile to SdrObject import creates it's gradient objects.
+ Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
+ map it back to the corresponding tools PolyPolygon and the Gradient and just call
+ OutputDevice::DrawGradient which creates the necessary compatible actions.
+
+ XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
+
+ Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
+ inside GDIMetaFile::Rotate, nothing to take care of here.
+ The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
+ with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
+ XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
+ to the comment action. A closing end token is created in the destructor.
+ Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
+ SdrRectObj.
+ The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
+ of filled objects, even simple colored polygons. It is added as extra information; the
+ Metafile actions between the two tokens are interpreted as output generated from those
+ fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
+ actions.
+ Even for XFillTransparenceItem it is used, thus it may need to be supported in
+ UnifiedAlphaPrimitive2D, too, when interpreted as normally filled PolyPolygon.
+ Implemented for:
+ PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
+ and for PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D when detected unified alpha
+
+ XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
+
+ Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
+ is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
+ contained path accordingly.
+ The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
+ only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
+ would hinder to make use of PolyPolygon strokes. I will need to add support at:
+ PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
+ PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
+ PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
+ This can be done hierarchical, too.
+ Okay, base implementation done based on those three primitives.
+
+ FIELD_SEQ_BEGIN, FIELD_SEQ_END
+
+ Used from slideshow for URLs, created from diverse SvxField implementations inside
+ createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
+ inside ImpEditEngine::Paint.
+ Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps
+ text primitives (but is not limited to that). It contains the field type if special actions for the
+ support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
+ needed, it may be supported there.
+ FIELD_SEQ_BEGIN;PageField
+ FIELD_SEQ_END
+ Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
+
+ XTEXT
+
+ XTEXT_EOC(i) end of character
+ XTEXT_EOW(i) end of word
+ XTEXT_EOS(i) end of sentence
+
+ this three are with index and are created with the help of a i18n::XBreakIterator in
+ ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
+ data structure for holding those TEXT infos.
+ Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
+ primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
+ that this creations do not need to be done for all paints all the time. This would be
+ expensive since the BreakIterator and it's usage is expensive and for each paint also the
+ whole character stops would need to be created.
+ Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
+
+ XTEXT_EOL() end of line
+ XTEXT_EOP() end of paragraph
+
+ First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
+ i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
+ namely:
+ - TextHierarchyLinePrimitive2D: Encapsulates single line
+ - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
+ - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
+ Those are now supported in hierarchy. This means the MetaFile renderer will support them
+ by using them, reculrively using their content and adding MetaFile comments as needed.
+ This also means that when another text layouter will be used it will be necessary to
+ create/support the same HierarchyPrimitives to support users.
+ To transport the information using this hierarchy is best suited to all future needs;
+ the slideshow will be able to profit from it directly when using primitives; all other
+ renderers not interested in the text structure will just ignore the encapsulations.
+
+ XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
+ Supported now by the TextHierarchyBlockPrimitive2D.
+
+ EPSReplacementGraphic:
+ Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
+ hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
+ used to export the original again (if exists).
+ Not necessary to support with MetaFuleRenderer.
+
+ XTEXT_SCROLLRECT, XTEXT_PAINTRECT
+ Currently used to get extra MetaFile infos using GraphicExporter which again uses
+ SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
+ the rectangle data is added directly by the GraphicsExporter as comment. Does not need
+ to be adapted at once.
+ When adapting later, the only user - the diashow - should directly use the provided
+ Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
+
+ PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
+ VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
+ a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
+ was explicitely created for the printer already again to some default maximum
+ bitmap sizes.
+ Nothing to do here for the primitive renderer.
+
+ Support for vcl::PDFExtOutDevData:
+ PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
+ the OutDev. When set, some extra data is written there. Trying simple PDF export and
+ watching if i get those infos.
+ Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
+ the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
+ if i get a PDFExtOutDevData at the target output device.
+ Indeed, i get one. Checking what all may be done when that extra-device-info is there.
+
+ All in all i have to talk to SJ. I will need to emulate some of those actions, but
+ i need to discuss which ones.
+ In the future, all those infos would be taken from the primitive sequence anyways,
+ thus these extensions would potentially be temporary, too.
+ Discussed with SJ, added the necessary support and tested it. Details follow.
+
+ - In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
+ Added in primitive MetaFile renderer.
+ Checking URL: Indeed, current version exports it, but it is missing in primitive
+ CWS version. Adding support.
+ Okay, URLs work. Checked, Done.
+
+ - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
+ target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
+ This may be added in primitive MetaFile renderer.
+ Adding support...
+ OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
+ svxform. Have to talk to FS if this has to be like that. Especially since
+ ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
+ Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
+ that stuff to somewhere else, maybe tools or svtools ?!? We will see...
+ Moved to toolkit, so i have to link against it. I tried VCL first, but it did
+ not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name
+ may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
+ the lowest move,ment plave is toolkit.
+ Checked form control export, it works well. Done.
+
+ - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
+ generated. I will need to check what happens here with primitives.
+ To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
+ Added support, but feature is broken in main version, so i cannot test at all.
+ Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
+ SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
+ as intended, the original file is exported. Works, Done.
+
+
+
+
+ To be done:
+
+ - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
+
+
+
+ ****************************************************************************************************/
+
+ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ {
+ // directdraw of wrong spell primitive
+ // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
+ break;
+ }
+ case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
+ {
+ const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
+ bool bUsingPDFExtOutDevData(false);
+ basegfx::B2DVector aTranslate, aScale;
+ static bool bSuppressPDFExtOutDevDataSupport(false);
+
+ if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
+ {
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // goodies/source/graphic/grfmgr.cxx
+ const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
+
+ if(rGraphic.IsLink())
+ {
+ const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
+
+ if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
+ {
+ const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
+ {
+ bUsingPDFExtOutDevData = true;
+ mpPDFExtOutDevData->BeginGroup();
+ }
+ }
+ }
+ }
+
+ // process recursively and add MetaFile comment
+ process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D()));
+
+ if(bUsingPDFExtOutDevData)
+ {
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // goodies/source/graphic/grfmgr.cxx
+ const basegfx::B2DRange aCurrentRange(
+ aTranslate.getX(), aTranslate.getY(),
+ aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
+ const Rectangle aCurrentRect(
+ sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
+ sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
+ const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
+ Rectangle aCropRect;
+
+ if(rAttr.IsCropped())
+ {
+ // 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);
+ const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic(
+ rGraphicPrimitive.getGraphicObject().GetPrefSize(),
+ rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
+ const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
+ const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
+
+ if(!basegfx::fTools::equalZero(fDivX))
+ {
+ fFactorX = aScale.getX() / fDivX;
+ }
+
+ if(!basegfx::fTools::equalZero(fDivY))
+ {
+ fFactorY = aScale.getY() / fDivY;
+ }
+ }
+
+ // calculate crop range and rect
+ basegfx::B2DRange aCropRange;
+ aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
+ aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
+
+ aCropRect = Rectangle(
+ sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
+ sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
+ }
+
+ mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
+ rAttr.GetTransparency(),
+ aCurrentRect,
+ aCropRect);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+ {
+ const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
+ const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
+ bool bIsPrintableControl(false);
+
+ // find out if control is printable
+ if(rXControl.is())
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
+ ? xModelProperties->getPropertySetInfo()
+ : uno::Reference< beans::XPropertySetInfo >());
+ const ::rtl::OUString sPrintablePropertyName(RTL_CONSTASCII_USTRINGPARAM("Printable"));
+
+ if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
+ {
+ OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ OSL_ENSURE(false, "VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
+ }
+ }
+
+ // PDF export and printing only for printable controls
+ if(bIsPrintableControl)
+ {
+ const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
+ bool bDoProcessRecursively(true);
+
+ if(bPDFExport)
+ {
+ // PDF export. Emulate data handling from UnoControlPDFExportContact
+ // I have now moved describePDFControl to toolkit, thus i can implement the PDF
+ // form control support now as follows
+ ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl;
+ ::toolkitform::describePDFControl(rXControl, pPDFControl);
+
+ if(pPDFControl.get())
+ {
+ // still need to fill in the location (is a class Rectangle)
+ const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
+ const Rectangle aRectLogic(
+ (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()),
+ (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY()));
+ pPDFControl->Location = aRectLogic;
+
+ Size aFontSize(pPDFControl->TextFont.GetSize());
+ aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode());
+ pPDFControl->TextFont.SetSize(aFontSize);
+
+ mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
+ mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
+ mpPDFExtOutDevData->EndStructureElement();
+
+ // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
+ // do not process recursively
+ bDoProcessRecursively = false;
+ }
+ else
+ {
+ // PDF export did not work, try simple output.
+ // Fallback to printer output by not setting bDoProcessRecursively
+ // to false.
+ }
+ }
+
+ // #i93169# used flag the wrong way; true means that nothing was done yet
+ if(bDoProcessRecursively)
+ {
+ // printer output
+ try
+ {
+ // remember old graphics and create new
+ uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
+ const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
+
+ if(xNewGraphics.is())
+ {
+ // link graphics and view
+ xControlView->setGraphics(xNewGraphics);
+
+ // get position
+ const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
+
+ // draw it
+ xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
+ bDoProcessRecursively = false;
+
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_ENSURE(false, "VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
+ }
+ }
+
+ // process recursively if not done yet to export as decomposition (bitmap)
+ if(bDoProcessRecursively)
+ {
+ process(rControlPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
+ {
+ // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
+ // thus do the MetafileAction embedding stuff but just handle recursively.
+ const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
+ static const ByteString aCommentStringCommon("FIELD_SEQ_BEGIN");
+ static const ByteString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
+ static const ByteString aCommentStringEnd("FIELD_SEQ_END");
+
+ switch(rFieldPrimitive.getType())
+ {
+ default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
+ break;
+ }
+ case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
+ break;
+ }
+ case drawinglayer::primitive2d::FIELD_TYPE_URL :
+ {
+ const rtl::OUString& rURL = rFieldPrimitive.getString();
+ const String aOldString(rURL);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const BYTE* >(aOldString.GetBuffer()), 2 * aOldString.Len()));
+ break;
+ }
+ }
+
+ // process recursively
+ const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D());
+ process(rContent);
+
+ // for the end comment the type is not relevant yet, they are all the same. Just add.
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
+
+ if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
+ const Rectangle aRectLogic(
+ (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
+ (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
+ vcl::PDFExtOutDevBookmarkEntry aBookmark;
+ aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
+ aBookmark.aBookmark = rFieldPrimitive.getString();
+ std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
+ rBookmarks.push_back( aBookmark );
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
+ {
+ const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
+ static const ByteString aCommentString("XTEXT_EOL");
+
+ // process recursively and add MetaFile comment
+ process(rLinePrimitive.get2DDecomposition(getViewInformation2D()));
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
+ {
+ // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
+ // "XTEXT_EOC" is used, use here, too.
+ const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
+ static const ByteString aCommentString("XTEXT_EOC");
+
+ // process recursively and add MetaFile comment
+ process(rBulletPrimitive.get2DDecomposition(getViewInformation2D()));
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
+ {
+ const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
+ static const ByteString aCommentString("XTEXT_EOP");
+
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
+ }
+
+ // process recursively and add MetaFile comment
+ process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D()));
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->EndStructureElement();
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
+ {
+ const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
+ static const ByteString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
+ static const ByteString aCommentStringB("XTEXT_PAINTSHAPE_END");
+
+ // add MetaFile comment, process recursively and add MetaFile comment
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
+ process(rBlockPrimitive.get2DDecomposition(getViewInformation2D()));
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+ {
+ // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
+ const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
+ // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
+
+ // Adapt evtl. used special DrawMode
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ // directdraw of text simple portion; use default processing
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ // #i101169# if(pTextDecoratedCandidate)
+ {
+ // support for TEXT_ MetaFile actions only for decorated texts
+ if(!mxBreakIterator.is())
+ {
+ uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
+ mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), uno::UNO_QUERY);
+ }
+
+ if(mxBreakIterator.is())
+ {
+ const rtl::OUString& rTxt = rTextCandidate.getText();
+ const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
+
+ if(nTextLength)
+ {
+ const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale();
+ const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
+
+ sal_Int32 nDone;
+ sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
+ ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
+ sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
+ static const ByteString aCommentStringA("XTEXT_EOC");
+ static const ByteString aCommentStringB("XTEXT_EOW");
+ static const ByteString aCommentStringC("XTEXT_EOS");
+
+ for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
+ {
+ // create the entries for the respective break positions
+ if(i == nNextCellBreak)
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
+ nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
+ }
+ if(i == nNextWordBoundary.endPos)
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
+ nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
+ }
+ if(i == nNextSentenceBreak)
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
+ nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ // direct draw of hairline; use default processing
+ // also support SvtGraphicStroke MetaCommentAction
+ const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
+ const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
+ SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rHairlinePrimitive.getB2DPolygon(), &aLineColor, 0, 0, 0, 0);
+
+ impStartSvtGraphicStroke(pSvtGraphicStroke);
+ RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
+ {
+ // support SvtGraphicStroke MetaCommentAction
+ const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
+ SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rStrokePrimitive.getB2DPolygon(), 0, &rStrokePrimitive.getLineAttribute(),
+ &rStrokePrimitive.getStrokeAttribute(), 0, 0);
+
+ // Adapt OutDev's DrawMode if special ones were used
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptLineToFillDrawMode();
+
+ impStartSvtGraphicStroke(pSvtGraphicStroke);
+
+ // #i101491#
+ // Change default of fat line generation for MetaFiles: Create MetaPolyLineAction
+ // instead of decomposing all geometries when the polygon has more than given amount of
+ // points; else the decomposition will get too expensive quiclky. OTOH
+ // the decomposition provides the better quality e.g. taking edge roundings
+ // into account which will NOT be taken into account with LineInfo-based actions
+ const sal_uInt32 nSubPolygonCount(rStrokePrimitive.getB2DPolygon().count());
+ bool bDone(0 == nSubPolygonCount);
+
+ if(!bDone && nSubPolygonCount > 1000)
+ {
+ // create MetaPolyLineActions, but without LINE_DASH
+ const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
+
+ if(basegfx::fTools::more(rLine.getWidth(), 0.0))
+ {
+ const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
+ basegfx::B2DPolyPolygon aHairLinePolyPolygon;
+
+ if(0.0 == rStroke.getFullDotDashLen())
+ {
+ aHairLinePolyPolygon.append(rStrokePrimitive.getB2DPolygon());
+ }
+ else
+ {
+ basegfx::tools::applyLineDashing(
+ rStrokePrimitive.getB2DPolygon(), rStroke.getDotDashArray(),
+ &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen());
+ }
+
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
+ mpOutputDevice->SetLineColor(Color(aHairlineColor));
+ mpOutputDevice->SetFillColor();
+
+ aHairLinePolyPolygon.transform(maCurrentTransformation);
+
+ const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(rLine.getWidth()));
+
+ for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
+
+ if(aCandidate.count() > 1)
+ {
+ const Polygon aToolsPolygon(aCandidate);
+
+ mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
+ }
+ }
+
+ bDone = true;
+ }
+ }
+
+ if(!bDone)
+ {
+ // use decomposition (creates line geometry as filled polygon
+ // geometry)
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
+ {
+ // support SvtGraphicStroke MetaCommentAction
+ const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
+ SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rStrokeArrowPrimitive.getB2DPolygon(), 0, &rStrokeArrowPrimitive.getLineAttribute(),
+ &rStrokeArrowPrimitive.getStrokeAttribute(), &rStrokeArrowPrimitive.getStart(), &rStrokeArrowPrimitive.getEnd());
+
+ impStartSvtGraphicStroke(pSvtGraphicStroke);
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // direct draw of transformed BitmapEx primitive; use default processing
+ RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
+ {
+ // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ if(!mnSvtGraphicFillCount)
+ {
+ const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ if(aLocalPolyPolygon.count())
+ {
+ // calculate transformation. Get real object size, all values in FillBitmapAttribute
+ // are relative to the unified object
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap();
+ const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aLocalPolyPolygon));
+ const basegfx::B2DVector aOutlineSize(aOutlineRange.getRange());
+
+ // get absolute values
+ const basegfx::B2DVector aFillBitmapSize(rFillBitmapAttribute.getSize() * aOutlineSize);
+ const basegfx::B2DPoint aFillBitmapTopLeft(rFillBitmapAttribute.getTopLeft() * aOutlineSize);
+
+ // the scaling needs scale from pixel to logic coordinate system
+ const Bitmap& rBitmap = rFillBitmapAttribute.getBitmap();
+ Size aBmpSizePixel(rBitmap.GetSizePixel());
+
+ if(!aBmpSizePixel.Width())
+ {
+ aBmpSizePixel.Width() = 1;
+ }
+
+ if(!aBmpSizePixel.Height())
+ {
+ aBmpSizePixel.Height() = 1;
+ }
+
+ // setup transformation like in impgrfll
+ SvtGraphicFill::Transform aTransform;
+
+ // scale values are divided by bitmap pixel sizes
+ aTransform.matrix[0] = aFillBitmapSize.getX() / aBmpSizePixel.Width();
+ aTransform.matrix[4] = aFillBitmapSize.getY() / aBmpSizePixel.Height();
+
+ // translates are absolute
+ aTransform.matrix[2] = aFillBitmapTopLeft.getX();
+ aTransform.matrix[5] = aFillBitmapTopLeft.getY();
+
+ // setup fill graphic like in impgrfll
+ Graphic aFillGraphic = Graphic(rBitmap);
+ aFillGraphic.SetPrefMapMode(MapMode(MAP_PIXEL));
+ aFillGraphic.SetPrefSize(aBmpSizePixel);
+
+ pSvtGraphicFill = new SvtGraphicFill(
+ PolyPolygon(aLocalPolyPolygon),
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillTexture,
+ aTransform,
+ rFillBitmapAttribute.getTiling(),
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ aFillGraphic);
+ }
+ }
+
+ // Do use decomposition; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ impEndSvtGraphicFill(pSvtGraphicFill);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
+ {
+ // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ if(!mnSvtGraphicFillCount)
+ {
+ const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ if(aLocalPolyPolygon.count())
+ {
+ // re-create a VCL hatch as base data
+ const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
+ SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
+
+ switch(rFillHatchAttribute.getStyle())
+ {
+ default: // attribute::HATCHSTYLE_SINGLE :
+ {
+ eHatch = SvtGraphicFill::hatchSingle;
+ break;
+ }
+ case attribute::HATCHSTYLE_DOUBLE :
+ {
+ eHatch = SvtGraphicFill::hatchDouble;
+ break;
+ }
+ case attribute::HATCHSTYLE_TRIPLE :
+ {
+ eHatch = SvtGraphicFill::hatchTriple;
+ break;
+ }
+ }
+
+ SvtGraphicFill::Transform aTransform;
+
+ // scale
+ aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
+ aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
+
+ // rotate (was never correct in impgrfll anyways, use correct angle now)
+ aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
+ aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
+ aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
+ aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
+
+ pSvtGraphicFill = new SvtGraphicFill(
+ PolyPolygon(aLocalPolyPolygon),
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillHatch,
+ aTransform,
+ false,
+ eHatch,
+ Color(rFillHatchAttribute.getColor()),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic());
+ }
+ }
+
+ // Do use decomposition; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ impEndSvtGraphicFill(pSvtGraphicFill);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
+ {
+ const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
+
+ // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
+ // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
+ // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
+ Gradient aVCLGradient;
+ impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ // #i82145# ATM VCL printing of gradients using curved shapes does not work,
+ // i submitted the bug with the given ID to THB. When that task is fixed it is
+ // necessary to again remove this subdivision since it decreases possible
+ // printing quality (not even resolution-dependent for now). THB will tell
+ // me when that task is fixed in the master
+ const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
+
+ // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+ {
+ // setup gradient stuff like in like in impgrfll
+ SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
+
+ switch(aVCLGradient.GetStyle())
+ {
+ default : // GRADIENT_LINEAR:
+ case GRADIENT_AXIAL:
+ eGrad = SvtGraphicFill::gradientLinear;
+ break;
+ case GRADIENT_RADIAL:
+ case GRADIENT_ELLIPTICAL:
+ eGrad = SvtGraphicFill::gradientRadial;
+ break;
+ case GRADIENT_SQUARE:
+ case GRADIENT_RECT:
+ eGrad = SvtGraphicFill::gradientRectangular;
+ break;
+ }
+
+ pSvtGraphicFill = new SvtGraphicFill(
+ aToolsPolyPolygon,
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillGradient,
+ SvtGraphicFill::Transform(),
+ false,
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ eGrad,
+ aVCLGradient.GetStartColor(),
+ aVCLGradient.GetEndColor(),
+ aVCLGradient.GetSteps(),
+ Graphic());
+ }
+
+ // call VCL directly; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
+ impEndSvtGraphicFill(pSvtGraphicFill);
+
+ // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above
+ // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+ {
+ // setup simple color fill stuff like in impgrfll
+ pSvtGraphicFill = new SvtGraphicFill(
+ PolyPolygon(aLocalPolyPolygon),
+ Color(aPolygonColor),
+ 0.0,
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillSolid,
+ SvtGraphicFill::Transform(),
+ false,
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic());
+ }
+
+ // set line and fill color
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ // call VCL directly; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ impEndSvtGraphicFill(pSvtGraphicFill);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ {
+ // direct draw of MetaFile, use default pocessing
+ RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // mask group. Special handling for MetaFiles.
+ const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
+
+ if(rMaskCandidate.getChildren().hasElements())
+ {
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+ if(aMask.count())
+ {
+ // prepare new mask polygon and rescue current one
+ aMask.transform(maCurrentTransformation);
+ const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
+
+ if(maClipPolyPolygon.count())
+ {
+ // there is already a clip polygon set; build clipped union of
+ // current mask polygon and new one
+ maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
+ }
+ else
+ {
+ // use mask directly
+ maClipPolyPolygon = aMask;
+ }
+
+ if(maClipPolyPolygon.count())
+ {
+ // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
+ // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
+ // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
+ mpOutputDevice->Push(PUSH_CLIPREGION);
+ //mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon))));
+ mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
+ }
+
+ // recursively paint content
+ process(rMaskCandidate.getChildren());
+
+ if(maClipPolyPolygon.count())
+ {
+ // restore VCL clip region
+ mpOutputDevice->Pop();
+ }
+
+ // restore to rescued clip polygon
+ maClipPolyPolygon = aLastClipPolyPolygon;
+ }
+ else
+ {
+ // no mask, no clipping. recursively paint content
+ process(rMaskCandidate.getChildren());
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ // modified color group. Force output to unified color. Use default pocessing.
+ RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D :
+ {
+ // for metafile: Need to examine what the pure vcl version is doing here actually
+ // - uses DrawTransparent with metafile for content and a gradient
+ // - uses DrawTransparent for single PolyPoylgons directly. Can be detected by
+ // checking the content for single PolyPolygonColorPrimitive2D
+ const primitive2d::UnifiedAlphaPrimitive2D& rUniAlphaCandidate = static_cast< const primitive2d::UnifiedAlphaPrimitive2D& >(rCandidate);
+ const primitive2d::Primitive2DSequence rContent = rUniAlphaCandidate.getChildren();
+
+ if(rContent.hasElements())
+ {
+ // try to identify a single PolyPolygonColorPrimitive2D in the
+ // content part of the alpha primitive
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0;
+ static bool bForceToMetafile(false);
+
+ if(!bForceToMetafile && 1 == rContent.getLength())
+ {
+ const primitive2d::Primitive2DReference xReference(rContent[0]);
+ pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
+ }
+
+ // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
+ // PolyPolygonBitmapPrimitive2D are derived from PolyPolygonColorPrimitive2D.
+ // Check also for correct ID to exclude derived implementations
+ if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitiveID())
+ {
+ // single transparent PolyPolygon identified, use directly
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+ {
+ // setup simple color with transparence fill stuff like in impgrfll
+ pSvtGraphicFill = new SvtGraphicFill(
+ PolyPolygon(aLocalPolyPolygon),
+ Color(aPolygonColor),
+ rUniAlphaCandidate.getAlpha(),
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillSolid,
+ SvtGraphicFill::Transform(),
+ false,
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic());
+ }
+
+ // set line and fill color
+ const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniAlphaCandidate.getAlpha() * 100.0));
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ // call VCL directly; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ mpOutputDevice->DrawTransparent(
+ PolyPolygon(aLocalPolyPolygon),
+ nTransPercentVcl);
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
+ else
+ {
+ // svae old mfCurrentUnifiedTransparence and set new one
+ // so that contained SvtGraphicStroke may use the current one
+ const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
+ // #i105377# paint the content metafile opaque as the transparency gets
+ // split of into the gradient below
+ // mfCurrentUnifiedTransparence = rUniAlphaCandidate.getAlpha();
+ mfCurrentUnifiedTransparence = 0;
+
+ // various content, create content-metafile
+ GDIMetaFile aContentMetafile;
+ const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
+
+ // restore mfCurrentUnifiedTransparence; it may have been used
+ // while processing the sub-content in impDumpToMetaFile
+ mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
+
+ // create uniform VCL gradient for uniform transparency
+ Gradient aVCLGradient;
+ const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniAlphaCandidate.getAlpha() * 255.0));
+ const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
+
+ aVCLGradient.SetStyle(GRADIENT_LINEAR);
+ aVCLGradient.SetStartColor(aTransColor);
+ aVCLGradient.SetEndColor(aTransColor);
+ aVCLGradient.SetAngle(0);
+ aVCLGradient.SetBorder(0);
+ aVCLGradient.SetOfsX(0);
+ aVCLGradient.SetOfsY(0);
+ aVCLGradient.SetStartIntensity(100);
+ aVCLGradient.SetEndIntensity(100);
+ aVCLGradient.SetSteps(2);
+
+ // render it to VCL
+ mpOutputDevice->DrawTransparent(
+ aContentMetafile, aPrimitiveRectangle.TopLeft(),
+ aPrimitiveRectangle.GetSize(), aVCLGradient);
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D :
+ {
+ // for metafile: Need to examine what the pure vcl version is doing here actually
+ // - uses DrawTransparent with metafile for content and a gradient
+ // i can detect this here with checking the gradient part for a single
+ // FillGradientPrimitive2D and reconstruct the gradient.
+ // If that detection goes wrong, i have to create an alpha-blended bitmap. Eventually
+ // do that in stripes, else RenderAlphaPrimitive2D may just be used
+ const primitive2d::AlphaPrimitive2D& rAlphaCandidate = static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate);
+ const primitive2d::Primitive2DSequence rContent = rAlphaCandidate.getChildren();
+ const primitive2d::Primitive2DSequence rAlpha = rAlphaCandidate.getAlpha();
+
+ if(rContent.hasElements() && rAlpha.hasElements())
+ {
+ // try to identify a single FillGradientPrimitive2D in the
+ // alpha part of the primitive
+ const primitive2d::FillGradientPrimitive2D* pFiGradient = 0;
+ static bool bForceToBigTransparentVDev(false);
+
+ if(!bForceToBigTransparentVDev && 1 == rAlpha.getLength())
+ {
+ const primitive2d::Primitive2DReference xReference(rAlpha[0]);
+ pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
+ }
+
+ // Check also for correct ID to exclude derived implementations
+ if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitiveID())
+ {
+ // various content, create content-metafile
+ GDIMetaFile aContentMetafile;
+ const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
+
+ // re-create a VCL-gradient from FillGradientPrimitive2D
+ Gradient aVCLGradient;
+ impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
+
+ // render it to VCL
+ mpOutputDevice->DrawTransparent(
+ aContentMetafile, aPrimitiveRectangle.TopLeft(),
+ aPrimitiveRectangle.GetSize(), aVCLGradient);
+ }
+ else
+ {
+ // sub-transparence group. Draw to VDev first.
+ // this may get refined to tiling when resolution is too big here
+
+ // need to avoid switching off MapMode stuff here; maybe need another
+ // tooling class, cannot just do the same as with the pixel renderer.
+ // Need to experiment...
+
+ // Okay, basic implementation finished and tested. The DPI stuff was hard
+ // and not easy to find out that it's needed.
+ // Since this will not yet happen normally (as long as noone constructs
+ // alpha primitives with non-trivial alpha content) i will for now not
+ // refine to tiling here.
+
+ basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
+ aViewRange.transform(maCurrentTransformation);
+ const Rectangle aRectLogic(
+ (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
+ (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
+ const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
+ const Size aSizePixel(aRectPixel.GetSize());
+ const Point aEmptyPoint;
+ VirtualDevice aBufferDevice;
+
+ if(aBufferDevice.SetOutputSizePixel(aSizePixel))
+ {
+ // create and set MapModes for target devices
+ MapMode aNewMapMode(mpOutputDevice->GetMapMode());
+ aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
+ aBufferDevice.SetMapMode(aNewMapMode);
+
+ // prepare view transformation for target renderers
+ // ATTENTION! Need to apply another scaling because of the potential DPI differences
+ // between Printer and VDev (mpOutputDevice and aBufferDevice here).
+ // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used.
+ basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation());
+ const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH));
+ const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH));
+ const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth());
+ const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight());
+
+ if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
+ {
+ aViewTransform.scale(fDPIXChange, fDPIYChange);
+ }
+
+ // create view information and pixel renderer. Reuse known ViewInformation
+ // except new transformation and range
+ const geometry::ViewInformation2D aViewInfo(
+ getViewInformation2D().getObjectTransformation(),
+ aViewTransform,
+ aViewRange,
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+
+ VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice);
+
+ // draw content using pixel renderer
+ aBufferProcessor.process(rContent);
+ const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
+
+ // draw alpha using pixel renderer
+ aBufferDevice.Erase();
+ aBufferProcessor.process(rAlpha);
+ const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false);
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew(String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
+ aNew << aBmContent;
+ }
+#endif
+
+ // paint
+ mpOutputDevice->DrawBitmapEx(
+ aRectLogic.TopLeft(),
+ aRectLogic.GetSize(),
+ BitmapEx(aBmContent, aBmAlpha));
+ }
+ }
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // use default transform group pocessing
+ RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ {
+ // new XDrawPage for ViewInformation2D
+ RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ {
+ // use default marker array pocessing
+ RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ // use default point array pocessing
+ RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
+ {
+ // ChartPrimitive2D
+ const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
+
+ if(!renderChartPrimitive2D(
+ rChartPrimitive,
+ *mpOutputDevice,
+ getViewInformation2D()))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D :
+ {
+ // structured tag primitive
+ const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
+ const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
+ const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
+
+ if(mpPDFExtOutDevData && bTagUsed)
+ {
+ // write start tag
+ mpPDFExtOutDevData->BeginStructureElement(rTagElement);
+ }
+
+ // proccess childs normally
+ process(rStructureTagCandidate.getChildren());
+
+ if(mpPDFExtOutDevData && bTagUsed)
+ {
+ // write end tag
+ mpPDFExtOutDevData->EndStructureElement();
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_HITTESTPRIMITIVE2D :
+ {
+ // #i99123#
+ // invisible primitive; to rebuilt the old MetaFile creation, it is necessary to
+ // not ignore them (as it was thought), but to add a MetaFile entry for them.
+ basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D()));
+
+ if(!aInvisibleRange.isEmpty())
+ {
+ aInvisibleRange.transform(maCurrentTransformation);
+ const Rectangle aRectLogic(
+ (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()),
+ (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY()));
+
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawRect(aRectLogic);
+ }
+
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ break;
+ }
+ }
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
new file mode 100644
index 000000000000..ef351002a1ea
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -0,0 +1,579 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclpixelprocessor2d.cxx,v $
+ *
+ * $Revision: 1.16 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-26 16:21:48 $
+ *
+ * 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/processor2d/vclpixelprocessor2d.hxx>
+#include <vcl/outdev.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
+#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
+#include <drawinglayer/primitive2d/chartprimitive2d.hxx>
+#include <helperchartrenderer.hxx>
+#include <helperwrongspellrenderer.hxx>
+#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <vcl/hatch.hxx>
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <drawinglayer/primitive2d/invertprimitive2d.hxx>
+#include <cstdio>
+#include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ VclPixelProcessor2D::VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
+ : VclProcessor2D(rViewInformation, rOutDev),
+ maOriginalMapMode(rOutDev.GetMapMode())
+ {
+ // prepare maCurrentTransformation matrix with viewTransformation to target directly to pixels
+ maCurrentTransformation = rViewInformation.getObjectToViewTransformation();
+
+ // prepare output directly to pixels
+ mpOutputDevice->Push(PUSH_MAPMODE);
+ mpOutputDevice->SetMapMode();
+
+ // react on AntiAliasing settings
+ if(getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ else
+ {
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ }
+
+ VclPixelProcessor2D::~VclPixelProcessor2D()
+ {
+ // restore MapMode
+ mpOutputDevice->Pop();
+
+ // restore AntiAliasing
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
+ }
+
+ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ {
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
+ {
+ // directdraw of wrong spell primitive; added test possibility to check wrong spell decompose
+ static bool bHandleWrongSpellDirectly(true);
+
+ if(bHandleWrongSpellDirectly)
+ {
+ const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
+
+ if(!renderWrongSpellPrimitive2D(
+ rWrongSpellPrimitive,
+ *mpOutputDevice,
+ maCurrentTransformation,
+ maBColorModifierStack))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+ else
+ {
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+ {
+ // directdraw of text simple portion; added test possibility to check text decompose
+ static bool bForceSimpleTextDecomposition(false);
+
+ // Adapt evtl. used special DrawMode
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ if(!bForceSimpleTextDecomposition && getOptionsDrawinglayer().IsRenderSimpleTextDirect())
+ {
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+ }
+ else
+ {
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+ {
+ // directdraw of text simple portion; added test possibility to check text decompose
+ static bool bForceComplexTextDecomposition(false);
+
+ // Adapt evtl. used special DrawMode
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ if(!bForceComplexTextDecomposition && getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
+ {
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+ }
+ else
+ {
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ // direct draw of hairline
+ RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), true);
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // direct draw of transformed BitmapEx primitive
+ RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
+ {
+ // direct draw of fillBitmapPrimitive
+ RenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
+ {
+ if(getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // For AA, direct render has to be avoided since it uses XOR maskings which will not
+ // work with AA. Instead, the decompose which uses MaskPrimitive2D with fillings is
+ // used
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ else
+ {
+ // direct draw of gradient
+ RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
+ {
+ // direct draw of bitmap
+ RenderPolyPolygonBitmapPrimitive2D(static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ // direct draw of PolyPolygon with color
+ RenderPolyPolygonColorPrimitive2D(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
+ {
+ // #i98289#
+ const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+ const sal_uInt16 nOldAntiAliase(mpOutputDevice->GetAntialiasing());
+
+ if(bForceLineSnap)
+ {
+ mpOutputDevice->SetAntialiasing(nOldAntiAliase | ANTIALIASING_PIXELSNAPHAIRLINE);
+ }
+
+ // direct draw of MetaFile
+ RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
+
+ if(bForceLineSnap)
+ {
+ mpOutputDevice->SetAntialiasing(nOldAntiAliase);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ // mask group.
+ RenderMaskPrimitive2DPixel(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ // modified color group. Force output to unified color.
+ RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D :
+ {
+ // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
+ // use the faster OutputDevice::DrawTransparent method
+ const primitive2d::UnifiedAlphaPrimitive2D& rUniAlphaCandidate = static_cast< const primitive2d::UnifiedAlphaPrimitive2D& >(rCandidate);
+ const primitive2d::Primitive2DSequence rContent = rUniAlphaCandidate.getChildren();
+ bool bDrawTransparentUsed(false);
+
+ // since DEV300 m33 DrawTransparent is supported in VCL (for some targets
+ // natively), so i am now enabling this shortcut
+ static bool bAllowUsingDrawTransparent(true);
+
+ if(bAllowUsingDrawTransparent && rContent.hasElements() && 1 == rContent.getLength())
+ {
+ const primitive2d::Primitive2DReference xReference(rContent[0]);
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
+
+ if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitiveID())
+ {
+ // single transparent PolyPolygon identified, use directly
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ mpOutputDevice->DrawTransparent(aLocalPolyPolygon, rUniAlphaCandidate.getAlpha());
+ bDrawTransparentUsed = true;
+ }
+ }
+
+ if(!bDrawTransparentUsed)
+ {
+ // unified sub-transparence. Draw to VDev first.
+ RenderUnifiedAlphaPrimitive2D(rUniAlphaCandidate);
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D :
+ {
+ // sub-transparence group. Draw to VDev first.
+ RenderAlphaPrimitive2D(static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // transform group.
+ RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ {
+ // new XDrawPage for ViewInformation2D
+ RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ {
+ // marker array
+ RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ // point array
+ RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+ {
+ // control primitive
+ const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
+ const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
+
+ try
+ {
+ // remember old graphics and create new
+ uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
+ const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
+
+ if(xNewGraphics.is())
+ {
+ // link graphics and view
+ xControlView->setGraphics(xNewGraphics);
+
+ // get position
+ const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0));
+
+ // find out if the control is already visualized as a VCL-ChildWindow. If yes,
+ // it does not need to be painted at all.
+ uno::Reference< awt::XWindow2 > xControlWindow(rXControl, uno::UNO_QUERY_THROW);
+ const bool bControlIsVisibleAsChildWindow(rXControl->getPeer().is() && xControlWindow->isVisible());
+
+ if(!bControlIsVisibleAsChildWindow)
+ {
+ // draw it. Do not forget to use the evtl. offsetted origin of the target device,
+ // e.g. when used with mask/transparence buffer device
+ const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
+ xControlView->draw(
+ aOrigin.X() + basegfx::fround(aTopLeftPixel.getX()),
+ aOrigin.Y() + basegfx::fround(aTopLeftPixel.getY()));
+ }
+
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+
+ // process recursively and use the decomposition as Bitmap
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ // the stroke primitive may be decomposed to filled polygons. To keep
+ // evtl. set DrawModes aka DRAWMODE_BLACKLINE, DRAWMODE_GRAYLINE,
+ // DRAWMODE_GHOSTEDLINE, DRAWMODE_WHITELINE or DRAWMODE_SETTINGSLINE
+ // working, these need to be copied to the corresponding fill modes
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptLineToFillDrawMode();
+
+ // polygon stroke primitive
+ static bool bSuppressFatToHairlineCorrection(false);
+
+ if(bSuppressFatToHairlineCorrection)
+ {
+ // remeber that we enter a PolygonStrokePrimitive2D decomposition,
+ // used for AA thick line drawing
+ mnPolygonStrokePrimitive2D++;
+
+ // with AA there is no need to handle thin lines special
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // leave PolygonStrokePrimitive2D
+ mnPolygonStrokePrimitive2D--;
+ }
+ else
+ {
+ // Lines with 1 and 2 pixel width without AA need special treatment since their vsiualisation
+ // as filled polygons is geometrically corret but looks wrong since polygon filling avoids
+ // the right and bottom pixels. The used method evaluates that and takes the correct action,
+ // including calling recursively with decomposition if line is wide enough
+ const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
+
+ RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive);
+ }
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
+ {
+ // chart primitive in pixel renderer; restore original DrawMode during call
+ // since the evtl. used ChartPrettyPainter will use the MapMode
+ const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
+ mpOutputDevice->Push(PUSH_MAPMODE);
+ mpOutputDevice->SetMapMode(maOriginalMapMode);
+
+ if(!renderChartPrimitive2D(
+ rChartPrimitive,
+ *mpOutputDevice,
+ getViewInformation2D()))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
+ }
+
+ mpOutputDevice->Pop();
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D :
+ {
+ static bool bForceIgnoreHatchSmoothing(false);
+
+ if(bForceIgnoreHatchSmoothing || getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // if AA is used (or ignore smoothing is on), there is no need to smooth
+ // hatch painting, use decomposition
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ else
+ {
+ // without AA, use VCL to draw the hatch. It snaps hatch distances to the next pixel
+ // and forces hatch distance to be >= 3 pixels to make the hatch display look smoother.
+ // This is wrong in principle, but looks nicer. This could also be done here directly
+ // without VCL usage if needed
+ const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive = static_cast< const primitive2d::FillHatchPrimitive2D& >(rCandidate);
+
+ // create hatch polygon in range size and discrete coordinates
+ basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getObjectRange());
+ aHatchRange.transform(maCurrentTransformation);
+ const basegfx::B2DPolygon aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange));
+
+ // set hatch line color
+ const basegfx::BColor aHatchColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aHatchColor));
+
+ // get hatch style
+ const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch();
+ HatchStyle eHatchStyle(HATCH_SINGLE);
+
+ switch(rFillHatchAttributes.getStyle())
+ {
+ default : // HATCHSTYLE_SINGLE
+ {
+ break;
+ }
+ case attribute::HATCHSTYLE_DOUBLE :
+ {
+ eHatchStyle = HATCH_DOUBLE;
+ break;
+ }
+ case attribute::HATCHSTYLE_TRIPLE :
+ {
+ eHatchStyle = HATCH_TRIPLE;
+ break;
+ }
+ }
+
+ // create hatch
+ const basegfx::B2DVector aDiscreteDistance(maCurrentTransformation * basegfx::B2DVector(rFillHatchAttributes.getDistance(), 0.0));
+ const sal_uInt32 nDistance(basegfx::fround(aDiscreteDistance.getLength()));
+ const sal_uInt16 nAngle10((sal_uInt16)basegfx::fround(rFillHatchAttributes.getAngle() / F_PI1800));
+ ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance, nAngle10);
+
+ // draw hatch using VCL
+ mpOutputDevice->DrawHatch(PolyPolygon(Polygon(aHatchPolygon)), aVCLHatch);
+ }
+ break;
+ }
+ case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D :
+ {
+ // #i98404# Handle directly, especially when AA is active
+ const primitive2d::BackgroundColorPrimitive2D& rPrimitive = static_cast< const primitive2d::BackgroundColorPrimitive2D& >(rCandidate);
+ const sal_uInt16 nOriginalAA(mpOutputDevice->GetAntialiasing());
+
+ // switch AA off in all cases
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
+
+ // create color for fill
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ // create rectangle for fill
+ const basegfx::B2DRange& aViewport(getViewInformation2D().getDiscreteViewport());
+ const Rectangle aRectangle(
+ (sal_Int32)floor(aViewport.getMinX()), (sal_Int32)floor(aViewport.getMinY()),
+ (sal_Int32)ceil(aViewport.getMaxX()), (sal_Int32)ceil(aViewport.getMaxY()));
+ mpOutputDevice->DrawRect(aRectangle);
+
+ // restore AA setting
+ mpOutputDevice->SetAntialiasing(nOriginalAA);
+
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D :
+ {
+ // #i97628#
+ // This primitive means that the content is derived from an active text edit,
+ // not from model data itself. Some renderers need to suppress this content, e.g.
+ // the pixel renderer used for displaying the edit view (like this one). It's
+ // not to be suppressed by the MetaFile renderers, so that the edited text is
+ // part of the MetaFile, e.g. needed for presentation previews.
+ // Action: Ignore here, do nothing.
+ break;
+ }
+ case PRIMITIVE2D_ID_INVERTPRIMITIVE2D :
+ {
+ // invert primitive (currently only used for HighContrast fallback for selection in SW and SC).
+ // Set OutDev to XOR
+ mpOutputDevice->Push();
+ mpOutputDevice->SetRasterOp( ROP_XOR );
+
+ // force paint color to white by using ColorModifierStack
+ const basegfx::BColor aColWhite(1.0, 1.0, 1.0);
+ const basegfx::BColorModifier aColorModifier(aColWhite, 0.0, basegfx::BCOLORMODIFYMODE_REPLACE);
+ maBColorModifierStack.push(aColorModifier);
+
+ // process content recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // restore ColorModifierStack
+ maBColorModifierStack.pop();
+
+ // restore OutDev
+ mpOutputDevice->Pop();
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ break;
+ }
+ }
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
new file mode 100644
index 000000000000..ede5aee730cf
--- /dev/null
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -0,0 +1,1413 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: vclprocessor2d.cxx,v $
+ *
+ * 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/processor2d/vclprocessor2d.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
+#include <tools/debug.hxx>
+#include <vcl/outdev.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <vclhelperbitmaptransform.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <vclhelperbitmaprender.hxx>
+#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
+#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <vclhelpergradient.hxx>
+#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vclhelperbufferdevice.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
+#include <svtools/ctloptions.hxx>
+#include <vcl/svapp.hxx>
+#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/metric.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// control support
+
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/XView.hpp>
+#include <drawinglayer/primitive2d/controlprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// for test, can be removed again
+
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor2d
+ {
+ //////////////////////////////////////////////////////////////////////////////
+ // UNO class usages
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::awt::XView;
+ using ::com::sun::star::awt::XGraphics;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::awt::PosSize::POSSIZE;
+
+ static FontUnderline mapTextLineStyle(primitive2d::FontUnderline eLineStyle)
+ {
+ switch(eLineStyle)
+ {
+ default:
+ DBG_WARNING1( "DrawingLayer: Unknown text line style attribute (%d)!", eLineStyle );
+ // fall through
+ case primitive2d::FONT_UNDERLINE_NONE: return UNDERLINE_NONE;
+ case primitive2d::FONT_UNDERLINE_SINGLE: return UNDERLINE_SINGLE;
+ case primitive2d::FONT_UNDERLINE_DOUBLE: return UNDERLINE_DOUBLE;
+ case primitive2d::FONT_UNDERLINE_DOTTED: return UNDERLINE_DOTTED;
+ case primitive2d::FONT_UNDERLINE_DASH: return UNDERLINE_DASH;
+ case primitive2d::FONT_UNDERLINE_LONGDASH: return UNDERLINE_LONGDASH;
+ case primitive2d::FONT_UNDERLINE_DASHDOT: return UNDERLINE_DASHDOT;
+ case primitive2d::FONT_UNDERLINE_DASHDOTDOT: return UNDERLINE_DASHDOTDOT;
+ case primitive2d::FONT_UNDERLINE_SMALLWAVE: return UNDERLINE_SMALLWAVE;
+ case primitive2d::FONT_UNDERLINE_WAVE: return UNDERLINE_WAVE;
+ case primitive2d::FONT_UNDERLINE_DOUBLEWAVE: return UNDERLINE_DOUBLEWAVE;
+ case primitive2d::FONT_UNDERLINE_BOLD: return UNDERLINE_BOLD;
+ case primitive2d::FONT_UNDERLINE_BOLDDOTTED: return UNDERLINE_BOLDDOTTED;
+ case primitive2d::FONT_UNDERLINE_BOLDDASH: return UNDERLINE_BOLDDASH;
+ case primitive2d::FONT_UNDERLINE_BOLDLONGDASH: return UNDERLINE_LONGDASH;
+ case primitive2d::FONT_UNDERLINE_BOLDDASHDOT: return UNDERLINE_BOLDDASHDOT;
+ case primitive2d::FONT_UNDERLINE_BOLDDASHDOTDOT:return UNDERLINE_BOLDDASHDOT;
+ case primitive2d::FONT_UNDERLINE_BOLDWAVE: return UNDERLINE_BOLDWAVE;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // rendering support
+
+ // directdraw of text simple portion or decorated portion primitive. When decorated, all the extra
+ // information is translated to VCL parameters and set at the font.
+ // Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring
+ // for VCL)
+ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+ {
+ // decompose matrix to have position and size of text
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform());
+ basegfx::B2DVector aFontScaling, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
+ bool bPrimitiveAccepted(false);
+
+ if(basegfx::fTools::equalZero(fShearX))
+ {
+ if(basegfx::fTools::less(aFontScaling.getX(), 0.0) && basegfx::fTools::less(aFontScaling.getY(), 0.0))
+ {
+ // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
+ // be expressed as rotation by PI. Use this since the Font rendering will not
+ // apply the negative scales in any form
+ aFontScaling = basegfx::absolute(aFontScaling);
+ fRotate += F_PI;
+ }
+
+ if(basegfx::fTools::more(aFontScaling.getX(), 0.0) && basegfx::fTools::more(aFontScaling.getY(), 0.0))
+ {
+ // Get the VCL font (use FontHeight as FontWidth)
+ Font aFont(primitive2d::getVclFontFromFontAttributes(
+ rTextCandidate.getFontAttributes(),
+ aFontScaling.getX(),
+ aFontScaling.getY(),
+ fRotate,
+ rTextCandidate.getLocale()));
+
+ // handle additional font attributes
+ const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
+ dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>( &rTextCandidate );
+
+ if( pTCPP != NULL )
+ {
+
+ // set the color of text decorations
+ const basegfx::BColor aTextlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getTextlineColor());
+ mpOutputDevice->SetTextLineColor( Color(aTextlineColor) );
+
+ // set Overline attribute
+ FontUnderline eFontOverline = mapTextLineStyle( pTCPP->getFontOverline() );
+ if( eFontOverline != UNDERLINE_NONE )
+ {
+ aFont.SetOverline( eFontOverline );
+ const basegfx::BColor aOverlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getOverlineColor());
+ mpOutputDevice->SetOverlineColor( Color(aOverlineColor) );
+ if( pTCPP->getWordLineMode() )
+ aFont.SetWordLineMode( true );
+ }
+
+ // set Underline attribute
+ FontUnderline eFontUnderline = mapTextLineStyle( pTCPP->getFontUnderline() );
+ if( eFontUnderline != UNDERLINE_NONE )
+ {
+ aFont.SetUnderline( eFontUnderline );
+ if( pTCPP->getWordLineMode() )
+ aFont.SetWordLineMode( true );
+//TODO: ??? if( pTCPP->getUnderlineAbove() )
+// aFont.SetUnderlineAbove( true );
+ }
+
+ // set Strikeout attribute
+ FontStrikeout eFontStrikeout = STRIKEOUT_NONE;
+ switch( pTCPP->getFontStrikeout() )
+ {
+ default:
+ DBG_WARNING1( "DrawingLayer: Unknown strikeout attribute (%d)!", pTCPP->getFontStrikeout() );
+ // fall through
+ case primitive2d::FONT_STRIKEOUT_NONE: eFontStrikeout = STRIKEOUT_NONE; break;
+ case primitive2d::FONT_STRIKEOUT_SINGLE: eFontStrikeout = STRIKEOUT_SINGLE; break;
+ case primitive2d::FONT_STRIKEOUT_DOUBLE: eFontStrikeout = STRIKEOUT_DOUBLE; break;
+ case primitive2d::FONT_STRIKEOUT_BOLD: eFontStrikeout = STRIKEOUT_BOLD; break;
+ case primitive2d::FONT_STRIKEOUT_SLASH: eFontStrikeout = STRIKEOUT_SLASH; break;
+ case primitive2d::FONT_STRIKEOUT_X: eFontStrikeout = STRIKEOUT_X; break;
+ }
+
+ if( eFontStrikeout != STRIKEOUT_NONE )
+ aFont.SetStrikeout( eFontStrikeout );
+
+ // set EmphasisMark attribute
+ FontEmphasisMark eFontEmphasisMark = EMPHASISMARK_NONE;
+ switch( pTCPP->getFontEmphasisMark() )
+ {
+ default:
+ DBG_WARNING1( "DrawingLayer: Unknown EmphasisMark style (%d)!", pTCPP->getFontEmphasisMark() );
+ // fall through
+ case primitive2d::FONT_EMPHASISMARK_NONE: eFontEmphasisMark = EMPHASISMARK_NONE; break;
+ case primitive2d::FONT_EMPHASISMARK_DOT: eFontEmphasisMark = EMPHASISMARK_DOT; break;
+ case primitive2d::FONT_EMPHASISMARK_CIRCLE: eFontEmphasisMark = EMPHASISMARK_CIRCLE; break;
+ case primitive2d::FONT_EMPHASISMARK_DISC: eFontEmphasisMark = EMPHASISMARK_DISC; break;
+ case primitive2d::FONT_EMPHASISMARK_ACCENT: eFontEmphasisMark = EMPHASISMARK_ACCENT; break;
+ }
+
+ if( eFontEmphasisMark != EMPHASISMARK_NONE )
+ {
+ DBG_ASSERT( (pTCPP->getEmphasisMarkAbove() != pTCPP->getEmphasisMarkBelow()),
+ "DrawingLayer: Bad EmphasisMark position!" );
+ if( pTCPP->getEmphasisMarkAbove() )
+ eFontEmphasisMark |= EMPHASISMARK_POS_ABOVE;
+ else
+ eFontEmphasisMark |= EMPHASISMARK_POS_BELOW;
+ aFont.SetEmphasisMark( eFontEmphasisMark );
+ }
+
+ // set Relief attribute
+ FontRelief eFontRelief = RELIEF_NONE;
+ switch( pTCPP->getFontRelief() )
+ {
+ default:
+ DBG_WARNING1( "DrawingLayer: Unknown Relief style (%d)!", pTCPP->getFontRelief() );
+ // fall through
+ case primitive2d::FONT_RELIEF_NONE: eFontRelief = RELIEF_NONE; break;
+ case primitive2d::FONT_RELIEF_EMBOSSED: eFontRelief = RELIEF_EMBOSSED; break;
+ case primitive2d::FONT_RELIEF_ENGRAVED: eFontRelief = RELIEF_ENGRAVED; break;
+ }
+
+ if( eFontRelief != RELIEF_NONE )
+ aFont.SetRelief( eFontRelief );
+
+ // set Shadow attribute
+ if( pTCPP->getShadow() )
+ aFont.SetShadow( true );
+ }
+
+ // create transformed integer DXArray in view coordinate system
+ ::std::vector< sal_Int32 > aTransformedDXArray;
+
+ if(rTextCandidate.getDXArray().size())
+ {
+ aTransformedDXArray.reserve(rTextCandidate.getDXArray().size());
+ const basegfx::B2DVector aPixelVector(maCurrentTransformation * basegfx::B2DVector(1.0, 0.0));
+ const double fPixelVectorFactor(aPixelVector.getLength());
+
+ for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin());
+ aStart != rTextCandidate.getDXArray().end(); aStart++)
+ {
+ aTransformedDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorFactor));
+ }
+ }
+
+ // set parameters and paint text snippet
+ const basegfx::BColor aRGBFontColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
+ const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
+ const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()));
+ const sal_uInt32 nOldLayoutMode(mpOutputDevice->GetLayoutMode());
+
+ if(rTextCandidate.getFontAttributes().getRTL())
+ {
+ sal_uInt32 nRTLLayoutMode(nOldLayoutMode & ~(TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG));
+ nRTLLayoutMode |= TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ mpOutputDevice->SetLayoutMode(nRTLLayoutMode);
+ }
+
+ mpOutputDevice->SetFont(aFont);
+ mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+
+ if(aTransformedDXArray.size())
+ {
+ mpOutputDevice->DrawTextArray(
+ aStartPoint,
+ rTextCandidate.getText(),
+ &(aTransformedDXArray[0]),
+ rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
+ }
+ else
+ {
+ mpOutputDevice->DrawText(
+ aStartPoint,
+ rTextCandidate.getText(),
+ rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
+ }
+
+ if(rTextCandidate.getFontAttributes().getRTL())
+ {
+ mpOutputDevice->SetLayoutMode(nOldLayoutMode);
+ }
+
+ bPrimitiveAccepted = true;
+ }
+ }
+
+ if(!bPrimitiveAccepted)
+ {
+ // let break down
+ process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ // direct draw of hairline
+ void VclProcessor2D::RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate, bool bPixelBased)
+ {
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+ mpOutputDevice->SetLineColor(Color(aHairlineColor));
+ mpOutputDevice->SetFillColor();
+
+ basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
+ aLocalPolygon.transform(maCurrentTransformation);
+
+ if(bPixelBased && getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete())
+ {
+ // #i98289#
+ // when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete
+ // allows to suppress AntiAliasing for pure horizontal or vertical lines. This is done since
+ // not-AntiAliased such lines look more pleasing to the eye (e.g. 2D chart content). This
+ // NEEDS to be done in discrete coordinates, so only useful for pixel based rendering.
+ aLocalPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aLocalPolygon);
+ }
+
+ mpOutputDevice->DrawPolyLine(aLocalPolygon, 0.0);
+ }
+
+ // direct draw of transformed BitmapEx primitive
+ void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+ {
+ // create local transform
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rBitmapCandidate.getTransform());
+ BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
+ bool bPainted(false);
+
+ if(maBColorModifierStack.count())
+ {
+ aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
+
+ if(aBitmapEx.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+ aPolygon.transform(aLocalTransform);
+
+ mpOutputDevice->SetFillColor(Color(aModifiedColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aPolygon);
+
+ bPainted = true;
+ }
+ }
+
+ if(!bPainted)
+ {
+ static bool bForceUseOfOwnTransformer(false);
+ static bool bUseGraphicManager(true);
+
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if(!bForceUseOfOwnTransformer && basegfx::fTools::equalZero(fShearX))
+ {
+ if(!bUseGraphicManager && basegfx::fTools::equalZero(fRotate))
+ {
+ RenderBitmapPrimitive2D_BitmapEx(*mpOutputDevice, aBitmapEx, aLocalTransform);
+ }
+ else
+ {
+ RenderBitmapPrimitive2D_GraphicManager(*mpOutputDevice, aBitmapEx, aLocalTransform);
+ }
+ }
+ else
+ {
+ if(!aBitmapEx.IsTransparent() && (!basegfx::fTools::equalZero(fShearX) || !basegfx::fTools::equalZero(fRotate)))
+ {
+ // parts will be uncovered, extend aBitmapEx with a mask bitmap
+ const Bitmap aContent(aBitmapEx.GetBitmap());
+ aBitmapEx = BitmapEx(aContent, Bitmap(aContent.GetSizePixel(), 1));
+ }
+
+ RenderBitmapPrimitive2D_self(*mpOutputDevice, aBitmapEx, aLocalTransform);
+ }
+ }
+ }
+
+ void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate)
+ {
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap());
+ bool bPrimitiveAccepted(false);
+
+ if(rFillBitmapAttribute.getTiling())
+ {
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rFillBitmapCandidate.getTransformation());
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if(basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
+ {
+ // no shear or rotate, draw direct in pixel coordinates
+ bPrimitiveAccepted = true;
+ BitmapEx aBitmapEx(rFillBitmapAttribute.getBitmap());
+ bool bPainted(false);
+
+ if(maBColorModifierStack.count())
+ {
+ aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
+
+ if(aBitmapEx.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
+ aPolygon.transform(aLocalTransform);
+
+ mpOutputDevice->SetFillColor(Color(aModifiedColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aPolygon);
+
+ bPainted = true;
+ }
+ }
+
+ if(!bPainted)
+ {
+ const basegfx::B2DPoint aObjTopLeft(aTranslate.getX(), aTranslate.getY());
+ const basegfx::B2DPoint aObjBottomRight(aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
+ const Point aObjTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjTopLeft.getX(), (sal_Int32)aObjTopLeft.getY())));
+ const Point aObjBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjBottomRight.getX(), (sal_Int32)aObjBottomRight.getY())));
+
+ const basegfx::B2DPoint aBmpTopLeft(aLocalTransform * rFillBitmapAttribute.getTopLeft());
+ const basegfx::B2DPoint aBmpBottomRight(aLocalTransform * basegfx::B2DPoint(rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize()));
+ const Point aBmpTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpTopLeft.getX(), (sal_Int32)aBmpTopLeft.getY())));
+ const Point aBmpBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpBottomRight.getX(), (sal_Int32)aBmpBottomRight.getY())));
+
+ sal_Int32 nOWidth(aObjBR.X() - aObjTL.X());
+ sal_Int32 nOHeight(aObjBR.Y() - aObjTL.Y());
+
+ // only do something when object has a size in discrete units
+ if(nOWidth > 0 && nOHeight > 0)
+ {
+ sal_Int32 nBWidth(aBmpBR.X() - aBmpTL.X());
+ sal_Int32 nBHeight(aBmpBR.Y() - aBmpTL.Y());
+
+ // only do something when bitmap fill has a size in discrete units
+ if(nBWidth > 0 && nBHeight > 0)
+ {
+ sal_Int32 nBLeft(aBmpTL.X());
+ sal_Int32 nBTop(aBmpTL.Y());
+
+ if(nBLeft > aObjTL.X())
+ {
+ nBLeft -= ((nBLeft / nBWidth) + 1L) * nBWidth;
+ }
+
+ if(nBLeft + nBWidth <= aObjTL.X())
+ {
+ nBLeft -= (nBLeft / nBWidth) * nBWidth;
+ }
+
+ if(nBTop > aObjTL.Y())
+ {
+ nBTop -= ((nBTop / nBHeight) + 1L) * nBHeight;
+ }
+
+ if(nBTop + nBHeight <= aObjTL.Y())
+ {
+ nBTop -= (nBTop / nBHeight) * nBHeight;
+ }
+
+ // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
+ // in vcl many times, create a size-optimized version
+ const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
+
+ if(aNeededBitmapSizePixel != aBitmapEx.GetSizePixel())
+ {
+ aBitmapEx.Scale(aNeededBitmapSizePixel);
+ }
+
+ // prepare OutDev
+ const Point aEmptyPoint(0, 0);
+ const Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
+ const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
+ mpOutputDevice->EnableMapMode(false);
+
+ for(sal_Int32 nXPos(nBLeft); nXPos < aObjTL.X() + nOWidth; nXPos += nBWidth)
+ {
+ for(sal_Int32 nYPos(nBTop); nYPos < aObjTL.Y() + nOHeight; nYPos += nBHeight)
+ {
+ const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if(aOutRectPixel.IsOver(aVisiblePixel))
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+ }
+ }
+ }
+
+ // restore OutDev
+ mpOutputDevice->EnableMapMode(bWasEnabled);
+ }
+ }
+ }
+ }
+ }
+
+ if(!bPrimitiveAccepted)
+ {
+ // do not accept, use decomposition
+ process(rFillBitmapCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ // direct draw of gradient
+ void VclProcessor2D::RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
+ {
+ const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
+ basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
+ basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ if(aStartColor == aEndColor)
+ {
+ // no gradient at all, draw as polygon
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(aStartColor));
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ }
+ else
+ {
+ impDrawGradientToOutDev(
+ *mpOutputDevice, aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(),
+ aStartColor, aEndColor, rGradient.getBorder(),
+ -rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), false);
+ }
+ }
+
+ // direct draw of bitmap
+ void VclProcessor2D::RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate)
+ {
+ bool bDone(false);
+ const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon();
+
+ if(rPolyPolygon.count())
+ {
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute = rPolygonCandidate.getFillBitmap();
+ const Bitmap& rBitmap = rFillBitmapAttribute.getBitmap();
+
+ if(rBitmap.IsEmpty())
+ {
+ // empty bitmap, done
+ bDone = true;
+ }
+ else
+ {
+ // try to catch cases where the bitmap will be color-modified to a single
+ // color (e.g. shadow). This would NOT be optimizable with an alpha channel
+ // at the Bitmap which we do not have here. When this should change, this
+ // optimization has to be reworked accordingly.
+ const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
+
+ if(nBColorModifierStackCount)
+ {
+ const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
+
+ if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode())
+ {
+ // the bitmap fill is in unified color, so we can replace it with
+ // a single polygon fill. The form of the fill depends on tiling
+ if(rFillBitmapAttribute.getTiling())
+ {
+ // with tiling, fill the whole PolyPolygon with the modifier color
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
+
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ }
+ else
+ {
+ // without tiling, only the area common to the bitmap tile and the
+ // PolyPolygon is filled. Create the bitmap tile area in object
+ // coordinates. For this, the object transformation needs to be created
+ // from the already scaled PolyPolygon. The tile area in object
+ // coordinates wil always be non-rotated, so it's not necessary to
+ // work with a polygon here
+ basegfx::B2DRange aTileRange(rFillBitmapAttribute.getTopLeft(),
+ rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize());
+ const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.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());
+ aTileRange.transform(aNewObjectTransform);
+
+ // now clip the object polyPolygon against the tile range
+ // to get the common area (OR)
+ basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(rPolyPolygon, aTileRange, true, false);
+
+ if(aTarget.count())
+ {
+ aTarget.transform(maCurrentTransformation);
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+ mpOutputDevice->DrawPolyPolygon(aTarget);
+ }
+ }
+
+ bDone = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // empty polyPolygon, done
+ bDone = true;
+ }
+
+ if(!bDone)
+ {
+ // use default decomposition
+ process(rPolygonCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ }
+
+ // direct draw of PolyPolygon with color
+ void VclProcessor2D::RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate)
+ {
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+
+ if(mnPolygonStrokePrimitive2D && getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // when AA is on and this filled polygons are the result of stroked line geometry,
+ // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aPolygonColor));
+ const sal_uInt32 nCount(aLocalPolyPolygon.count());
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0);
+ }
+ }
+
+ static bool bTestPolygonClipping(false);
+ if(bTestPolygonClipping)
+ {
+ static bool bInside(true);
+ static bool bFilled(false);
+ static bool bLine(false);
+
+ basegfx::B2DRange aRange(aLocalPolyPolygon.getB2DRange());
+ aRange.grow(aRange.getWidth() * -0.1);
+
+ if(bFilled)
+ {
+ basegfx::B2DPolyPolygon aFilledClipped(basegfx::tools::clipPolyPolygonOnRange(aLocalPolyPolygon, aRange, bInside, false));
+ basegfx::BColor aRand(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0);
+ mpOutputDevice->SetFillColor(Color(aRand));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolyPolygon(aFilledClipped);
+ }
+
+ if(bLine)
+ {
+ basegfx::B2DPolyPolygon aLineClipped(basegfx::tools::clipPolyPolygonOnRange(aLocalPolyPolygon, aRange, bInside, true));
+ basegfx::BColor aRand(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0);
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aRand));
+
+ for(sal_uInt32 a(0); a < aLineClipped.count(); a++)
+ {
+ mpOutputDevice->DrawPolyLine(aLineClipped.getB2DPolygon(a), 0.0);
+ }
+ }
+ }
+ }
+
+ // direct draw of MetaFile
+ void VclProcessor2D::RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
+ {
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rMetaCandidate.getTransform());
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
+ {
+ // #i102175# handle special case: If scale is negative in (x,y) (3rd quadrant), it can
+ // be expressed as rotation by PI. This needs to be done for Metafiles since
+ // these can be rotated, but not really mirrored
+ aScale = basegfx::absolute(aScale);
+ fRotate += F_PI;
+ }
+
+ // get BoundRect
+ basegfx::B2DRange aOutlineRange(rMetaCandidate.getB2DRange(getViewInformation2D()));
+ aOutlineRange.transform(maCurrentTransformation);
+
+ // Due to the integer MapModes used from VCL aind inside MetaFiles errors of up to three
+ // pixels in size may happen. As long as there is no better way (e.g. convert the MetaFile
+ // to primitives) it is necessary to reduce maximum pixel size by 1 in X and Y and to use
+ // the inner pixel bounds accordingly (ceil resp. floor). This will also be done for logic
+ // units e.g. when creating a new MetaFile, but since much huger value ranges are used
+ // there typically will be okay for this compromize.
+ Rectangle aDestRectView(
+ // !!CAUTION!! Here, ceil and floor are exchanged BY PURPOSE, do NOT copy when
+ // looking for a standard conversion to rectangle (!)
+ (sal_Int32)ceil(aOutlineRange.getMinX()), (sal_Int32)ceil(aOutlineRange.getMinY()),
+ (sal_Int32)floor(aOutlineRange.getMaxX()), (sal_Int32)floor(aOutlineRange.getMaxY()));
+
+ // get metafile (copy it)
+ GDIMetaFile aMetaFile;
+
+ if(maBColorModifierStack.count())
+ {
+ const basegfx::BColor aRGBBaseColor(0, 0, 0);
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
+ aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
+ }
+ else
+ {
+ aMetaFile = rMetaCandidate.getMetaFile();
+ }
+
+ // rotation
+ if(!basegfx::fTools::equalZero(fRotate))
+ {
+ // #i103530#
+ // MetaFile::Rotate has no input parameter check, so the parameter needs to be
+ // well-aligned to the old range [0..3600] 10th degrees with inverse orientation
+ sal_Int16 nRotation((sal_Int16)((fRotate / F_PI180) * -10.0));
+
+ while(nRotation < 0)
+ nRotation += 3600;
+
+ while(nRotation >= 3600)
+ nRotation -= 3600;
+
+ aMetaFile.Rotate(nRotation);
+ }
+
+ // Prepare target output size
+ Size aDestSize(aDestRectView.GetSize());
+
+ if(aDestSize.getWidth() && aDestSize.getHeight())
+ {
+ // Get preferred Metafile output size. When it's very equal to the output size, it's probably
+ // a rounding error somewhere, so correct it to get a 1:1 output without single pixel scalings
+ // of the Metafile (esp. for contaned Bitmaps, e.g 3D charts)
+ const Size aPrefSize(mpOutputDevice->LogicToPixel(aMetaFile.GetPrefSize(), aMetaFile.GetPrefMapMode()));
+
+ if(aPrefSize.getWidth() && (aPrefSize.getWidth() - 1 == aDestSize.getWidth() || aPrefSize.getWidth() + 1 == aDestSize.getWidth()))
+ {
+ aDestSize.setWidth(aPrefSize.getWidth());
+ }
+
+ if(aPrefSize.getHeight() && (aPrefSize.getHeight() - 1 == aDestSize.getHeight() || aPrefSize.getHeight() + 1 == aDestSize.getHeight()))
+ {
+ aDestSize.setHeight(aPrefSize.getHeight());
+ }
+
+ // paint it
+ aMetaFile.WindStart();
+ aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestSize);
+ }
+ }
+
+ // mask group. Force output to VDev and create mask from given mask
+ void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate)
+ {
+ if(rMaskCandidate.getChildren().hasElements())
+ {
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+ if(aMask.count())
+ {
+ aMask.transform(maCurrentTransformation);
+ const basegfx::B2DRange aRange(basegfx::tools::getRange(aMask));
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+
+ if(aBufferDevice.isVisible())
+ {
+ // remember last OutDev and set to content
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ mpOutputDevice = &aBufferDevice.getContent();
+
+ // paint to it
+ process(rMaskCandidate.getChildren());
+
+ // back to old OutDev
+ mpOutputDevice = pLastOutputDevice;
+
+ // draw mask
+ if(getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // with AA, use 8bit AlphaMask to get nice borders
+ VirtualDevice& rAlpha = aBufferDevice.getAlpha();
+ rAlpha.SetLineColor();
+ rAlpha.SetFillColor(COL_BLACK);
+ rAlpha.DrawPolyPolygon(aMask);
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
+ }
+ else
+ {
+ // No AA, use 1bit mask
+ VirtualDevice& rMask = aBufferDevice.getMask();
+ rMask.SetLineColor();
+ rMask.SetFillColor(COL_BLACK);
+ rMask.DrawPolyPolygon(aMask);
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
+ }
+ }
+ }
+ }
+ }
+
+ // modified color group. Force output to unified color.
+ void VclProcessor2D::RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate)
+ {
+ if(rModifiedCandidate.getChildren().hasElements())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+ }
+
+ // unified sub-transparence. Draw to VDev first.
+ void VclProcessor2D::RenderUnifiedAlphaPrimitive2D(const primitive2d::UnifiedAlphaPrimitive2D& rTransCandidate)
+ {
+ static bool bForceToDecomposition(false);
+
+ if(rTransCandidate.getChildren().hasElements())
+ {
+ if(bForceToDecomposition)
+ {
+ // use decomposition
+ process(rTransCandidate.get2DDecomposition(getViewInformation2D()));
+ }
+ else
+ {
+ if(0.0 == rTransCandidate.getAlpha())
+ {
+ // no transparence used, so just use the content
+ process(rTransCandidate.getChildren());
+ }
+ else if(rTransCandidate.getAlpha() > 0.0 && rTransCandidate.getAlpha() < 1.0)
+ {
+ // alpha is in visible range
+ basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D()));
+ aRange.transform(maCurrentTransformation);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+
+ if(aBufferDevice.isVisible())
+ {
+ // remember last OutDev and set to content
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ mpOutputDevice = &aBufferDevice.getContent();
+
+ // paint content to it
+ process(rTransCandidate.getChildren());
+
+ // back to old OutDev
+ mpOutputDevice = pLastOutputDevice;
+
+ // dump buffer to outdev using given alpha
+ aBufferDevice.paint(rTransCandidate.getAlpha());
+ }
+ }
+ }
+ }
+ }
+
+ // sub-transparence group. Draw to VDev first.
+ void VclProcessor2D::RenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D& rTransCandidate)
+ {
+ if(rTransCandidate.getChildren().hasElements())
+ {
+ basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D()));
+ aRange.transform(maCurrentTransformation);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+
+ if(aBufferDevice.isVisible())
+ {
+ // remember last OutDev and set to content
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ mpOutputDevice = &aBufferDevice.getContent();
+
+ // paint content to it
+ process(rTransCandidate.getChildren());
+
+ // set to mask
+ mpOutputDevice = &aBufferDevice.getAlpha();
+
+ // when painting alpha masks, reset the color stack
+ basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
+ maBColorModifierStack = basegfx::BColorModifierStack();
+
+ // paint mask to it (always with alpha intensities, evtl. with AA)
+ process(rTransCandidate.getAlpha());
+
+ // back to old color stack
+ maBColorModifierStack = aLastBColorModifierStack;
+
+ // back to old OutDev
+ mpOutputDevice = pLastOutputDevice;
+
+ // dump buffer to outdev
+ aBufferDevice.paint();
+ }
+ }
+ }
+
+ // transform group.
+ void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate)
+ {
+ // remember current transformation and ViewInformation
+ const basegfx::B2DHomMatrix aLastCurrentTransformation(maCurrentTransformation);
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new transformations for CurrentTransformation
+ // and for local ViewInformation2D
+ maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ getViewInformation2D().getVisualizedPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess content
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ maCurrentTransformation = aLastCurrentTransformation;
+ updateViewInformation(aLastViewInformation2D);
+ }
+
+ // new XDrawPage for ViewInformation2D
+ void VclProcessor2D::RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate)
+ {
+ // remember current transformation and ViewInformation
+ const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
+
+ // create new local ViewInformation2D
+ const geometry::ViewInformation2D aViewInformation2D(
+ getViewInformation2D().getObjectTransformation(),
+ getViewInformation2D().getViewTransformation(),
+ getViewInformation2D().getViewport(),
+ rPagePreviewCandidate.getXDrawPage(),
+ getViewInformation2D().getViewTime(),
+ getViewInformation2D().getExtendedInformationSequence());
+ updateViewInformation(aViewInformation2D);
+
+ // proccess decomposed content
+ process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation2D);
+ }
+
+ // marker
+ void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkArrayCandidate)
+ {
+ static bool bCheckCompleteMarkerDecompose(false);
+ if(bCheckCompleteMarkerDecompose)
+ {
+ process(rMarkArrayCandidate.get2DDecomposition(getViewInformation2D()));
+ return;
+ }
+
+ // get data
+ const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions();
+ const sal_uInt32 nCount(rPositions.size());
+
+ if(nCount && !rMarkArrayCandidate.getMarker().IsEmpty())
+ {
+ // get pixel size
+ const BitmapEx& rMarker(rMarkArrayCandidate.getMarker());
+ const Size aBitmapSize(rMarker.GetSizePixel());
+
+ if(aBitmapSize.Width() && aBitmapSize.Height())
+ {
+ // get discrete half size
+ const basegfx::B2DVector aDiscreteHalfSize(
+ (aBitmapSize.getWidth() - 1.0) * 0.5,
+ (aBitmapSize.getHeight() - 1.0) * 0.5);
+ const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
+
+ // do not forget evtl. moved origin in target device MapMode when
+ // switching it off; it would be missing and lead to wrong positions.
+ // All his could be done using logic sizes and coordinates, too, but
+ // we want a 1:1 bitmap rendering here, so it's more safe and faster
+ // to work with switching off MapMode usage completely.
+ const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
+
+ mpOutputDevice->EnableMapMode(false);
+
+ for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
+ {
+ const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * (*aIter)) - aDiscreteHalfSize);
+ const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()), basegfx::fround(aDiscreteTopLeft.getY()));
+
+ mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker);
+ }
+
+ mpOutputDevice->EnableMapMode(bWasEnabled);
+ }
+ }
+ }
+
+ // point
+ void VclProcessor2D::RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate)
+ {
+ const std::vector< basegfx::B2DPoint >& rPositions = rPointArrayCandidate.getPositions();
+ const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
+ const Color aVCLColor(aRGBColor);
+
+ for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
+ {
+ const basegfx::B2DPoint aViewPosition(maCurrentTransformation * (*aIter));
+ const Point aPos(basegfx::fround(aViewPosition.getX()), basegfx::fround(aViewPosition.getY()));
+
+ mpOutputDevice->DrawPixel(aPos, aVCLColor);
+ }
+ }
+
+ void VclProcessor2D::RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate)
+ {
+ // #i101491# method restructured to clearly use the DrawPolyLine
+ // calls starting from a deined line width
+ const attribute::LineAttribute& rLineAttribute = rPolygonStrokeCandidate.getLineAttribute();
+ const double fLineWidth(rLineAttribute.getWidth());
+ bool bDone(false);
+
+ if(basegfx::fTools::more(fLineWidth, 0.0))
+ {
+ const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(fLineWidth, 0.0));
+ const double fDiscreteLineWidth(aDiscreteUnit.getLength());
+ const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokeCandidate.getStrokeAttribute();
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
+ basegfx::B2DPolyPolygon aHairlinePolyPolygon;
+
+ mpOutputDevice->SetLineColor(Color(aHairlineColor));
+ mpOutputDevice->SetFillColor();
+
+ if(0.0 == rStrokeAttribute.getFullDotDashLen())
+ {
+ // no line dashing, just copy
+ aHairlinePolyPolygon.append(rPolygonStrokeCandidate.getB2DPolygon());
+ }
+ else
+ {
+ // else apply LineStyle
+ basegfx::tools::applyLineDashing(rPolygonStrokeCandidate.getB2DPolygon(),
+ rStrokeAttribute.getDotDashArray(),
+ &aHairlinePolyPolygon, 0, rStrokeAttribute.getFullDotDashLen());
+ }
+
+ const sal_uInt32 nCount(aHairlinePolyPolygon.count());
+
+ if(nCount)
+ {
+ const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing());
+ aHairlinePolyPolygon.transform(maCurrentTransformation);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ basegfx::B2DPolygon aCandidate(aHairlinePolyPolygon.getB2DPolygon(a));
+
+ if(bAntiAliased)
+ {
+ if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.0))
+ {
+ // line in range ]0.0 .. 1.0[
+ // paint as simple hairline
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+ bDone = true;
+ }
+ else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.0))
+ {
+ // line in range [1.0 .. 2.0[
+ // paint as 2x2 with dynamic line distance
+ basegfx::B2DHomMatrix aMat;
+ const double fDistance(fDiscreteLineWidth - 1.0);
+ const double fHalfDistance(fDistance * 0.5);
+
+ aMat.set(0, 2, -fHalfDistance);
+ aMat.set(1, 2, -fHalfDistance);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, fDistance);
+ aMat.set(1, 2, 0.0);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, 0.0);
+ aMat.set(1, 2, fDistance);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, -fDistance);
+ aMat.set(1, 2, 0.0);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+ bDone = true;
+ }
+ else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 3.0))
+ {
+ // line in range [2.0 .. 3.0]
+ // paint as cross in a 3x3 with dynamic line distance
+ basegfx::B2DHomMatrix aMat;
+ const double fDistance((fDiscreteLineWidth - 1.0) * 0.5);
+
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, -fDistance);
+ aMat.set(1, 2, 0.0);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, fDistance);
+ aMat.set(1, 2, -fDistance);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, fDistance);
+ aMat.set(1, 2, fDistance);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, -fDistance);
+ aMat.set(1, 2, fDistance);
+ aCandidate.transform(aMat);
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+ bDone = true;
+ }
+ else
+ {
+ // #i101491# line width above 3.0
+ }
+ }
+ else
+ {
+ if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.5))
+ {
+ // line width below 1.5, draw the basic hairline polygon
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+ bDone = true;
+ }
+ else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.5))
+ {
+ // line width is in range ]1.5 .. 2.5], use four hairlines
+ // drawn in a square
+ basegfx::B2DHomMatrix aMat;
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, 1.0);
+ aMat.set(1, 2, 0.0);
+ aCandidate.transform(aMat);
+
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, 0.0);
+ aMat.set(1, 2, 1.0);
+ aCandidate.transform(aMat);
+
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+
+ aMat.set(0, 2, -1.0);
+ aMat.set(1, 2, 0.0);
+ aCandidate.transform(aMat);
+
+ mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
+ bDone = true;
+ }
+ else
+ {
+ // #i101491# line width is above 2.5
+ }
+ }
+
+ if(!bDone && rPolygonStrokeCandidate.getB2DPolygon().count() > 1000)
+ {
+ // #i101491# If the polygon complexity uses more than a given amount, do
+ // use OuputDevice::DrawPolyLine directly; this will avoid buffering all
+ // decompositions in primtives (memory) and fallback to old line painting
+ // for very complex polygons, too
+ mpOutputDevice->DrawPolyLine(aCandidate, fDiscreteLineWidth, rLineAttribute.getLineJoin());
+ bDone = true;
+ }
+ }
+ }
+ }
+
+ if(!bDone)
+ {
+ // remeber that we enter a PolygonStrokePrimitive2D decomposition,
+ // used for AA thick line drawing
+ mnPolygonStrokePrimitive2D++;
+
+ // line width is big enough for standard filled polygon visualisation or zero
+ process(rPolygonStrokeCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // leave PolygonStrokePrimitive2D
+ mnPolygonStrokePrimitive2D--;
+ }
+ }
+
+ void VclProcessor2D::adaptLineToFillDrawMode() const
+ {
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+
+ if(nOriginalDrawMode & (DRAWMODE_BLACKLINE|DRAWMODE_GRAYLINE|DRAWMODE_GHOSTEDLINE|DRAWMODE_WHITELINE|DRAWMODE_SETTINGSLINE))
+ {
+ sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode);
+
+ if(nOriginalDrawMode & DRAWMODE_BLACKLINE)
+ {
+ nAdaptedDrawMode |= DRAWMODE_BLACKFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_GRAYLINE)
+ {
+ nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_GHOSTEDLINE)
+ {
+ nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_WHITELINE)
+ {
+ nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_SETTINGSLINE)
+ {
+ nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL;
+ }
+
+ mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
+ }
+ }
+
+ void VclProcessor2D::adaptTextToFillDrawMode() const
+ {
+ const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ if(nOriginalDrawMode & (DRAWMODE_BLACKTEXT|DRAWMODE_GRAYTEXT|DRAWMODE_GHOSTEDTEXT|DRAWMODE_WHITETEXT|DRAWMODE_SETTINGSTEXT))
+ {
+ sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode);
+
+ if(nOriginalDrawMode & DRAWMODE_BLACKTEXT)
+ {
+ nAdaptedDrawMode |= DRAWMODE_BLACKFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_GRAYTEXT)
+ {
+ nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_GHOSTEDTEXT)
+ {
+ nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_WHITETEXT)
+ {
+ nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
+ }
+
+ if(nOriginalDrawMode & DRAWMODE_SETTINGSTEXT)
+ {
+ nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
+ }
+ else
+ {
+ nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL;
+ }
+
+ mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // process support
+
+ VclProcessor2D::VclProcessor2D(
+ const geometry::ViewInformation2D& rViewInformation,
+ OutputDevice& rOutDev)
+ : BaseProcessor2D(rViewInformation),
+ mpOutputDevice(&rOutDev),
+ maBColorModifierStack(),
+ maCurrentTransformation(),
+ maDrawinglayerOpt(),
+ mnPolygonStrokePrimitive2D(0)
+ {
+ // set digit language, derived from SvtCTLOptions to have the correct
+ // number display for arabic/hindi numerals
+ const SvtCTLOptions aSvtCTLOptions;
+ LanguageType eLang(LANGUAGE_SYSTEM);
+
+ if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ }
+ else if(SvtCTLOptions::NUMERALS_ARABIC == aSvtCTLOptions.GetCTLTextNumerals())
+ {
+ eLang = LANGUAGE_ENGLISH;
+ }
+ else
+ {
+ eLang = (LanguageType)Application::GetSettings().GetLanguage();
+ }
+
+ rOutDev.SetDigitLanguage(eLang);
+ }
+
+ VclProcessor2D::~VclProcessor2D()
+ {
+ }
+ } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/baseprocessor3d.cxx b/drawinglayer/source/processor3d/baseprocessor3d.cxx
new file mode 100644
index 000000000000..7d630f2522be
--- /dev/null
+++ b/drawinglayer/source/processor3d/baseprocessor3d.cxx
@@ -0,0 +1,122 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: baseprocessor3d.cxx,v $
+ *
+ * $Revision: 1.7 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/baseprocessor3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ void BaseProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D& /*rCandidate*/)
+ {
+ }
+
+ BaseProcessor3D::BaseProcessor3D(const geometry::ViewInformation3D& rViewInformation)
+ : maViewInformation3D(rViewInformation)
+ {
+ }
+
+ BaseProcessor3D::~BaseProcessor3D()
+ {
+ }
+
+ void BaseProcessor3D::process(const primitive3d::Primitive3DSequence& rSource)
+ {
+ if(rSource.hasElements())
+ {
+ const sal_Int32 nCount(rSource.getLength());
+
+ for(sal_Int32 a(0L); a < nCount; a++)
+ {
+ // get reference
+ const primitive3d::Primitive3DReference xReference(rSource[a]);
+
+ if(xReference.is())
+ {
+ // try to cast to BasePrimitive3D implementation
+ const primitive3d::BasePrimitive3D* pBasePrimitive = dynamic_cast< const primitive3d::BasePrimitive3D* >(xReference.get());
+
+ if(pBasePrimitive)
+ {
+ processBasePrimitive3D(*pBasePrimitive);
+ }
+ else
+ {
+ // unknown implementation, use UNO API call instead and process recursively
+ const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation3D().getViewInformationSequence());
+ process(xReference->getDecomposition(rViewParameters));
+ }
+ }
+ }
+ }
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ CollectingProcessor3D::CollectingProcessor3D(const geometry::ViewInformation3D& rViewInformation)
+ : BaseProcessor3D(rViewInformation),
+ maPrimitive3DSequence()
+ {
+ }
+
+ CollectingProcessor3D::~CollectingProcessor3D()
+ {
+ }
+
+ void CollectingProcessor3D::process(const primitive3d::Primitive3DSequence& rSource)
+ {
+ // accept everything
+ primitive3d::appendPrimitive3DSequenceToPrimitive3DSequence(maPrimitive3DSequence, rSource);
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/cutfindprocessor3d.cxx b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx
new file mode 100644
index 000000000000..99f5801c60e3
--- /dev/null
+++ b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx
@@ -0,0 +1,199 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: zbufferprocessor3d.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/cutfindprocessor3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolygon.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ CutFindProcessor::CutFindProcessor(const geometry::ViewInformation3D& rViewInformation,
+ const basegfx::B3DPoint& rFront,
+ const basegfx::B3DPoint& rBack,
+ bool bAnyHit)
+ : BaseProcessor3D(rViewInformation),
+ maFront(rFront),
+ maBack(rBack),
+ maResult(),
+ maCombinedTransform(),
+ mbAnyHit(bAnyHit)
+ {
+ }
+
+ void CutFindProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
+ {
+ if(getAnyHit() && maResult.size())
+ {
+ // stop processing as soon as a hit was recognized
+ return;
+ }
+
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
+ {
+ // transform group.
+ const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
+
+ // remember old and transform front, back to object coordinates
+ const basegfx::B3DPoint aLastFront(maFront);
+ const basegfx::B3DPoint aLastBack(maBack);
+ basegfx::B3DHomMatrix aInverseTrans(rPrimitive.getTransformation());
+ aInverseTrans.invert();
+ maFront *= aInverseTrans;
+ maBack *= aInverseTrans;
+
+ // remember current and create new transformation; add new object transform from right side
+ const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
+ const geometry::ViewInformation3D aNewViewInformation3D(
+ aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
+ aLastViewInformation3D.getOrientation(),
+ aLastViewInformation3D.getProjection(),
+ aLastViewInformation3D.getDeviceToView(),
+ aLastViewInformation3D.getViewTime(),
+ aLastViewInformation3D.getExtendedInformationSequence());
+ updateViewInformation(aNewViewInformation3D);
+
+ // #i102956# remember needed back-transform for found cuts (combine from right side)
+ const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform);
+ maCombinedTransform = maCombinedTransform * rPrimitive.getTransformation();
+
+ // let break down
+ process(rPrimitive.getChildren());
+
+ // restore transformations and front, back
+ maCombinedTransform = aLastCombinedTransform;
+ updateViewInformation(aLastViewInformation3D);
+ maFront = aLastFront;
+ maBack = aLastBack;
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
+ {
+ // PolygonHairlinePrimitive3D, not used for hit test with planes, ignore. This
+ // means that also thick line expansion will not be hit-tested as
+ // PolyPolygonMaterialPrimitive3D
+ break;
+ }
+ case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
+ {
+ // #i97321#
+ // For HatchTexturePrimitive3D, do not use the decomposition since it will produce
+ // clipped hatch lines in 3D. It can be used when the hatch also has a filling, but for
+ // simplicity, just use the children which are the PolyPolygonMaterialPrimitive3D
+ // which define the hatched areas anyways; for HitTest this is more than adequate
+ const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rCandidate);
+ process(rPrimitive.getChildren());
+ break;
+ }
+ case PRIMITIVE3D_ID_HITTESTPRIMITIVE3D :
+ {
+ // HitTestPrimitive3D, force usage due to we are doing a hit test and this
+ // primitive only gets generated on 3d objects without fill, exactly for this
+ // purpose
+ const primitive3d::HitTestPrimitive3D& rPrimitive = static_cast< const primitive3d::HitTestPrimitive3D& >(rCandidate);
+ process(rPrimitive.getChildren());
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // PolyPolygonMaterialPrimitive3D
+ const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
+
+ if(!maFront.equal(maBack))
+ {
+ const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon();
+ const sal_uInt32 nPolyCount(rPolyPolygon.count());
+
+ if(nPolyCount)
+ {
+ const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(0));
+ const sal_uInt32 nPointCount(aPolygon.count());
+
+ if(nPointCount > 2)
+ {
+ const basegfx::B3DVector aPlaneNormal(aPolygon.getNormal());
+
+ if(!aPlaneNormal.equalZero())
+ {
+ const basegfx::B3DPoint aPointOnPlane(aPolygon.getB3DPoint(0));
+ double fCut(0.0);
+
+ if(basegfx::tools::getCutBetweenLineAndPlane(aPlaneNormal, aPointOnPlane, maFront, maBack, fCut))
+ {
+ const basegfx::B3DPoint aCutPoint(basegfx::interpolate(maFront, maBack, fCut));
+
+ if(basegfx::tools::isInside(rPolyPolygon, aCutPoint, false))
+ {
+ // #i102956# add result. Do not forget to do this in the coordinate
+ // system the processor get started with, so use the collected
+ // combined transformation from processed TransformPrimitive3D's
+ maResult.push_back(maCombinedTransform * aCutPoint);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get3DDecomposition(getViewInformation3D()));
+ break;
+ }
+ }
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
new file mode 100644
index 000000000000..d9194ca4b5eb
--- /dev/null
+++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
@@ -0,0 +1,578 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: defaultprocessor3d.cxx,v $
+ *
+ * $Revision: 1.13 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/defaultprocessor3d.hxx>
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/texture/texture.hxx>
+#include <drawinglayer/texture/texture3d.hxx>
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+#include <drawinglayer/attribute/materialattribute3d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <drawinglayer/attribute/sdrattribute3d.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ void DefaultProcessor3D::impRenderGradientTexturePrimitive3D(const primitive3d::GradientTexturePrimitive3D& rPrimitive, bool bTransparence)
+ {
+ const primitive3d::Primitive3DSequence& rSubSequence = rPrimitive.getChildren();
+
+ if(rSubSequence.hasElements())
+ {
+ // rescue values
+ const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
+ const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
+ const bool bOldSimpleTextureActive(mbSimpleTextureActive);
+ texture::GeoTexSvx* pOldTex = (bTransparence) ? mpTransparenceGeoTexSvx : mpGeoTexSvx;
+
+ // create texture
+ const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getGradient();
+ const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
+ const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle());
+ sal_uInt32 nSteps(rFillGradient.getSteps());
+ const basegfx::BColor aStart(rFillGradient.getStartColor());
+ const basegfx::BColor aEnd(rFillGradient.getEndColor());
+ const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
+ texture::GeoTexSvx* pNewTex = 0L;
+
+ if(nMaxSteps)
+ {
+ // there IS a color distance
+ if(nSteps == 0L)
+ {
+ nSteps = nMaxSteps;
+ }
+
+ if(nSteps < 2L)
+ {
+ nSteps = 2L;
+ }
+
+ if(nSteps > nMaxSteps)
+ {
+ nSteps = nMaxSteps;
+ }
+
+ switch(aGradientStyle)
+ {
+ case attribute::GRADIENTSTYLE_LINEAR:
+ {
+ pNewTex = new texture::GeoTexSvxGradientLinear(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), -rFillGradient.getAngle());
+ break;
+ }
+ case attribute::GRADIENTSTYLE_AXIAL:
+ {
+ pNewTex = new texture::GeoTexSvxGradientAxial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), -rFillGradient.getAngle());
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RADIAL:
+ {
+ pNewTex = new texture::GeoTexSvxGradientRadial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY());
+ break;
+ }
+ case attribute::GRADIENTSTYLE_ELLIPTICAL:
+ {
+ pNewTex = new texture::GeoTexSvxGradientElliptical(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle());
+ break;
+ }
+ case attribute::GRADIENTSTYLE_SQUARE:
+ {
+ pNewTex = new texture::GeoTexSvxGradientSquare(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle());
+ break;
+ }
+ case attribute::GRADIENTSTYLE_RECT:
+ {
+ pNewTex = new texture::GeoTexSvxGradientRect(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle());
+ break;
+ }
+ }
+
+ mbSimpleTextureActive = false;
+ }
+ else
+ {
+ // no color distance -> same color, use simple texture
+ pNewTex = new texture::GeoTexSvxMono(aStart, 1.0 - aStart.luminance());
+ mbSimpleTextureActive = true;
+ }
+
+ // set created texture
+ if(bTransparence)
+ {
+ mpTransparenceGeoTexSvx = pNewTex;
+ }
+ else
+ {
+ mpGeoTexSvx = pNewTex;
+ }
+
+ // process sub-list
+ process(rSubSequence);
+
+ // delete texture
+ delete pNewTex;
+
+ // restore values
+ mbModulate = bOldModulate;
+ mbFilter = bOldFilter;
+ mbSimpleTextureActive = bOldSimpleTextureActive;
+
+ if(bTransparence)
+ {
+ mpTransparenceGeoTexSvx = pOldTex;
+ }
+ else
+ {
+ mpGeoTexSvx = pOldTex;
+ }
+ }
+ }
+
+ void DefaultProcessor3D::impRenderHatchTexturePrimitive3D(const primitive3d::HatchTexturePrimitive3D& rPrimitive)
+ {
+ const primitive3d::Primitive3DSequence& rSubSequence = rPrimitive.getChildren();
+
+ if(rSubSequence.hasElements())
+ {
+ // rescue values
+ const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
+ const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
+ texture::GeoTexSvx* pOldTex = mpGeoTexSvx;
+
+ // calculate logic pixel size in object coordinates. Create transformation view
+ // to object by inverting ObjectToView
+ basegfx::B3DHomMatrix aInvObjectToView(getViewInformation3D().getObjectToView());
+ aInvObjectToView.invert();
+
+ // back-project discrete coordinates to object coordinates and extract
+ // maximum distance
+ const basegfx::B3DPoint aZero(aInvObjectToView * basegfx::B3DPoint(0.0, 0.0, 0.0));
+ const basegfx::B3DPoint aOne(aInvObjectToView * basegfx::B3DPoint(1.0, 1.0, 1.0));
+ const basegfx::B3DVector aLogicPixel(aOne - aZero);
+ double fLogicPixelSizeWorld(::std::max(::std::max(fabs(aLogicPixel.getX()), fabs(aLogicPixel.getY())), fabs(aLogicPixel.getZ())));
+
+ // calculate logic pixel size in texture coordinates
+ const double fLogicTexSizeX(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getX());
+ const double fLogicTexSizeY(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getY());
+ const double fLogicTexSize(fLogicTexSizeX > fLogicTexSizeY ? fLogicTexSizeX : fLogicTexSizeY);
+
+ // create texture and set
+ texture::GeoTexSvxMultiHatch* pNewTex = new texture::GeoTexSvxMultiHatch(rPrimitive, fLogicTexSize);
+ mpGeoTexSvx = pNewTex;
+
+ // process sub-list
+ process(rSubSequence);
+
+ // delete texture
+ delete mpGeoTexSvx;
+
+ // restore values
+ mbModulate = bOldModulate;
+ mbFilter = bOldFilter;
+ mpGeoTexSvx = pOldTex;
+ }
+ }
+
+ void DefaultProcessor3D::impRenderBitmapTexturePrimitive3D(const primitive3d::BitmapTexturePrimitive3D& rPrimitive)
+ {
+ const primitive3d::Primitive3DSequence& rSubSequence = rPrimitive.getChildren();
+
+ if(rSubSequence.hasElements())
+ {
+ // rescue values
+ const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate();
+ const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter();
+ texture::GeoTexSvx* pOldTex = mpGeoTexSvx;
+
+ // create texture
+ const attribute::FillBitmapAttribute& rFillBitmapAttribute = rPrimitive.getBitmap();
+
+ if(rFillBitmapAttribute.getTiling())
+ {
+ mpGeoTexSvx = new texture::GeoTexSvxBitmapTiled(
+ rFillBitmapAttribute.getBitmap(),
+ rFillBitmapAttribute.getTopLeft() * rPrimitive.getTextureSize(),
+ rFillBitmapAttribute.getSize() * rPrimitive.getTextureSize());
+ }
+ else
+ {
+ mpGeoTexSvx = new texture::GeoTexSvxBitmap(
+ rFillBitmapAttribute.getBitmap(),
+ rFillBitmapAttribute.getTopLeft() * rPrimitive.getTextureSize(),
+ rFillBitmapAttribute.getSize() * rPrimitive.getTextureSize());
+ }
+
+ // process sub-list
+ process(rSubSequence);
+
+ // delete texture
+ delete mpGeoTexSvx;
+
+ // restore values
+ mbModulate = bOldModulate;
+ mbFilter = bOldFilter;
+ mpGeoTexSvx = pOldTex;
+ }
+ }
+
+ void DefaultProcessor3D::impRenderModifiedColorPrimitive3D(const primitive3d::ModifiedColorPrimitive3D& rModifiedCandidate)
+ {
+ const primitive3d::Primitive3DSequence& rSubSequence = rModifiedCandidate.getChildren();
+
+ if(rSubSequence.hasElements())
+ {
+ // put modifier on stack
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+
+ // process sub-list
+ process(rModifiedCandidate.getChildren());
+
+ // remove modifier from stack
+ maBColorModifierStack.pop();
+ }
+ }
+
+ void DefaultProcessor3D::impRenderPolygonHairlinePrimitive3D(const primitive3d::PolygonHairlinePrimitive3D& rPrimitive)
+ {
+ basegfx::B3DPolygon aHairline(rPrimitive.getB3DPolygon());
+
+ if(aHairline.count())
+ {
+ // hairlines need no extra data, clear it
+ aHairline.clearTextureCoordinates();
+ aHairline.clearNormals();
+ aHairline.clearBColors();
+
+ // transform to device coordinates (-1.0 .. 1.0) and check for visibility
+ aHairline.transform(getViewInformation3D().getObjectToView());
+ const basegfx::B3DRange a3DRange(basegfx::tools::getRange(aHairline));
+ const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY());
+
+ if(a2DRange.overlaps(maRasterRange))
+ {
+ const attribute::MaterialAttribute3D aMaterial(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
+
+ rasterconvertB3DPolygon(aMaterial, aHairline);
+ }
+ }
+ }
+
+ void DefaultProcessor3D::impRenderPolyPolygonMaterialPrimitive3D(const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive)
+ {
+ basegfx::B3DPolyPolygon aFill(rPrimitive.getB3DPolyPolygon());
+ basegfx::BColor aObjectColor(rPrimitive.getMaterial().getColor());
+ bool bPaintIt(aFill.count());
+
+ // #i98295# get ShadeMode. Correct early when only flat is possible due to missing normals
+ const ::com::sun::star::drawing::ShadeMode aShadeMode(
+ aFill.areNormalsUsed() ?
+ getSdrSceneAttribute().getShadeMode() : ::com::sun::star::drawing::ShadeMode_FLAT);
+
+ if(bPaintIt)
+ {
+ // get rid of texture coordinates if there is no texture
+ if(aFill.areTextureCoordinatesUsed() && !getGeoTexSvx() && !getTransparenceGeoTexSvx())
+ {
+ aFill.clearTextureCoordinates();
+ }
+
+ // #i98295# get rid of normals and color early when not needed
+ if(::com::sun::star::drawing::ShadeMode_FLAT == aShadeMode)
+ {
+ aFill.clearNormals();
+ aFill.clearBColors();
+ }
+
+ // transform to device coordinates (-1.0 .. 1.0) and check for visibility
+ aFill.transform(getViewInformation3D().getObjectToView());
+ const basegfx::B3DRange a3DRange(basegfx::tools::getRange(aFill));
+ const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY());
+
+ bPaintIt = a2DRange.overlaps(maRasterRange);
+ }
+
+ // check if it shall be painted regarding hiding of normals (backface culling)
+ if(bPaintIt && !rPrimitive.getDoubleSided())
+ {
+ // get plane normal of polygon in view coordinates (with ZBuffer values),
+ // left-handed coordinate system
+ const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0L).getNormal());
+
+ if(aPlaneNormal.getZ() > 0.0)
+ {
+ bPaintIt = false;
+ }
+ }
+
+ if(bPaintIt)
+ {
+ // prepare ObjectToEye in NormalTransform
+ basegfx::B3DHomMatrix aNormalTransform(getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation());
+
+ if(getSdrSceneAttribute().getTwoSidedLighting())
+ {
+ // get plane normal of polygon in view coordinates (with ZBuffer values),
+ // left-handed coordinate system
+ const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0L).getNormal());
+
+ if(aPlaneNormal.getZ() > 0.0)
+ {
+ // mirror normals
+ aNormalTransform.scale(-1.0, -1.0, -1.0);
+ }
+ }
+
+ switch(aShadeMode)
+ {
+ case ::com::sun::star::drawing::ShadeMode_PHONG:
+ {
+ // phong shading. Transform normals to eye coor
+ aFill.transformNormals(aNormalTransform);
+ break;
+ }
+ case ::com::sun::star::drawing::ShadeMode_SMOOTH:
+ {
+ // gouraud shading. Transform normals to eye coor
+ aFill.transformNormals(aNormalTransform);
+
+ // prepare color model parameters, evtl. use blend color
+ const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor());
+ const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular());
+ const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission());
+ const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity());
+
+ // solve color model for each normal vector, set colors at points. Clear normals.
+ for(sal_uInt32 a(0L); a < aFill.count(); a++)
+ {
+ basegfx::B3DPolygon aPartFill(aFill.getB3DPolygon(a));
+
+ for(sal_uInt32 b(0L); b < aPartFill.count(); b++)
+ {
+ // solve color model. Transform normal to eye coor
+ const basegfx::B3DVector aNormal(aPartFill.getNormal(b));
+ const basegfx::BColor aSolvedColor(getSdrLightingAttribute().solveColorModel(aNormal, aColor, rSpecular, rEmission, nSpecularIntensity));
+ aPartFill.setBColor(b, aSolvedColor);
+ }
+
+ // clear normals on this part polygon and write it back
+ aPartFill.clearNormals();
+ aFill.setB3DPolygon(a, aPartFill);
+ }
+ break;
+ }
+ case ::com::sun::star::drawing::ShadeMode_FLAT:
+ {
+ // flat shading. Get plane vector in eye coordinates
+ const basegfx::B3DVector aPlaneEyeNormal(aNormalTransform * rPrimitive.getB3DPolyPolygon().getB3DPolygon(0L).getNormal());
+
+ // prepare color model parameters, evtl. use blend color
+ const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor());
+ const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular());
+ const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission());
+ const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity());
+
+ // solve color model for plane vector and use that color for whole plane
+ aObjectColor = getSdrLightingAttribute().solveColorModel(aPlaneEyeNormal, aColor, rSpecular, rEmission, nSpecularIntensity);
+ break;
+ }
+ default: // case ::com::sun::star::drawing::ShadeMode_DRAFT:
+ {
+ // draft, just use object color which is already set. Delete all other infos
+ aFill.clearNormals();
+ aFill.clearBColors();
+ break;
+ }
+ }
+
+ // draw it to ZBuffer
+ const attribute::MaterialAttribute3D aMaterial(
+ maBColorModifierStack.getModifiedColor(aObjectColor),
+ rPrimitive.getMaterial().getSpecular(),
+ rPrimitive.getMaterial().getEmission(),
+ rPrimitive.getMaterial().getSpecularIntensity());
+
+ rasterconvertB3DPolyPolygon(aMaterial, aFill);
+ }
+ }
+
+ void DefaultProcessor3D::impRenderTransformPrimitive3D(const primitive3d::TransformPrimitive3D& rTransformCandidate)
+ {
+ // transform group. Remember current transformations
+ const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
+
+ // create new transformation; add new object transform from right side
+ const geometry::ViewInformation3D aNewViewInformation3D(
+ aLastViewInformation3D.getObjectTransformation() * rTransformCandidate.getTransformation(),
+ aLastViewInformation3D.getOrientation(),
+ aLastViewInformation3D.getProjection(),
+ aLastViewInformation3D.getDeviceToView(),
+ aLastViewInformation3D.getViewTime(),
+ aLastViewInformation3D.getExtendedInformationSequence());
+ updateViewInformation(aNewViewInformation3D);
+
+ // let break down recursively
+ process(rTransformCandidate.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation3D);
+ }
+
+ void DefaultProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rBasePrimitive)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ switch(rBasePrimitive.getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D :
+ {
+ // GradientTexturePrimitive3D
+ const primitive3d::GradientTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::GradientTexturePrimitive3D& >(rBasePrimitive);
+ impRenderGradientTexturePrimitive3D(rPrimitive, false);
+ break;
+ }
+ case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
+ {
+ // HatchTexturePrimitive3D
+ static bool bDoHatchDecomposition(false);
+
+ if(bDoHatchDecomposition)
+ {
+ // let break down
+ process(rBasePrimitive.get3DDecomposition(getViewInformation3D()));
+ }
+ else
+ {
+ // hatchTexturePrimitive3D
+ const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rBasePrimitive);
+ impRenderHatchTexturePrimitive3D(rPrimitive);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D :
+ {
+ // BitmapTexturePrimitive3D
+ const primitive3d::BitmapTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::BitmapTexturePrimitive3D& >(rBasePrimitive);
+ impRenderBitmapTexturePrimitive3D(rPrimitive);
+ break;
+ }
+ case PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D :
+ {
+ // AlphaTexturePrimitive3D
+ const primitive3d::AlphaTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::AlphaTexturePrimitive3D& >(rBasePrimitive);
+ impRenderGradientTexturePrimitive3D(rPrimitive, true);
+ break;
+ }
+ case PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D :
+ {
+ // ModifiedColorPrimitive3D
+ // Force output to unified color.
+ const primitive3d::ModifiedColorPrimitive3D& rPrimitive = static_cast< const primitive3d::ModifiedColorPrimitive3D& >(rBasePrimitive);
+ impRenderModifiedColorPrimitive3D(rPrimitive);
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
+ {
+ // directdraw of PolygonHairlinePrimitive3D
+ const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rBasePrimitive);
+ impRenderPolygonHairlinePrimitive3D(rPrimitive);
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // directdraw of PolyPolygonMaterialPrimitive3D
+ const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rBasePrimitive);
+ impRenderPolyPolygonMaterialPrimitive3D(rPrimitive);
+ break;
+ }
+ case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
+ {
+ // transform group (TransformPrimitive3D)
+ impRenderTransformPrimitive3D(static_cast< const primitive3d::TransformPrimitive3D& >(rBasePrimitive));
+ break;
+ }
+ default:
+ {
+ // process recursively
+ process(rBasePrimitive.get3DDecomposition(getViewInformation3D()));
+ break;
+ }
+ }
+ }
+
+ DefaultProcessor3D::DefaultProcessor3D(
+ const geometry::ViewInformation3D& rViewInformation,
+ const attribute::SdrSceneAttribute& rSdrSceneAttribute,
+ const attribute::SdrLightingAttribute& rSdrLightingAttribute)
+ : BaseProcessor3D(rViewInformation),
+ mrSdrSceneAttribute(rSdrSceneAttribute),
+ mrSdrLightingAttribute(rSdrLightingAttribute),
+ maRasterRange(),
+ maBColorModifierStack(),
+ mpGeoTexSvx(0),
+ mpTransparenceGeoTexSvx(0),
+ mbModulate(false),
+ mbFilter(false),
+ mbSimpleTextureActive(false)
+ {
+ // a derivation has to set maRasterRange which is used in the basic render methods.
+ // Setting to default here ([0.0 .. 1.0] in X,Y) to avoid problems
+ maRasterRange.expand(basegfx::B2DTuple(0.0, 0.0));
+ maRasterRange.expand(basegfx::B2DTuple(1.0, 1.0));
+ }
+
+ DefaultProcessor3D::~DefaultProcessor3D()
+ {
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/geometry2dextractor.cxx b/drawinglayer/source/processor3d/geometry2dextractor.cxx
new file mode 100644
index 000000000000..8c19a4a2e3b8
--- /dev/null
+++ b/drawinglayer/source/processor3d/geometry2dextractor.cxx
@@ -0,0 +1,178 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: geometry2dextractor.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/geometry2dextractor.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ // as tooling, the process() implementation takes over API handling and calls this
+ // virtual render method when the primitive implementation is BasePrimitive3D-based.
+ void Geometry2DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
+ {
+ // transform group. Remember current transformations
+ const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
+ const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
+
+ // create new transformation; add new object transform from right side
+ const geometry::ViewInformation3D aNewViewInformation3D(
+ aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
+ aLastViewInformation3D.getOrientation(),
+ aLastViewInformation3D.getProjection(),
+ aLastViewInformation3D.getDeviceToView(),
+ aLastViewInformation3D.getViewTime(),
+ aLastViewInformation3D.getExtendedInformationSequence());
+ updateViewInformation(aNewViewInformation3D);
+
+ // let break down recursively
+ process(rPrimitive.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation3D);
+ break;
+ }
+ case PRIMITIVE3D_ID_MODIFIEDCOLORPRIMITIVE3D :
+ {
+ // ModifiedColorPrimitive3D; push, process and pop
+ const primitive3d::ModifiedColorPrimitive3D& rModifiedCandidate = static_cast< const primitive3d::ModifiedColorPrimitive3D& >(rCandidate);
+ const primitive3d::Primitive3DSequence& rSubSequence = rModifiedCandidate.getChildren();
+
+ if(rSubSequence.hasElements())
+ {
+ maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
+ process(rModifiedCandidate.getChildren());
+ maBColorModifierStack.pop();
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
+ {
+ // PolygonHairlinePrimitive3D
+ const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rCandidate);
+ basegfx::B2DPolygon a2DHairline(basegfx::tools::createB2DPolygonFromB3DPolygon(rPrimitive.getB3DPolygon(), getViewInformation3D().getObjectToView()));
+
+ if(a2DHairline.count())
+ {
+ a2DHairline.transform(getObjectTransformation());
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(a2DHairline, aModifiedColor));
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(maPrimitive2DSequence, xRef);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // PolyPolygonMaterialPrimitive3D
+ const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
+ basegfx::B2DPolyPolygon a2DFill(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rPrimitive.getB3DPolyPolygon(), getViewInformation3D().getObjectToView()));
+
+ if(a2DFill.count())
+ {
+ a2DFill.transform(getObjectTransformation());
+ const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(rPrimitive.getMaterial().getColor()));
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(a2DFill, aModifiedColor));
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(maPrimitive2DSequence, xRef);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_GRADIENTTEXTUREPRIMITIVE3D :
+ case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
+ case PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D :
+ case PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D :
+ case PRIMITIVE3D_ID_UNIFIEDALPHATEXTUREPRIMITIVE3D :
+ {
+ // TexturePrimitive3D: Process children, do not try to decompose
+ const primitive3d::TexturePrimitive3D& rTexturePrimitive = static_cast< const primitive3d::TexturePrimitive3D& >(rCandidate);
+ const primitive3d::Primitive3DSequence aChildren(rTexturePrimitive.getChildren());
+
+ if(aChildren.hasElements())
+ {
+ process(aChildren);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_SHADOWPRIMITIVE3D :
+ {
+ // accept but ignore labels and shadow; these should be extracted seperately
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get3DDecomposition(getViewInformation3D()));
+ break;
+ }
+ }
+ }
+
+ Geometry2DExtractingProcessor::Geometry2DExtractingProcessor(
+ const geometry::ViewInformation3D& rViewInformation,
+ const basegfx::B2DHomMatrix& rObjectTransformation)
+ : BaseProcessor3D(rViewInformation),
+ maPrimitive2DSequence(),
+ maObjectTransformation(rObjectTransformation),
+ maBColorModifierStack()
+ {
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/makefile.mk b/drawinglayer/source/processor3d/makefile.mk
new file mode 100644
index 000000000000..2ae2ae52f2f2
--- /dev/null
+++ b/drawinglayer/source/processor3d/makefile.mk
@@ -0,0 +1,58 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.5 $
+#
+# last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+#
+# 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=processor3d
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/baseprocessor3d.obj \
+ $(SLO)$/cutfindprocessor3d.obj \
+ $(SLO)$/defaultprocessor3d.obj \
+ $(SLO)$/shadow3dextractor.obj \
+ $(SLO)$/geometry2dextractor.obj \
+ $(SLO)$/zbufferprocessor3d.obj
+
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx
new file mode 100644
index 000000000000..66d3c073854f
--- /dev/null
+++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx
@@ -0,0 +1,306 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: shadow3dextractor.cxx,v $
+ *
+ * $Revision: 1.9 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/shadow3dextractor.hxx>
+#include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
+#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
+#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ // as tooling, the process() implementation takes over API handling and calls this
+ // virtual render method when the primitive implementation is BasePrimitive3D-based.
+ void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ switch(rCandidate.getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_SHADOWPRIMITIVE3D :
+ {
+ // shadow3d object. Call recursive with content and start conversion
+ const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate);
+
+ // set new target
+ primitive2d::Primitive2DSequence aNewSubList;
+ primitive2d::Primitive2DSequence* pLastTargetSequence = mpPrimitive2DSequence;
+ mpPrimitive2DSequence = &aNewSubList;
+
+ // activate convert
+ const bool bLastConvert(mbConvert);
+ mbConvert = true;
+
+ // set projection flag
+ const bool bLastUseProjection(mbUseProjection);
+ mbUseProjection = rPrimitive.getShadow3D();
+
+ // process content
+ process(rPrimitive.getChildren());
+
+ // restore values
+ mbUseProjection = bLastUseProjection;
+ mbConvert = bLastConvert;
+ mpPrimitive2DSequence = pLastTargetSequence;
+
+ // create 2d shadow primitive with result
+ const primitive2d::Primitive2DReference xRef(new primitive2d::ShadowPrimitive2D(rPrimitive.getShadowTransform(), rPrimitive.getShadowColor(), aNewSubList));
+
+ if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0))
+ {
+ // create simpleTransparencePrimitive, add created primitives
+ const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1L);
+ const primitive2d::Primitive2DReference xRef2(new primitive2d::UnifiedAlphaPrimitive2D(aNewTransPrimitiveVector, rPrimitive.getShadowTransparence()));
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef2);
+ }
+ else
+ {
+ // add directly
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
+ {
+ // transform group. Remember current transformations
+ const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
+ const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
+
+ // create new transformation; add new object transform from right side
+ const geometry::ViewInformation3D aNewViewInformation3D(
+ aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
+ aLastViewInformation3D.getOrientation(),
+ aLastViewInformation3D.getProjection(),
+ aLastViewInformation3D.getDeviceToView(),
+ aLastViewInformation3D.getViewTime(),
+ aLastViewInformation3D.getExtendedInformationSequence());
+ updateViewInformation(aNewViewInformation3D);
+
+ if(mbShadowProjectionIsValid)
+ {
+ // update buffered WorldToEye and EyeToView
+ maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
+ maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
+ }
+
+ // let break down
+ process(rPrimitive.getChildren());
+
+ // restore transformations
+ updateViewInformation(aLastViewInformation3D);
+
+ if(mbShadowProjectionIsValid)
+ {
+ // update buffered WorldToEye and EyeToView
+ maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
+ maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
+ {
+ // PolygonHairlinePrimitive3D
+ if(mbConvert)
+ {
+ const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rCandidate);
+ basegfx::B2DPolygon a2DHairline;
+
+ if(mbUseProjection)
+ {
+ if(mbShadowProjectionIsValid)
+ {
+ a2DHairline = impDoShadowProjection(rPrimitive.getB3DPolygon());
+ }
+ }
+ else
+ {
+ a2DHairline = basegfx::tools::createB2DPolygonFromB3DPolygon(rPrimitive.getB3DPolygon(), getViewInformation3D().getObjectToView());
+ }
+
+ if(a2DHairline.count())
+ {
+ a2DHairline.transform(getObjectTransformation());
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(a2DHairline, maPrimitiveColor));
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ }
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // PolyPolygonMaterialPrimitive3D
+ if(mbConvert)
+ {
+ const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
+ basegfx::B2DPolyPolygon a2DFill;
+
+ if(mbUseProjection)
+ {
+ if(mbShadowProjectionIsValid)
+ {
+ a2DFill = impDoShadowProjection(rPrimitive.getB3DPolyPolygon());
+ }
+ }
+ else
+ {
+ a2DFill = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rPrimitive.getB3DPolyPolygon(), getViewInformation3D().getObjectToView());
+ }
+
+ if(a2DFill.count())
+ {
+ a2DFill.transform(getObjectTransformation());
+ const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(a2DFill, maPrimitiveColor));
+ primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ }
+ }
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate.get3DDecomposition(getViewInformation3D()));
+ break;
+ }
+ }
+ }
+
+ Shadow3DExtractingProcessor::Shadow3DExtractingProcessor(
+ const geometry::ViewInformation3D& rViewInformation,
+ const basegfx::B2DHomMatrix& rObjectTransformation,
+ const basegfx::B3DVector& rLightNormal,
+ double fShadowSlant,
+ const basegfx::B3DRange& rContained3DRange)
+ : BaseProcessor3D(rViewInformation),
+ maPrimitive2DSequence(),
+ mpPrimitive2DSequence(&maPrimitive2DSequence),
+ maObjectTransformation(rObjectTransformation),
+ maWorldToEye(),
+ maEyeToView(),
+ maLightNormal(rLightNormal),
+ maShadowPlaneNormal(),
+ maPlanePoint(),
+ mfLightPlaneScalar(0.0),
+ maPrimitiveColor(),
+ mbShadowProjectionIsValid(false),
+ mbConvert(false),
+ mbUseProjection(false)
+ {
+ // normalize light normal, get and normalize shadow plane normal and calculate scalar from it
+ maLightNormal.normalize();
+ maShadowPlaneNormal = basegfx::B3DVector(0.0, sin(fShadowSlant), cos(fShadowSlant));
+ maShadowPlaneNormal.normalize();
+ mfLightPlaneScalar = maLightNormal.scalar(maShadowPlaneNormal);
+
+ // use only when scalar is > 0.0, so the light is in front of the object
+ if(basegfx::fTools::more(mfLightPlaneScalar, 0.0))
+ {
+ // prepare buffered WorldToEye and EyeToView
+ maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
+ maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
+
+ // calculate range to get front edge around which to rotate the shadow's projection
+ basegfx::B3DRange aContained3DRange(rContained3DRange);
+ aContained3DRange.transform(getWorldToEye());
+ maPlanePoint.setX(maShadowPlaneNormal.getX() < 0.0 ? aContained3DRange.getMinX() : aContained3DRange.getMaxX());
+ maPlanePoint.setY(maShadowPlaneNormal.getY() > 0.0 ? aContained3DRange.getMinY() : aContained3DRange.getMaxY());
+ maPlanePoint.setZ(aContained3DRange.getMinZ() - (aContained3DRange.getDepth() / 8.0));
+
+ // set flag that shadow projection is prepared and allowed
+ mbShadowProjectionIsValid = true;
+ }
+ }
+
+ basegfx::B2DPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolygon& rSource)
+ {
+ basegfx::B2DPolygon aRetval;
+
+ for(sal_uInt32 a(0L); a < rSource.count(); a++)
+ {
+ // get point, transform to eye coordinate system
+ basegfx::B3DPoint aCandidate(rSource.getB3DPoint(a));
+ aCandidate *= getWorldToEye();
+
+ // we are in eye coordinates
+ // ray is (aCandidate + fCut * maLightNormal)
+ // plane is (maPlanePoint, maShadowPlaneNormal)
+ // maLightNormal.scalar(maShadowPlaneNormal) is already in mfLightPlaneScalar and > 0.0
+ // get cut point of ray with shadow plane
+ const double fCut(basegfx::B3DVector(maPlanePoint - aCandidate).scalar(maShadowPlaneNormal) / mfLightPlaneScalar);
+ aCandidate += maLightNormal * fCut;
+
+ // transform to view, use 2d coordinates
+ aCandidate *= getEyeToView();
+ aRetval.append(basegfx::B2DPoint(aCandidate.getX(), aCandidate.getY()));
+ }
+
+ // copy closed flag
+ aRetval.setClosed(rSource.isClosed());
+
+ return aRetval;
+ }
+
+ basegfx::B2DPolyPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolyPolygon& rSource)
+ {
+ basegfx::B2DPolyPolygon aRetval;
+
+ for(sal_uInt32 a(0L); a < rSource.count(); a++)
+ {
+ aRetval.append(impDoShadowProjection(rSource.getB3DPolygon(a)));
+ }
+
+ return aRetval;
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
new file mode 100644
index 000000000000..b5a59e10a119
--- /dev/null
+++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
@@ -0,0 +1,747 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: zbufferprocessor3d.cxx,v $
+ *
+ * $Revision: 1.5 $
+ *
+ * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $
+ *
+ * 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/processor3d/zbufferprocessor3d.hxx>
+#include <basegfx/raster/bpixelraster.hxx>
+#include <vcl/bmpacc.hxx>
+#include <basegfx/raster/rasterconvert3d.hxx>
+#include <basegfx/raster/bzpixelraster.hxx>
+#include <drawinglayer/attribute/materialattribute3d.hxx>
+#include <drawinglayer/texture/texture.hxx>
+#include <drawinglayer/attribute/sdrattribute3d.hxx>
+#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
+#include <drawinglayer/primitive3d/textureprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
+#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+ BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize)
+ {
+ BitmapEx aRetval;
+ const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth());
+ const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight());
+
+ if(nWidth && nHeight)
+ {
+ const Size aDestSize(nWidth, nHeight);
+ sal_uInt8 nInitAlpha(255);
+ Bitmap aContent(aDestSize, 24);
+ AlphaMask aAlpha(aDestSize, &nInitAlpha);
+ BitmapWriteAccess* pContent = aContent.AcquireWriteAccess();
+ BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess();
+
+ if(pContent && pAlpha)
+ {
+ if(mnAntiAlialize)
+ {
+ const sal_uInt16 nDivisor(mnAntiAlialize * mnAntiAlialize);
+
+ for(sal_uInt32 y(0L); y < nHeight; y++)
+ {
+ for(sal_uInt32 x(0L); x < nWidth; x++)
+ {
+ sal_uInt16 nRed(0);
+ sal_uInt16 nGreen(0);
+ sal_uInt16 nBlue(0);
+ sal_uInt16 nOpacity(0);
+ sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize));
+
+ for(sal_uInt32 c(0); c < mnAntiAlialize; c++)
+ {
+ for(sal_uInt32 d(0); d < mnAntiAlialize; d++)
+ {
+ const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
+ nRed = nRed + rPixel.getRed();
+ nGreen = nGreen + rPixel.getGreen();
+ nBlue = nBlue + rPixel.getBlue();
+ nOpacity = nOpacity + rPixel.getOpacity();
+ }
+
+ nIndex += rRaster.getWidth() - mnAntiAlialize;
+ }
+
+ nOpacity = nOpacity / nDivisor;
+
+ if(nOpacity)
+ {
+ pContent->SetPixel(y, x, BitmapColor(
+ (sal_uInt8)(nRed / nDivisor),
+ (sal_uInt8)(nGreen / nDivisor),
+ (sal_uInt8)(nBlue / nDivisor)));
+ pAlpha->SetPixel(y, x, BitmapColor(255 - (sal_uInt8)nOpacity));
+ }
+ }
+ }
+ }
+ else
+ {
+ sal_uInt32 nIndex(0L);
+
+ for(sal_uInt32 y(0L); y < nHeight; y++)
+ {
+ for(sal_uInt32 x(0L); x < nWidth; x++)
+ {
+ const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++));
+
+ if(rPixel.getOpacity())
+ {
+ pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue()));
+ pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity()));
+ }
+ }
+ }
+ }
+
+ delete pContent;
+ delete pAlpha;
+ }
+
+ aRetval = BitmapEx(aContent, aAlpha);
+
+ // #i101811# set PrefMapMode and PrefSize at newly created Bitmap
+ aRetval.SetPrefMapMode(MAP_100TH_MM);
+ aRetval.SetPrefSize(Size(nWidth, nHeight));
+ }
+
+ return aRetval;
+ }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
+class ZBufferRasterConverter3D : public basegfx::RasterConverter3D
+{
+private:
+ const drawinglayer::processor3d::DefaultProcessor3D& mrProcessor;
+ basegfx::BZPixelRaster& mrBuffer;
+
+ // interpolators for a single line span
+ basegfx::ip_single maIntZ;
+ basegfx::ip_triple maIntColor;
+ basegfx::ip_triple maIntNormal;
+ basegfx::ip_double maIntTexture;
+ basegfx::ip_triple maIntInvTexture;
+
+ // current material to use for ratsreconversion
+ const drawinglayer::attribute::MaterialAttribute3D* mpCurrentMaterial;
+
+ // bitfield
+ // some boolean flags for line span interpolator usages
+ unsigned mbModifyColor : 1;
+ unsigned mbUseTex : 1;
+ unsigned mbHasTexCoor : 1;
+ unsigned mbHasInvTexCoor : 1;
+ unsigned mbUseNrm : 1;
+ unsigned mbUseCol : 1;
+
+ void getTextureCoor(basegfx::B2DPoint& rTarget) const
+ {
+ if(mbHasTexCoor)
+ {
+ rTarget.setX(maIntTexture.getX().getVal());
+ rTarget.setY(maIntTexture.getY().getVal());
+ }
+ else if(mbHasInvTexCoor)
+ {
+ const double fZFactor(maIntInvTexture.getZ().getVal());
+ const double fInvZFactor(basegfx::fTools::equalZero(fZFactor) ? 1.0 : 1.0 / fZFactor);
+ rTarget.setX(maIntInvTexture.getX().getVal() * fInvZFactor);
+ rTarget.setY(maIntInvTexture.getY().getVal() * fInvZFactor);
+ }
+ }
+
+ void incrementLineSpanInterpolators(double fStep)
+ {
+ maIntZ.increment(fStep);
+
+ if(mbUseTex)
+ {
+ if(mbHasTexCoor)
+ {
+ maIntTexture.increment(fStep);
+ }
+ else if(mbHasInvTexCoor)
+ {
+ maIntInvTexture.increment(fStep);
+ }
+ }
+
+ if(mbUseNrm)
+ {
+ maIntNormal.increment(fStep);
+ }
+
+ if(mbUseCol)
+ {
+ maIntColor.increment(fStep);
+ }
+ }
+
+ double decideColorAndOpacity(basegfx::BColor& rColor)
+ {
+ // init values with full opacity and material color
+ OSL_ENSURE(0 != mpCurrentMaterial, "CurrentMaterial not set (!)");
+ double fOpacity(1.0);
+ rColor = mpCurrentMaterial->getColor();
+
+ if(mbUseTex)
+ {
+ basegfx::B2DPoint aTexCoor(0.0, 0.0);
+ getTextureCoor(aTexCoor);
+
+ if(mrProcessor.getGeoTexSvx())
+ {
+ // calc color in spot. This may also set to invisible already when
+ // e.g. bitmap textures have transparent parts
+ mrProcessor.getGeoTexSvx()->modifyBColor(aTexCoor, rColor, fOpacity);
+ }
+
+ if(basegfx::fTools::more(fOpacity, 0.0) && mrProcessor.getTransparenceGeoTexSvx())
+ {
+ // calc opacity. Object has a 2nd texture, a transparence texture
+ mrProcessor.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor, fOpacity);
+ }
+ }
+
+ if(basegfx::fTools::more(fOpacity, 0.0))
+ {
+ if(mrProcessor.getGeoTexSvx())
+ {
+ if(mbUseNrm)
+ {
+ // blend texture with phong
+ rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
+ basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
+ rColor,
+ mpCurrentMaterial->getSpecular(),
+ mpCurrentMaterial->getEmission(),
+ mpCurrentMaterial->getSpecularIntensity());
+ }
+ else if(mbUseCol)
+ {
+ // blend texture with gouraud
+ basegfx::BColor aBlendColor(maIntColor.getX().getVal(), maIntColor.getY().getVal(), maIntColor.getZ().getVal());
+ rColor *= aBlendColor;
+ }
+ else if(mrProcessor.getModulate())
+ {
+ // blend texture with single material color
+ rColor *= mpCurrentMaterial->getColor();
+ }
+ }
+ else
+ {
+ if(mbUseNrm)
+ {
+ // modify color with phong
+ rColor = mrProcessor.getSdrLightingAttribute().solveColorModel(
+ basegfx::B3DVector(maIntNormal.getX().getVal(), maIntNormal.getY().getVal(), maIntNormal.getZ().getVal()),
+ rColor,
+ mpCurrentMaterial->getSpecular(),
+ mpCurrentMaterial->getEmission(),
+ mpCurrentMaterial->getSpecularIntensity());
+ }
+ else if(mbUseCol)
+ {
+ // modify color with gouraud
+ rColor.setRed(maIntColor.getX().getVal());
+ rColor.setGreen(maIntColor.getY().getVal());
+ rColor.setBlue(maIntColor.getZ().getVal());
+ }
+ }
+
+ if(mbModifyColor)
+ {
+ rColor = mrProcessor.getBColorModifierStack().getModifiedColor(rColor);
+ }
+ }
+
+ return fOpacity;
+ }
+
+ void setupLineSpanInterpolators(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB)
+ {
+ // get inverse XDelta
+ const double xInvDelta(1.0 / (rB.getX().getVal() - rA.getX().getVal()));
+
+ // prepare Z-interpolator
+ const double fZA(rA.getZ().getVal());
+ const double fZB(rB.getZ().getVal());
+ maIntZ = basegfx::ip_single(fZA, (fZB - fZA) * xInvDelta);
+
+ // get bools and init other interpolators on demand accordingly
+ mbModifyColor = mrProcessor.getBColorModifierStack().count();
+ mbHasTexCoor = SCANLINE_EMPTY_INDEX != rA.getTextureIndex() && SCANLINE_EMPTY_INDEX != rB.getTextureIndex();
+ mbHasInvTexCoor = SCANLINE_EMPTY_INDEX != rA.getInverseTextureIndex() && SCANLINE_EMPTY_INDEX != rB.getInverseTextureIndex();
+ const bool bTextureActive(mrProcessor.getGeoTexSvx() || mrProcessor.getTransparenceGeoTexSvx());
+ mbUseTex = bTextureActive && (mbHasTexCoor || mbHasInvTexCoor || mrProcessor.getSimpleTextureActive());
+ const bool bUseColorTex(mbUseTex && mrProcessor.getGeoTexSvx());
+ const bool bNeedNrmOrCol(!bUseColorTex || (bUseColorTex && mrProcessor.getModulate()));
+ mbUseNrm = bNeedNrmOrCol && SCANLINE_EMPTY_INDEX != rA.getNormalIndex() && SCANLINE_EMPTY_INDEX != rB.getNormalIndex();
+ mbUseCol = !mbUseNrm && bNeedNrmOrCol && SCANLINE_EMPTY_INDEX != rA.getColorIndex() && SCANLINE_EMPTY_INDEX != rB.getColorIndex();
+
+ if(mbUseTex)
+ {
+ if(mbHasTexCoor)
+ {
+ const basegfx::ip_double& rTA(getTextureInterpolators()[rA.getTextureIndex()]);
+ const basegfx::ip_double& rTB(getTextureInterpolators()[rB.getTextureIndex()]);
+ maIntTexture = basegfx::ip_double(
+ rTA.getX().getVal(), (rTB.getX().getVal() - rTA.getX().getVal()) * xInvDelta,
+ rTA.getY().getVal(), (rTB.getY().getVal() - rTA.getY().getVal()) * xInvDelta);
+ }
+ else if(mbHasInvTexCoor)
+ {
+ const basegfx::ip_triple& rITA(getInverseTextureInterpolators()[rA.getInverseTextureIndex()]);
+ const basegfx::ip_triple& rITB(getInverseTextureInterpolators()[rB.getInverseTextureIndex()]);
+ maIntInvTexture = basegfx::ip_triple(
+ rITA.getX().getVal(), (rITB.getX().getVal() - rITA.getX().getVal()) * xInvDelta,
+ rITA.getY().getVal(), (rITB.getY().getVal() - rITA.getY().getVal()) * xInvDelta,
+ rITA.getZ().getVal(), (rITB.getZ().getVal() - rITA.getZ().getVal()) * xInvDelta);
+ }
+ }
+
+ if(mbUseNrm)
+ {
+ const basegfx::ip_triple& rNA(getNormalInterpolators()[rA.getNormalIndex()]);
+ const basegfx::ip_triple& rNB(getNormalInterpolators()[rB.getNormalIndex()]);
+ maIntNormal = basegfx::ip_triple(
+ rNA.getX().getVal(), (rNB.getX().getVal() - rNA.getX().getVal()) * xInvDelta,
+ rNA.getY().getVal(), (rNB.getY().getVal() - rNA.getY().getVal()) * xInvDelta,
+ rNA.getZ().getVal(), (rNB.getZ().getVal() - rNA.getZ().getVal()) * xInvDelta);
+ }
+
+ if(mbUseCol)
+ {
+ const basegfx::ip_triple& rCA(getColorInterpolators()[rA.getColorIndex()]);
+ const basegfx::ip_triple& rCB(getColorInterpolators()[rB.getColorIndex()]);
+ maIntColor = basegfx::ip_triple(
+ rCA.getX().getVal(), (rCB.getX().getVal() - rCA.getX().getVal()) * xInvDelta,
+ rCA.getY().getVal(), (rCB.getY().getVal() - rCA.getY().getVal()) * xInvDelta,
+ rCA.getZ().getVal(), (rCB.getZ().getVal() - rCA.getZ().getVal()) * xInvDelta);
+ }
+ }
+
+ virtual void processLineSpan(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount);
+
+public:
+ ZBufferRasterConverter3D(basegfx::BZPixelRaster& rBuffer, const drawinglayer::processor3d::ZBufferProcessor3D& rProcessor)
+ : basegfx::RasterConverter3D(),
+ mrProcessor(rProcessor),
+ mrBuffer(rBuffer),
+ maIntZ(),
+ maIntColor(),
+ maIntNormal(),
+ maIntTexture(),
+ maIntInvTexture(),
+ mpCurrentMaterial(0),
+ mbModifyColor(false),
+ mbUseTex(false),
+ mbHasTexCoor(false),
+ mbUseNrm(false),
+ mbUseCol(false)
+ {}
+
+ void setCurrentMaterial(const drawinglayer::attribute::MaterialAttribute3D& rMaterial)
+ {
+ mpCurrentMaterial = &rMaterial;
+ }
+};
+
+void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount)
+{
+ if(!(nSpanCount & 0x0001))
+ {
+ if(nLine >= 0 && nLine < (sal_Int32)mrBuffer.getHeight())
+ {
+ sal_uInt32 nXA(::std::min(mrBuffer.getWidth(), (sal_uInt32)::std::max((sal_Int32)0, basegfx::fround(rA.getX().getVal()))));
+ const sal_uInt32 nXB(::std::min(mrBuffer.getWidth(), (sal_uInt32)::std::max((sal_Int32)0, basegfx::fround(rB.getX().getVal()))));
+
+ if(nXA < nXB)
+ {
+ // prepare the span interpolators
+ setupLineSpanInterpolators(rA, rB);
+
+ // bring span interpolators to start condition by incrementing with the possible difference of
+ // clamped and non-clamped XStart. Interpolators are setup relying on double precision
+ // X-values, so that difference is the correct value to compensate for possible clampings
+ incrementLineSpanInterpolators(static_cast<double>(nXA) - rA.getX().getVal());
+
+ // prepare scanline index
+ sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY(nXA, static_cast<sal_uInt32>(nLine)));
+ basegfx::BColor aNewColor;
+
+ while(nXA < nXB)
+ {
+ // early-test Z values if we need to do anything at all
+ const double fNewZ(::std::max(0.0, ::std::min((double)0xffff, maIntZ.getVal())));
+ const sal_uInt16 nNewZ(static_cast< sal_uInt16 >(fNewZ));
+ sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex));
+
+ if(nNewZ > rOldZ)
+ {
+ // detect color and opacity for this pixel
+ const sal_uInt16 nOpacity(::std::max((sal_Int16)0, static_cast< sal_Int16 >(decideColorAndOpacity(aNewColor) * 255.0)));
+
+ if(nOpacity > 0)
+ {
+ // avoid color overrun
+ aNewColor.clamp();
+
+ if(nOpacity >= 0x00ff)
+ {
+ // full opacity, set z and color
+ rOldZ = nNewZ;
+ mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff);
+ }
+ else
+ {
+ basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex);
+
+ if(rDest.getOpacity())
+ {
+ // both transparent, mix color based on front pixel's opacity
+ // (the new one)
+ const sal_uInt16 nTransparence(0x0100 - nOpacity);
+ rDest.setRed((sal_uInt8)(((rDest.getRed() * nTransparence) + ((sal_uInt16)(255.0 * aNewColor.getRed()) * nOpacity)) >> 8));
+ rDest.setGreen((sal_uInt8)(((rDest.getGreen() * nTransparence) + ((sal_uInt16)(255.0 * aNewColor.getGreen()) * nOpacity)) >> 8));
+ rDest.setBlue((sal_uInt8)(((rDest.getBlue() * nTransparence) + ((sal_uInt16)(255.0 * aNewColor.getBlue()) * nOpacity)) >> 8));
+
+ if(0xff != rDest.getOpacity())
+ {
+ // destination is also transparent, mix opacities by weighting
+ // old opacity with new pixel's transparence and adding new opacity
+ rDest.setOpacity((sal_uInt8)(((rDest.getOpacity() * nTransparence) >> 8) + nOpacity));
+ }
+ }
+ else
+ {
+ // dest is not visible. Set color.
+ rDest = basegfx::BPixel(aNewColor, (sal_uInt8)nOpacity);
+ }
+ }
+ }
+ }
+
+ // increments
+ nScanlineIndex++;
+ nXA++;
+ incrementLineSpanInterpolators(1.0);
+ }
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace processor3d
+ {
+ // the processing method for a single, known primitive
+ void ZBufferProcessor3D::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rBasePrimitive)
+ {
+ // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch
+ switch(rBasePrimitive.getPrimitiveID())
+ {
+ case PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D :
+ {
+ // AlphaTexturePrimitive3D
+ const primitive3d::AlphaTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::AlphaTexturePrimitive3D& >(rBasePrimitive);
+
+ if(mbProcessTransparent)
+ {
+ impRenderGradientTexturePrimitive3D(rPrimitive, true);
+ }
+ else
+ {
+ mbContainsTransparent = true;
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
+ {
+ // directdraw of PolygonHairlinePrimitive3D
+ const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rBasePrimitive);
+
+ // do something when either not transparent and no transMap, or transparent and a TransMap
+ if((bool)mbProcessTransparent == (0 != getTransparenceGeoTexSvx()))
+ {
+ impRenderPolygonHairlinePrimitive3D(rPrimitive);
+ }
+ break;
+ }
+ case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
+ {
+ // directdraw of PolyPolygonMaterialPrimitive3D
+ const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rBasePrimitive);
+
+ // do something when either not transparent and no transMap, or transparent and a TransMap
+ if((bool)mbProcessTransparent == (0 != getTransparenceGeoTexSvx()))
+ {
+ impRenderPolyPolygonMaterialPrimitive3D(rPrimitive);
+ }
+ break;
+ }
+ default:
+ {
+ // use the DefaultProcessor3D::processBasePrimitive3D()
+ DefaultProcessor3D::processBasePrimitive3D(rBasePrimitive);
+ break;
+ }
+ }
+ }
+
+ void ZBufferProcessor3D::processNonTransparent(const primitive3d::Primitive3DSequence& rSource)
+ {
+ if(mpBZPixelRaster)
+ {
+ mbProcessTransparent = false;
+ mbContainsTransparent = false;
+ process(rSource);
+ }
+ }
+
+ void ZBufferProcessor3D::processTransparent(const primitive3d::Primitive3DSequence& rSource)
+ {
+ if(mpBZPixelRaster && mbContainsTransparent)
+ {
+ mbProcessTransparent = true;
+ process(rSource);
+ }
+ }
+
+ void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const
+ {
+ if(mpBZPixelRaster)
+ {
+ mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
+
+ if(mnAntiAlialize > 1)
+ {
+ const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+
+ if(bForceLineSnap)
+ {
+ basegfx::B3DHomMatrix aTransform;
+ basegfx::B3DPolygon aSnappedHairline(rHairline);
+ const double fScaleDown(1.0 / mnAntiAlialize);
+ const double fScaleUp(mnAntiAlialize);
+
+ // take oversampling out
+ aTransform.scale(fScaleDown, fScaleDown, 1.0);
+ aSnappedHairline.transform(aTransform);
+
+ // snap to integer
+ aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
+
+ // add oversampling again
+ aTransform.identity();
+ aTransform.scale(fScaleUp, fScaleUp, 1.0);
+
+ if(false)
+ {
+ // when really want to go to single pixel lines, move to center.
+ // Without this translation, all hor/ver hairlines will be centered exactly
+ // between two pixel lines (which looks best)
+ const double fTranslateToCenter(mnAntiAlialize * 0.5);
+ aTransform.translate(fTranslateToCenter, fTranslateToCenter, 0.0);
+ }
+
+ aSnappedHairline.transform(aTransform);
+
+ mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
+ }
+ else
+ {
+ mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
+ }
+ }
+ else
+ {
+ mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1);
+ }
+ }
+ }
+
+ void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const
+ {
+ if(mpBZPixelRaster)
+ {
+ mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
+ mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, 0, mpBZPixelRaster->getHeight());
+ }
+ }
+
+ ZBufferProcessor3D::ZBufferProcessor3D(
+ const geometry::ViewInformation3D& rViewInformation3D,
+ const geometry::ViewInformation2D& rViewInformation2D,
+ const attribute::SdrSceneAttribute& rSdrSceneAttribute,
+ const attribute::SdrLightingAttribute& rSdrLightingAttribute,
+ double fSizeX,
+ double fSizeY,
+ const basegfx::B2DRange& rVisiblePart,
+ sal_uInt16 nAntiAlialize)
+ : DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute),
+ mpBZPixelRaster(0),
+ maInvEyeToView(),
+ mpZBufferRasterConverter3D(0),
+ mnAntiAlialize(nAntiAlialize),
+ mbProcessTransparent(false),
+ mbContainsTransparent(false)
+ {
+ // generate ViewSizes
+ const double fFullViewSizeX((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(fSizeX, 0.0)).getLength());
+ const double fFullViewSizeY((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fSizeY)).getLength());
+ const double fViewSizeX(fFullViewSizeX * rVisiblePart.getWidth());
+ const double fViewSizeY(fFullViewSizeY * rVisiblePart.getHeight());
+
+ // generate RasterWidth and RasterHeight
+ const sal_uInt32 nRasterWidth((sal_uInt32)basegfx::fround(fViewSizeX) + 1);
+ const sal_uInt32 nRasterHeight((sal_uInt32)basegfx::fround(fViewSizeY) + 1);
+
+ if(nRasterWidth && nRasterHeight)
+ {
+ // create view unit buffer
+ mpBZPixelRaster = new basegfx::BZPixelRaster(
+ mnAntiAlialize ? nRasterWidth * mnAntiAlialize : nRasterWidth,
+ mnAntiAlialize ? nRasterHeight * mnAntiAlialize : nRasterHeight);
+ OSL_ENSURE(mpBZPixelRaster, "ZBufferProcessor3D: Could not allocate basegfx::BZPixelRaster (!)");
+
+ // create DeviceToView for Z-Buffer renderer since Z is handled
+ // different from standard 3D transformations (Z is mirrored). Also
+ // the transformation includes the step from unit device coordinates
+ // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete]
+
+ basegfx::B3DHomMatrix aDeviceToView;
+
+ {
+ // step one:
+ //
+ // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also
+ // necessary to
+ // - flip Y due to screen orientation
+ // - flip Z due to Z-Buffer orientation from back to front
+
+ aDeviceToView.scale(0.5, -0.5, -0.5);
+ aDeviceToView.translate(0.5, 0.5, 0.5);
+ }
+
+ {
+ // step two:
+ //
+ // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates
+ //
+ // #i102611#
+ // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0]
+ // could be used, but a 'unused' value is needed, so '0' is used what reduces
+ // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors
+ // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen.
+ // Instead of checking those by basegfx::fTools methods which would cost
+ // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer
+ // range, thus resulting in [1.5 .. 65534.5]
+ const double fMaxZDepth(65533.0);
+ aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0);
+
+ if(mnAntiAlialize)
+ aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth);
+ else
+ aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth);
+
+ aDeviceToView.translate(0.0, 0.0, 1.5);
+ }
+
+ // update local ViewInformation3D with own DeviceToView
+ const geometry::ViewInformation3D aNewViewInformation3D(
+ getViewInformation3D().getObjectTransformation(),
+ getViewInformation3D().getOrientation(),
+ getViewInformation3D().getProjection(),
+ aDeviceToView,
+ getViewInformation3D().getViewTime(),
+ getViewInformation3D().getExtendedInformationSequence());
+ updateViewInformation(aNewViewInformation3D);
+
+ // prepare inverse EyeToView transformation. This can be done in constructor
+ // since changes in object transformations when processing TransformPrimitive3Ds
+ // do not influence this prepared partial transformation
+ maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
+ maInvEyeToView.invert();
+
+ // prepare maRasterRange
+ maRasterRange.reset();
+ maRasterRange.expand(basegfx::B2DPoint(0.0, 0.0));
+ maRasterRange.expand(basegfx::B2DPoint(mpBZPixelRaster->getWidth(), mpBZPixelRaster->getHeight()));
+
+ // create the raster converter
+ mpZBufferRasterConverter3D = new ZBufferRasterConverter3D(*mpBZPixelRaster, *this);
+ }
+ }
+
+ ZBufferProcessor3D::~ZBufferProcessor3D()
+ {
+ if(mpBZPixelRaster)
+ {
+ delete mpZBufferRasterConverter3D;
+ delete mpBZPixelRaster;
+ }
+ }
+
+ BitmapEx ZBufferProcessor3D::getBitmapEx() const
+ {
+ if(mpBZPixelRaster)
+ {
+ return BPixelRasterToBitmapEx(*mpBZPixelRaster, mnAntiAlialize);
+ }
+
+ return BitmapEx();
+ }
+ } // end of namespace processor3d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/texture/makefile.mk b/drawinglayer/source/texture/makefile.mk
new file mode 100644
index 000000000000..abbb303cea0f
--- /dev/null
+++ b/drawinglayer/source/texture/makefile.mk
@@ -0,0 +1,53 @@
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# last change: $Author: aw $ $Date: 2008-04-16 04:59:59 $
+#
+# 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=texture
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/texture.obj \
+ $(SLO)$/texture3d.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx
new file mode 100644
index 000000000000..4f784c71897f
--- /dev/null
+++ b/drawinglayer/source/texture/texture.cxx
@@ -0,0 +1,728 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: texture.cxx,v $
+ *
+ * $Revision: 1.6 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:34 $
+ *
+ * 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/texture/texture.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvx::GeoTexSvx()
+ {
+ }
+
+ GeoTexSvx::~GeoTexSvx()
+ {
+ }
+
+ bool GeoTexSvx::operator==(const GeoTexSvx& /*rGeoTexSvx*/) const
+ {
+ // default implementation says yes (no data -> no difference)
+ return true;
+ }
+
+ void GeoTexSvx::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& /*rMatrices*/)
+ {
+ // default implementation does nothing
+ }
+
+ void GeoTexSvx::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ // base implementation creates random color (for testing only, may also be pure virtual)
+ rBColor.setRed((rand() & 0x7fff) / 32767.0);
+ rBColor.setGreen((rand() & 0x7fff) / 32767.0);
+ rBColor.setBlue((rand() & 0x7fff) / 32767.0);
+ }
+
+ void GeoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
+ {
+ // base implementation uses inverse of luminance of solved color (for testing only, may also be pure virtual)
+ basegfx::BColor aBaseColor;
+ modifyBColor(rUV, aBaseColor, rfOpacity);
+ rfOpacity = 1.0 - aBaseColor.luminance();
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ void GeoTexSvxGradient::impAppendMatrix(::std::vector< basegfx::B2DHomMatrix >& rMatrices, const basegfx::B2DRange& rRange)
+ {
+ basegfx::B2DHomMatrix aNew;
+ aNew.set(0, 0, rRange.getWidth());
+ aNew.set(1, 1, rRange.getHeight());
+ aNew.set(0, 2, rRange.getMinX());
+ aNew.set(1, 2, rRange.getMinY());
+ rMatrices.push_back(maGradientInfo.maTextureTransform * aNew);
+ }
+
+ void GeoTexSvxGradient::impAppendColorsRadial(::std::vector< basegfx::BColor >& rColors)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ rColors.push_back(maStart);
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps - 1L; a++)
+ {
+ rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)maGradientInfo.mnSteps));
+ }
+
+ rColors.push_back(maEnd);
+ }
+ }
+
+ GeoTexSvxGradient::GeoTexSvxGradient(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder)
+ : maTargetRange(rTargetRange),
+ maStart(rStart),
+ maEnd(rEnd),
+ mfBorder(fBorder)
+ {
+ maGradientInfo.mnSteps = nSteps;
+ maGradientInfo.mfAspectRatio = 1.0;
+ }
+
+ GeoTexSvxGradient::~GeoTexSvxGradient()
+ {
+ }
+
+ bool GeoTexSvxGradient::operator==(const GeoTexSvx& rGeoTexSvx) const
+ {
+ const GeoTexSvxGradient* pCompare = dynamic_cast< const GeoTexSvxGradient* >(&rGeoTexSvx);
+ return (pCompare
+ && maGradientInfo.maTextureTransform == pCompare->maGradientInfo.maTextureTransform
+ && maTargetRange == pCompare->maTargetRange
+ && maGradientInfo.mnSteps == pCompare->maGradientInfo.mnSteps
+ && maGradientInfo.mfAspectRatio == pCompare->maGradientInfo.mfAspectRatio
+ && mfBorder == pCompare->mfBorder);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientLinear::GeoTexSvxGradientLinear(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createLinearODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ nSteps,
+ fBorder,
+ fAngle);
+ }
+
+ GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear()
+ {
+ }
+
+ void GeoTexSvxGradientLinear::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fTop(mfBorder);
+ const double fStripeWidth((1.0 - fTop) / maGradientInfo.mnSteps);
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ const double fOffsetUpper(fStripeWidth * (double)a);
+
+ // create matrix
+ const basegfx::B2DRange aRect(0.0, fTop + fOffsetUpper, 1.0, 1.0);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientLinear::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ rColors.push_back(maStart);
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)(maGradientInfo.mnSteps + 1L)));
+ }
+ }
+ }
+
+ void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getLinearGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientAxial::GeoTexSvxGradientAxial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createAxialODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ nSteps,
+ fBorder,
+ fAngle);
+ }
+
+ GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial()
+ {
+ }
+
+ void GeoTexSvxGradientAxial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fHalfBorder(mfBorder * 0.5);
+ double fTop(fHalfBorder);
+ double fBottom(1.0 - fHalfBorder);
+ const double fStripeWidth((fBottom - fTop) / ((maGradientInfo.mnSteps * 2L) - 1L));
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ const double fOffset(fStripeWidth * (double)a);
+
+ // create matrix
+ const basegfx::B2DRange aRect(0.0, fTop + fOffset, 1.0, fBottom - fOffset);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientAxial::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ rColors.push_back(maEnd);
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ rColors.push_back(interpolate(maEnd, maStart, (double)a / (double)maGradientInfo.mnSteps));
+ }
+ }
+ }
+
+ void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getAxialGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientRadial::GeoTexSvxGradientRadial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createRadialODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ basegfx::B2DVector(fOffsetX,fOffsetY),
+ nSteps,
+ fBorder);
+ }
+
+ GeoTexSvxGradientRadial::~GeoTexSvxGradientRadial()
+ {
+ }
+
+ void GeoTexSvxGradientRadial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fHalfBorder((1.0 - mfBorder) * 0.5);
+ double fLeft(0.5 - fHalfBorder);
+ double fTop(0.5 - fHalfBorder);
+ double fRight(0.5 + fHalfBorder);
+ double fBottom(0.5 + fHalfBorder);
+ double fIncrementX, fIncrementY;
+
+ if(maGradientInfo.mfAspectRatio > 1.0)
+ {
+ fIncrementY = (fBottom - fTop) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
+ }
+ else
+ {
+ fIncrementX = (fRight - fLeft) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
+ }
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ // next step
+ fLeft += fIncrementX;
+ fRight -= fIncrementX;
+ fTop += fIncrementY;
+ fBottom -= fIncrementY;
+
+ // create matrix
+ const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientRadial::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ impAppendColorsRadial(rColors);
+ }
+
+ void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getRadialGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createEllipticalODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ basegfx::B2DVector(fOffsetX,fOffsetY),
+ nSteps,
+ fBorder,
+ fAngle);
+ }
+
+ GeoTexSvxGradientElliptical::~GeoTexSvxGradientElliptical()
+ {
+ }
+
+ void GeoTexSvxGradientElliptical::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fHalfBorder((1.0 - mfBorder) * 0.5);
+ double fLeft(0.5 - fHalfBorder);
+ double fTop(0.5 - fHalfBorder);
+ double fRight(0.5 + fHalfBorder);
+ double fBottom(0.5 + fHalfBorder);
+ double fIncrementX, fIncrementY;
+
+ if(maGradientInfo.mfAspectRatio > 1.0)
+ {
+ fIncrementY = (fBottom - fTop) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
+ }
+ else
+ {
+ fIncrementX = (fRight - fLeft) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
+ }
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ // next step
+ fLeft += fIncrementX;
+ fRight -= fIncrementX;
+ fTop += fIncrementY;
+ fBottom -= fIncrementY;
+
+ // create matrix
+ const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientElliptical::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ impAppendColorsRadial(rColors);
+ }
+
+ void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getEllipticalGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientSquare::GeoTexSvxGradientSquare(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createSquareODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ basegfx::B2DVector(fOffsetX,fOffsetY),
+ nSteps,
+ fBorder,
+ fAngle);
+ }
+
+ GeoTexSvxGradientSquare::~GeoTexSvxGradientSquare()
+ {
+ }
+
+ void GeoTexSvxGradientSquare::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fHalfBorder((1.0 - mfBorder) * 0.5);
+ double fLeft(0.5 - fHalfBorder);
+ double fTop(0.5 - fHalfBorder);
+ double fRight(0.5 + fHalfBorder);
+ double fBottom(0.5 + fHalfBorder);
+ double fIncrementX, fIncrementY;
+
+ if(maGradientInfo.mfAspectRatio > 1.0)
+ {
+ const double fWidth(fRight - fLeft);
+ const double fHalfAspectExpansion(((maGradientInfo.mfAspectRatio - 1.0) * 0.5) * fWidth);
+ fTop -= fHalfAspectExpansion;
+ fBottom += fHalfAspectExpansion;
+ fIncrementX = fWidth / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
+ }
+ else
+ {
+ const double fHeight(fBottom - fTop);
+ const double fHalfAspectExpansion((((1.0 / maGradientInfo.mfAspectRatio) - 1.0) * 0.5) * fHeight);
+ fLeft -= fHalfAspectExpansion;
+ fRight += fHalfAspectExpansion;
+ fIncrementY = fHeight / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
+ }
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ // next step
+ fLeft += fIncrementX;
+ fRight -= fIncrementX;
+ fTop += fIncrementY;
+ fBottom -= fIncrementY;
+
+ // create matrix
+ const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientSquare::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ impAppendColorsRadial(rColors);
+ }
+
+ void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getSquareGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxGradientRect::GeoTexSvxGradientRect(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
+ : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
+ {
+ basegfx::tools::createRectangularODFGradientInfo(maGradientInfo,
+ rTargetRange,
+ basegfx::B2DVector(fOffsetX,fOffsetY),
+ nSteps,
+ fBorder,
+ fAngle);
+ }
+
+ GeoTexSvxGradientRect::~GeoTexSvxGradientRect()
+ {
+ }
+
+ void GeoTexSvxGradientRect::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ if(maGradientInfo.mnSteps)
+ {
+ const double fHalfBorder((1.0 - mfBorder) * 0.5);
+ double fLeft(0.5 - fHalfBorder);
+ double fTop(0.5 - fHalfBorder);
+ double fRight(0.5 + fHalfBorder);
+ double fBottom(0.5 + fHalfBorder);
+ double fIncrementX, fIncrementY;
+
+ if(maGradientInfo.mfAspectRatio > 1.0)
+ {
+ fIncrementY = (fBottom - fTop) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
+ }
+ else
+ {
+ fIncrementX = (fRight - fLeft) / (double)(maGradientInfo.mnSteps * 2L);
+ fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
+ }
+
+ for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
+ {
+ // next step
+ fLeft += fIncrementX;
+ fRight -= fIncrementX;
+ fTop += fIncrementY;
+ fBottom -= fIncrementY;
+
+ // create matrix
+ const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom);
+ impAppendMatrix(rMatrices, aRect);
+ }
+ }
+ }
+
+ void GeoTexSvxGradientRect::appendColors(::std::vector< basegfx::BColor >& rColors)
+ {
+ impAppendColorsRadial(rColors);
+ }
+
+ void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ const double fScaler(basegfx::tools::getRectangularGradientAlpha(rUV, maGradientInfo));
+
+ rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxHatch::GeoTexSvxHatch(const basegfx::B2DRange& rTargetRange, double fDistance, double fAngle)
+ : mfDistance(0.1),
+ mfAngle(fAngle),
+ mnSteps(10L)
+ {
+ double fTargetSizeX(rTargetRange.getWidth());
+ double fTargetSizeY(rTargetRange.getHeight());
+ double fTargetOffsetX(rTargetRange.getMinX());
+ double fTargetOffsetY(rTargetRange.getMinY());
+
+ // add object expansion
+ if(0.0 != fAngle)
+ {
+ const double fAbsCos(fabs(cos(fAngle)));
+ const double fAbsSin(fabs(sin(fAngle)));
+ const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
+ const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
+ fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
+ fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
+ fTargetSizeX = fNewX;
+ fTargetSizeY = fNewY;
+ }
+
+ // add object scale before rotate
+ maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
+
+ // add texture rotate after scale to keep perpendicular angles
+ if(0.0 != fAngle)
+ {
+ basegfx::B2DPoint aCenter(0.5, 0.5);
+ aCenter *= maTextureTransform;
+
+ maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
+ maTextureTransform.rotate(fAngle);
+ maTextureTransform.translate(aCenter.getX(), aCenter.getY());
+ }
+
+ // add object translate
+ maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
+
+ // prepare height for texture
+ const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0);
+ mnSteps = basegfx::fround(fSteps + 0.5);
+ mfDistance = 1.0 / fSteps;
+
+ // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
+ maBackTextureTransform = maTextureTransform;
+ maBackTextureTransform.invert();
+ }
+
+ GeoTexSvxHatch::~GeoTexSvxHatch()
+ {
+ }
+
+ bool GeoTexSvxHatch::operator==(const GeoTexSvx& rGeoTexSvx) const
+ {
+ const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx);
+ return (pCompare
+ && maTextureTransform == pCompare->maTextureTransform
+ && mfDistance == pCompare->mfDistance
+ && mfAngle == pCompare->mfAngle
+ && mnSteps == pCompare->mnSteps);
+ }
+
+ void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ for(sal_uInt32 a(1L); a < mnSteps; a++)
+ {
+ // create matrix
+ const double fOffset(mfDistance * (double)a);
+ basegfx::B2DHomMatrix aNew;
+ aNew.set(1, 2, fOffset);
+ rMatrices.push_back(maTextureTransform * aNew);
+ }
+ }
+
+ double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
+ {
+ const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV);
+ return fmod(aCoor.getY(), mfDistance);
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxTiled::GeoTexSvxTiled(const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize)
+ : maTopLeft(rTopLeft),
+ maSize(rSize)
+ {
+ if(basegfx::fTools::lessOrEqual(maSize.getX(), 0.0))
+ {
+ maSize.setX(1.0);
+ }
+
+ if(basegfx::fTools::lessOrEqual(maSize.getY(), 0.0))
+ {
+ maSize.setY(1.0);
+ }
+ }
+
+ GeoTexSvxTiled::~GeoTexSvxTiled()
+ {
+ }
+
+ bool GeoTexSvxTiled::operator==(const GeoTexSvx& rGeoTexSvx) const
+ {
+ const GeoTexSvxTiled* pCompare = dynamic_cast< const GeoTexSvxTiled* >(&rGeoTexSvx);
+ return (pCompare
+ && maTopLeft == pCompare->maTopLeft
+ && maSize == pCompare->maSize);
+ }
+
+ void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ {
+ double fStartX(maTopLeft.getX());
+ double fStartY(maTopLeft.getY());
+
+ if(basegfx::fTools::more(fStartX, 0.0))
+ {
+ fStartX -= (floor(fStartX / maSize.getX()) + 1.0) * maSize.getX();
+ }
+
+ if(basegfx::fTools::less(fStartX + maSize.getX(), 0.0))
+ {
+ fStartX += floor(-fStartX / maSize.getX()) * maSize.getX();
+ }
+
+ if(basegfx::fTools::more(fStartY, 0.0))
+ {
+ fStartY -= (floor(fStartY / maSize.getY()) + 1.0) * maSize.getY();
+ }
+
+ if(basegfx::fTools::less(fStartY + maSize.getY(), 0.0))
+ {
+ fStartY += floor(-fStartY / maSize.getY()) * maSize.getY();
+ }
+
+ for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += maSize.getY())
+ {
+ for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += maSize.getX())
+ {
+ basegfx::B2DHomMatrix aNew;
+
+ aNew.set(0, 0, maSize.getX());
+ aNew.set(1, 1, maSize.getY());
+ aNew.set(0, 2, fPosX);
+ aNew.set(1, 2, fPosY);
+
+ rMatrices.push_back(aNew);
+ }
+ }
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/drawinglayer/source/texture/texture3d.cxx b/drawinglayer/source/texture/texture3d.cxx
new file mode 100644
index 000000000000..0e103ad385c9
--- /dev/null
+++ b/drawinglayer/source/texture/texture3d.cxx
@@ -0,0 +1,271 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: texture3d.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: aw $ $Date: 2008-05-27 14:11:34 $
+ *
+ * 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/texture/texture3d.hxx>
+#include <vcl/bmpacc.hxx>
+#include <drawinglayer/attribute/fillattribute.hxx>
+#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxMono::GeoTexSvxMono(const basegfx::BColor& rSingleColor, double fOpacity)
+ : maSingleColor(rSingleColor),
+ mfOpacity(fOpacity)
+ {
+ }
+
+ bool GeoTexSvxMono::operator==(const GeoTexSvx& rGeoTexSvx) const
+ {
+ const GeoTexSvxMono* pCompare = dynamic_cast< const GeoTexSvxMono* >(&rGeoTexSvx);
+ return (pCompare
+ && maSingleColor == pCompare->maSingleColor
+ && mfOpacity == pCompare->mfOpacity);
+ }
+
+ void GeoTexSvxMono::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
+ {
+ rBColor = maSingleColor;
+ }
+
+ void GeoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& /*rUV*/, double& rfOpacity) const
+ {
+ rfOpacity = mfOpacity;
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxBitmap::GeoTexSvxBitmap(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize)
+ : maBitmap(rBitmap),
+ mpRead(0L),
+ maTopLeft(rTopLeft),
+ maSize(rSize),
+ mfMulX(0.0),
+ mfMulY(0.0)
+ {
+ mpRead = maBitmap.AcquireReadAccess();
+ OSL_ENSURE(mpRead, "GeoTexSvxBitmap: Got no read access to Bitmap (!)");
+ mfMulX = (double)mpRead->Width() / maSize.getX();
+ mfMulY = (double)mpRead->Height() / maSize.getY();
+ }
+
+ GeoTexSvxBitmap::~GeoTexSvxBitmap()
+ {
+ delete mpRead;
+ }
+
+ bool GeoTexSvxBitmap::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const
+ {
+ if(mpRead)
+ {
+ rX = (sal_Int32)((rUV.getX() - maTopLeft.getX()) * mfMulX);
+
+ if(rX >= 0L && rX < mpRead->Width())
+ {
+ rY = (sal_Int32)((rUV.getY() - maTopLeft.getY()) * mfMulY);
+
+ return (rY >= 0L && rY < mpRead->Height());
+ }
+ }
+
+ return false;
+ }
+
+ void GeoTexSvxBitmap::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
+ {
+ sal_Int32 nX, nY;
+
+ if(impIsValid(rUV, nX, nY))
+ {
+ const double fConvertColor(1.0 / 255.0);
+ const BitmapColor aBMCol(mpRead->GetColor(nY, nX));
+ const basegfx::BColor aBSource(
+ (double)aBMCol.GetRed() * fConvertColor,
+ (double)aBMCol.GetGreen() * fConvertColor,
+ (double)aBMCol.GetBlue() * fConvertColor);
+
+ rBColor = aBSource;
+ }
+ else
+ {
+ rfOpacity = 0.0;
+ }
+ }
+
+ void GeoTexSvxBitmap::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
+ {
+ sal_Int32 nX, nY;
+
+ if(impIsValid(rUV, nX, nY))
+ {
+ const BitmapColor aBMCol(mpRead->GetColor(nY, nX));
+ const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue());
+
+ rfOpacity = ((double)(0xff - aColor.GetLuminance()) * (1.0 / 255.0));
+ }
+ else
+ {
+ rfOpacity = 0.0;
+ }
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxBitmapTiled::GeoTexSvxBitmapTiled(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize)
+ : GeoTexSvxBitmap(rBitmap, rTopLeft, rSize)
+ {
+ }
+
+ void GeoTexSvxBitmapTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
+ {
+ if(mpRead)
+ {
+ GeoTexSvxBitmap::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity);
+ }
+ }
+
+ void GeoTexSvxBitmapTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
+ {
+ if(mpRead)
+ {
+ GeoTexSvxBitmap::modifyOpacity(impGetCorrected(rUV), rfOpacity);
+ }
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace texture
+ {
+ GeoTexSvxMultiHatch::GeoTexSvxMultiHatch(const primitive3d::HatchTexturePrimitive3D& rPrimitive, double fLogicPixelSize)
+ : mfLogicPixelSize(fLogicPixelSize),
+ mp0(0L),
+ mp1(0L),
+ mp2(0L)
+ {
+ const attribute::FillHatchAttribute& rHatch(rPrimitive.getHatch());
+ const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
+ const double fAngleA(-rHatch.getAngle());
+ maColor = rHatch.getColor();
+ mbFillBackground = rHatch.isFillBackground();
+ mp0 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA);
+
+ if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
+ {
+ mp1 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI2);
+ }
+
+ if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
+ {
+ mp2 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI4);
+ }
+ }
+
+ GeoTexSvxMultiHatch::~GeoTexSvxMultiHatch()
+ {
+ delete mp0;
+ delete mp1;
+ delete mp2;
+ }
+
+ bool GeoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const
+ {
+ if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize)
+ {
+ return true;
+ }
+
+ if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize)
+ {
+ return true;
+ }
+
+ if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ void GeoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
+ {
+ if(impIsOnHatch(rUV))
+ {
+ rBColor = maColor;
+ }
+ else if(!mbFillBackground)
+ {
+ rfOpacity = 0.0;
+ }
+ }
+
+ void GeoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
+ {
+ if(mbFillBackground || impIsOnHatch(rUV))
+ {
+ rfOpacity = 1.0;
+ }
+ else
+ {
+ rfOpacity = 0.0;
+ }
+ }
+ } // end of namespace texture
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof