1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #include "precompiled_svx.hxx"
25*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/sdrmeasureprimitive2d.hxx>
26*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
27*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrix.hxx>
28*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
29*b1cdbd2cSJim Jagielski #include <svx/sdr/attribute/sdrtextattribute.hxx>
30*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygontools.hxx>
31*b1cdbd2cSJim Jagielski #include <basegfx/tools/canvastools.hxx>
32*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/groupprimitive2d.hxx>
33*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
34*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrixtools.hxx>
35*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx>
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski using namespace com::sun::star;
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
42*b1cdbd2cSJim Jagielski 
43*b1cdbd2cSJim Jagielski namespace drawinglayer
44*b1cdbd2cSJim Jagielski {
45*b1cdbd2cSJim Jagielski 	namespace primitive2d
46*b1cdbd2cSJim Jagielski 	{
impCreatePart(const attribute::SdrLineAttribute & rLineAttribute,const basegfx::B2DHomMatrix & rObjectMatrix,const basegfx::B2DPoint & rStart,const basegfx::B2DPoint & rEnd,bool bLeftActive,bool bRightActive) const47*b1cdbd2cSJim Jagielski 		Primitive2DReference SdrMeasurePrimitive2D::impCreatePart(
48*b1cdbd2cSJim Jagielski 			const attribute::SdrLineAttribute& rLineAttribute,
49*b1cdbd2cSJim Jagielski 			const basegfx::B2DHomMatrix& rObjectMatrix,
50*b1cdbd2cSJim Jagielski 			const basegfx::B2DPoint& rStart,
51*b1cdbd2cSJim Jagielski 			const basegfx::B2DPoint& rEnd,
52*b1cdbd2cSJim Jagielski 			bool bLeftActive,
53*b1cdbd2cSJim Jagielski 			bool bRightActive) const
54*b1cdbd2cSJim Jagielski 		{
55*b1cdbd2cSJim Jagielski 			const attribute::SdrLineStartEndAttribute& rLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
56*b1cdbd2cSJim Jagielski 			basegfx::B2DPolygon aPolygon;
57*b1cdbd2cSJim Jagielski 
58*b1cdbd2cSJim Jagielski 			aPolygon.append(rStart);
59*b1cdbd2cSJim Jagielski 			aPolygon.append(rEnd);
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski 			if(rLineStartEnd.isDefault() || (!bLeftActive && !bRightActive))
62*b1cdbd2cSJim Jagielski 			{
63*b1cdbd2cSJim Jagielski 				return createPolygonLinePrimitive(
64*b1cdbd2cSJim Jagielski 					aPolygon,
65*b1cdbd2cSJim Jagielski 					rObjectMatrix,
66*b1cdbd2cSJim Jagielski 					rLineAttribute,
67*b1cdbd2cSJim Jagielski 					attribute::SdrLineStartEndAttribute());
68*b1cdbd2cSJim Jagielski 			}
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski             if(bLeftActive && bRightActive)
71*b1cdbd2cSJim Jagielski 			{
72*b1cdbd2cSJim Jagielski 				return createPolygonLinePrimitive(
73*b1cdbd2cSJim Jagielski 					aPolygon,
74*b1cdbd2cSJim Jagielski 					rObjectMatrix,
75*b1cdbd2cSJim Jagielski 					rLineAttribute,
76*b1cdbd2cSJim Jagielski 					rLineStartEnd);
77*b1cdbd2cSJim Jagielski 			}
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski 			const basegfx::B2DPolyPolygon aEmpty;
80*b1cdbd2cSJim Jagielski 			const attribute::SdrLineStartEndAttribute aLineStartEnd(
81*b1cdbd2cSJim Jagielski 				bLeftActive ? rLineStartEnd.getStartPolyPolygon() : aEmpty, bRightActive ? rLineStartEnd.getEndPolyPolygon() : aEmpty,
82*b1cdbd2cSJim Jagielski 				bLeftActive ? rLineStartEnd.getStartWidth() : 0.0, bRightActive ? rLineStartEnd.getEndWidth() : 0.0,
83*b1cdbd2cSJim Jagielski 				bLeftActive ? rLineStartEnd.isStartActive() : false, bRightActive ? rLineStartEnd.isEndActive() : false,
84*b1cdbd2cSJim Jagielski 				bLeftActive ? rLineStartEnd.isStartCentered() : false, bRightActive? rLineStartEnd.isEndCentered() : false);
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski 			return createPolygonLinePrimitive(aPolygon, rObjectMatrix, rLineAttribute, aLineStartEnd);
87*b1cdbd2cSJim Jagielski 		}
88*b1cdbd2cSJim Jagielski 
create2DDecomposition(const geometry::ViewInformation2D & aViewInformation) const89*b1cdbd2cSJim Jagielski 		Primitive2DSequence SdrMeasurePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
90*b1cdbd2cSJim Jagielski 		{
91*b1cdbd2cSJim Jagielski 			Primitive2DSequence aRetval;
92*b1cdbd2cSJim Jagielski 			SdrBlockTextPrimitive2D* pBlockText = 0;
93*b1cdbd2cSJim Jagielski 			basegfx::B2DRange aTextRange;
94*b1cdbd2cSJim Jagielski 			double fTextX((getStart().getX() + getEnd().getX()) * 0.5);
95*b1cdbd2cSJim Jagielski 			double fTextY((getStart().getX() + getEnd().getX()) * 0.5);
96*b1cdbd2cSJim Jagielski 			const basegfx::B2DVector aLine(getEnd() - getStart());
97*b1cdbd2cSJim Jagielski 			const double fDistance(aLine.getLength());
98*b1cdbd2cSJim Jagielski 			const double fAngle(atan2(aLine.getY(), aLine.getX()));
99*b1cdbd2cSJim Jagielski 			bool bAutoUpsideDown(false);
100*b1cdbd2cSJim Jagielski 			const attribute::SdrTextAttribute rTextAttribute = getSdrLSTAttribute().getText();
101*b1cdbd2cSJim Jagielski             const basegfx::B2DHomMatrix aObjectMatrix(
102*b1cdbd2cSJim Jagielski                 basegfx::tools::createShearXRotateTranslateB2DHomMatrix(0.0, fAngle, getStart()));
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski             // preapare text, but do not add yet; it needs to be aligned to
105*b1cdbd2cSJim Jagielski             // the line geometry
106*b1cdbd2cSJim Jagielski 			if(!rTextAttribute.isDefault())
107*b1cdbd2cSJim Jagielski 			{
108*b1cdbd2cSJim Jagielski 				basegfx::B2DHomMatrix aTextMatrix;
109*b1cdbd2cSJim Jagielski 				double fTestAngle(fAngle);
110*b1cdbd2cSJim Jagielski 
111*b1cdbd2cSJim Jagielski 				if(getTextRotation())
112*b1cdbd2cSJim Jagielski 				{
113*b1cdbd2cSJim Jagielski 					aTextMatrix.rotate(-90.0 * F_PI180);
114*b1cdbd2cSJim Jagielski 					fTestAngle -= (90.0 * F_PI180);
115*b1cdbd2cSJim Jagielski 
116*b1cdbd2cSJim Jagielski 					if(getTextAutoAngle() && fTestAngle < -F_PI)
117*b1cdbd2cSJim Jagielski 					{
118*b1cdbd2cSJim Jagielski 						fTestAngle += F_2PI;
119*b1cdbd2cSJim Jagielski 					}
120*b1cdbd2cSJim Jagielski 				}
121*b1cdbd2cSJim Jagielski 
122*b1cdbd2cSJim Jagielski 				if(getTextAutoAngle())
123*b1cdbd2cSJim Jagielski 				{
124*b1cdbd2cSJim Jagielski 					if(fTestAngle > (F_PI / 4.0) || fTestAngle < (-F_PI * (3.0 / 4.0)))
125*b1cdbd2cSJim Jagielski 					{
126*b1cdbd2cSJim Jagielski 						bAutoUpsideDown = true;
127*b1cdbd2cSJim Jagielski 					}
128*b1cdbd2cSJim Jagielski 				}
129*b1cdbd2cSJim Jagielski 
130*b1cdbd2cSJim Jagielski 				// create primitive and get text range
131*b1cdbd2cSJim Jagielski 				pBlockText = new SdrBlockTextPrimitive2D(
132*b1cdbd2cSJim Jagielski                     &rTextAttribute.getSdrText(),
133*b1cdbd2cSJim Jagielski                     rTextAttribute.getOutlinerParaObject(),
134*b1cdbd2cSJim Jagielski                     aTextMatrix,
135*b1cdbd2cSJim Jagielski                     SDRTEXTHORZADJUST_CENTER,
136*b1cdbd2cSJim Jagielski                     SDRTEXTVERTADJUST_CENTER,
137*b1cdbd2cSJim Jagielski                     rTextAttribute.isScroll(),
138*b1cdbd2cSJim Jagielski                     false,
139*b1cdbd2cSJim Jagielski                     false,
140*b1cdbd2cSJim Jagielski                     false,
141*b1cdbd2cSJim Jagielski 					false);
142*b1cdbd2cSJim Jagielski 
143*b1cdbd2cSJim Jagielski                 aTextRange = pBlockText->getB2DRange(aViewInformation);
144*b1cdbd2cSJim Jagielski 			}
145*b1cdbd2cSJim Jagielski 
146*b1cdbd2cSJim Jagielski             // prepare line attribute and result
147*b1cdbd2cSJim Jagielski 			{
148*b1cdbd2cSJim Jagielski 	            const attribute::SdrLineAttribute rLineAttribute(getSdrLSTAttribute().getLine());
149*b1cdbd2cSJim Jagielski 				bool bArrowsOutside(false);
150*b1cdbd2cSJim Jagielski 				bool bMainLineSplitted(false);
151*b1cdbd2cSJim Jagielski 				const attribute::SdrLineStartEndAttribute& rLineStartEnd = getSdrLSTAttribute().getLineStartEnd();
152*b1cdbd2cSJim Jagielski 				double fStartArrowW(0.0);
153*b1cdbd2cSJim Jagielski 				double fStartArrowH(0.0);
154*b1cdbd2cSJim Jagielski 				double fEndArrowW(0.0);
155*b1cdbd2cSJim Jagielski 				double fEndArrowH(0.0);
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski 				if(!rLineStartEnd.isDefault())
158*b1cdbd2cSJim Jagielski 				{
159*b1cdbd2cSJim Jagielski 					if(rLineStartEnd.isStartActive())
160*b1cdbd2cSJim Jagielski 					{
161*b1cdbd2cSJim Jagielski 						const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(rLineStartEnd.getStartPolyPolygon()));
162*b1cdbd2cSJim Jagielski 						fStartArrowW = rLineStartEnd.getStartWidth();
163*b1cdbd2cSJim Jagielski 						fStartArrowH = aArrowRange.getHeight() * fStartArrowW / aArrowRange.getWidth();
164*b1cdbd2cSJim Jagielski 
165*b1cdbd2cSJim Jagielski 						if(rLineStartEnd.isStartCentered())
166*b1cdbd2cSJim Jagielski 						{
167*b1cdbd2cSJim Jagielski 							fStartArrowH *= 0.5;
168*b1cdbd2cSJim Jagielski 						}
169*b1cdbd2cSJim Jagielski 					}
170*b1cdbd2cSJim Jagielski 
171*b1cdbd2cSJim Jagielski 					if(rLineStartEnd.isEndActive())
172*b1cdbd2cSJim Jagielski 					{
173*b1cdbd2cSJim Jagielski 						const basegfx::B2DRange aArrowRange(basegfx::tools::getRange(rLineStartEnd.getEndPolyPolygon()));
174*b1cdbd2cSJim Jagielski 						fEndArrowW = rLineStartEnd.getEndWidth();
175*b1cdbd2cSJim Jagielski 						fEndArrowH = aArrowRange.getHeight() * fEndArrowW / aArrowRange.getWidth();
176*b1cdbd2cSJim Jagielski 
177*b1cdbd2cSJim Jagielski 						if(rLineStartEnd.isEndCentered())
178*b1cdbd2cSJim Jagielski 						{
179*b1cdbd2cSJim Jagielski 							fEndArrowH *= 0.5;
180*b1cdbd2cSJim Jagielski 						}
181*b1cdbd2cSJim Jagielski 					}
182*b1cdbd2cSJim Jagielski 				}
183*b1cdbd2cSJim Jagielski 
184*b1cdbd2cSJim Jagielski 				const double fSpaceNeededByArrows(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.5));
185*b1cdbd2cSJim Jagielski 				const double fArrowsOutsideLen((fStartArrowH + fEndArrowH + fStartArrowW + fEndArrowW) * 0.5);
186*b1cdbd2cSJim Jagielski 				const double fHalfLineWidth(rLineAttribute.getWidth() * 0.5);
187*b1cdbd2cSJim Jagielski 
188*b1cdbd2cSJim Jagielski 				if(fSpaceNeededByArrows > fDistance)
189*b1cdbd2cSJim Jagielski 				{
190*b1cdbd2cSJim Jagielski 					bArrowsOutside = true;
191*b1cdbd2cSJim Jagielski 				}
192*b1cdbd2cSJim Jagielski 
193*b1cdbd2cSJim Jagielski 				MeasureTextPosition eHorizontal(getHorizontal());
194*b1cdbd2cSJim Jagielski 				MeasureTextPosition eVertical(getVertical());
195*b1cdbd2cSJim Jagielski 
196*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_AUTOMATIC == eVertical)
197*b1cdbd2cSJim Jagielski 				{
198*b1cdbd2cSJim Jagielski 					eVertical = MEASURETEXTPOSITION_NEGATIVE;
199*b1cdbd2cSJim Jagielski 				}
200*b1cdbd2cSJim Jagielski 
201*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_CENTERED == eVertical)
202*b1cdbd2cSJim Jagielski 				{
203*b1cdbd2cSJim Jagielski 					bMainLineSplitted = true;
204*b1cdbd2cSJim Jagielski 				}
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_AUTOMATIC == eHorizontal)
207*b1cdbd2cSJim Jagielski 				{
208*b1cdbd2cSJim Jagielski 					if(aTextRange.getWidth() > fDistance)
209*b1cdbd2cSJim Jagielski 					{
210*b1cdbd2cSJim Jagielski 						eHorizontal = MEASURETEXTPOSITION_NEGATIVE;
211*b1cdbd2cSJim Jagielski 					}
212*b1cdbd2cSJim Jagielski 					else
213*b1cdbd2cSJim Jagielski 					{
214*b1cdbd2cSJim Jagielski 						eHorizontal = MEASURETEXTPOSITION_CENTERED;
215*b1cdbd2cSJim Jagielski 					}
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski 					if(bMainLineSplitted)
218*b1cdbd2cSJim Jagielski 					{
219*b1cdbd2cSJim Jagielski 						if(aTextRange.getWidth() + fSpaceNeededByArrows > fDistance)
220*b1cdbd2cSJim Jagielski 						{
221*b1cdbd2cSJim Jagielski 							bArrowsOutside = true;
222*b1cdbd2cSJim Jagielski 						}
223*b1cdbd2cSJim Jagielski 					}
224*b1cdbd2cSJim Jagielski 					else
225*b1cdbd2cSJim Jagielski 					{
226*b1cdbd2cSJim Jagielski 						const double fSmallArrowNeed(fStartArrowH + fEndArrowH + ((fStartArrowW + fEndArrowW) * 0.125));
227*b1cdbd2cSJim Jagielski 
228*b1cdbd2cSJim Jagielski 						if(aTextRange.getWidth() + fSmallArrowNeed > fDistance)
229*b1cdbd2cSJim Jagielski 						{
230*b1cdbd2cSJim Jagielski 							bArrowsOutside = true;
231*b1cdbd2cSJim Jagielski 						}
232*b1cdbd2cSJim Jagielski 					}
233*b1cdbd2cSJim Jagielski 				}
234*b1cdbd2cSJim Jagielski 
235*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_CENTERED != eHorizontal)
236*b1cdbd2cSJim Jagielski 				{
237*b1cdbd2cSJim Jagielski 					bArrowsOutside = true;
238*b1cdbd2cSJim Jagielski 				}
239*b1cdbd2cSJim Jagielski 
240*b1cdbd2cSJim Jagielski 				// switch text above/below?
241*b1cdbd2cSJim Jagielski 				if(getBelow() || (bAutoUpsideDown && !getTextRotation()))
242*b1cdbd2cSJim Jagielski 				{
243*b1cdbd2cSJim Jagielski 					if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
244*b1cdbd2cSJim Jagielski 					{
245*b1cdbd2cSJim Jagielski 						eVertical = MEASURETEXTPOSITION_POSITIVE;
246*b1cdbd2cSJim Jagielski 					}
247*b1cdbd2cSJim Jagielski 					else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
248*b1cdbd2cSJim Jagielski 					{
249*b1cdbd2cSJim Jagielski 						eVertical = MEASURETEXTPOSITION_NEGATIVE;
250*b1cdbd2cSJim Jagielski 					}
251*b1cdbd2cSJim Jagielski 				}
252*b1cdbd2cSJim Jagielski 
253*b1cdbd2cSJim Jagielski 				const double fMainLineOffset(getBelow() ? getDistance() : -getDistance());
254*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aMainLeft(0.0, fMainLineOffset);
255*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aMainRight(fDistance, fMainLineOffset);
256*b1cdbd2cSJim Jagielski 
257*b1cdbd2cSJim Jagielski 				// main line
258*b1cdbd2cSJim Jagielski 				if(bArrowsOutside)
259*b1cdbd2cSJim Jagielski 				{
260*b1cdbd2cSJim Jagielski 					double fLenLeft(fArrowsOutsideLen);
261*b1cdbd2cSJim Jagielski 					double fLenRight(fArrowsOutsideLen);
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski 					if(!bMainLineSplitted)
264*b1cdbd2cSJim Jagielski 					{
265*b1cdbd2cSJim Jagielski 						if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
266*b1cdbd2cSJim Jagielski 						{
267*b1cdbd2cSJim Jagielski 							fLenLeft = fStartArrowH + aTextRange.getWidth();
268*b1cdbd2cSJim Jagielski 						}
269*b1cdbd2cSJim Jagielski 						else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
270*b1cdbd2cSJim Jagielski 						{
271*b1cdbd2cSJim Jagielski 							fLenRight = fEndArrowH + aTextRange.getWidth();
272*b1cdbd2cSJim Jagielski 						}
273*b1cdbd2cSJim Jagielski 					}
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski 					const basegfx::B2DPoint aMainLeftLeft(aMainLeft.getX() - fLenLeft, aMainLeft.getY());
276*b1cdbd2cSJim Jagielski 					const basegfx::B2DPoint aMainRightRight(aMainRight.getX() + fLenRight, aMainRight.getY());
277*b1cdbd2cSJim Jagielski 
278*b1cdbd2cSJim Jagielski 					appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeftLeft, aMainLeft, false, true));
279*b1cdbd2cSJim Jagielski 					appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainRight, aMainRightRight, true, false));
280*b1cdbd2cSJim Jagielski 
281*b1cdbd2cSJim Jagielski 					if(!bMainLineSplitted || MEASURETEXTPOSITION_CENTERED != eHorizontal)
282*b1cdbd2cSJim Jagielski 					{
283*b1cdbd2cSJim Jagielski 						appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainRight, false, false));
284*b1cdbd2cSJim Jagielski 					}
285*b1cdbd2cSJim Jagielski 				}
286*b1cdbd2cSJim Jagielski 				else
287*b1cdbd2cSJim Jagielski 				{
288*b1cdbd2cSJim Jagielski 					if(bMainLineSplitted)
289*b1cdbd2cSJim Jagielski 					{
290*b1cdbd2cSJim Jagielski 						const double fHalfLength((fDistance - (aTextRange.getWidth() + (fStartArrowH + fEndArrowH) * 0.25)) * 0.5);
291*b1cdbd2cSJim Jagielski 						const basegfx::B2DPoint aMainInnerLeft(aMainLeft.getX() + fHalfLength, aMainLeft.getY());
292*b1cdbd2cSJim Jagielski 						const basegfx::B2DPoint aMainInnerRight(aMainRight.getX() - fHalfLength, aMainRight.getY());
293*b1cdbd2cSJim Jagielski 
294*b1cdbd2cSJim Jagielski 						appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainInnerLeft, true, false));
295*b1cdbd2cSJim Jagielski 						appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainInnerRight, aMainRight, false, true));
296*b1cdbd2cSJim Jagielski 					}
297*b1cdbd2cSJim Jagielski 					else
298*b1cdbd2cSJim Jagielski 					{
299*b1cdbd2cSJim Jagielski 						appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aMainLeft, aMainRight, true, true));
300*b1cdbd2cSJim Jagielski 					}
301*b1cdbd2cSJim Jagielski 				}
302*b1cdbd2cSJim Jagielski 
303*b1cdbd2cSJim Jagielski 				// left/right help line value preparation
304*b1cdbd2cSJim Jagielski 				const double fTopEdge(getBelow() ? getUpper() + getDistance() : -getUpper() - getDistance());
305*b1cdbd2cSJim Jagielski 				const double fBottomLeft(getBelow() ? getLower() - getLeftDelta() : getLeftDelta() - getLower());
306*b1cdbd2cSJim Jagielski 				const double fBottomRight(getBelow() ? getLower() - getRightDelta() : getRightDelta() - getLower());
307*b1cdbd2cSJim Jagielski 
308*b1cdbd2cSJim Jagielski 				// left help line
309*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aLeftUp(0.0, fTopEdge);
310*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aLeftDown(0.0, fBottomLeft);
311*b1cdbd2cSJim Jagielski 
312*b1cdbd2cSJim Jagielski 				appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aLeftDown, aLeftUp, false, false));
313*b1cdbd2cSJim Jagielski 
314*b1cdbd2cSJim Jagielski 				// right help line
315*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aRightUp(fDistance, fTopEdge);
316*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aRightDown(fDistance, fBottomRight);
317*b1cdbd2cSJim Jagielski 
318*b1cdbd2cSJim Jagielski 				appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, impCreatePart(rLineAttribute, aObjectMatrix, aRightDown, aRightUp, false, false));
319*b1cdbd2cSJim Jagielski 
320*b1cdbd2cSJim Jagielski 				// text horizontal position
321*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_NEGATIVE == eHorizontal)
322*b1cdbd2cSJim Jagielski 				{
323*b1cdbd2cSJim Jagielski 					// left
324*b1cdbd2cSJim Jagielski 					const double fSmall(fArrowsOutsideLen * 0.18);
325*b1cdbd2cSJim Jagielski 					fTextX = aMainLeft.getX() - (fStartArrowH + aTextRange.getWidth() + fSmall + fHalfLineWidth);
326*b1cdbd2cSJim Jagielski 
327*b1cdbd2cSJim Jagielski 					if(bMainLineSplitted)
328*b1cdbd2cSJim Jagielski 					{
329*b1cdbd2cSJim Jagielski 						fTextX -= (fArrowsOutsideLen - fStartArrowH);
330*b1cdbd2cSJim Jagielski 					}
331*b1cdbd2cSJim Jagielski 
332*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
333*b1cdbd2cSJim Jagielski 					{
334*b1cdbd2cSJim Jagielski 						fTextX -= rTextAttribute.getTextRightDistance();
335*b1cdbd2cSJim Jagielski 					}
336*b1cdbd2cSJim Jagielski 				}
337*b1cdbd2cSJim Jagielski 				else if(MEASURETEXTPOSITION_POSITIVE == eHorizontal)
338*b1cdbd2cSJim Jagielski 				{
339*b1cdbd2cSJim Jagielski 					// right
340*b1cdbd2cSJim Jagielski 					const double fSmall(fArrowsOutsideLen * 0.18);
341*b1cdbd2cSJim Jagielski 					fTextX = aMainRight.getX() + (fEndArrowH + fSmall + fHalfLineWidth);
342*b1cdbd2cSJim Jagielski 
343*b1cdbd2cSJim Jagielski 					if(bMainLineSplitted)
344*b1cdbd2cSJim Jagielski 					{
345*b1cdbd2cSJim Jagielski 						fTextX += (fArrowsOutsideLen - fEndArrowH);
346*b1cdbd2cSJim Jagielski 					}
347*b1cdbd2cSJim Jagielski 
348*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
349*b1cdbd2cSJim Jagielski 					{
350*b1cdbd2cSJim Jagielski 						fTextX += rTextAttribute.getTextLeftDistance();
351*b1cdbd2cSJim Jagielski 					}
352*b1cdbd2cSJim Jagielski 				}
353*b1cdbd2cSJim Jagielski 				else // MEASURETEXTPOSITION_CENTERED
354*b1cdbd2cSJim Jagielski 				{
355*b1cdbd2cSJim Jagielski 					// centered
356*b1cdbd2cSJim Jagielski 					fTextX = aMainLeft.getX() + ((fDistance - aTextRange.getWidth()) * 0.5);
357*b1cdbd2cSJim Jagielski 
358*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
359*b1cdbd2cSJim Jagielski 					{
360*b1cdbd2cSJim Jagielski 						fTextX += (rTextAttribute.getTextLeftDistance() - rTextAttribute.getTextRightDistance()) / 2L;
361*b1cdbd2cSJim Jagielski 					}
362*b1cdbd2cSJim Jagielski 				}
363*b1cdbd2cSJim Jagielski 
364*b1cdbd2cSJim Jagielski 				// text vertical position
365*b1cdbd2cSJim Jagielski 				if(MEASURETEXTPOSITION_NEGATIVE == eVertical)
366*b1cdbd2cSJim Jagielski 				{
367*b1cdbd2cSJim Jagielski 					// top
368*b1cdbd2cSJim Jagielski 					const double fSmall(fArrowsOutsideLen * 0.10);
369*b1cdbd2cSJim Jagielski 					fTextY = aMainLeft.getY() - (aTextRange.getHeight() + fSmall + fHalfLineWidth);
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
372*b1cdbd2cSJim Jagielski 					{
373*b1cdbd2cSJim Jagielski 						fTextY -= rTextAttribute.getTextLowerDistance();
374*b1cdbd2cSJim Jagielski 					}
375*b1cdbd2cSJim Jagielski 				}
376*b1cdbd2cSJim Jagielski 				else if(MEASURETEXTPOSITION_POSITIVE == eVertical)
377*b1cdbd2cSJim Jagielski 				{
378*b1cdbd2cSJim Jagielski 					// bottom
379*b1cdbd2cSJim Jagielski 					const double fSmall(fArrowsOutsideLen * 0.10);
380*b1cdbd2cSJim Jagielski 					fTextY = aMainLeft.getY() + (fSmall + fHalfLineWidth);
381*b1cdbd2cSJim Jagielski 
382*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
383*b1cdbd2cSJim Jagielski 					{
384*b1cdbd2cSJim Jagielski 						fTextY += rTextAttribute.getTextUpperDistance();
385*b1cdbd2cSJim Jagielski 					}
386*b1cdbd2cSJim Jagielski 				}
387*b1cdbd2cSJim Jagielski 				else // MEASURETEXTPOSITION_CENTERED
388*b1cdbd2cSJim Jagielski 				{
389*b1cdbd2cSJim Jagielski 					// centered
390*b1cdbd2cSJim Jagielski 					fTextY = aMainLeft.getY() - (aTextRange.getHeight() * 0.5);
391*b1cdbd2cSJim Jagielski 
392*b1cdbd2cSJim Jagielski 					if(!rTextAttribute.isDefault())
393*b1cdbd2cSJim Jagielski 					{
394*b1cdbd2cSJim Jagielski 						fTextY += (rTextAttribute.getTextUpperDistance() - rTextAttribute.getTextLowerDistance()) / 2L;
395*b1cdbd2cSJim Jagielski 					}
396*b1cdbd2cSJim Jagielski 				}
397*b1cdbd2cSJim Jagielski 			}
398*b1cdbd2cSJim Jagielski 
399*b1cdbd2cSJim Jagielski 			if(getSdrLSTAttribute().getLine().isDefault())
400*b1cdbd2cSJim Jagielski             {
401*b1cdbd2cSJim Jagielski                 // embed line geometry to invisible (100% transparent) line group for HitTest
402*b1cdbd2cSJim Jagielski                 const Primitive2DReference xHiddenLines(new HiddenGeometryPrimitive2D(aRetval));
403*b1cdbd2cSJim Jagielski 
404*b1cdbd2cSJim Jagielski 				aRetval = Primitive2DSequence(&xHiddenLines, 1);
405*b1cdbd2cSJim Jagielski             }
406*b1cdbd2cSJim Jagielski 
407*b1cdbd2cSJim Jagielski             if(pBlockText)
408*b1cdbd2cSJim Jagielski 			{
409*b1cdbd2cSJim Jagielski 				// create transformation to text primitive end position
410*b1cdbd2cSJim Jagielski 				basegfx::B2DHomMatrix aChange;
411*b1cdbd2cSJim Jagielski 
412*b1cdbd2cSJim Jagielski 				// handle auto text rotation
413*b1cdbd2cSJim Jagielski 				if(bAutoUpsideDown)
414*b1cdbd2cSJim Jagielski 				{
415*b1cdbd2cSJim Jagielski 					aChange.rotate(F_PI);
416*b1cdbd2cSJim Jagielski 				}
417*b1cdbd2cSJim Jagielski 
418*b1cdbd2cSJim Jagielski 				// move from aTextRange.TopLeft to fTextX, fTextY
419*b1cdbd2cSJim Jagielski 				aChange.translate(fTextX - aTextRange.getMinX(), fTextY - aTextRange.getMinY());
420*b1cdbd2cSJim Jagielski 
421*b1cdbd2cSJim Jagielski 				// apply object matrix
422*b1cdbd2cSJim Jagielski 				aChange *= aObjectMatrix;
423*b1cdbd2cSJim Jagielski 
424*b1cdbd2cSJim Jagielski 				// apply to existing text primitive
425*b1cdbd2cSJim Jagielski 				SdrTextPrimitive2D* pNewBlockText = pBlockText->createTransformedClone(aChange);
426*b1cdbd2cSJim Jagielski 				OSL_ENSURE(pNewBlockText, "SdrMeasurePrimitive2D::create2DDecomposition: Could not create transformed clone of text primitive (!)");
427*b1cdbd2cSJim Jagielski 				delete pBlockText;
428*b1cdbd2cSJim Jagielski 
429*b1cdbd2cSJim Jagielski 				// add to local primitives
430*b1cdbd2cSJim Jagielski 				appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, Primitive2DReference(pNewBlockText));
431*b1cdbd2cSJim Jagielski 			}
432*b1cdbd2cSJim Jagielski 
433*b1cdbd2cSJim Jagielski 			// add shadow
434*b1cdbd2cSJim Jagielski 			if(!getSdrLSTAttribute().getShadow().isDefault())
435*b1cdbd2cSJim Jagielski 			{
436*b1cdbd2cSJim Jagielski                 aRetval = createEmbeddedShadowPrimitive(
437*b1cdbd2cSJim Jagielski 					aRetval,
438*b1cdbd2cSJim Jagielski 					getSdrLSTAttribute().getShadow());
439*b1cdbd2cSJim Jagielski 			}
440*b1cdbd2cSJim Jagielski 
441*b1cdbd2cSJim Jagielski 			return aRetval;
442*b1cdbd2cSJim Jagielski 		}
443*b1cdbd2cSJim Jagielski 
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)444*b1cdbd2cSJim Jagielski 		SdrMeasurePrimitive2D::SdrMeasurePrimitive2D(
445*b1cdbd2cSJim Jagielski 			const attribute::SdrLineShadowTextAttribute& rSdrLSTAttribute,
446*b1cdbd2cSJim Jagielski 			const basegfx::B2DPoint& rStart,
447*b1cdbd2cSJim Jagielski 			const basegfx::B2DPoint& rEnd,
448*b1cdbd2cSJim Jagielski 			MeasureTextPosition eHorizontal,
449*b1cdbd2cSJim Jagielski 			MeasureTextPosition eVertical,
450*b1cdbd2cSJim Jagielski 			double fDistance,
451*b1cdbd2cSJim Jagielski 			double fUpper,
452*b1cdbd2cSJim Jagielski 			double fLower,
453*b1cdbd2cSJim Jagielski 			double fLeftDelta,
454*b1cdbd2cSJim Jagielski 			double fRightDelta,
455*b1cdbd2cSJim Jagielski 			bool bBelow,
456*b1cdbd2cSJim Jagielski 			bool bTextRotation,
457*b1cdbd2cSJim Jagielski 			bool bTextAutoAngle)
458*b1cdbd2cSJim Jagielski 		:	BufferedDecompositionPrimitive2D(),
459*b1cdbd2cSJim Jagielski 			maSdrLSTAttribute(rSdrLSTAttribute),
460*b1cdbd2cSJim Jagielski 			maStart(rStart),
461*b1cdbd2cSJim Jagielski 			maEnd(rEnd),
462*b1cdbd2cSJim Jagielski 			meHorizontal(eHorizontal),
463*b1cdbd2cSJim Jagielski 			meVertical(eVertical),
464*b1cdbd2cSJim Jagielski 			mfDistance(fDistance),
465*b1cdbd2cSJim Jagielski 			mfUpper(fUpper),
466*b1cdbd2cSJim Jagielski 			mfLower(fLower),
467*b1cdbd2cSJim Jagielski 			mfLeftDelta(fLeftDelta),
468*b1cdbd2cSJim Jagielski 			mfRightDelta(fRightDelta),
469*b1cdbd2cSJim Jagielski 			mbBelow(bBelow),
470*b1cdbd2cSJim Jagielski 			mbTextRotation(bTextRotation),
471*b1cdbd2cSJim Jagielski 			mbTextAutoAngle(bTextAutoAngle)
472*b1cdbd2cSJim Jagielski 		{
473*b1cdbd2cSJim Jagielski 		}
474*b1cdbd2cSJim Jagielski 
operator ==(const BasePrimitive2D & rPrimitive) const475*b1cdbd2cSJim Jagielski 		bool SdrMeasurePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
476*b1cdbd2cSJim Jagielski 		{
477*b1cdbd2cSJim Jagielski 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
478*b1cdbd2cSJim Jagielski 			{
479*b1cdbd2cSJim Jagielski 				const SdrMeasurePrimitive2D& rCompare = (SdrMeasurePrimitive2D&)rPrimitive;
480*b1cdbd2cSJim Jagielski 
481*b1cdbd2cSJim Jagielski 				return (getStart() == rCompare.getStart()
482*b1cdbd2cSJim Jagielski 					&& getEnd() == rCompare.getEnd()
483*b1cdbd2cSJim Jagielski 					&& getHorizontal() == rCompare.getHorizontal()
484*b1cdbd2cSJim Jagielski 					&& getVertical() == rCompare.getVertical()
485*b1cdbd2cSJim Jagielski 					&& getDistance() == rCompare.getDistance()
486*b1cdbd2cSJim Jagielski 					&& getUpper() == rCompare.getUpper()
487*b1cdbd2cSJim Jagielski 					&& getLower() == rCompare.getLower()
488*b1cdbd2cSJim Jagielski 					&& getLeftDelta() == rCompare.getLeftDelta()
489*b1cdbd2cSJim Jagielski 					&& getRightDelta() == rCompare.getRightDelta()
490*b1cdbd2cSJim Jagielski 					&& getBelow() == rCompare.getBelow()
491*b1cdbd2cSJim Jagielski 					&& getTextRotation() == rCompare.getTextRotation()
492*b1cdbd2cSJim Jagielski 					&& getTextAutoAngle() == rCompare.getTextAutoAngle()
493*b1cdbd2cSJim Jagielski 					&& getSdrLSTAttribute() == rCompare.getSdrLSTAttribute());
494*b1cdbd2cSJim Jagielski 			}
495*b1cdbd2cSJim Jagielski 
496*b1cdbd2cSJim Jagielski 			return false;
497*b1cdbd2cSJim Jagielski 		}
498*b1cdbd2cSJim Jagielski 
499*b1cdbd2cSJim Jagielski 		// provide unique ID
500*b1cdbd2cSJim Jagielski 		ImplPrimitrive2DIDBlock(SdrMeasurePrimitive2D, PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D)
501*b1cdbd2cSJim Jagielski 
502*b1cdbd2cSJim Jagielski 	} // end of namespace primitive2d
503*b1cdbd2cSJim Jagielski } // end of namespace drawinglayer
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
506*b1cdbd2cSJim Jagielski // eof
507