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 // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_svx.hxx"
26*b1cdbd2cSJim Jagielski #include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx>
27*b1cdbd2cSJim Jagielski #include <svx/svdoashp.hxx>
28*b1cdbd2cSJim Jagielski #include <svx/sdr/contact/displayinfo.hxx>
29*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
30*b1cdbd2cSJim Jagielski #include <svx/svditer.hxx>
31*b1cdbd2cSJim Jagielski #include <svx/sdr/primitive2d/sdrcustomshapeprimitive2d.hxx>
32*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygontools.hxx>
33*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygon.hxx>
34*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrixtools.hxx>
35*b1cdbd2cSJim Jagielski #include <svx/obj3d.hxx>
36*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski namespace sdr
41*b1cdbd2cSJim Jagielski {
42*b1cdbd2cSJim Jagielski 	namespace contact
43*b1cdbd2cSJim Jagielski 	{
ViewContactOfSdrObjCustomShape(SdrObjCustomShape & rCustomShape)44*b1cdbd2cSJim Jagielski 		ViewContactOfSdrObjCustomShape::ViewContactOfSdrObjCustomShape(SdrObjCustomShape& rCustomShape)
45*b1cdbd2cSJim Jagielski 		:	ViewContactOfTextObj(rCustomShape)
46*b1cdbd2cSJim Jagielski 		{
47*b1cdbd2cSJim Jagielski 		}
48*b1cdbd2cSJim Jagielski 
~ViewContactOfSdrObjCustomShape()49*b1cdbd2cSJim Jagielski 		ViewContactOfSdrObjCustomShape::~ViewContactOfSdrObjCustomShape()
50*b1cdbd2cSJim Jagielski 		{
51*b1cdbd2cSJim Jagielski 		}
52*b1cdbd2cSJim Jagielski 
getCorrectedTextBoundRect() const53*b1cdbd2cSJim Jagielski         basegfx::B2DRange ViewContactOfSdrObjCustomShape::getCorrectedTextBoundRect() const
54*b1cdbd2cSJim Jagielski         {
55*b1cdbd2cSJim Jagielski 			const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
56*b1cdbd2cSJim Jagielski 			Rectangle aTextBound(aObjectBound);
57*b1cdbd2cSJim Jagielski             GetCustomShapeObj().GetTextBounds(aTextBound);
58*b1cdbd2cSJim Jagielski             basegfx::B2DRange aTextRange(aTextBound.Left(), aTextBound.Top(), aTextBound.Right(), aTextBound.Bottom());
59*b1cdbd2cSJim Jagielski             const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom());
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski             // no need to correct if no extra text range
62*b1cdbd2cSJim Jagielski             if(aTextRange != aObjectRange)
63*b1cdbd2cSJim Jagielski             {
64*b1cdbd2cSJim Jagielski 			    const GeoStat& rGeoStat(GetCustomShapeObj().GetGeoStat());
65*b1cdbd2cSJim Jagielski 
66*b1cdbd2cSJim Jagielski                 // only correct when rotation and/or shear is used
67*b1cdbd2cSJim Jagielski                 if(rGeoStat.nShearWink || rGeoStat.nDrehWink )
68*b1cdbd2cSJim Jagielski 			    {
69*b1cdbd2cSJim Jagielski                     // text range needs to be corrected by
70*b1cdbd2cSJim Jagielski                     // aObjectRange.getCenter() - aRotObjectRange.getCenter() since it's
71*b1cdbd2cSJim Jagielski                     // defined differenly by using rotation around object center. Start
72*b1cdbd2cSJim Jagielski                     // with positive part
73*b1cdbd2cSJim Jagielski                     basegfx::B2DVector aTranslation(aObjectRange.getCenter());
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski                     // get rotated and sheared object's range
76*b1cdbd2cSJim Jagielski                     basegfx::B2DRange aRotObjectRange(aObjectRange);
77*b1cdbd2cSJim Jagielski 				    basegfx::B2DHomMatrix aRotMatrix;
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski                     aRotMatrix.translate(-aObjectRange.getMinimum().getX(), -aObjectRange.getMinimum().getY());
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski                     if(rGeoStat.nShearWink)
82*b1cdbd2cSJim Jagielski 				    {
83*b1cdbd2cSJim Jagielski 					    aRotMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000));
84*b1cdbd2cSJim Jagielski 				    }
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski 				    if(rGeoStat.nDrehWink)
87*b1cdbd2cSJim Jagielski 				    {
88*b1cdbd2cSJim Jagielski 					    aRotMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000);
89*b1cdbd2cSJim Jagielski 				    }
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski                     aRotMatrix.translate(aObjectRange.getMinimum().getX(), aObjectRange.getMinimum().getY());
92*b1cdbd2cSJim Jagielski                     aRotObjectRange.transform(aRotMatrix);
93*b1cdbd2cSJim Jagielski 
94*b1cdbd2cSJim Jagielski                     // add negative translation part
95*b1cdbd2cSJim Jagielski                     aTranslation -= aRotObjectRange.getCenter();
96*b1cdbd2cSJim Jagielski 
97*b1cdbd2cSJim Jagielski                     // create new range
98*b1cdbd2cSJim Jagielski                     aTextRange = basegfx::B2DRange(
99*b1cdbd2cSJim Jagielski                         aTextRange.getMinX() + aTranslation.getX(), aTextRange.getMinY() + aTranslation.getY(),
100*b1cdbd2cSJim Jagielski                         aTextRange.getMaxX() + aTranslation.getX(), aTextRange.getMaxY() + aTranslation.getY());
101*b1cdbd2cSJim Jagielski                 }
102*b1cdbd2cSJim Jagielski             }
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski             return aTextRange;
105*b1cdbd2cSJim Jagielski         }
106*b1cdbd2cSJim Jagielski 
createViewIndependentPrimitive2DSequence() const107*b1cdbd2cSJim Jagielski         drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrObjCustomShape::createViewIndependentPrimitive2DSequence() const
108*b1cdbd2cSJim Jagielski 		{
109*b1cdbd2cSJim Jagielski 			drawinglayer::primitive2d::Primitive2DSequence xRetval;
110*b1cdbd2cSJim Jagielski 			const SfxItemSet& rItemSet = GetCustomShapeObj().GetMergedItemSet();
111*b1cdbd2cSJim Jagielski 
112*b1cdbd2cSJim Jagielski             // #i98072# Get shandow and text; eventually suppress the text if it's
113*b1cdbd2cSJim Jagielski             // a TextPath FontworkGallery object
114*b1cdbd2cSJim Jagielski 			const drawinglayer::attribute::SdrShadowTextAttribute aAttribute(
115*b1cdbd2cSJim Jagielski 				drawinglayer::primitive2d::createNewSdrShadowTextAttribute(
116*b1cdbd2cSJim Jagielski 					rItemSet,
117*b1cdbd2cSJim Jagielski 					GetCustomShapeObj().getText(0),
118*b1cdbd2cSJim Jagielski 					GetCustomShapeObj().IsTextPath()));
119*b1cdbd2cSJim Jagielski 			drawinglayer::primitive2d::Primitive2DSequence xGroup;
120*b1cdbd2cSJim Jagielski 			bool bHasText(!aAttribute.getText().isDefault());
121*b1cdbd2cSJim Jagielski 
122*b1cdbd2cSJim Jagielski 			// create Primitive2DSequence from sub-geometry
123*b1cdbd2cSJim Jagielski 			const SdrObject* pSdrObjRepresentation = GetCustomShapeObj().GetSdrObjectFromCustomShape();
124*b1cdbd2cSJim Jagielski 			bool b3DShape(false);
125*b1cdbd2cSJim Jagielski 
126*b1cdbd2cSJim Jagielski 			if(pSdrObjRepresentation)
127*b1cdbd2cSJim Jagielski 			{
128*b1cdbd2cSJim Jagielski 				SdrObjListIter aIterator(*pSdrObjRepresentation);
129*b1cdbd2cSJim Jagielski 
130*b1cdbd2cSJim Jagielski 				while(aIterator.IsMore())
131*b1cdbd2cSJim Jagielski 				{
132*b1cdbd2cSJim Jagielski 					SdrObject& rCandidate = *aIterator.Next();
133*b1cdbd2cSJim Jagielski 
134*b1cdbd2cSJim Jagielski 					if(!b3DShape && dynamic_cast< E3dObject* >(&rCandidate))
135*b1cdbd2cSJim Jagielski 					{
136*b1cdbd2cSJim Jagielski 						b3DShape = true;
137*b1cdbd2cSJim Jagielski 					}
138*b1cdbd2cSJim Jagielski 
139*b1cdbd2cSJim Jagielski 					const drawinglayer::primitive2d::Primitive2DSequence xNew(rCandidate.GetViewContact().getViewIndependentPrimitive2DSequence());
140*b1cdbd2cSJim Jagielski 					drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xGroup, xNew);
141*b1cdbd2cSJim Jagielski 				}
142*b1cdbd2cSJim Jagielski 			}
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski 			if(bHasText || xGroup.hasElements())
145*b1cdbd2cSJim Jagielski 			{
146*b1cdbd2cSJim Jagielski 				// prepare text box geometry
147*b1cdbd2cSJim Jagielski 				basegfx::B2DHomMatrix aTextBoxMatrix;
148*b1cdbd2cSJim Jagielski                 bool bWordWrap(false);
149*b1cdbd2cSJim Jagielski 
150*b1cdbd2cSJim Jagielski 				if(bHasText)
151*b1cdbd2cSJim Jagielski 				{
152*b1cdbd2cSJim Jagielski 					// take unrotated snap rect as default, then get the
153*b1cdbd2cSJim Jagielski 					// unrotated text box. Rotation needs to be done centered
154*b1cdbd2cSJim Jagielski 					const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
155*b1cdbd2cSJim Jagielski                     const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom());
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski                     // #i101684# get the text range unrotated and absolute to the object range
158*b1cdbd2cSJim Jagielski                     const basegfx::B2DRange aTextRange(getCorrectedTextBoundRect());
159*b1cdbd2cSJim Jagielski 
160*b1cdbd2cSJim Jagielski 					// give text object a size
161*b1cdbd2cSJim Jagielski                     aTextBoxMatrix.scale(aTextRange.getWidth(), aTextRange.getHeight());
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski                     // check if we have a rotation/shear at all to take care of
164*b1cdbd2cSJim Jagielski 					const double fExtraTextRotation(GetCustomShapeObj().GetExtraTextRotation());
165*b1cdbd2cSJim Jagielski 					const GeoStat& rGeoStat(GetCustomShapeObj().GetGeoStat());
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski                     if(rGeoStat.nShearWink || rGeoStat.nDrehWink || !basegfx::fTools::equalZero(fExtraTextRotation))
168*b1cdbd2cSJim Jagielski 					{
169*b1cdbd2cSJim Jagielski                         if(aObjectRange != aTextRange)
170*b1cdbd2cSJim Jagielski                         {
171*b1cdbd2cSJim Jagielski 						    // move relative to unrotated object range
172*b1cdbd2cSJim Jagielski 						    aTextBoxMatrix.translate(
173*b1cdbd2cSJim Jagielski                                 aTextRange.getMinX() - aObjectRange.getMinimum().getX(),
174*b1cdbd2cSJim Jagielski                                 aTextRange.getMinY() - aObjectRange.getMinimum().getY());
175*b1cdbd2cSJim Jagielski                         }
176*b1cdbd2cSJim Jagielski 
177*b1cdbd2cSJim Jagielski 						if(!basegfx::fTools::equalZero(fExtraTextRotation))
178*b1cdbd2cSJim Jagielski 						{
179*b1cdbd2cSJim Jagielski 		                    basegfx::B2DVector aTranslation(
180*b1cdbd2cSJim Jagielski 								( aTextRange.getWidth() / 2 ) + ( aTextRange.getMinX() - aObjectRange.getMinimum().getX() ),
181*b1cdbd2cSJim Jagielski 								( aTextRange.getHeight() / 2 ) + ( aTextRange.getMinY() - aObjectRange.getMinimum().getY() ) );
182*b1cdbd2cSJim Jagielski 							aTextBoxMatrix.translate( -aTranslation.getX(), -aTranslation.getY() );
183*b1cdbd2cSJim Jagielski 							aTextBoxMatrix.rotate((360.0 - fExtraTextRotation) * F_PI180);
184*b1cdbd2cSJim Jagielski 							aTextBoxMatrix.translate( aTranslation.getX(), aTranslation.getY() );
185*b1cdbd2cSJim Jagielski 						}
186*b1cdbd2cSJim Jagielski 
187*b1cdbd2cSJim Jagielski 						if(rGeoStat.nShearWink)
188*b1cdbd2cSJim Jagielski 						{
189*b1cdbd2cSJim Jagielski 							aTextBoxMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000));
190*b1cdbd2cSJim Jagielski 						}
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski 						if(rGeoStat.nDrehWink)
193*b1cdbd2cSJim Jagielski 						{
194*b1cdbd2cSJim Jagielski 							aTextBoxMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000);
195*b1cdbd2cSJim Jagielski 						}
196*b1cdbd2cSJim Jagielski 
197*b1cdbd2cSJim Jagielski 						// give text it's target position
198*b1cdbd2cSJim Jagielski 						aTextBoxMatrix.translate(aObjectRange.getMinimum().getX(), aObjectRange.getMinimum().getY());
199*b1cdbd2cSJim Jagielski 					}
200*b1cdbd2cSJim Jagielski                     else
201*b1cdbd2cSJim Jagielski                     {
202*b1cdbd2cSJim Jagielski 						aTextBoxMatrix.translate(aTextRange.getMinX(), aTextRange.getMinY());
203*b1cdbd2cSJim Jagielski                     }
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski                     // check if SdrTextWordWrapItem is set
206*b1cdbd2cSJim Jagielski                     bWordWrap = ((SdrTextWordWrapItem&)(GetCustomShapeObj().GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue();
207*b1cdbd2cSJim Jagielski 				}
208*b1cdbd2cSJim Jagielski 
209*b1cdbd2cSJim Jagielski 				// create primitive
210*b1cdbd2cSJim Jagielski 				const drawinglayer::primitive2d::Primitive2DReference xReference(
211*b1cdbd2cSJim Jagielski                     new drawinglayer::primitive2d::SdrCustomShapePrimitive2D(
212*b1cdbd2cSJim Jagielski 					    aAttribute,
213*b1cdbd2cSJim Jagielski 					    xGroup,
214*b1cdbd2cSJim Jagielski 					    aTextBoxMatrix,
215*b1cdbd2cSJim Jagielski 					    bWordWrap,
216*b1cdbd2cSJim Jagielski 					    b3DShape,
217*b1cdbd2cSJim Jagielski 					    false));		// #SJ# New parameter to force to clipped BlockText for SC
218*b1cdbd2cSJim Jagielski 				xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
219*b1cdbd2cSJim Jagielski 			}
220*b1cdbd2cSJim Jagielski 
221*b1cdbd2cSJim Jagielski 			// #119863# always append an invisible outline for the cases where no visible content exists
222*b1cdbd2cSJim Jagielski             if(true)
223*b1cdbd2cSJim Jagielski             {
224*b1cdbd2cSJim Jagielski 			    const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
225*b1cdbd2cSJim Jagielski                 const basegfx::B2DRange aObjectRange(
226*b1cdbd2cSJim Jagielski 				    aObjectBound.Left(), aObjectBound.Top(),
227*b1cdbd2cSJim Jagielski 				    aObjectBound.Right(), aObjectBound.Bottom());
228*b1cdbd2cSJim Jagielski 
229*b1cdbd2cSJim Jagielski 				// create object matrix
230*b1cdbd2cSJim Jagielski 				const GeoStat& rGeoStat(GetCustomShapeObj().GetGeoStat());
231*b1cdbd2cSJim Jagielski 				const double fShearX(rGeoStat.nShearWink ? tan((36000 - rGeoStat.nShearWink) * F_PI18000) : 0.0);
232*b1cdbd2cSJim Jagielski 				const double fRotate(rGeoStat.nDrehWink ? (36000 - rGeoStat.nDrehWink) * F_PI18000 : 0.0);
233*b1cdbd2cSJim Jagielski 				const basegfx::B2DHomMatrix aObjectMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
234*b1cdbd2cSJim Jagielski 					aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
235*b1cdbd2cSJim Jagielski 					aObjectRange.getMinX(), aObjectRange.getMinY()));
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski                 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
238*b1cdbd2cSJim Jagielski 				    drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
239*b1cdbd2cSJim Jagielski 					    false,
240*b1cdbd2cSJim Jagielski                         aObjectMatrix));
241*b1cdbd2cSJim Jagielski             }
242*b1cdbd2cSJim Jagielski 
243*b1cdbd2cSJim Jagielski 			return xRetval;
244*b1cdbd2cSJim Jagielski 		}
245*b1cdbd2cSJim Jagielski 	} // end of namespace contact
246*b1cdbd2cSJim Jagielski } // end of namespace sdr
247*b1cdbd2cSJim Jagielski 
248*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
249*b1cdbd2cSJim Jagielski // eof
250