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