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