Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx>
30 : : #include <svx/svdoashp.hxx>
31 : : #include <svx/sdr/contact/displayinfo.hxx>
32 : : #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
33 : : #include <svx/svditer.hxx>
34 : : #include <svx/sdr/primitive2d/sdrcustomshapeprimitive2d.hxx>
35 : : #include <basegfx/polygon/b2dpolygontools.hxx>
36 : : #include <basegfx/polygon/b2dpolygon.hxx>
37 : : #include <basegfx/matrix/b2dhommatrixtools.hxx>
38 : : #include <svx/obj3d.hxx>
39 : : #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
40 : :
41 : : //////////////////////////////////////////////////////////////////////////////
42 : :
43 : : namespace sdr
44 : : {
45 : : namespace contact
46 : : {
47 : 642 : ViewContactOfSdrObjCustomShape::ViewContactOfSdrObjCustomShape(SdrObjCustomShape& rCustomShape)
48 : 642 : : ViewContactOfTextObj(rCustomShape)
49 : : {
50 : 642 : }
51 : :
52 : 630 : ViewContactOfSdrObjCustomShape::~ViewContactOfSdrObjCustomShape()
53 : : {
54 [ - + ]: 1260 : }
55 : :
56 : 18 : basegfx::B2DRange ViewContactOfSdrObjCustomShape::getCorrectedTextBoundRect() const
57 : : {
58 : 18 : const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
59 : 18 : Rectangle aTextBound(aObjectBound);
60 [ + - ]: 18 : GetCustomShapeObj().GetTextBounds(aTextBound);
61 [ + - ]: 18 : basegfx::B2DRange aTextRange(aTextBound.Left(), aTextBound.Top(), aTextBound.Right(), aTextBound.Bottom());
62 [ + - ]: 18 : const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom());
63 : :
64 : : // no need to correct if no extra text range
65 [ + - ][ - + ]: 18 : if(aTextRange != aObjectRange)
66 : : {
67 : 0 : const GeoStat& rGeoStat(GetCustomShapeObj().GetGeoStat());
68 : :
69 : : // only correct when rotation and/or shear is used
70 [ # # ][ # # ]: 0 : if(rGeoStat.nShearWink || rGeoStat.nDrehWink )
71 : : {
72 : : // text range needs to be corrected by
73 : : // aObjectRange.getCenter() - aRotObjectRange.getCenter() since it's
74 : : // defined differenly by using rotation around object center. Start
75 : : // with positive part
76 [ # # ]: 0 : basegfx::B2DVector aTranslation(aObjectRange.getCenter());
77 : :
78 : : // get rotated and sheared object's range
79 : 0 : basegfx::B2DRange aRotObjectRange(aObjectRange);
80 [ # # ]: 0 : basegfx::B2DHomMatrix aRotMatrix;
81 : :
82 [ # # ][ # # ]: 0 : aRotMatrix.translate(-aObjectRange.getMinimum().getX(), -aObjectRange.getMinimum().getY());
[ # # ]
83 : :
84 [ # # ]: 0 : if(rGeoStat.nShearWink)
85 : : {
86 [ # # ]: 0 : aRotMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000));
87 : : }
88 : :
89 [ # # ]: 0 : if(rGeoStat.nDrehWink)
90 : : {
91 [ # # ]: 0 : aRotMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000);
92 : : }
93 : :
94 [ # # ][ # # ]: 0 : aRotMatrix.translate(aObjectRange.getMinimum().getX(), aObjectRange.getMinimum().getY());
[ # # ]
95 [ # # ]: 0 : aRotObjectRange.transform(aRotMatrix);
96 : :
97 : : // add negative translation part
98 [ # # ]: 0 : aTranslation -= aRotObjectRange.getCenter();
99 : :
100 : : // create new range
101 : : aTextRange = basegfx::B2DRange(
102 [ # # ][ # # ]: 0 : aTextRange.getMinX() + aTranslation.getX(), aTextRange.getMinY() + aTranslation.getY(),
103 [ # # ][ # # ]: 18 : aTextRange.getMaxX() + aTranslation.getX(), aTextRange.getMaxY() + aTranslation.getY());
[ # # ][ # # ]
104 : : }
105 : : }
106 : :
107 : 18 : return aTextRange;
108 : : }
109 : :
110 : 309 : drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrObjCustomShape::createViewIndependentPrimitive2DSequence() const
111 : : {
112 [ + - ]: 309 : drawinglayer::primitive2d::Primitive2DSequence xRetval;
113 [ + - ]: 309 : const SfxItemSet& rItemSet = GetCustomShapeObj().GetMergedItemSet();
114 : :
115 : : // #i98072# Get shandow and text; eventually suppress the text if it's
116 : : // a TextPath FontworkGallery object
117 : : const drawinglayer::attribute::SdrShadowTextAttribute aAttribute(
118 : : drawinglayer::primitive2d::createNewSdrShadowTextAttribute(
119 : : rItemSet,
120 [ + - ]: 309 : GetCustomShapeObj().getText(0),
121 [ + - ][ + - ]: 618 : GetCustomShapeObj().IsTextPath()));
122 [ + - ]: 309 : drawinglayer::primitive2d::Primitive2DSequence xGroup;
123 [ + - ]: 309 : bool bHasText(!aAttribute.getText().isDefault());
124 : :
125 : : // create Primitive2DSequence from sub-geometry
126 [ + - ]: 309 : const SdrObject* pSdrObjRepresentation = GetCustomShapeObj().GetSdrObjectFromCustomShape();
127 : 309 : bool b3DShape(false);
128 : :
129 [ - + ]: 309 : if(pSdrObjRepresentation)
130 : : {
131 [ # # ]: 0 : SdrObjListIter aIterator(*pSdrObjRepresentation);
132 : :
133 [ # # ]: 0 : while(aIterator.IsMore())
134 : : {
135 [ # # ]: 0 : SdrObject& rCandidate = *aIterator.Next();
136 : :
137 [ # # ][ # # ]: 0 : if(!b3DShape && dynamic_cast< E3dObject* >(&rCandidate))
[ # # ]
138 : : {
139 : 0 : b3DShape = true;
140 : : }
141 : :
142 [ # # ][ # # ]: 0 : const drawinglayer::primitive2d::Primitive2DSequence xNew(rCandidate.GetViewContact().getViewIndependentPrimitive2DSequence());
143 [ # # ]: 0 : drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xGroup, xNew);
144 [ # # ]: 0 : }
145 : : }
146 : :
147 [ + + ][ - + ]: 309 : if(bHasText || xGroup.hasElements())
[ + + ]
148 : : {
149 : : // prepare text box geometry
150 [ + - ]: 18 : basegfx::B2DHomMatrix aTextBoxMatrix;
151 : 18 : bool bWordWrap(false);
152 : :
153 [ + - ]: 18 : if(bHasText)
154 : : {
155 : : // take unrotated snap rect as default, then get the
156 : : // unrotated text box. Rotation needs to be done centered
157 : 18 : const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
158 [ + - ]: 18 : const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom());
159 : :
160 : : // #i101684# get the text range unrotated and absolute to the object range
161 [ + - ]: 18 : const basegfx::B2DRange aTextRange(getCorrectedTextBoundRect());
162 : :
163 : : // Rotation before scaling
164 [ + - ][ - + ]: 18 : if(!basegfx::fTools::equalZero(GetCustomShapeObj().GetExtraTextRotation(true)))
165 : : {
166 : 0 : basegfx::B2DVector aTranslation(0.5, 0.5);
167 [ # # ]: 0 : aTextBoxMatrix.translate( -aTranslation.getX(), -aTranslation.getY() );
168 [ # # ][ # # ]: 0 : aTextBoxMatrix.rotate((360.0 - GetCustomShapeObj().GetExtraTextRotation(true)) * F_PI180);
169 [ # # ]: 0 : aTextBoxMatrix.translate( aTranslation.getX(), aTranslation.getY() );
170 : : }
171 : : // give text object a size
172 [ + - ][ + - ]: 18 : aTextBoxMatrix.scale(aTextRange.getWidth(), aTextRange.getHeight());
[ + - ]
173 : :
174 : : // check if we have a rotation/shear at all to take care of
175 [ + - ]: 18 : const double fExtraTextRotation(GetCustomShapeObj().GetExtraTextRotation());
176 : 18 : const GeoStat& rGeoStat(GetCustomShapeObj().GetGeoStat());
177 : :
178 [ + - ][ - + ]: 18 : if(rGeoStat.nShearWink || rGeoStat.nDrehWink || !basegfx::fTools::equalZero(fExtraTextRotation))
[ - + ][ + - ]
179 : : {
180 [ # # ][ # # ]: 0 : if(aObjectRange != aTextRange)
181 : : {
182 : : // move relative to unrotated object range
183 : : aTextBoxMatrix.translate(
184 [ # # ][ # # ]: 0 : aTextRange.getMinX() - aObjectRange.getMinimum().getX(),
185 [ # # ][ # # ]: 0 : aTextRange.getMinY() - aObjectRange.getMinimum().getY());
[ # # ]
186 : : }
187 : :
188 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fExtraTextRotation))
189 : : {
190 : : basegfx::B2DVector aTranslation(
191 [ # # ][ # # ]: 0 : ( aTextRange.getWidth() / 2 ) + ( aTextRange.getMinX() - aObjectRange.getMinimum().getX() ),
[ # # ]
192 [ # # ][ # # ]: 0 : ( aTextRange.getHeight() / 2 ) + ( aTextRange.getMinY() - aObjectRange.getMinimum().getY() ) );
[ # # ]
193 [ # # ]: 0 : aTextBoxMatrix.translate( -aTranslation.getX(), -aTranslation.getY() );
194 [ # # ]: 0 : aTextBoxMatrix.rotate((360.0 - fExtraTextRotation) * F_PI180);
195 [ # # ]: 0 : aTextBoxMatrix.translate( aTranslation.getX(), aTranslation.getY() );
196 : : }
197 : :
198 [ # # ]: 0 : if(rGeoStat.nShearWink)
199 : : {
200 [ # # ]: 0 : aTextBoxMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000));
201 : : }
202 : :
203 [ # # ]: 0 : if(rGeoStat.nDrehWink)
204 : : {
205 [ # # ]: 0 : aTextBoxMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000);
206 : : }
207 : :
208 : : // give text it's target position
209 [ # # ][ # # ]: 0 : aTextBoxMatrix.translate(aObjectRange.getMinimum().getX(), aObjectRange.getMinimum().getY());
[ # # ]
210 : : }
211 : : else
212 : : {
213 [ + - ][ + - ]: 18 : aTextBoxMatrix.translate(aTextRange.getMinX(), aTextRange.getMinY());
[ + - ]
214 : : }
215 : :
216 : : // check if SdrTextWordWrapItem is set
217 [ + - ]: 18 : bWordWrap = ((SdrTextWordWrapItem&)(GetCustomShapeObj().GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue();
218 : : }
219 : :
220 : : // create primitive
221 : : const drawinglayer::primitive2d::Primitive2DReference xReference(
222 : : new drawinglayer::primitive2d::SdrCustomShapePrimitive2D(
223 : : aAttribute,
224 : : xGroup,
225 : : aTextBoxMatrix,
226 : : bWordWrap,
227 : : b3DShape,
228 [ + - ][ + - ]: 18 : false)); // #SJ# New parameter to force to clipped BlockText for SC
[ + - ]
229 [ + - ][ + - ]: 18 : xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
[ + - ][ + - ]
230 : : }
231 : :
232 : : // always append an invisible outline for the cases where no visible content exists
233 : 309 : const Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect());
234 : : const basegfx::B2DRange aObjectRange(
235 : 309 : aObjectBound.Left(), aObjectBound.Top(),
236 [ + - ]: 618 : aObjectBound.Right(), aObjectBound.Bottom());
237 : :
238 : : drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
239 : : drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
240 [ + - ][ + - ]: 309 : false, aObjectRange));
241 : :
242 [ + - ][ + - ]: 309 : return xRetval;
243 : : }
244 : : } // end of namespace contact
245 : : } // end of namespace sdr
246 : :
247 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|