1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_drawinglayer.hxx"
26 
27 #include <drawinglayer/primitive2d/helplineprimitive2d.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
30 #include <basegfx/polygon/b2dpolygonclipper.hxx>
31 #include <basegfx/tools/canvastools.hxx>
32 #include <drawinglayer/geometry/viewinformation2d.hxx>
33 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
34 
35 //////////////////////////////////////////////////////////////////////////////
36 
37 using namespace com::sun::star;
38 
39 //////////////////////////////////////////////////////////////////////////////
40 
41 namespace drawinglayer
42 {
43 	namespace primitive2d
44 	{
create2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const45 		Primitive2DSequence HelplinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
46 		{
47 			std::vector< BasePrimitive2D* > aTempPrimitiveTarget;
48 
49 			if(!rViewInformation.getViewport().isEmpty() && !getDirection().equalZero())
50 			{
51 				// position to view coordinates, DashLen and DashLen in logic
52 				const basegfx::B2DPoint aViewPosition(rViewInformation.getObjectToViewTransformation() * getPosition());
53 
54 				switch(getStyle())
55 				{
56 					default : // HELPLINESTYLE2D_POINT
57 					{
58 						const double fViewFixValue(15.0);
59 						basegfx::B2DVector aNormalizedDirection(getDirection());
60 						aNormalizedDirection.normalize();
61 						aNormalizedDirection *= fViewFixValue;
62 						const basegfx::B2DPoint aStartA(aViewPosition - aNormalizedDirection);
63 						const basegfx::B2DPoint aEndA(aViewPosition + aNormalizedDirection);
64 						basegfx::B2DPolygon aLineA;
65 						aLineA.append(aStartA);
66 						aLineA.append(aEndA);
67 						aLineA.transform(rViewInformation.getInverseObjectToViewTransformation());
68 						PolygonMarkerPrimitive2D* pNewA = new PolygonMarkerPrimitive2D(aLineA, getRGBColA(), getRGBColB(), getDiscreteDashLength());
69 						aTempPrimitiveTarget.push_back(pNewA);
70 
71 						const basegfx::B2DVector aPerpendicularNormalizedDirection(basegfx::getPerpendicular(aNormalizedDirection));
72 						const basegfx::B2DPoint aStartB(aViewPosition - aPerpendicularNormalizedDirection);
73 						const basegfx::B2DPoint aEndB(aViewPosition + aPerpendicularNormalizedDirection);
74 						basegfx::B2DPolygon aLineB;
75 						aLineB.append(aStartB);
76 						aLineB.append(aEndB);
77 						aLineB.transform(rViewInformation.getInverseObjectToViewTransformation());
78 						PolygonMarkerPrimitive2D* pNewB = new PolygonMarkerPrimitive2D(aLineB, getRGBColA(), getRGBColB(), getDiscreteDashLength());
79 						aTempPrimitiveTarget.push_back(pNewB);
80 
81 						break;
82 					}
83 					case HELPLINESTYLE2D_LINE :
84 					{
85 						basegfx::B2DPolygon aLine;
86 
87 						if(basegfx::areParallel(getDirection(), basegfx::B2DVector(1.0, 0.0)))
88 						{
89 							// parallel to X-Axis, get cuts with Y-Axes
90 							const double fCutA((rViewInformation.getDiscreteViewport().getMinX() - aViewPosition.getX()) / getDirection().getX());
91 							const double fCutB((rViewInformation.getDiscreteViewport().getMaxX() - aViewPosition.getX()) / getDirection().getX());
92 							const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection()));
93 							const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection()));
94 							const bool bBothLeft(aPosA.getX() < rViewInformation.getDiscreteViewport().getMinX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMinX());
95 							const bool bBothRight(aPosA.getX() > rViewInformation.getDiscreteViewport().getMaxX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMaxX());
96 
97 							if(!bBothLeft && !bBothRight)
98 							{
99 								aLine.append(aPosA);
100 								aLine.append(aPosB);
101 							}
102 						}
103 						else
104 						{
105 							// get cuts with X-Axes
106 							const double fCutA((rViewInformation.getDiscreteViewport().getMinY() - aViewPosition.getY()) / getDirection().getY());
107 							const double fCutB((rViewInformation.getDiscreteViewport().getMaxY() - aViewPosition.getY()) / getDirection().getY());
108 							const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection()));
109 							const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection()));
110 							const bool bBothAbove(aPosA.getY() < rViewInformation.getDiscreteViewport().getMinY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMinY());
111 							const bool bBothBelow(aPosA.getY() > rViewInformation.getDiscreteViewport().getMaxY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMaxY());
112 
113 							if(!bBothAbove && !bBothBelow)
114 							{
115 								aLine.append(aPosA);
116 								aLine.append(aPosB);
117 							}
118 						}
119 
120 						if(aLine.count())
121 						{
122 							// clip against visible area
123 							const basegfx::B2DPolyPolygon aResult(basegfx::tools::clipPolygonOnRange(aLine, rViewInformation.getDiscreteViewport(), true, true));
124 
125 							for(sal_uInt32 a(0L); a < aResult.count(); a++)
126 							{
127 								basegfx::B2DPolygon aPart(aResult.getB2DPolygon(a));
128 								aPart.transform(rViewInformation.getInverseObjectToViewTransformation());
129 								PolygonMarkerPrimitive2D* pNew = new PolygonMarkerPrimitive2D(aPart, getRGBColA(), getRGBColB(), getDiscreteDashLength());
130 								aTempPrimitiveTarget.push_back(pNew);
131 							}
132 						}
133 
134 						break;
135 					}
136 				}
137 			}
138 
139 			// prepare return value
140 			Primitive2DSequence aRetval(aTempPrimitiveTarget.size());
141 
142 			for(sal_uInt32 a(0L); a < aTempPrimitiveTarget.size(); a++)
143 			{
144 				const Primitive2DReference xRef(aTempPrimitiveTarget[a]);
145 				aRetval[a] = xRef;
146 			}
147 
148 			return aRetval;
149 		}
150 
HelplinePrimitive2D(const basegfx::B2DPoint & rPosition,const basegfx::B2DVector & rDirection,HelplineStyle2D eStyle,const basegfx::BColor & rRGBColA,const basegfx::BColor & rRGBColB,double fDiscreteDashLength)151 		HelplinePrimitive2D::HelplinePrimitive2D(
152 			const basegfx::B2DPoint& rPosition,
153 			const basegfx::B2DVector& rDirection,
154 			HelplineStyle2D eStyle,
155 			const basegfx::BColor& rRGBColA,
156 			const basegfx::BColor& rRGBColB,
157 			double fDiscreteDashLength)
158 		:	BufferedDecompositionPrimitive2D(),
159 			maPosition(rPosition),
160 			maDirection(rDirection),
161 			meStyle(eStyle),
162 			maRGBColA(rRGBColA),
163 			maRGBColB(rRGBColB),
164 			mfDiscreteDashLength(fDiscreteDashLength),
165 			maLastObjectToViewTransformation(),
166 			maLastViewport()
167 		{
168 		}
169 
operator ==(const BasePrimitive2D & rPrimitive) const170 		bool HelplinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
171 		{
172 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
173 			{
174 				const HelplinePrimitive2D& rCompare = (HelplinePrimitive2D&)rPrimitive;
175 
176 				return (getPosition() == rCompare.getPosition()
177 					&& getDirection() == rCompare.getDirection()
178 					&& getStyle() == rCompare.getStyle()
179 					&& getRGBColA() == rCompare.getRGBColA()
180 					&& getRGBColB() == rCompare.getRGBColB()
181 					&& getDiscreteDashLength() == rCompare.getDiscreteDashLength());
182 			}
183 
184 			return false;
185 		}
186 
get2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const187 		Primitive2DSequence HelplinePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
188 		{
189 			::osl::MutexGuard aGuard( m_aMutex );
190 
191 			if(getBuffered2DDecomposition().hasElements())
192 			{
193 				if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
194 				{
195 					// conditions of last local decomposition have changed, delete
196 					const_cast< HelplinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
197 				}
198 			}
199 
200 			if(!getBuffered2DDecomposition().hasElements())
201 			{
202 				// remember ViewRange and ViewTransformation
203 				const_cast< HelplinePrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
204 				const_cast< HelplinePrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport();
205 			}
206 
207 			// use parent implementation
208 			return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
209 		}
210 
211 		// provide unique ID
212 		ImplPrimitrive2DIDBlock(HelplinePrimitive2D, PRIMITIVE2D_ID_HELPLINEPRIMITIVE2D)
213 
214 	} // end of namespace primitive2d
215 } // end of namespace drawinglayer
216 
217 //////////////////////////////////////////////////////////////////////////////
218 // eof
219