update dev300-m58
[ooovba.git] / svx / source / sdr / primitive2d / sdrmeasureprimitive2d.cxx
blob8f9d863a41eb51e90d1178d72207c806ddded44c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sdrmeasureprimitive2d.cxx,v $
11 * $Revision: 1.2.18.1 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/primitive2d/sdrmeasureprimitive2d.hxx>
34 #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
35 #include <basegfx/matrix/b2dhommatrix.hxx>
36 #include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
37 #include <svx/sdr/attribute/sdrtextattribute.hxx>
38 #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 #include <basegfx/tools/canvastools.hxx>
40 #include <drawinglayer/primitive2d/groupprimitive2d.hxx>
41 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
42 #include <drawinglayer/primitive2d/hittestprimitive2d.hxx>
44 //////////////////////////////////////////////////////////////////////////////
46 using namespace com::sun::star;
48 //////////////////////////////////////////////////////////////////////////////
50 namespace drawinglayer
52 namespace primitive2d
54 Primitive2DReference SdrMeasurePrimitive2D::impCreatePart(
55 const basegfx::B2DHomMatrix& rObjectMatrix,
56 const basegfx::B2DPoint& rStart,
57 const basegfx::B2DPoint& rEnd,
58 bool bLeftActive,
59 bool bRightActive) const
61 basegfx::B2DPolygon aPolygon;
62 aPolygon.append(rStart);
63 aPolygon.append(rEnd);
65 if(!getSdrLSTAttribute().getLineStartEnd() || (!bLeftActive && !bRightActive))
67 return createPolygonLinePrimitive(aPolygon, rObjectMatrix, *getSdrLSTAttribute().getLine(), 0L);
70 if(bLeftActive && bRightActive)
72 return createPolygonLinePrimitive(aPolygon, rObjectMatrix, *getSdrLSTAttribute().getLine(), getSdrLSTAttribute().getLineStartEnd());
75 const attribute::SdrLineStartEndAttribute* pLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
76 const basegfx::B2DPolyPolygon aEmpty;
77 const attribute::SdrLineStartEndAttribute aLineStartEnd(
78 bLeftActive ? pLineStartEnd->getStartPolyPolygon() : aEmpty, bRightActive ? pLineStartEnd->getEndPolyPolygon() : aEmpty,
79 bLeftActive ? pLineStartEnd->getStartWidth() : 0.0, bRightActive ? pLineStartEnd->getEndWidth() : 0.0,
80 bLeftActive ? pLineStartEnd->isStartActive() : false, bRightActive ? pLineStartEnd->isEndActive() : false,
81 bLeftActive ? pLineStartEnd->isStartCentered() : false, bRightActive? pLineStartEnd->isEndCentered() : false);
83 return createPolygonLinePrimitive(aPolygon, rObjectMatrix, *getSdrLSTAttribute().getLine(), &aLineStartEnd);
86 Primitive2DSequence SdrMeasurePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& aViewInformation) const
88 Primitive2DSequence aRetval;
89 SdrBlockTextPrimitive2D* pBlockText = 0L;
90 basegfx::B2DRange aTextRange;
91 double fTextX((getStart().getX() + getEnd().getX()) * 0.5);
92 double fTextY((getStart().getX() + getEnd().getX()) * 0.5);
93 const basegfx::B2DVector aLine(getEnd() - getStart());
94 const double fDistance(aLine.getLength());
95 const double fAngle(atan2(aLine.getY(), aLine.getX()));
96 bool bAutoUpsideDown(false);
97 const attribute::SdrTextAttribute* pTextAttribute = getSdrLSTAttribute().getText();
99 basegfx::B2DHomMatrix aObjectMatrix;
100 aObjectMatrix.rotate(fAngle);
101 aObjectMatrix.translate(getStart().getX(), getStart().getY());
103 if(pTextAttribute)
105 basegfx::B2DHomMatrix aTextMatrix;
106 double fTestAngle(fAngle);
108 if(getTextRotation())
110 aTextMatrix.rotate(-90.0 * F_PI180);
111 fTestAngle -= (90.0 * F_PI180);
113 if(getTextAutoAngle() && fTestAngle < -F_PI)
115 fTestAngle += F_2PI;
119 if(getTextAutoAngle())
121 if(fTestAngle > (F_PI / 4.0) || fTestAngle < (-F_PI * (3.0 / 4.0)))
123 bAutoUpsideDown = true;
127 // create primitive and get text range
128 pBlockText = new SdrBlockTextPrimitive2D(
129 &pTextAttribute->getSdrText(),
130 pTextAttribute->getOutlinerParaObject(),
131 aTextMatrix,
132 pTextAttribute->isScroll(),
133 false,
134 false);
135 aTextRange = pBlockText->getB2DRange(aViewInformation);
138 // prepare line attribute and result
139 const attribute::SdrLineAttribute* pLineAttribute(getSdrLSTAttribute().getLine());
141 if(!pLineAttribute)
143 // if initially no line is defined, create one for HitTest and BoundRect
144 pLineAttribute = new attribute::SdrLineAttribute(basegfx::BColor(0.0, 0.0, 0.0));
148 bool bArrowsOutside(false);
149 bool bMainLineSplitted(false);
150 const attribute::SdrLineStartEndAttribute* pLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
151 double fStartArrowW(0.0);
152 double fStartArrowH(0.0);
153 double fEndArrowW(0.0);
154 double fEndArrowH(0.0);
156 if(pLineStartEnd)
158 if(pLineStartEnd->isStartActive())
160 const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(pLineStartEnd->getStartPolyPolygon()));
161 fStartArrowW = pLineStartEnd->getStartWidth();
162 fStartArrowH = aArrowRange.getHeight() * fStartArrowW / aArrowRange.getWidth();
164 if(pLineStartEnd->isStartCentered())
166 fStartArrowH *= 0.5;
170 if(pLineStartEnd->isEndActive())
172 const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(pLineStartEnd->getEndPolyPolygon()));
173 fEndArrowW = pLineStartEnd->getEndWidth();
174 fEndArrowH = aArrowRange.getHeight() * fEndArrowW / aArrowRange.getWidth();
176 if(pLineStartEnd->isEndCentered())
178 fEndArrowH *= 0.5;
183 const double fSpaceNeededByArrows(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.5));
184 const double fArrowsOutsideLen((fStartArrowH + fEndArrowH + fStartArrowW + fEndArrowW) * 0.5);
185 const double fHalfLineWidth(pLineAttribute->getWidth() * 0.5);
187 if(fSpaceNeededByArrows > fDistance)
189 bArrowsOutside = true;
192 MeasureTextPosition eHorizontal(getHorizontal());
193 MeasureTextPosition eVertical(getVertical());
195 if(MEASURETEXTPOSITION_AUTOMATIC == eVertical)
197 eVertical = MEASURETEXTPOSITION_NEGATIVE;
200 if(MEASURETEXTPOSITION_CENTERED == eVertical)
202 bMainLineSplitted = true;
205 if(MEASURETEXTPOSITION_AUTOMATIC == eHorizontal)
207 if(aTextRange.getWidth() > fDistance)
209 eHorizontal = MEASURETEXTPOSITION_NEGATIVE;
211 else
213 eHorizontal = MEASURETEXTPOSITION_CENTERED;
216 if(bMainLineSplitted)
218 if(aTextRange.getWidth() + fSpaceNeededByArrows > fDistance)
220 bArrowsOutside = true;
223 else
225 const double fSmallArrowNeed(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.125));
227 if(aTextRange.getWidth() + fSmallArrowNeed > fDistance)
229 bArrowsOutside = true;
234 if(MEASURETEXTPOSITION_CENTERED != eHorizontal)
236 bArrowsOutside = true;
239 // switch text above/below?
240 if(getBelow() || (bAutoUpsideDown && !getTextRotation()))
242 if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
244 eVertical = MEASURETEXTPOSITION_POSITIVE;
246 else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
248 eVertical = MEASURETEXTPOSITION_NEGATIVE;
252 const double fMainLineOffset(getBelow() ? getDistance() : -getDistance());
253 const basegfx::B2DPoint aMainLeft(0.0, fMainLineOffset);
254 const basegfx::B2DPoint aMainRight(fDistance, fMainLineOffset);
256 // main line
257 if(bArrowsOutside)
259 double fLenLeft(fArrowsOutsideLen);
260 double fLenRight(fArrowsOutsideLen);
262 if(!bMainLineSplitted)
264 if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
266 fLenLeft = fStartArrowH + aTextRange.getWidth();
268 else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
270 fLenRight = fEndArrowH + aTextRange.getWidth();
274 const basegfx::B2DPoint aMainLeftLeft(aMainLeft.getX() - fLenLeft, aMainLeft.getY());
275 const basegfx::B2DPoint aMainRightRight(aMainRight.getX() + fLenRight, aMainRight.getY());
277 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeftLeft, aMainLeft, false, true));
278 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainRight, aMainRightRight, true, false));
280 if(!bMainLineSplitted || MEASURETEXTPOSITION_CENTERED != eHorizontal)
282 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainRight, false, false));
285 else
287 if(bMainLineSplitted)
289 const double fHalfLength((fDistance - (aTextRange.getWidth() + (fStartArrowH + fEndArrowH) * 0.25)) * 0.5);
290 const basegfx::B2DPoint aMainInnerLeft(aMainLeft.getX() + fHalfLength, aMainLeft.getY());
291 const basegfx::B2DPoint aMainInnerRight(aMainRight.getX() - fHalfLength, aMainRight.getY());
293 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainInnerLeft, true, false));
294 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainInnerRight, aMainRight, false, true));
296 else
298 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainRight, true, true));
302 // left/right help line value preparation
303 const double fTopEdge(getBelow() ? getUpper() + getDistance() : -getUpper() - getDistance());
304 const double fBottomLeft(getBelow() ? getLower() - getLeftDelta() : getLeftDelta() - getLower());
305 const double fBottomRight(getBelow() ? getLower() - getRightDelta() : getRightDelta() - getLower());
307 // left help line
308 const basegfx::B2DPoint aLeftUp(0.0, fTopEdge);
309 const basegfx::B2DPoint aLeftDown(0.0, fBottomLeft);
311 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aLeftDown, aLeftUp, false, false));
313 // right help line
314 const basegfx::B2DPoint aRightUp(fDistance, fTopEdge);
315 const basegfx::B2DPoint aRightDown(fDistance, fBottomRight);
317 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aRightDown, aRightUp, false, false));
319 // text horizontal position
320 if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
322 // left
323 const double fSmall(fArrowsOutsideLen * 0.18);
324 fTextX = aMainLeft.getX() - (fStartArrowH + aTextRange.getWidth() + fSmall + fHalfLineWidth);
326 if(bMainLineSplitted)
328 fTextX -= (fArrowsOutsideLen - fStartArrowH);
331 if(pTextAttribute)
333 fTextX -= pTextAttribute->getTextRightDistance();
336 else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
338 // right
339 const double fSmall(fArrowsOutsideLen * 0.18);
340 fTextX = aMainRight.getX() + (fEndArrowH + fSmall + fHalfLineWidth);
342 if(bMainLineSplitted)
344 fTextX += (fArrowsOutsideLen - fEndArrowH);
347 if(pTextAttribute)
349 fTextX += pTextAttribute->getTextLeftDistance();
352 else // MEASURETEXTPOSITION_CENTERED
354 // centered
355 fTextX = aMainLeft.getX() + ((fDistance - aTextRange.getWidth()) * 0.5);
357 if(pTextAttribute)
359 fTextX += (pTextAttribute->getTextLeftDistance() - pTextAttribute->getTextRightDistance()) / 2L;
363 // text vertical position
364 if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
366 // top
367 const double fSmall(fArrowsOutsideLen * 0.10);
368 fTextY = aMainLeft.getY() - (aTextRange.getHeight() + fSmall + fHalfLineWidth);
370 if(pTextAttribute)
372 fTextY -= pTextAttribute->getTextLowerDistance();
375 else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
377 // bottom
378 const double fSmall(fArrowsOutsideLen * 0.10);
379 fTextY = aMainLeft.getY() + (fSmall + fHalfLineWidth);
381 if(pTextAttribute)
383 fTextY += pTextAttribute->getTextUpperDistance();
386 else // MEASURETEXTPOSITION_CENTERED
388 // centered
389 fTextY = aMainLeft.getY() - (aTextRange.getHeight() * 0.5);
391 if(pTextAttribute)
393 fTextY += (pTextAttribute->getTextUpperDistance() - pTextAttribute->getTextLowerDistance()) / 2L;
398 if(!getSdrLSTAttribute().getLine())
400 // embed line geometry to invisible line group
401 const Primitive2DReference xHiddenLines(new HitTestPrimitive2D(aRetval));
402 aRetval = Primitive2DSequence(&xHiddenLines, 1);
404 // delete temporary LineAttribute again
405 delete pLineAttribute;
408 if(pBlockText)
410 // create transformation to text primitive end position
411 basegfx::B2DHomMatrix aChange;
413 // handle auto text rotation
414 if(bAutoUpsideDown)
416 aChange.rotate(F_PI);
419 // move from aTextRange.TopLeft to fTextX, fTextY
420 aChange.translate(fTextX - aTextRange.getMinX(), fTextY - aTextRange.getMinY());
422 // apply object matrix
423 aChange *= aObjectMatrix;
425 // apply to existing text primitive
426 SdrTextPrimitive2D* pNewBlockText = pBlockText->createTransformedClone(aChange);
427 OSL_ENSURE(pNewBlockText, "SdrMeasurePrimitive2D::createLocalDecomposition: Could not create transformed clone of text primitive (!)");
428 delete pBlockText;
430 // add to local primitives
431 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, Primitive2DReference(pNewBlockText));
434 // add shadow
435 if(getSdrLSTAttribute().getShadow())
437 aRetval = createEmbeddedShadowPrimitive(aRetval, *getSdrLSTAttribute().getShadow());
440 return aRetval;
443 SdrMeasurePrimitive2D::SdrMeasurePrimitive2D(
444 const attribute::SdrLineShadowTextAttribute& rSdrLSTAttribute,
445 const basegfx::B2DPoint& rStart,
446 const basegfx::B2DPoint& rEnd,
447 MeasureTextPosition eHorizontal,
448 MeasureTextPosition eVertical,
449 double fDistance,
450 double fUpper,
451 double fLower,
452 double fLeftDelta,
453 double fRightDelta,
454 bool bBelow,
455 bool bTextRotation,
456 bool bTextAutoAngle)
457 : BasePrimitive2D(),
458 maSdrLSTAttribute(rSdrLSTAttribute),
459 maStart(rStart),
460 maEnd(rEnd),
461 meHorizontal(eHorizontal),
462 meVertical(eVertical),
463 mfDistance(fDistance),
464 mfUpper(fUpper),
465 mfLower(fLower),
466 mfLeftDelta(fLeftDelta),
467 mfRightDelta(fRightDelta),
468 mbBelow(bBelow),
469 mbTextRotation(bTextRotation),
470 mbTextAutoAngle(bTextAutoAngle)
474 bool SdrMeasurePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
476 if(BasePrimitive2D::operator==(rPrimitive))
478 const SdrMeasurePrimitive2D& rCompare = (SdrMeasurePrimitive2D&)rPrimitive;
480 return (getStart() == rCompare.getStart()
481 && getEnd() == rCompare.getEnd()
482 && getHorizontal() == rCompare.getHorizontal()
483 && getVertical() == rCompare.getVertical()
484 && getDistance() == rCompare.getDistance()
485 && getUpper() == rCompare.getUpper()
486 && getLower() == rCompare.getLower()
487 && getLeftDelta() == rCompare.getLeftDelta()
488 && getRightDelta() == rCompare.getRightDelta()
489 && getBelow() == rCompare.getBelow()
490 && getTextRotation() == rCompare.getTextRotation()
491 && getTextAutoAngle() == rCompare.getTextAutoAngle()
492 && getSdrLSTAttribute() == rCompare.getSdrLSTAttribute());
495 return false;
498 // provide unique ID
499 ImplPrimitrive2DIDBlock(SdrMeasurePrimitive2D, PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D)
501 } // end of namespace primitive2d
502 } // end of namespace drawinglayer
504 //////////////////////////////////////////////////////////////////////////////
505 // eof