summaryrefslogtreecommitdiff
path: root/svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx')
-rw-r--r--svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx510
1 files changed, 510 insertions, 0 deletions
diff --git a/svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx b/svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx
new file mode 100644
index 000000000000..e4403cd6df49
--- /dev/null
+++ b/svx/source/sdr/primitive2d/sdrmeasureprimitive2d.cxx
@@ -0,0 +1,510 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_svx.hxx"
+#include <svx/sdr/primitive2d/sdrmeasureprimitive2d.hxx>
+#include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
+#include <svx/sdr/attribute/sdrtextattribute.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
+#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DReference SdrMeasurePrimitive2D::impCreatePart(
+ const attribute::SdrLineAttribute& rLineAttribute,
+ const basegfx::B2DHomMatrix& rObjectMatrix,
+ const basegfx::B2DPoint& rStart,
+ const basegfx::B2DPoint& rEnd,
+ bool bLeftActive,
+ bool bRightActive) const
+ {
+ const attribute::SdrLineStartEndAttribute& rLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
+ basegfx::B2DPolygon aPolygon;
+
+ aPolygon.append(rStart);
+ aPolygon.append(rEnd);
+
+ if(rLineStartEnd.isDefault() || (!bLeftActive && !bRightActive))
+ {
+ return createPolygonLinePrimitive(
+ aPolygon,
+ rObjectMatrix,
+ rLineAttribute,
+ attribute::SdrLineStartEndAttribute());
+ }
+
+ if(bLeftActive && bRightActive)
+ {
+ return createPolygonLinePrimitive(
+ aPolygon,
+ rObjectMatrix,
+ rLineAttribute,
+ rLineStartEnd);
+ }
+
+ const basegfx::B2DPolyPolygon aEmpty;
+ const attribute::SdrLineStartEndAttribute aLineStartEnd(
+ bLeftActive ? rLineStartEnd.getStartPolyPolygon() : aEmpty, bRightActive ? rLineStartEnd.getEndPolyPolygon() : aEmpty,
+ bLeftActive ? rLineStartEnd.getStartWidth() : 0.0, bRightActive ? rLineStartEnd.getEndWidth() : 0.0,
+ bLeftActive ? rLineStartEnd.isStartActive() : false, bRightActive ? rLineStartEnd.isEndActive() : false,
+ bLeftActive ? rLineStartEnd.isStartCentered() : false, bRightActive? rLineStartEnd.isEndCentered() : false);
+
+ return createPolygonLinePrimitive(aPolygon, rObjectMatrix, rLineAttribute, aLineStartEnd);
+ }
+
+ Primitive2DSequence SdrMeasurePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
+ {
+ Primitive2DSequence aRetval;
+ SdrBlockTextPrimitive2D* pBlockText = 0;
+ basegfx::B2DRange aTextRange;
+ double fTextX((getStart().getX() + getEnd().getX()) * 0.5);
+ double fTextY((getStart().getX() + getEnd().getX()) * 0.5);
+ const basegfx::B2DVector aLine(getEnd() - getStart());
+ const double fDistance(aLine.getLength());
+ const double fAngle(atan2(aLine.getY(), aLine.getX()));
+ bool bAutoUpsideDown(false);
+ const attribute::SdrTextAttribute rTextAttribute = getSdrLSTAttribute().getText();
+ const basegfx::B2DHomMatrix aObjectMatrix(
+ basegfx::tools::createShearXRotateTranslateB2DHomMatrix(0.0, fAngle, getStart()));
+
+ // preapare text, but do not add yet; it needs to be aligned to
+ // the line geometry
+ if(!rTextAttribute.isDefault())
+ {
+ basegfx::B2DHomMatrix aTextMatrix;
+ double fTestAngle(fAngle);
+
+ if(getTextRotation())
+ {
+ aTextMatrix.rotate(-90.0 * F_PI180);
+ fTestAngle -= (90.0 * F_PI180);
+
+ if(getTextAutoAngle() && fTestAngle < -F_PI)
+ {
+ fTestAngle += F_2PI;
+ }
+ }
+
+ if(getTextAutoAngle())
+ {
+ if(fTestAngle > (F_PI / 4.0) || fTestAngle < (-F_PI * (3.0 / 4.0)))
+ {
+ bAutoUpsideDown = true;
+ }
+ }
+
+ // create primitive and get text range
+ pBlockText = new SdrBlockTextPrimitive2D(
+ &rTextAttribute.getSdrText(),
+ rTextAttribute.getOutlinerParaObject(),
+ aTextMatrix,
+ SDRTEXTHORZADJUST_CENTER,
+ SDRTEXTVERTADJUST_CENTER,
+ rTextAttribute.isScroll(),
+ false,
+ false,
+ false,
+ false);
+
+ aTextRange = pBlockText->getB2DRange(aViewInformation);
+ }
+
+ // prepare line attribute and result
+ {
+ const attribute::SdrLineAttribute rLineAttribute(getSdrLSTAttribute().getLine());
+ bool bArrowsOutside(false);
+ bool bMainLineSplitted(false);
+ const attribute::SdrLineStartEndAttribute& rLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
+ double fStartArrowW(0.0);
+ double fStartArrowH(0.0);
+ double fEndArrowW(0.0);
+ double fEndArrowH(0.0);
+
+ if(!rLineStartEnd.isDefault())
+ {
+ if(rLineStartEnd.isStartActive())
+ {
+ const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(rLineStartEnd.getStartPolyPolygon()));
+ fStartArrowW = rLineStartEnd.getStartWidth();
+ fStartArrowH = aArrowRange.getHeight() * fStartArrowW / aArrowRange.getWidth();
+
+ if(rLineStartEnd.isStartCentered())
+ {
+ fStartArrowH *= 0.5;
+ }
+ }
+
+ if(rLineStartEnd.isEndActive())
+ {
+ const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(rLineStartEnd.getEndPolyPolygon()));
+ fEndArrowW = rLineStartEnd.getEndWidth();
+ fEndArrowH = aArrowRange.getHeight() * fEndArrowW / aArrowRange.getWidth();
+
+ if(rLineStartEnd.isEndCentered())
+ {
+ fEndArrowH *= 0.5;
+ }
+ }
+ }
+
+ const double fSpaceNeededByArrows(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.5));
+ const double fArrowsOutsideLen((fStartArrowH + fEndArrowH + fStartArrowW + fEndArrowW) * 0.5);
+ const double fHalfLineWidth(rLineAttribute.getWidth() * 0.5);
+
+ if(fSpaceNeededByArrows > fDistance)
+ {
+ bArrowsOutside = true;
+ }
+
+ MeasureTextPosition eHorizontal(getHorizontal());
+ MeasureTextPosition eVertical(getVertical());
+
+ if(MEASURETEXTPOSITION_AUTOMATIC == eVertical)
+ {
+ eVertical = MEASURETEXTPOSITION_NEGATIVE;
+ }
+
+ if(MEASURETEXTPOSITION_CENTERED == eVertical)
+ {
+ bMainLineSplitted = true;
+ }
+
+ if(MEASURETEXTPOSITION_AUTOMATIC == eHorizontal)
+ {
+ if(aTextRange.getWidth() > fDistance)
+ {
+ eHorizontal = MEASURETEXTPOSITION_NEGATIVE;
+ }
+ else
+ {
+ eHorizontal = MEASURETEXTPOSITION_CENTERED;
+ }
+
+ if(bMainLineSplitted)
+ {
+ if(aTextRange.getWidth() + fSpaceNeededByArrows > fDistance)
+ {
+ bArrowsOutside = true;
+ }
+ }
+ else
+ {
+ const double fSmallArrowNeed(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.125));
+
+ if(aTextRange.getWidth() + fSmallArrowNeed > fDistance)
+ {
+ bArrowsOutside = true;
+ }
+ }
+ }
+
+ if(MEASURETEXTPOSITION_CENTERED != eHorizontal)
+ {
+ bArrowsOutside = true;
+ }
+
+ // switch text above/below?
+ if(getBelow() || (bAutoUpsideDown && !getTextRotation()))
+ {
+ if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
+ {
+ eVertical = MEASURETEXTPOSITION_POSITIVE;
+ }
+ else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
+ {
+ eVertical = MEASURETEXTPOSITION_NEGATIVE;
+ }
+ }
+
+ const double fMainLineOffset(getBelow() ? getDistance() : -getDistance());
+ const basegfx::B2DPoint aMainLeft(0.0, fMainLineOffset);
+ const basegfx::B2DPoint aMainRight(fDistance, fMainLineOffset);
+
+ // main line
+ if(bArrowsOutside)
+ {
+ double fLenLeft(fArrowsOutsideLen);
+ double fLenRight(fArrowsOutsideLen);
+
+ if(!bMainLineSplitted)
+ {
+ if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
+ {
+ fLenLeft = fStartArrowH + aTextRange.getWidth();
+ }
+ else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
+ {
+ fLenRight = fEndArrowH + aTextRange.getWidth();
+ }
+ }
+
+ const basegfx::B2DPoint aMainLeftLeft(aMainLeft.getX() - fLenLeft, aMainLeft.getY());
+ const basegfx::B2DPoint aMainRightRight(aMainRight.getX() + fLenRight, aMainRight.getY());
+
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeftLeft, aMainLeft, false, true));
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainRight, aMainRightRight, true, false));
+
+ if(!bMainLineSplitted || MEASURETEXTPOSITION_CENTERED != eHorizontal)
+ {
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainRight, false, false));
+ }
+ }
+ else
+ {
+ if(bMainLineSplitted)
+ {
+ const double fHalfLength((fDistance - (aTextRange.getWidth() + (fStartArrowH + fEndArrowH) * 0.25)) * 0.5);
+ const basegfx::B2DPoint aMainInnerLeft(aMainLeft.getX() + fHalfLength, aMainLeft.getY());
+ const basegfx::B2DPoint aMainInnerRight(aMainRight.getX() - fHalfLength, aMainRight.getY());
+
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainInnerLeft, true, false));
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainInnerRight, aMainRight, false, true));
+ }
+ else
+ {
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainRight, true, true));
+ }
+ }
+
+ // left/right help line value preparation
+ const double fTopEdge(getBelow() ? getUpper() + getDistance() : -getUpper() - getDistance());
+ const double fBottomLeft(getBelow() ? getLower() - getLeftDelta() : getLeftDelta() - getLower());
+ const double fBottomRight(getBelow() ? getLower() - getRightDelta() : getRightDelta() - getLower());
+
+ // left help line
+ const basegfx::B2DPoint aLeftUp(0.0, fTopEdge);
+ const basegfx::B2DPoint aLeftDown(0.0, fBottomLeft);
+
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aLeftDown, aLeftUp, false, false));
+
+ // right help line
+ const basegfx::B2DPoint aRightUp(fDistance, fTopEdge);
+ const basegfx::B2DPoint aRightDown(fDistance, fBottomRight);
+
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aRightDown, aRightUp, false, false));
+
+ // text horizontal position
+ if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
+ {
+ // left
+ const double fSmall(fArrowsOutsideLen * 0.18);
+ fTextX = aMainLeft.getX() - (fStartArrowH + aTextRange.getWidth() + fSmall + fHalfLineWidth);
+
+ if(bMainLineSplitted)
+ {
+ fTextX -= (fArrowsOutsideLen - fStartArrowH);
+ }
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextX -= rTextAttribute.getTextRightDistance();
+ }
+ }
+ else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
+ {
+ // right
+ const double fSmall(fArrowsOutsideLen * 0.18);
+ fTextX = aMainRight.getX() + (fEndArrowH + fSmall + fHalfLineWidth);
+
+ if(bMainLineSplitted)
+ {
+ fTextX += (fArrowsOutsideLen - fEndArrowH);
+ }
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextX += rTextAttribute.getTextLeftDistance();
+ }
+ }
+ else // MEASURETEXTPOSITION_CENTERED
+ {
+ // centered
+ fTextX = aMainLeft.getX() + ((fDistance - aTextRange.getWidth()) * 0.5);
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextX += (rTextAttribute.getTextLeftDistance() - rTextAttribute.getTextRightDistance()) / 2L;
+ }
+ }
+
+ // text vertical position
+ if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
+ {
+ // top
+ const double fSmall(fArrowsOutsideLen * 0.10);
+ fTextY = aMainLeft.getY() - (aTextRange.getHeight() + fSmall + fHalfLineWidth);
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextY -= rTextAttribute.getTextLowerDistance();
+ }
+ }
+ else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
+ {
+ // bottom
+ const double fSmall(fArrowsOutsideLen * 0.10);
+ fTextY = aMainLeft.getY() + (fSmall + fHalfLineWidth);
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextY += rTextAttribute.getTextUpperDistance();
+ }
+ }
+ else // MEASURETEXTPOSITION_CENTERED
+ {
+ // centered
+ fTextY = aMainLeft.getY() - (aTextRange.getHeight() * 0.5);
+
+ if(!rTextAttribute.isDefault())
+ {
+ fTextY += (rTextAttribute.getTextUpperDistance() - rTextAttribute.getTextLowerDistance()) / 2L;
+ }
+ }
+ }
+
+ if(getSdrLSTAttribute().getLine().isDefault())
+ {
+ // embed line geometry to invisible (100% transparent) line group for HitTest
+ const Primitive2DReference xHiddenLines(new HiddenGeometryPrimitive2D(aRetval));
+
+ aRetval = Primitive2DSequence(&xHiddenLines, 1);
+ }
+
+ if(pBlockText)
+ {
+ // create transformation to text primitive end position
+ basegfx::B2DHomMatrix aChange;
+
+ // handle auto text rotation
+ if(bAutoUpsideDown)
+ {
+ aChange.rotate(F_PI);
+ }
+
+ // move from aTextRange.TopLeft to fTextX, fTextY
+ aChange.translate(fTextX - aTextRange.getMinX(), fTextY - aTextRange.getMinY());
+
+ // apply object matrix
+ aChange *= aObjectMatrix;
+
+ // apply to existing text primitive
+ SdrTextPrimitive2D* pNewBlockText = pBlockText->createTransformedClone(aChange);
+ OSL_ENSURE(pNewBlockText, "SdrMeasurePrimitive2D::create2DDecomposition: Could not create transformed clone of text primitive (!)");
+ delete pBlockText;
+
+ // add to local primitives
+ appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, Primitive2DReference(pNewBlockText));
+ }
+
+ // add shadow
+ if(!getSdrLSTAttribute().getShadow().isDefault())
+ {
+ aRetval = createEmbeddedShadowPrimitive(
+ aRetval,
+ getSdrLSTAttribute().getShadow());
+ }
+
+ return aRetval;
+ }
+
+ SdrMeasurePrimitive2D::SdrMeasurePrimitive2D(
+ const attribute::SdrLineShadowTextAttribute& rSdrLSTAttribute,
+ const basegfx::B2DPoint& rStart,
+ const basegfx::B2DPoint& rEnd,
+ MeasureTextPosition eHorizontal,
+ MeasureTextPosition eVertical,
+ double fDistance,
+ double fUpper,
+ double fLower,
+ double fLeftDelta,
+ double fRightDelta,
+ bool bBelow,
+ bool bTextRotation,
+ bool bTextAutoAngle)
+ : BufferedDecompositionPrimitive2D(),
+ maSdrLSTAttribute(rSdrLSTAttribute),
+ maStart(rStart),
+ maEnd(rEnd),
+ meHorizontal(eHorizontal),
+ meVertical(eVertical),
+ mfDistance(fDistance),
+ mfUpper(fUpper),
+ mfLower(fLower),
+ mfLeftDelta(fLeftDelta),
+ mfRightDelta(fRightDelta),
+ mbBelow(bBelow),
+ mbTextRotation(bTextRotation),
+ mbTextAutoAngle(bTextAutoAngle)
+ {
+ }
+
+ bool SdrMeasurePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const SdrMeasurePrimitive2D& rCompare = (SdrMeasurePrimitive2D&)rPrimitive;
+
+ return (getStart() == rCompare.getStart()
+ && getEnd() == rCompare.getEnd()
+ && getHorizontal() == rCompare.getHorizontal()
+ && getVertical() == rCompare.getVertical()
+ && getDistance() == rCompare.getDistance()
+ && getUpper() == rCompare.getUpper()
+ && getLower() == rCompare.getLower()
+ && getLeftDelta() == rCompare.getLeftDelta()
+ && getRightDelta() == rCompare.getRightDelta()
+ && getBelow() == rCompare.getBelow()
+ && getTextRotation() == rCompare.getTextRotation()
+ && getTextAutoAngle() == rCompare.getTextAutoAngle()
+ && getSdrLSTAttribute() == rCompare.getSdrLSTAttribute());
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SdrMeasurePrimitive2D, PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
+// eof