Update ooo320-m1
[ooovba.git] / svx / source / sdr / primitive2d / sdrmeasureprimitive2d.cxx
blob1db2b4a6c16200d1f0b71376fa717c513cf908ef
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 SDRTEXTHORZADJUST_CENTER,
133 SDRTEXTVERTADJUST_CENTER,
134 pTextAttribute->isScroll(),
135 false,
136 false,
137 false);
138 aTextRange = pBlockText->getB2DRange(aViewInformation);
141 // prepare line attribute and result
142 const attribute::SdrLineAttribute* pLineAttribute(getSdrLSTAttribute().getLine());
144 if(!pLineAttribute)
146 // if initially no line is defined, create one for HitTest and BoundRect
147 pLineAttribute = new attribute::SdrLineAttribute(basegfx::BColor(0.0, 0.0, 0.0));
151 bool bArrowsOutside(false);
152 bool bMainLineSplitted(false);
153 const attribute::SdrLineStartEndAttribute* pLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
154 double fStartArrowW(0.0);
155 double fStartArrowH(0.0);
156 double fEndArrowW(0.0);
157 double fEndArrowH(0.0);
159 if(pLineStartEnd)
161 if(pLineStartEnd->isStartActive())
163 const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(pLineStartEnd->getStartPolyPolygon()));
164 fStartArrowW = pLineStartEnd->getStartWidth();
165 fStartArrowH = aArrowRange.getHeight() * fStartArrowW / aArrowRange.getWidth();
167 if(pLineStartEnd->isStartCentered())
169 fStartArrowH *= 0.5;
173 if(pLineStartEnd->isEndActive())
175 const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(pLineStartEnd->getEndPolyPolygon()));
176 fEndArrowW = pLineStartEnd->getEndWidth();
177 fEndArrowH = aArrowRange.getHeight() * fEndArrowW / aArrowRange.getWidth();
179 if(pLineStartEnd->isEndCentered())
181 fEndArrowH *= 0.5;
186 const double fSpaceNeededByArrows(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.5));
187 const double fArrowsOutsideLen((fStartArrowH + fEndArrowH + fStartArrowW + fEndArrowW) * 0.5);
188 const double fHalfLineWidth(pLineAttribute->getWidth() * 0.5);
190 if(fSpaceNeededByArrows > fDistance)
192 bArrowsOutside = true;
195 MeasureTextPosition eHorizontal(getHorizontal());
196 MeasureTextPosition eVertical(getVertical());
198 if(MEASURETEXTPOSITION_AUTOMATIC == eVertical)
200 eVertical = MEASURETEXTPOSITION_NEGATIVE;
203 if(MEASURETEXTPOSITION_CENTERED == eVertical)
205 bMainLineSplitted = true;
208 if(MEASURETEXTPOSITION_AUTOMATIC == eHorizontal)
210 if(aTextRange.getWidth() > fDistance)
212 eHorizontal = MEASURETEXTPOSITION_NEGATIVE;
214 else
216 eHorizontal = MEASURETEXTPOSITION_CENTERED;
219 if(bMainLineSplitted)
221 if(aTextRange.getWidth() + fSpaceNeededByArrows > fDistance)
223 bArrowsOutside = true;
226 else
228 const double fSmallArrowNeed(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.125));
230 if(aTextRange.getWidth() + fSmallArrowNeed > fDistance)
232 bArrowsOutside = true;
237 if(MEASURETEXTPOSITION_CENTERED != eHorizontal)
239 bArrowsOutside = true;
242 // switch text above/below?
243 if(getBelow() || (bAutoUpsideDown && !getTextRotation()))
245 if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
247 eVertical = MEASURETEXTPOSITION_POSITIVE;
249 else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
251 eVertical = MEASURETEXTPOSITION_NEGATIVE;
255 const double fMainLineOffset(getBelow() ? getDistance() : -getDistance());
256 const basegfx::B2DPoint aMainLeft(0.0, fMainLineOffset);
257 const basegfx::B2DPoint aMainRight(fDistance, fMainLineOffset);
259 // main line
260 if(bArrowsOutside)
262 double fLenLeft(fArrowsOutsideLen);
263 double fLenRight(fArrowsOutsideLen);
265 if(!bMainLineSplitted)
267 if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
269 fLenLeft = fStartArrowH + aTextRange.getWidth();
271 else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
273 fLenRight = fEndArrowH + aTextRange.getWidth();
277 const basegfx::B2DPoint aMainLeftLeft(aMainLeft.getX() - fLenLeft, aMainLeft.getY());
278 const basegfx::B2DPoint aMainRightRight(aMainRight.getX() + fLenRight, aMainRight.getY());
280 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeftLeft, aMainLeft, false, true));
281 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainRight, aMainRightRight, true, false));
283 if(!bMainLineSplitted || MEASURETEXTPOSITION_CENTERED != eHorizontal)
285 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainRight, false, false));
288 else
290 if(bMainLineSplitted)
292 const double fHalfLength((fDistance - (aTextRange.getWidth() + (fStartArrowH + fEndArrowH) * 0.25)) * 0.5);
293 const basegfx::B2DPoint aMainInnerLeft(aMainLeft.getX() + fHalfLength, aMainLeft.getY());
294 const basegfx::B2DPoint aMainInnerRight(aMainRight.getX() - fHalfLength, aMainRight.getY());
296 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainInnerLeft, true, false));
297 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainInnerRight, aMainRight, false, true));
299 else
301 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aMainLeft, aMainRight, true, true));
305 // left/right help line value preparation
306 const double fTopEdge(getBelow() ? getUpper() + getDistance() : -getUpper() - getDistance());
307 const double fBottomLeft(getBelow() ? getLower() - getLeftDelta() : getLeftDelta() - getLower());
308 const double fBottomRight(getBelow() ? getLower() - getRightDelta() : getRightDelta() - getLower());
310 // left help line
311 const basegfx::B2DPoint aLeftUp(0.0, fTopEdge);
312 const basegfx::B2DPoint aLeftDown(0.0, fBottomLeft);
314 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aLeftDown, aLeftUp, false, false));
316 // right help line
317 const basegfx::B2DPoint aRightUp(fDistance, fTopEdge);
318 const basegfx::B2DPoint aRightDown(fDistance, fBottomRight);
320 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(aObjectMatrix, aRightDown, aRightUp, false, false));
322 // text horizontal position
323 if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
325 // left
326 const double fSmall(fArrowsOutsideLen * 0.18);
327 fTextX = aMainLeft.getX() - (fStartArrowH + aTextRange.getWidth() + fSmall + fHalfLineWidth);
329 if(bMainLineSplitted)
331 fTextX -= (fArrowsOutsideLen - fStartArrowH);
334 if(pTextAttribute)
336 fTextX -= pTextAttribute->getTextRightDistance();
339 else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
341 // right
342 const double fSmall(fArrowsOutsideLen * 0.18);
343 fTextX = aMainRight.getX() + (fEndArrowH + fSmall + fHalfLineWidth);
345 if(bMainLineSplitted)
347 fTextX += (fArrowsOutsideLen - fEndArrowH);
350 if(pTextAttribute)
352 fTextX += pTextAttribute->getTextLeftDistance();
355 else // MEASURETEXTPOSITION_CENTERED
357 // centered
358 fTextX = aMainLeft.getX() + ((fDistance - aTextRange.getWidth()) * 0.5);
360 if(pTextAttribute)
362 fTextX += (pTextAttribute->getTextLeftDistance() - pTextAttribute->getTextRightDistance()) / 2L;
366 // text vertical position
367 if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
369 // top
370 const double fSmall(fArrowsOutsideLen * 0.10);
371 fTextY = aMainLeft.getY() - (aTextRange.getHeight() + fSmall + fHalfLineWidth);
373 if(pTextAttribute)
375 fTextY -= pTextAttribute->getTextLowerDistance();
378 else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
380 // bottom
381 const double fSmall(fArrowsOutsideLen * 0.10);
382 fTextY = aMainLeft.getY() + (fSmall + fHalfLineWidth);
384 if(pTextAttribute)
386 fTextY += pTextAttribute->getTextUpperDistance();
389 else // MEASURETEXTPOSITION_CENTERED
391 // centered
392 fTextY = aMainLeft.getY() - (aTextRange.getHeight() * 0.5);
394 if(pTextAttribute)
396 fTextY += (pTextAttribute->getTextUpperDistance() - pTextAttribute->getTextLowerDistance()) / 2L;
401 if(!getSdrLSTAttribute().getLine())
403 // embed line geometry to invisible line group
404 const Primitive2DReference xHiddenLines(new HitTestPrimitive2D(aRetval));
405 aRetval = Primitive2DSequence(&xHiddenLines, 1);
407 // delete temporary LineAttribute again
408 delete pLineAttribute;
411 if(pBlockText)
413 // create transformation to text primitive end position
414 basegfx::B2DHomMatrix aChange;
416 // handle auto text rotation
417 if(bAutoUpsideDown)
419 aChange.rotate(F_PI);
422 // move from aTextRange.TopLeft to fTextX, fTextY
423 aChange.translate(fTextX - aTextRange.getMinX(), fTextY - aTextRange.getMinY());
425 // apply object matrix
426 aChange *= aObjectMatrix;
428 // apply to existing text primitive
429 SdrTextPrimitive2D* pNewBlockText = pBlockText->createTransformedClone(aChange);
430 OSL_ENSURE(pNewBlockText, "SdrMeasurePrimitive2D::createLocalDecomposition: Could not create transformed clone of text primitive (!)");
431 delete pBlockText;
433 // add to local primitives
434 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, Primitive2DReference(pNewBlockText));
437 // add shadow
438 if(getSdrLSTAttribute().getShadow())
440 aRetval = createEmbeddedShadowPrimitive(aRetval, *getSdrLSTAttribute().getShadow());
443 return aRetval;
446 SdrMeasurePrimitive2D::SdrMeasurePrimitive2D(
447 const attribute::SdrLineShadowTextAttribute& rSdrLSTAttribute,
448 const basegfx::B2DPoint& rStart,
449 const basegfx::B2DPoint& rEnd,
450 MeasureTextPosition eHorizontal,
451 MeasureTextPosition eVertical,
452 double fDistance,
453 double fUpper,
454 double fLower,
455 double fLeftDelta,
456 double fRightDelta,
457 bool bBelow,
458 bool bTextRotation,
459 bool bTextAutoAngle)
460 : BasePrimitive2D(),
461 maSdrLSTAttribute(rSdrLSTAttribute),
462 maStart(rStart),
463 maEnd(rEnd),
464 meHorizontal(eHorizontal),
465 meVertical(eVertical),
466 mfDistance(fDistance),
467 mfUpper(fUpper),
468 mfLower(fLower),
469 mfLeftDelta(fLeftDelta),
470 mfRightDelta(fRightDelta),
471 mbBelow(bBelow),
472 mbTextRotation(bTextRotation),
473 mbTextAutoAngle(bTextAutoAngle)
477 bool SdrMeasurePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
479 if(BasePrimitive2D::operator==(rPrimitive))
481 const SdrMeasurePrimitive2D& rCompare = (SdrMeasurePrimitive2D&)rPrimitive;
483 return (getStart() == rCompare.getStart()
484 && getEnd() == rCompare.getEnd()
485 && getHorizontal() == rCompare.getHorizontal()
486 && getVertical() == rCompare.getVertical()
487 && getDistance() == rCompare.getDistance()
488 && getUpper() == rCompare.getUpper()
489 && getLower() == rCompare.getLower()
490 && getLeftDelta() == rCompare.getLeftDelta()
491 && getRightDelta() == rCompare.getRightDelta()
492 && getBelow() == rCompare.getBelow()
493 && getTextRotation() == rCompare.getTextRotation()
494 && getTextAutoAngle() == rCompare.getTextAutoAngle()
495 && getSdrLSTAttribute() == rCompare.getSdrLSTAttribute());
498 return false;
501 // provide unique ID
502 ImplPrimitrive2DIDBlock(SdrMeasurePrimitive2D, PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D)
504 } // end of namespace primitive2d
505 } // end of namespace drawinglayer
507 //////////////////////////////////////////////////////////////////////////////
508 // eof