LibreOffice Module svx (master)  1
svdoashp.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 #include <svx/svdoashp.hxx>
22 #include <svx/unoapi.hxx>
23 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
24 #include <com/sun/star/drawing/XShape.hpp>
25 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
26 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/awt/Rectangle.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <com/sun/star/uno/Sequence.h>
34 #include <tools/helpers.hxx>
35 #include <svx/svddrag.hxx>
36 #include <svx/svddrgmt.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svditer.hxx>
40 #include <svx/svdobj.hxx>
41 #include <svx/svdtrans.hxx>
42 #include <svx/dialmgr.hxx>
43 #include <svx/strings.hrc>
44 #include <editeng/eeitem.hxx>
45 #include <editeng/editstat.hxx>
46 #include <editeng/adjustitem.hxx>
47 #include <svx/svdoutl.hxx>
48 #include <editeng/outlobj.hxx>
49 #include <svx/sdtfchim.hxx>
53 #include <com/sun/star/beans/PropertyValues.hpp>
54 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
55 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
56 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
57 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
58 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
60 #include <svx/xlineit0.hxx>
61 #include <svx/xlnclit.hxx>
64 #include <svx/xlntrit.hxx>
65 #include <svx/xfillit0.hxx>
66 #include <svx/xfltrit.hxx>
67 #include <svx/xflclit.hxx>
68 #include <svx/xflgrit.hxx>
69 #include <svx/xflhtit.hxx>
70 #include <svx/xbtmpit.hxx>
71 #include <vcl/virdev.hxx>
72 #include <svx/svdview.hxx>
73 #include <svx/sdmetitm.hxx>
74 #include <svx/sdprcitm.hxx>
75 #include <svx/sdshitm.hxx>
76 #include <svx/sdsxyitm.hxx>
77 #include <svx/sdtmfitm.hxx>
78 #include <svx/sdasitm.hxx>
85 #include <svdobjplusdata.hxx>
86 #include <sal/log.hxx>
87 #include <o3tl/string_view.hxx>
89 
90 using namespace ::com::sun::star;
91 using namespace ::com::sun::star::uno;
92 using namespace ::com::sun::star::lang;
93 using namespace ::com::sun::star::beans;
94 using namespace ::com::sun::star::drawing;
95 
96 static void lcl_ShapeSegmentFromBinary( EnhancedCustomShapeSegment& rSegInfo, sal_uInt16 nSDat )
97 {
98  switch( nSDat >> 8 )
99  {
100  case 0x00 :
101  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO;
102  rSegInfo.Count = nSDat & 0xff;
103  if ( !rSegInfo.Count )
104  rSegInfo.Count = 1;
105  break;
106  case 0x20 :
107  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
108  rSegInfo.Count = nSDat & 0xff;
109  if ( !rSegInfo.Count )
110  rSegInfo.Count = 1;
111  break;
112  case 0x40 :
113  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
114  rSegInfo.Count = nSDat & 0xff;
115  if ( !rSegInfo.Count )
116  rSegInfo.Count = 1;
117  break;
118  case 0x60 :
119  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
120  rSegInfo.Count = 0;
121  break;
122  case 0x80 :
123  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
124  rSegInfo.Count = 0;
125  break;
126  case 0xa1 :
127  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
128  rSegInfo.Count = ( nSDat & 0xff ) / 3;
129  break;
130  case 0xa2 :
131  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
132  rSegInfo.Count = ( nSDat & 0xff ) / 3;
133  break;
134  case 0xa3 :
135  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO;
136  rSegInfo.Count = ( nSDat & 0xff ) >> 2;
137  break;
138  case 0xa4 :
139  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC;
140  rSegInfo.Count = ( nSDat & 0xff ) >> 2;
141  break;
142  case 0xa5 :
143  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
144  rSegInfo.Count = ( nSDat & 0xff ) >> 2;
145  break;
146  case 0xa6 :
147  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
148  rSegInfo.Count = ( nSDat & 0xff ) >> 2;
149  break;
150  case 0xa7 :
151  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
152  rSegInfo.Count = nSDat & 0xff;
153  break;
154  case 0xa8 :
155  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
156  rSegInfo.Count = nSDat & 0xff;
157  break;
158  case 0xaa :
159  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
160  rSegInfo.Count = 0;
161  break;
162  case 0xab :
163  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
164  rSegInfo.Count = 0;
165  break;
166  default:
167  case 0xf8 :
168  rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN;
169  rSegInfo.Count = nSDat;
170  break;
171  }
172 }
173 
174 static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape )
175 {
176  MSO_SPT eRetValue = mso_sptNil;
177 
178  OUString aEngine( rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue() );
179  if ( aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" )
180  {
181  OUString sShapeType;
182  const SdrCustomShapeGeometryItem& rGeometryItem( rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
183  const Any* pAny = rGeometryItem.GetPropertyValueByName( "Type" );
184  if ( pAny && ( *pAny >>= sShapeType ) )
185  eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType );
186  }
187  return eRetValue;
188 };
189 
190 static bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape )
191 {
192  bool bRet = false;
193  MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) );
194  switch( eShapeType )
195  {
196  case mso_sptAccentBorderCallout90 : // 2 ortho
197  case mso_sptBorderCallout1 : // 2 diag
198  case mso_sptBorderCallout2 : // 3
199  {
200  bRet = true;
201  }
202  break;
203  default: break;
204  }
205  return bRet;
206 }
207 
208 // #i37011# create a clone with all attributes changed to shadow attributes
209 // and translation executed, too.
210 static SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet)
211 {
212  SdrObject* pRetval = nullptr;
213  const bool bShadow(rOriginalSet.Get(SDRATTR_SHADOW).GetValue());
214 
215  if(bShadow)
216  {
217  // create a shadow representing object
218  const sal_Int32 nXDist(rOriginalSet.Get(SDRATTR_SHADOWXDIST).GetValue());
219  const sal_Int32 nYDist(rOriginalSet.Get(SDRATTR_SHADOWYDIST).GetValue());
220  const ::Color aShadowColor(rOriginalSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue());
221  const sal_uInt16 nShadowTransparence(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE).GetValue());
222  pRetval = rOriginal.CloneSdrObject(rOriginal.getSdrModelFromSdrObject());
223  DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)");
224 
225  // look for used stuff
226  SdrObjListIter aIterator(rOriginal);
227  bool bLineUsed(false);
228  bool bAllFillUsed(false);
229  bool bSolidFillUsed(false);
230  bool bGradientFillUsed(false);
231  bool bHatchFillUsed(false);
232  bool bBitmapFillUsed(false);
233 
234  while(aIterator.IsMore())
235  {
236  SdrObject* pObj = aIterator.Next();
237  drawing::FillStyle eFillStyle = pObj->GetMergedItem(XATTR_FILLSTYLE).GetValue();
238 
239  if(!bLineUsed)
240  {
241  drawing::LineStyle eLineStyle = pObj->GetMergedItem(XATTR_LINESTYLE).GetValue();
242 
243  if(drawing::LineStyle_NONE != eLineStyle)
244  {
245  bLineUsed = true;
246  }
247  }
248 
249  if(!bAllFillUsed)
250  {
251  if(!bSolidFillUsed && drawing::FillStyle_SOLID == eFillStyle)
252  {
253  bSolidFillUsed = true;
254  bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
255  }
256  if(!bGradientFillUsed && drawing::FillStyle_GRADIENT == eFillStyle)
257  {
258  bGradientFillUsed = true;
259  bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
260  }
261  if(!bHatchFillUsed && drawing::FillStyle_HATCH == eFillStyle)
262  {
263  bHatchFillUsed = true;
264  bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
265  }
266  if(!bBitmapFillUsed && drawing::FillStyle_BITMAP == eFillStyle)
267  {
268  bBitmapFillUsed = true;
269  bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
270  }
271  }
272  }
273 
274  // translate to shadow coordinates
275  pRetval->NbcMove(Size(nXDist, nYDist));
276 
277  // set items as needed
278  SfxItemSet aTempSet(rOriginalSet);
279 
280  // if a SvxWritingModeItem (Top->Bottom) is set the text object
281  // is creating a paraobject, but paraobjects can not be created without model. So
282  // we are preventing the crash by setting the writing mode always left to right,
283  // this is not bad since our shadow geometry does not contain text.
284  aTempSet.Put( SvxWritingModeItem( css::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) );
285 
286  // no shadow
287  aTempSet.Put(makeSdrShadowItem(false));
288  aTempSet.Put(makeSdrShadowXDistItem(0));
289  aTempSet.Put(makeSdrShadowYDistItem(0));
290 
291  // line color and transparency like shadow
292  if(bLineUsed)
293  {
294  aTempSet.Put(XLineColorItem(OUString(), aShadowColor));
295  aTempSet.Put(XLineTransparenceItem(nShadowTransparence));
296  }
297 
298  // fill color and transparency like shadow
299  if(bSolidFillUsed)
300  {
301  aTempSet.Put(XFillColorItem(OUString(), aShadowColor));
302  aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
303  }
304 
305  // gradient and transparency like shadow
306  if(bGradientFillUsed)
307  {
308  XGradient aGradient(rOriginalSet.Get(XATTR_FILLGRADIENT).GetGradientValue());
309  sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance());
310  sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance());
311 
312  if(aGradient.GetStartIntens() != 100)
313  {
314  nStartLuminance = static_cast<sal_uInt8>(nStartLuminance * (static_cast<double>(aGradient.GetStartIntens()) / 100.0));
315  }
316 
317  if(aGradient.GetEndIntens() != 100)
318  {
319  nEndLuminance = static_cast<sal_uInt8>(nEndLuminance * (static_cast<double>(aGradient.GetEndIntens()) / 100.0));
320  }
321 
322  ::Color aStartColor(
323  static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetRed()) / 256),
324  static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetGreen()) / 256),
325  static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetBlue()) / 256));
326 
327  ::Color aEndColor(
328  static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetRed()) / 256),
329  static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetGreen()) / 256),
330  static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetBlue()) / 256));
331 
332  aGradient.SetStartColor(aStartColor);
333  aGradient.SetEndColor(aEndColor);
334  aTempSet.Put(XFillGradientItem(aGradient));
335  aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
336  }
337 
338  // hatch and transparency like shadow
339  if(bHatchFillUsed)
340  {
341  XHatch aHatch(rOriginalSet.Get(XATTR_FILLHATCH).GetHatchValue());
342  aHatch.SetColor(aShadowColor);
343  aTempSet.Put(XFillHatchItem(aHatch));
344  aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
345  }
346 
347  // bitmap and transparency like shadow
348  if(bBitmapFillUsed)
349  {
350  GraphicObject aGraphicObject(rOriginalSet.Get(XATTR_FILLBITMAP).GetGraphicObject());
351  BitmapEx aBitmapEx(aGraphicObject.GetGraphic().GetBitmapEx());
352 
353  if(!aBitmapEx.IsEmpty())
354  {
356  pVirDev->SetOutputSizePixel(aBitmapEx.GetSizePixel());
357  BitmapFilter::Filter(aBitmapEx, BitmapShadowFilter(aShadowColor));
358  pVirDev->DrawBitmapEx(Point(), aBitmapEx);
359  aGraphicObject.SetGraphic(Graphic(pVirDev->GetBitmapEx(Point(0,0), aBitmapEx.GetSizePixel())));
360  }
361 
362  aTempSet.Put(XFillBitmapItem(aGraphicObject));
363  aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
364  }
365 
366  // set attributes and paint shadow object
367  pRetval->SetMergedItemSet( aTempSet );
368  }
369  return pRetval;
370 }
371 
372 
373 Reference< XCustomShapeEngine > const & SdrObjCustomShape::GetCustomShapeEngine() const
374 {
375  if (mxCustomShapeEngine.is())
376  return mxCustomShapeEngine;
377 
378  Reference< XShape > aXShape = GetXShapeForSdrObject(const_cast<SdrObjCustomShape*>(this));
379  if ( !aXShape )
380  return mxCustomShapeEngine;
381 
383 
384  OUString aEngine(GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue());
385  static constexpr OUStringLiteral sEnhancedCustomShapeEngine = u"com.sun.star.drawing.EnhancedCustomShapeEngine";
386  if ( aEngine.isEmpty() )
387  aEngine = sEnhancedCustomShapeEngine;
388 
389  {
390  static constexpr OUStringLiteral sCustomShape = u"CustomShape";
391  Sequence< PropertyValue > aPropValues{ comphelper::makePropertyValue(sCustomShape,
392  aXShape) };
393  Sequence< Any > aArgument{ Any(aPropValues) };
394  try
395  {
396  Reference<XInterface> xInterface(xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aEngine, aArgument, xContext));
397  if (xInterface.is())
398  mxCustomShapeEngine.set( xInterface, UNO_QUERY );
399  }
400  catch (const css::loader::CannotActivateFactoryException&)
401  {
402  }
403  }
404 
405  return mxCustomShapeEngine;
406 }
407 
409 {
410  if ( !mXRenderedCustomShape.is() )
411  {
412  Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
413  if ( xCustomShapeEngine.is() )
414  const_cast<SdrObjCustomShape*>(this)->mXRenderedCustomShape = xCustomShapeEngine->render();
415  }
416  SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is()
418  : nullptr;
419  return pRenderedCustomShape;
420 }
421 
422 // #i37011# Shadow geometry creation
424 {
426  {
427  const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
428  if(pSdrObject)
429  {
430  const SfxItemSet& rOriginalSet = GetObjectItemSet();
431  const bool bShadow(rOriginalSet.Get( SDRATTR_SHADOW ).GetValue());
432 
433  if(bShadow)
434  {
435  // create a clone with all attributes changed to shadow attributes
436  // and translation executed, too.
437  const_cast<SdrObjCustomShape*>(this)->mpLastShadowGeometry =
438  ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet);
439  }
440  }
441  }
442 
443  return mpLastShadowGeometry;
444 }
445 
447 {
448  static const OUStringLiteral sTextPath( u"TextPath" );
449  bool bTextPathOn = false;
451  const Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
452  if ( pAny )
453  *pAny >>= bTextPathOn;
454  return bTextPathOn;
455 }
456 
458 {
459  bool bRet = false;
460  OUString sShapeType;
461  static const OUStringLiteral sType( u"Type" );
463  const Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
464  if ( pAny )
465  *pAny >>= sShapeType;
467 
468  return bRet;
469 }
470 
472 {
473  bool bMirroredX = false;
475  const css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "MirroredX" );
476  if ( pAny )
477  *pAny >>= bMirroredX;
478  return bMirroredX;
479 }
481 {
482  bool bMirroredY = false;
484  const css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "MirroredY" );
485  if ( pAny )
486  *pAny >>= bMirroredY;
487  return bMirroredY;
488 }
489 void SdrObjCustomShape::SetMirroredX( const bool bMirrorX )
490 {
492  PropertyValue aPropVal;
493  aPropVal.Name = "MirroredX";
494  aPropVal.Value <<= bMirrorX;
495  aGeometryItem.SetPropertyValue( aPropVal );
496  SetMergedItem( aGeometryItem );
497 }
498 void SdrObjCustomShape::SetMirroredY( const bool bMirrorY )
499 {
501  PropertyValue aPropVal;
502  aPropVal.Name = "MirroredY";
503  aPropVal.Value <<= bMirrorY;
504  aGeometryItem.SetPropertyValue( aPropVal );
505  SetMergedItem( aGeometryItem );
506 }
507 
508 double SdrObjCustomShape::GetExtraTextRotation( const bool bPreRotation ) const
509 {
510  const css::uno::Any* pAny;
512  pAny = rGeometryItem.GetPropertyValueByName( bPreRotation ? OUString( "TextPreRotateAngle" ) : OUString( "TextRotateAngle" ) );
513  double fExtraTextRotateAngle = 0.0;
514  if ( pAny )
515  *pAny >>= fExtraTextRotateAngle;
516  return fExtraTextRotateAngle;
517 }
518 
520 {
521  bool bRet = false;
522 
523  Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
524  if ( xCustomShapeEngine.is() )
525  {
526  awt::Rectangle aR( xCustomShapeEngine->getTextBounds() );
527  if ( aR.Width > 1 && aR.Height > 1 )
528  {
529  rTextBound = tools::Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) );
530  bRet = true;
531  }
532  }
533  return bRet;
534 }
536 {
537  basegfx::B2DPolyPolygon aRetval;
538  Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
539  if ( xCustomShapeEngine.is() )
540  {
541  css::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry();
542  try
543  {
545  if ( !bBezierAllowed && aRetval.areControlPointsUsed())
546  {
547  aRetval = basegfx::utils::adaptiveSubdivideByAngle(aRetval);
548  }
549  }
550  catch ( const css::lang::IllegalArgumentException & )
551  {
552  }
553  }
554  return aRetval;
555 }
556 
557 std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles() const
558 {
559  std::vector< SdrCustomShapeInteraction > aRet;
560  try
561  {
562  Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
563  if ( xCustomShapeEngine.is() )
564  {
565  int i;
566  Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() );
567  for ( i = 0; i < xInteractionHandles.getLength(); i++ )
568  {
569  if ( xInteractionHandles[ i ].is() )
570  {
571  SdrCustomShapeInteraction aSdrCustomShapeInteraction;
572  aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ];
573  aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition();
574 
576  switch( ImpGetCustomShapeType( *this ) )
577  {
578  case mso_sptAccentBorderCallout90 : // 2 ortho
579  {
580  if (i == 0)
582  else if (i == 1)
584  }
585  break;
586 
587  case mso_sptChevron :
588  case mso_sptHomePlate :
590  break;
591 
594  case mso_sptCloudCallout :
596  {
597  if (i == 0)
599  }
600  break;
601 
602  case mso_sptBorderCallout1 : // 2 diag
603  {
604  if (i == 0)
606  else if (i == 1)
608  }
609  break;
610  case mso_sptBorderCallout2 : // 3
611  {
612  if (i == 0)
614  else if (i == 2)
616  }
617  break;
618  case mso_sptCallout90 :
621  case mso_sptCallout1 :
622  case mso_sptCallout2 :
623  case mso_sptCallout3 :
624  case mso_sptAccentCallout1 :
625  case mso_sptAccentCallout2 :
626  case mso_sptAccentCallout3 :
627  case mso_sptBorderCallout3 :
631  {
632  if (i == 0)
634  }
635  break;
636  default: break;
637  }
638  aSdrCustomShapeInteraction.nMode = nMode;
639  aRet.push_back( aSdrCustomShapeInteraction );
640  }
641  }
642  }
643  }
644  catch( const uno::RuntimeException& )
645  {
646  }
647  return aRet;
648 }
649 
650 
651 // BaseProperties section
652 #define DEFAULT_MINIMUM_SIGNED_COMPARE (sal_Int32(0x80000000))
653 #define DEFAULT_MAXIMUM_SIGNED_COMPARE (sal_Int32(0x7fffffff))
654 
655 static sal_Int32 GetNumberOfProperties ( const SvxMSDffHandle* pData )
656 {
657  sal_Int32 nPropertiesNeeded=1; // position is always needed
658  SvxMSDffHandleFlags nFlags = pData->nFlags;
659 
660  if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X )
661  nPropertiesNeeded++;
662  if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y )
663  nPropertiesNeeded++;
664  if ( nFlags & SvxMSDffHandleFlags::SWITCHED )
665  nPropertiesNeeded++;
666  if ( nFlags & SvxMSDffHandleFlags::POLAR )
667  {
668  nPropertiesNeeded++;
669  if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE )
670  {
672  nPropertiesNeeded++;
674  nPropertiesNeeded++;
675  }
676  }
677  else if ( nFlags & SvxMSDffHandleFlags::RANGE )
678  {
680  nPropertiesNeeded++;
682  nPropertiesNeeded++;
684  nPropertiesNeeded++;
686  nPropertiesNeeded++;
687  }
688 
689  return nPropertiesNeeded;
690 }
691 
692 static void lcl_ShapePropertiesFromDFF( const SvxMSDffHandle* pData, css::beans::PropertyValues& rPropValues )
693 {
694  SvxMSDffHandleFlags nFlags = pData->nFlags;
695  sal_Int32 n=0;
696  auto pPropValues = rPropValues.getArray();
697 
698  // POSITION
699  {
700  css::drawing::EnhancedCustomShapeParameterPair aPosition;
701  EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, true, true );
702  EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, true, false );
703  pPropValues[ n ].Name = "Position";
704  pPropValues[ n++ ].Value <<= aPosition;
705  }
706  if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X )
707  {
708  pPropValues[ n ].Name = "MirroredX";
709  pPropValues[ n++ ].Value <<= true;
710  }
711  if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y )
712  {
713  pPropValues[ n ].Name = "MirroredY";
714  pPropValues[ n++ ].Value <<= true;
715  }
716  if ( nFlags & SvxMSDffHandleFlags::SWITCHED )
717  {
718  pPropValues[ n ].Name = "Switched";
719  pPropValues[ n++ ].Value <<= true;
720  }
721  if ( nFlags & SvxMSDffHandleFlags::POLAR )
722  {
723  css::drawing::EnhancedCustomShapeParameterPair aCenter;
725  bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true );
727  bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
728  pPropValues[ n ].Name = "Polar";
729  pPropValues[ n++ ].Value <<= aCenter;
730  if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE )
731  {
733  {
734  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
736  bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
737  pPropValues[ n ].Name = "RadiusRangeMinimum";
738  pPropValues[ n++ ].Value <<= aRadiusRangeMinimum;
739  }
741  {
742  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
744  bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
745  pPropValues[ n ].Name = "RadiusRangeMaximum";
746  pPropValues[ n++ ].Value <<= aRadiusRangeMaximum;
747  }
748  }
749  }
750  else if ( nFlags & SvxMSDffHandleFlags::RANGE )
751  {
753  {
754  css::drawing::EnhancedCustomShapeParameter aRangeXMinimum;
756  bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
757  pPropValues[ n ].Name = "RangeXMinimum";
758  pPropValues[ n++ ].Value <<= aRangeXMinimum;
759  }
761  {
762  css::drawing::EnhancedCustomShapeParameter aRangeXMaximum;
764  bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
765  pPropValues[ n ].Name = "RangeXMaximum";
766  pPropValues[ n++ ].Value <<= aRangeXMaximum;
767  }
769  {
770  css::drawing::EnhancedCustomShapeParameter aRangeYMinimum;
772  bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL ), true );
773  pPropValues[ n ].Name = "RangeYMinimum";
774  pPropValues[ n++ ].Value <<= aRangeYMinimum;
775  }
777  {
778  css::drawing::EnhancedCustomShapeParameter aRangeYMaximum;
780  bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL ), false );
781  pPropValues[ n ].Name = "RangeYMaximum";
782  pPropValues[ n++ ].Value <<= aRangeYMaximum;
783  }
784  }
785 }
786 
787 std::unique_ptr<sdr::properties::BaseProperties> SdrObjCustomShape::CreateObjectSpecificProperties()
788 {
789  return std::make_unique<sdr::properties::CustomShapeProperties>(*this);
790 }
791 
793 : SdrTextObj(rSdrModel)
794  , fObjectRotation(0.0)
795  , mbAdjustingTextFrameWidthAndHeight(false)
796  , mpLastShadowGeometry(nullptr)
797 {
798  m_bClosedObj = true; // custom shapes may be filled
799  mbTextFrame = true;
800 }
801 
803 : SdrTextObj(rSdrModel, rSource)
804  , fObjectRotation(0.0)
805  , mbAdjustingTextFrameWidthAndHeight(false)
806  , mpLastShadowGeometry(nullptr)
807 {
808  m_bClosedObj = true; // custom shapes may be filled
809  mbTextFrame = true;
810 
815 }
816 
818 {
819  // delete buffered display geometry
821 }
822 
823 void SdrObjCustomShape::MergeDefaultAttributes( const OUString* pType )
824 {
825  PropertyValue aPropVal;
826  OUString sShapeType;
827  static const OUStringLiteral sType( u"Type" );
829  if ( pType && !pType->isEmpty() )
830  {
831  sal_Int32 nType = pType->toInt32();
832  if ( nType )
833  sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) );
834  else
835  sShapeType = *pType;
836 
837  aPropVal.Name = sType;
838  aPropVal.Value <<= sShapeType;
839  aGeometryItem.SetPropertyValue( aPropVal );
840  }
841  else
842  {
843  Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
844  if ( pAny )
845  *pAny >>= sShapeType;
846  }
847  MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
848 
849  const sal_Int32* pDefData = nullptr;
850  const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
851  if ( pDefCustomShape )
852  pDefData = pDefCustomShape->pDefData;
853 
854  css::uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
855 
856 
857  // AdjustmentValues
858 
859  static const OUStringLiteral sAdjustmentValues( u"AdjustmentValues" );
860  const Any* pAny = aGeometryItem.GetPropertyValueByName( sAdjustmentValues );
861  if ( pAny )
862  *pAny >>= seqAdjustmentValues;
863  if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values
864  {
865  // first check if there are adjustment values are to be appended
866  sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength();
867  sal_Int32 nAdjustmentDefaults = *pDefData++;
868  if ( nAdjustmentDefaults > nAdjustmentValues )
869  seqAdjustmentValues.realloc( nAdjustmentDefaults );
870  auto pseqAdjustmentValues = seqAdjustmentValues.getArray();
871  for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ )
872  {
873  pseqAdjustmentValues[ i ].Value <<= pDefData[ i ];
874  pseqAdjustmentValues[ i ].State = css::beans::PropertyState_DIRECT_VALUE;
875  }
876  // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue)
877  sal_Int32 nCount = std::min(nAdjustmentValues, nAdjustmentDefaults);
878  for ( i = 0; i < nCount; i++ )
879  {
880  if ( seqAdjustmentValues[ i ].State != css::beans::PropertyState_DIRECT_VALUE )
881  {
882  pseqAdjustmentValues[ i ].Value <<= pDefData[ i ];
883  pseqAdjustmentValues[ i ].State = css::beans::PropertyState_DIRECT_VALUE;
884  }
885  }
886  }
887  aPropVal.Name = sAdjustmentValues;
888  aPropVal.Value <<= seqAdjustmentValues;
889  aGeometryItem.SetPropertyValue( aPropVal );
890 
891 
892  // Coordsize
893 
894  static const OUStringLiteral sViewBox( u"ViewBox" );
895  const Any* pViewBox = aGeometryItem.GetPropertyValueByName( sViewBox );
896  css::awt::Rectangle aViewBox;
897  if ( !pViewBox || !(*pViewBox >>= aViewBox ) )
898  {
899  if ( pDefCustomShape )
900  {
901  aViewBox.X = 0;
902  aViewBox.Y = 0;
903  aViewBox.Width = pDefCustomShape->nCoordWidth;
904  aViewBox.Height= pDefCustomShape->nCoordHeight;
905  aPropVal.Name = sViewBox;
906  aPropVal.Value <<= aViewBox;
907  aGeometryItem.SetPropertyValue( aPropVal );
908  }
909  }
910 
911  static const OUStringLiteral sPath( u"Path" );
912 
913 
914  // Path/Coordinates
915 
916  static const OUStringLiteral sCoordinates( u"Coordinates" );
917  pAny = aGeometryItem.GetPropertyValueByName( sPath, sCoordinates );
918  if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
919  {
920  sal_Int32 i, nCount = pDefCustomShape->nVertices;
921  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates( nCount );
922  auto pseqCoordinates = seqCoordinates.getArray();
923  for ( i = 0; i < nCount; i++ )
924  {
925  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
926  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
927  }
928  aPropVal.Name = sCoordinates;
929  aPropVal.Value <<= seqCoordinates;
930  aGeometryItem.SetPropertyValue( sPath, aPropVal );
931  }
932 
933  // Path/GluePoints
934  static const OUStringLiteral sGluePoints( u"GluePoints" );
935  pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints );
936  if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
937  {
938  sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
939  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqGluePoints( nCount );
940  auto pseqGluePoints = seqGluePoints.getArray();
941  for ( i = 0; i < nCount; i++ )
942  {
943  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
944  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
945  }
946  aPropVal.Name = sGluePoints;
947  aPropVal.Value <<= seqGluePoints;
948  aGeometryItem.SetPropertyValue( sPath, aPropVal );
949  }
950 
951  // Path/Segments
952  static const OUStringLiteral sSegments( u"Segments" );
953  pAny = aGeometryItem.GetPropertyValueByName( sPath, sSegments );
954  if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
955  {
956  sal_Int32 i, nCount = pDefCustomShape->nElements;
957  css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > seqSegments( nCount );
958  auto pseqSegments = seqSegments.getArray();
959  for ( i = 0; i < nCount; i++ )
960  {
961  EnhancedCustomShapeSegment& rSegInfo = pseqSegments[ i ];
962  sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
963  lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
964  }
965  aPropVal.Name = sSegments;
966  aPropVal.Value <<= seqSegments;
967  aGeometryItem.SetPropertyValue( sPath, aPropVal );
968  }
969 
970  // Path/StretchX
971  static const OUStringLiteral sStretchX( u"StretchX" );
972  pAny = aGeometryItem.GetPropertyValueByName( sPath, sStretchX );
973  if ( !pAny && pDefCustomShape )
974  {
975  sal_Int32 nXRef = pDefCustomShape->nXRef;
976  if ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE )
977  {
978  aPropVal.Name = sStretchX;
979  aPropVal.Value <<= nXRef;
980  aGeometryItem.SetPropertyValue( sPath, aPropVal );
981  }
982  }
983 
984  // Path/StretchY
985  static const OUStringLiteral sStretchY( u"StretchY" );
986  pAny = aGeometryItem.GetPropertyValueByName( sPath, sStretchY );
987  if ( !pAny && pDefCustomShape )
988  {
989  sal_Int32 nYRef = pDefCustomShape->nYRef;
990  if ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE )
991  {
992  aPropVal.Name = sStretchY;
993  aPropVal.Value <<= nYRef;
994  aGeometryItem.SetPropertyValue( sPath, aPropVal );
995  }
996  }
997 
998  // Path/TextFrames
999  static const OUStringLiteral sTextFrames( u"TextFrames" );
1000  pAny = aGeometryItem.GetPropertyValueByName( sPath, sTextFrames );
1001  if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1002  {
1003  sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1004  css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > seqTextFrames( nCount );
1005  auto pseqTextFrames = seqTextFrames.getArray();
1006  const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1007  for ( i = 0; i < nCount; i++, pRectangles++ )
1008  {
1009  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1010  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1011  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1012  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1013  }
1014  aPropVal.Name = sTextFrames;
1015  aPropVal.Value <<= seqTextFrames;
1016  aGeometryItem.SetPropertyValue( sPath, aPropVal );
1017  }
1018 
1019  // Equations
1020  static const OUStringLiteral sEquations( u"Equations" );
1021  pAny = aGeometryItem.GetPropertyValueByName( sEquations );
1022  if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1023  {
1024  sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1025  css::uno::Sequence< OUString > seqEquations( nCount );
1026  auto pseqEquations = seqEquations.getArray();
1027  const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1028  for ( i = 0; i < nCount; i++, pData++ )
1029  pseqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1030  aPropVal.Name = sEquations;
1031  aPropVal.Value <<= seqEquations;
1032  aGeometryItem.SetPropertyValue( aPropVal );
1033  }
1034 
1035  // Handles
1036  static const OUStringLiteral sHandles( u"Handles" );
1037  pAny = aGeometryItem.GetPropertyValueByName( sHandles );
1038  if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1039  {
1040  sal_Int32 i, nCount = pDefCustomShape->nHandles;
1041  const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1042  css::uno::Sequence< css::beans::PropertyValues > seqHandles( nCount );
1043  auto pseqHandles = seqHandles.getArray();
1044  for ( i = 0; i < nCount; i++, pData++ )
1045  {
1046  sal_Int32 nPropertiesNeeded;
1047  css::beans::PropertyValues& rPropValues = pseqHandles[ i ];
1048  nPropertiesNeeded = GetNumberOfProperties( pData );
1049  rPropValues.realloc( nPropertiesNeeded );
1050  lcl_ShapePropertiesFromDFF( pData, rPropValues );
1051  }
1052  aPropVal.Name = sHandles;
1053  aPropVal.Value <<= seqHandles;
1054  aGeometryItem.SetPropertyValue( aPropVal );
1055  }
1056  else if (pAny && sShapeType.startsWith("ooxml-") && sShapeType != "ooxml-non-primitive")
1057  {
1058  // ODF is not able to store the ooxml way of connecting handle to an adjustment
1059  // value by name, e.g. attribute RefX="adj". So the information is lost, when exporting
1060  // a pptx to odp, for example. This part reconstructs this information for the
1061  // ooxml preset shapes from their definition.
1062  css::uno::Sequence<css::beans::PropertyValues> seqHandles;
1063  *pAny >>= seqHandles;
1064  auto seqHandlesRange = asNonConstRange(seqHandles);
1065  bool bChanged(false);
1066  for (sal_Int32 i = 0; i < seqHandles.getLength(); i++)
1067  {
1068  comphelper::SequenceAsHashMap aHandleProps(seqHandles[i]);
1069  OUString sFirstRefType;
1070  sal_Int32 nFirstAdjRef;
1071  OUString sSecondRefType;
1072  sal_Int32 nSecondAdjRef;
1073  PresetOOXHandleAdj::GetOOXHandleAdjRelation(sShapeType, i, sFirstRefType, nFirstAdjRef,
1074  sSecondRefType, nSecondAdjRef);
1075  if (sFirstRefType != "na" && 0 <= nFirstAdjRef
1076  && nFirstAdjRef < seqAdjustmentValues.getLength())
1077  {
1078  bChanged |= aHandleProps.createItemIfMissing(sFirstRefType, nFirstAdjRef);
1079  }
1080  if (sSecondRefType != "na" && 0 <= nSecondAdjRef
1081  && nSecondAdjRef < seqAdjustmentValues.getLength())
1082  {
1083  bChanged |= aHandleProps.createItemIfMissing(sSecondRefType, nSecondAdjRef);
1084  }
1085  aHandleProps >> seqHandlesRange[i];
1086  }
1087  if (bChanged)
1088  {
1089  aPropVal.Name = sHandles;
1090  aPropVal.Value <<= seqHandles;
1091  aGeometryItem.SetPropertyValue(aPropVal);
1092  }
1093  }
1094 
1095  SetMergedItem( aGeometryItem );
1096 }
1097 
1098 bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const
1099 {
1100  bool bIsDefaultGeometry = false;
1101 
1102  OUString sShapeType;
1104 
1105  const Any *pAny = rGeometryItem.GetPropertyValueByName( "Type" );
1106  if ( pAny )
1107  *pAny >>= sShapeType;
1108 
1109  MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
1110 
1111  const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1112  static const OUStringLiteral sPath( u"Path" );
1113  switch( eDefaultType )
1114  {
1115  case DefaultType::Viewbox :
1116  {
1117  const Any* pViewBox = rGeometryItem.GetPropertyValueByName( "ViewBox" );
1118  css::awt::Rectangle aViewBox;
1119  if (pViewBox && (*pViewBox >>= aViewBox) && pDefCustomShape)
1120  {
1121  if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth )
1122  && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) )
1123  bIsDefaultGeometry = true;
1124  }
1125  }
1126  break;
1127 
1128  case DefaultType::Path :
1129  {
1130  pAny = rGeometryItem.GetPropertyValueByName( sPath, "Coordinates" );
1131  if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
1132  {
1133  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1;
1134  if ( *pAny >>= seqCoordinates1 )
1135  {
1136  sal_Int32 i, nCount = pDefCustomShape->nVertices;
1137  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates2( nCount );
1138  auto pseqCoordinates2 = seqCoordinates2.getArray();
1139  for ( i = 0; i < nCount; i++ )
1140  {
1141  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
1142  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
1143  }
1144  if ( seqCoordinates1 == seqCoordinates2 )
1145  bIsDefaultGeometry = true;
1146  }
1147  }
1148  else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == nullptr ) ) )
1149  bIsDefaultGeometry = true;
1150  }
1151  break;
1152 
1154  {
1155  pAny = rGeometryItem.GetPropertyValueByName( sPath, "GluePoints" );
1156  if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
1157  {
1158  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1;
1159  if ( *pAny >>= seqGluePoints1 )
1160  {
1161  sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
1162  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqGluePoints2( nCount );
1163  auto pseqGluePoints2 = seqGluePoints2.getArray();
1164  for ( i = 0; i < nCount; i++ )
1165  {
1166  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
1167  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
1168  }
1169  if ( seqGluePoints1 == seqGluePoints2 )
1170  bIsDefaultGeometry = true;
1171  }
1172  }
1173  else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) )
1174  bIsDefaultGeometry = true;
1175  }
1176  break;
1177 
1178  case DefaultType::Segments :
1179  {
1180  // Path/Segments
1181  pAny = rGeometryItem.GetPropertyValueByName( sPath, "Segments" );
1182  if ( pAny )
1183  {
1184  css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > seqSegments1;
1185  if ( *pAny >>= seqSegments1 )
1186  {
1187  if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
1188  {
1189  sal_Int32 i, nCount = pDefCustomShape->nElements;
1190  if ( nCount )
1191  {
1192  css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > seqSegments2( nCount );
1193  auto pseqSegments2 = seqSegments2.getArray();
1194  for ( i = 0; i < nCount; i++ )
1195  {
1196  EnhancedCustomShapeSegment& rSegInfo = pseqSegments2[ i ];
1197  sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1198  lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
1199  }
1200  if ( seqSegments1 == seqSegments2 )
1201  bIsDefaultGeometry = true;
1202  }
1203  }
1204  else
1205  {
1206  // check if it's the default segment description ( M L Z N )
1207  if ( seqSegments1.getLength() == 4 )
1208  {
1209  if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO )
1210  && ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO )
1211  && ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
1212  && ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) )
1213  bIsDefaultGeometry = true;
1214  }
1215  }
1216  }
1217  }
1218  else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == nullptr ) ) )
1219  bIsDefaultGeometry = true;
1220  }
1221  break;
1222 
1223  case DefaultType::StretchX :
1224  {
1225  pAny = rGeometryItem.GetPropertyValueByName( sPath, "StretchX" );
1226  if ( pAny && pDefCustomShape )
1227  {
1228  sal_Int32 nStretchX = 0;
1229  if ( *pAny >>= nStretchX )
1230  {
1231  if ( pDefCustomShape->nXRef == nStretchX )
1232  bIsDefaultGeometry = true;
1233  }
1234  }
1235  else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1236  bIsDefaultGeometry = true;
1237  }
1238  break;
1239 
1240  case DefaultType::StretchY :
1241  {
1242  pAny = rGeometryItem.GetPropertyValueByName( sPath, "StretchY" );
1243  if ( pAny && pDefCustomShape )
1244  {
1245  sal_Int32 nStretchY = 0;
1246  if ( *pAny >>= nStretchY )
1247  {
1248  if ( pDefCustomShape->nYRef == nStretchY )
1249  bIsDefaultGeometry = true;
1250  }
1251  }
1252  else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1253  bIsDefaultGeometry = true;
1254  }
1255  break;
1256 
1257  case DefaultType::Equations :
1258  {
1259  pAny = rGeometryItem.GetPropertyValueByName( "Equations" );
1260  if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1261  {
1262  css::uno::Sequence< OUString > seqEquations1;
1263  if ( *pAny >>= seqEquations1 )
1264  {
1265  sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1266  css::uno::Sequence< OUString > seqEquations2( nCount );
1267  auto pseqEquations2 = seqEquations2.getArray();
1268 
1269  const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1270  for ( i = 0; i < nCount; i++, pData++ )
1271  pseqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1272 
1273  if ( seqEquations1 == seqEquations2 )
1274  bIsDefaultGeometry = true;
1275  }
1276  }
1277  else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == nullptr ) ) )
1278  bIsDefaultGeometry = true;
1279  }
1280  break;
1281 
1283  {
1284  pAny = rGeometryItem.GetPropertyValueByName( sPath, "TextFrames" );
1285  if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1286  {
1287  css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1;
1288  if ( *pAny >>= seqTextFrames1 )
1289  {
1290  sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1291  css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > seqTextFrames2( nCount );
1292  auto pseqTextFrames2 = seqTextFrames2.getArray();
1293  const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1294  for ( i = 0; i < nCount; i++, pRectangles++ )
1295  {
1296  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1297  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1298  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1299  EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1300  }
1301  if ( seqTextFrames1 == seqTextFrames2 )
1302  bIsDefaultGeometry = true;
1303  }
1304  }
1305  else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == nullptr ) ) )
1306  bIsDefaultGeometry = true;
1307  }
1308  break;
1309  }
1310  return bIsDefaultGeometry;
1311 }
1312 
1314 {
1315  rInfo.bResizeFreeAllowed=fObjectRotation == 0.0;
1316  rInfo.bResizePropAllowed=true;
1317  rInfo.bRotateFreeAllowed=true;
1318  rInfo.bRotate90Allowed =true;
1319  rInfo.bMirrorFreeAllowed=true;
1320  rInfo.bMirror45Allowed =true;
1321  rInfo.bMirror90Allowed =true;
1322  rInfo.bTransparenceAllowed = false;
1323  rInfo.bShearAllowed =true;
1324  rInfo.bEdgeRadiusAllowed=false;
1325  rInfo.bNoContortion =true;
1326 
1327  // #i37011#
1328  if ( !mXRenderedCustomShape.is() )
1329  return;
1330 
1331  const SdrObject* pRenderedCustomShape = SdrObject::getSdrObjectFromXShape( mXRenderedCustomShape );
1332  if ( !pRenderedCustomShape )
1333  return;
1334 
1335  // #i37262#
1336  // Iterate self over the contained objects, since there are combinations of
1337  // polygon and curve objects. In that case, aInfo.bCanConvToPath and
1338  // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and.
1339  SdrObjListIter aIterator(*pRenderedCustomShape);
1340  while(aIterator.IsMore())
1341  {
1342  SdrObject* pCandidate = aIterator.Next();
1343  SdrObjTransformInfoRec aInfo;
1344  pCandidate->TakeObjInfo(aInfo);
1345 
1346  // set path and poly conversion if one is possible since
1347  // this object will first be broken
1348  const bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly);
1349  if(rInfo.bCanConvToPath != bCanConvToPathOrPoly)
1350  {
1351  rInfo.bCanConvToPath = bCanConvToPathOrPoly;
1352  }
1353 
1354  if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly)
1355  {
1356  rInfo.bCanConvToPoly = bCanConvToPathOrPoly;
1357  }
1358 
1359  if(rInfo.bCanConvToContour != aInfo.bCanConvToContour)
1360  {
1361  rInfo.bCanConvToContour = aInfo.bCanConvToContour;
1362  }
1363 
1364  if(rInfo.bShearAllowed != aInfo.bShearAllowed)
1365  {
1366  rInfo.bShearAllowed = aInfo.bShearAllowed;
1367  }
1368  }
1369 }
1370 
1372 {
1373  return SdrObjKind::CustomShape;
1374 }
1375 
1376 // #115391# This implementation is based on the TextFrame size of the CustomShape and the
1377 // state of the ResizeShapeToFitText flag to correctly set TextMinFrameWidth/Height
1379 {
1380  if (getSdrModelFromSdrObject().IsCreatingDataObj() || getSdrModelFromSdrObject().IsPasteResize())
1381  return;
1382 
1383  // check if we need to change anything before creating an SfxItemSet, because that is expensive
1384  const bool bResizeShapeToFitText(GetObjectItem(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue());
1385  tools::Rectangle aTextBound(maRect);
1386  bool bChanged(false);
1387  if(bResizeShapeToFitText)
1388  bChanged = true;
1389  else if(GetTextBounds(aTextBound))
1390  bChanged = true;
1391  if (!bChanged)
1392  return;
1393 
1395  SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH> // contains SDRATTR_TEXT_MAXFRAMEWIDTH
1396  aSet(*GetObjectItemSet().GetPool());
1397 
1398  if(bResizeShapeToFitText)
1399  {
1400  // always reset MinWidthHeight to zero to only rely on text size and frame size
1401  // to allow resizing being completely dependent on text size only
1402  aSet.Put(makeSdrTextMinFrameWidthItem(0));
1403  aSet.Put(makeSdrTextMinFrameHeightItem(0));
1404  }
1405  else
1406  {
1407  // recreate from CustomShape-specific TextBounds
1410  const tools::Long nTWdt(std::max(tools::Long(0), static_cast<tools::Long>(aTextBound.GetWidth() - 1 - nHDist)));
1411  const tools::Long nTHgt(std::max(tools::Long(0), static_cast<tools::Long>(aTextBound.GetHeight() - 1 - nVDist)));
1412 
1413  aSet.Put(makeSdrTextMinFrameWidthItem(nTWdt));
1414  aSet.Put(makeSdrTextMinFrameHeightItem(nTHgt));
1415  }
1416 
1417  SetObjectItemSet(aSet);
1418 }
1419 
1421 {
1422  maRect = rRect;
1425 
1426  AdaptTextMinSize();
1427 
1428  ImpCheckShear();
1430  SetChanged();
1431 }
1432 
1434 {
1435  tools::Rectangle aBoundRect0;
1436  if ( m_pUserCall )
1437  aBoundRect0 = GetLastBoundRect();
1438  NbcSetSnapRect( rRect );
1441 }
1442 
1444 {
1445  maRect = rRect;
1448 
1449  AdaptTextMinSize();
1450 
1452  SetChanged();
1453 }
1454 
1456 {
1457  tools::Rectangle aBoundRect0;
1458  if ( m_pUserCall )
1459  aBoundRect0 = GetLastBoundRect();
1460  NbcSetLogicRect(rRect);
1463 }
1464 
1465 void SdrObjCustomShape::Move( const Size& rSiz )
1466 {
1467  if ( rSiz.Width() || rSiz.Height() )
1468  {
1469  tools::Rectangle aBoundRect0;
1470  if ( m_pUserCall )
1471  aBoundRect0 = GetLastBoundRect();
1472  NbcMove(rSiz);
1473  SetChanged();
1476  }
1477 }
1479 {
1480  SdrTextObj::NbcMove( rSiz );
1481  if ( mXRenderedCustomShape.is() )
1482  {
1484  if ( pRenderedCustomShape )
1485  {
1486  // #i97149# the visualisation shape needs to be informed
1487  // about change, too
1488  pRenderedCustomShape->ActionChanged();
1489  pRenderedCustomShape->NbcMove( rSiz );
1490  }
1491  }
1492 
1493  // #i37011# adapt geometry shadow
1495  {
1496  mpLastShadowGeometry->NbcMove( rSiz );
1497  }
1498 }
1499 
1500 void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact )
1501 {
1502  // taking care of handles that should not been changed
1503  tools::Rectangle aOld( maRect );
1504  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
1505 
1506  SdrTextObj::NbcResize( rRef, rxFact, ryFact );
1507 
1508  if ( ( rxFact.GetNumerator() != rxFact.GetDenominator() )
1509  || ( ryFact.GetNumerator()!= ryFact.GetDenominator() ) )
1510  {
1511  if ( ( ( rxFact.GetNumerator() < 0 ) && ( rxFact.GetDenominator() > 0 ) ) ||
1512  ( ( rxFact.GetNumerator() > 0 ) && ( rxFact.GetDenominator() < 0 ) ) )
1513  {
1514  SetMirroredX( !IsMirroredX() );
1515  }
1516  if ( ( ( ryFact.GetNumerator() < 0 ) && ( ryFact.GetDenominator() > 0 ) ) ||
1517  ( ( ryFact.GetNumerator() > 0 ) && ( ryFact.GetDenominator() < 0 ) ) )
1518  {
1519  SetMirroredY( !IsMirroredY() );
1520  }
1521  }
1522 
1523  for (const auto& rInteraction : aInteractionHandles)
1524  {
1525  try
1526  {
1527  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED )
1528  rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition );
1529  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_X )
1530  {
1531  sal_Int32 nX = ( rInteraction.aPosition.X - aOld.Left() ) + maRect.Left();
1532  rInteraction.xInteraction->setControllerPosition( css::awt::Point( nX, rInteraction.xInteraction->getPosition().Y ) );
1533  }
1534  else if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX )
1535  {
1536  sal_Int32 nX = maRect.Right() - (aOld.Right() - rInteraction.aPosition.X);
1537  rInteraction.xInteraction->setControllerPosition( css::awt::Point( nX, rInteraction.xInteraction->getPosition().Y ) );
1538  }
1539  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_Y )
1540  {
1541  sal_Int32 nY = ( rInteraction.aPosition.Y - aOld.Top() ) + maRect.Top();
1542  rInteraction.xInteraction->setControllerPosition( css::awt::Point( rInteraction.xInteraction->getPosition().X, nY ) );
1543  }
1544  }
1545  catch ( const uno::RuntimeException& )
1546  {
1547  }
1548  }
1549 
1550  // updating fObjectRotation
1551  Degree100 nTextObjRotation = maGeo.nRotationAngle;
1552  double fAngle = toDegrees(nTextObjRotation);
1553  if (IsMirroredX())
1554  {
1555  if (IsMirroredY())
1556  fObjectRotation = fAngle - 180.0;
1557  else
1558  fObjectRotation = -fAngle;
1559  }
1560  else
1561  {
1562  if (IsMirroredY())
1563  fObjectRotation = 180.0 - fAngle;
1564  else
1565  fObjectRotation = fAngle;
1566  }
1567  while (fObjectRotation < 0)
1568  fObjectRotation += 360.0;
1569  while (fObjectRotation >= 360.0)
1570  fObjectRotation -= 360.0;
1571 
1573 }
1574 
1575 void SdrObjCustomShape::NbcRotate( const Point& rRef, Degree100 nAngle, double sn, double cs )
1576 {
1577  bool bMirroredX = IsMirroredX();
1578  bool bMirroredY = IsMirroredY();
1579 
1580  fObjectRotation = fmod( fObjectRotation, 360.0 );
1581  if ( fObjectRotation < 0 )
1583 
1584  // the rotation angle for ashapes is stored in fObjectRotation, this rotation
1585  // has to be applied to the text object (which is internally using maGeo.nAngle).
1586  SdrTextObj::NbcRotate( maRect.TopLeft(), -maGeo.nRotationAngle, // retrieving the unrotated text object
1589  maGeo.nRotationAngle = 0_deg100; // resetting aGeo data
1590  maGeo.RecalcSinCos();
1591 
1592  Degree100 nW(static_cast<sal_Int32>( fObjectRotation * 100 )); // applying our object rotation
1593  if ( bMirroredX )
1594  nW = 36000_deg100 - nW;
1595  if ( bMirroredY )
1596  nW = 18000_deg100 - nW;
1597  nW = nW % 36000_deg100;
1598  if ( nW < 0_deg100 )
1599  nW = 36000_deg100 + nW;
1600  SdrTextObj::NbcRotate( maRect.TopLeft(), nW, // applying text rotation
1601  sin( toRadians(nW) ),
1602  cos( toRadians(nW) ) );
1603 
1604  int nSwap = 0;
1605  if ( bMirroredX )
1606  nSwap ^= 1;
1607  if ( bMirroredY )
1608  nSwap ^= 1;
1609 
1610  double fAngle = toDegrees(nAngle); // updating to our new object rotation
1611  fObjectRotation = fmod( nSwap ? fObjectRotation - fAngle : fObjectRotation + fAngle, 360.0 );
1612  if ( fObjectRotation < 0 )
1614 
1615  SdrTextObj::NbcRotate( rRef, nAngle, sn, cs ); // applying text rotation
1617 }
1618 
1619 void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 )
1620 {
1621  // TTTT: Fix for old mirroring, can be removed again in aw080
1622  // storing horizontal and vertical flipping without modifying the rotate angle
1623  // decompose other flipping to rotation and MirrorX.
1624  tools::Long ndx = rRef2.X()-rRef1.X();
1625  tools::Long ndy = rRef2.Y()-rRef1.Y();
1626 
1627  if(!ndx) // MirroredX
1628  {
1630  SdrTextObj::NbcMirror( rRef1, rRef2 );
1631  }
1632  else
1633  {
1634  if(!ndy) // MirroredY
1635  {
1637  SdrTextObj::NbcMirror( rRef1, rRef2 );
1638  }
1639  else // neither horizontal nor vertical
1640  {
1642 
1643  // call parent
1644  SdrTextObj::NbcMirror( rRef1, rRef2 );
1645 
1646  // update fObjectRotation
1647  Degree100 nTextObjRotation = maGeo.nRotationAngle;
1648  double fAngle = toDegrees(nTextObjRotation);
1649 
1650  bool bSingleFlip = (IsMirroredX()!= IsMirroredY());
1651 
1652  fObjectRotation = fmod( bSingleFlip ? -fAngle : fAngle, 360.0 );
1653 
1654  if ( fObjectRotation < 0 )
1655  {
1656  fObjectRotation = 360.0 + fObjectRotation;
1657  }
1658  }
1659  }
1660 
1662 }
1663 
1664 void SdrObjCustomShape::Shear( const Point& rRef, Degree100 nAngle, double tn, bool bVShear )
1665 {
1666  SdrTextObj::Shear( rRef, nAngle, tn, bVShear );
1668 }
1669 void SdrObjCustomShape::NbcShear( const Point& rRef, Degree100 nAngle, double tn, bool bVShear )
1670 {
1671  // TTTT: Fix for old mirroring, can be removed again in aw080
1672  SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear);
1673 
1674  // updating fObjectRotation
1675  Degree100 nTextObjRotation = maGeo.nRotationAngle;
1676  double fAngle = toDegrees(nTextObjRotation);
1677  if (IsMirroredX())
1678  {
1679  if (IsMirroredY())
1680  fObjectRotation = fAngle - 180.0;
1681  else
1682  fObjectRotation = -fAngle;
1683  }
1684  else
1685  {
1686  if (IsMirroredY())
1687  fObjectRotation = 180.0 - fAngle;
1688  else
1689  fObjectRotation = fAngle;
1690  }
1691  while (fObjectRotation < 0)
1692  fObjectRotation += 360.0;
1693  while (fObjectRotation >= 360.0)
1694  fObjectRotation -= 360.0;
1695 
1697 }
1698 
1700 {
1701  sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#
1702 
1703  // #i25616#
1704  if(!LineIsOutsideGeometry())
1705  {
1706  nWdt++;
1707  nWdt /= 2;
1708  }
1709 
1710  Point aPt;
1711  switch (nPosNum) {
1712  case 0: aPt=maRect.TopCenter(); aPt.AdjustY( -nWdt ); break;
1713  case 1: aPt=maRect.RightCenter(); aPt.AdjustX(nWdt ); break;
1714  case 2: aPt=maRect.BottomCenter(); aPt.AdjustY(nWdt ); break;
1715  case 3: aPt=maRect.LeftCenter(); aPt.AdjustX( -nWdt ); break;
1716  }
1717  if (maGeo.nShearAngle != 0_deg100) ShearPoint(aPt, maRect.TopLeft(), maGeo.mfTanShearAngle);
1719  aPt-=GetSnapRect().Center();
1720  SdrGluePoint aGP(aPt);
1721  aGP.SetPercent(false);
1722  return aGP;
1723 }
1724 
1725 
1726 // #i38892#
1728 {
1729  const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
1730 
1731  if(!pSdrObject)
1732  return;
1733 
1734  const SdrGluePointList* pSource = pSdrObject->GetGluePointList();
1735 
1736  if(!(pSource && pSource->GetCount()))
1737  return;
1738 
1740  {
1742  }
1743 
1745 
1746  if(!pList)
1747  return;
1748 
1749  SdrGluePointList aNewList;
1750  sal_uInt16 a;
1751 
1752  for(a = 0; a < pSource->GetCount(); a++)
1753  {
1754  SdrGluePoint aCopy((*pSource)[a]);
1755  aCopy.SetUserDefined(false);
1756  aNewList.Insert(aCopy);
1757  }
1758 
1759  bool bMirroredX = IsMirroredX();
1760  bool bMirroredY = IsMirroredY();
1761 
1762  Degree100 nShearAngle = maGeo.nShearAngle;
1763  double fTan = maGeo.mfTanShearAngle;
1764 
1765  if (maGeo.nRotationAngle || nShearAngle || bMirroredX || bMirroredY)
1766  {
1767  tools::Polygon aPoly( maRect );
1768  if( nShearAngle )
1769  {
1770  sal_uInt16 nPointCount=aPoly.GetSize();
1771  for (sal_uInt16 i=0; i<nPointCount; i++)
1772  ShearPoint(aPoly[i],maRect.Center(), fTan );
1773  }
1774  if (maGeo.nRotationAngle)
1775  aPoly.Rotate( maRect.Center(), to<Degree10>(maGeo.nRotationAngle) );
1776 
1777  tools::Rectangle aBoundRect( aPoly.GetBoundRect() );
1778  sal_Int32 nXDiff = aBoundRect.Left() - maRect.Left();
1779  sal_Int32 nYDiff = aBoundRect.Top() - maRect.Top();
1780 
1781  if (nShearAngle && bMirroredX != bMirroredY)
1782  {
1783  nShearAngle = -nShearAngle;
1784  fTan = -fTan;
1785  }
1786 
1787  Point aRef( maRect.GetWidth() / 2, maRect.GetHeight() / 2 );
1788  for ( a = 0; a < aNewList.GetCount(); a++ )
1789  {
1790  SdrGluePoint& rPoint = aNewList[ a ];
1791  Point aGlue( rPoint.GetPos() );
1792  if ( nShearAngle )
1793  ShearPoint( aGlue, aRef, fTan );
1794 
1795  RotatePoint(aGlue, aRef, sin(basegfx::deg2rad(fObjectRotation)),
1797  if ( bMirroredX )
1798  aGlue.setX( maRect.GetWidth() - aGlue.X() );
1799  if ( bMirroredY )
1800  aGlue.setY( maRect.GetHeight() - aGlue.Y() );
1801  aGlue.AdjustX( -nXDiff );
1802  aGlue.AdjustY( -nYDiff );
1803  rPoint.SetPos( aGlue );
1804  }
1805  }
1806 
1807  for(a = 0; a < pList->GetCount(); a++)
1808  {
1809  const SdrGluePoint& rCandidate = (*pList)[a];
1810 
1811  if(rCandidate.IsUserDefined())
1812  {
1813  aNewList.Insert(rCandidate);
1814  }
1815  }
1816 
1817  // copy new list to local. This is NOT very convenient behavior, the local
1818  // GluePointList should not be set, but we delivered by using GetGluePointList(),
1819  // maybe on demand. Since the local object is changed here, this is assumed to
1820  // be a result of GetGluePointList and thus the list is copied
1821  if(m_pPlusData)
1822  {
1823  m_pPlusData->SetGluePoints(aNewList);
1824  }
1825 }
1826 
1827 // #i38892#
1829 {
1832 }
1833 
1834 // #i38892#
1836 {
1838  {
1841  }
1842  else
1843  {
1844  return nullptr;
1845  }
1846 }
1847 
1848 
1850 {
1851  const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
1852  return ( GetInteractionHandles().size() + nBasicHdlCount );
1853 }
1854 
1856 {
1857  SdrTextObj::AddToHdlList(rHdlList);
1858 
1859  int nCustomShapeHdlNum = 0;
1860  for (SdrCustomShapeInteraction const & rInteraction : GetInteractionHandles())
1861  {
1862  if ( rInteraction.xInteraction.is() )
1863  {
1864  try
1865  {
1866  css::awt::Point aPosition( rInteraction.xInteraction->getPosition() );
1867  std::unique_ptr<SdrHdl> pH(new SdrHdl( Point( aPosition.X, aPosition.Y ), SdrHdlKind::CustomShape1 ));
1868  pH->SetPointNum( nCustomShapeHdlNum );
1869  pH->SetObj( const_cast<SdrObjCustomShape*>(this) );
1870  rHdlList.AddHdl(std::move(pH));
1871  }
1872  catch ( const uno::RuntimeException& )
1873  {
1874  }
1875  }
1876  ++nCustomShapeHdlNum;
1877  }
1878 }
1879 
1881 {
1882  return true;
1883 }
1884 
1886 {
1887  const SdrHdl* pHdl = rDrag.GetHdl();
1888 
1889  if(pHdl && SdrHdlKind::CustomShape1 == pHdl->GetKind())
1890  {
1891  rDrag.SetEndDragChangesAttributes(true);
1892  rDrag.SetNoSnap();
1893  }
1894  else
1895  {
1896  const SdrHdl* pHdl2 = rDrag.GetHdl();
1897  const SdrHdlKind eHdl((pHdl2 == nullptr) ? SdrHdlKind::Move : pHdl2->GetKind());
1898 
1899  switch( eHdl )
1900  {
1901  case SdrHdlKind::UpperLeft :
1902  case SdrHdlKind::Upper :
1903  case SdrHdlKind::UpperRight :
1904  case SdrHdlKind::Left :
1905  case SdrHdlKind::Right :
1906  case SdrHdlKind::LowerLeft :
1907  case SdrHdlKind::Lower :
1908  case SdrHdlKind::LowerRight :
1909  case SdrHdlKind::Move :
1910  {
1911  break;
1912  }
1913  default:
1914  {
1915  return false;
1916  }
1917  }
1918  }
1919 
1920  return true;
1921 }
1922 
1924 {
1925  tools::Rectangle aOld( maRect );
1926  bool bOldMirroredX( IsMirroredX() );
1927  bool bOldMirroredY( IsMirroredY() );
1928 
1929  tools::Rectangle aNewRect( rNewRect );
1930  aNewRect.Justify();
1931 
1932  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
1933 
1934  GeoStat aGeoStat( GetGeoStat() );
1935  if ( aNewRect.TopLeft()!= maRect.TopLeft() &&
1937  {
1938  Point aNewPos( aNewRect.TopLeft() );
1939  if ( maGeo.nShearAngle ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.mfTanShearAngle );
1940  if ( maGeo.nRotationAngle ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle );
1941  aNewRect.SetPos( aNewPos );
1942  }
1943  if ( aNewRect == maRect )
1944  return;
1945 
1946  SetLogicRect( aNewRect );
1948 
1949  if ( rNewRect.Left() > rNewRect.Right() )
1950  {
1951  Point aTop( ( GetSnapRect().Left() + GetSnapRect().Right() ) >> 1, GetSnapRect().Top() );
1952  Point aBottom( aTop.X(), aTop.Y() + 1000 );
1953  NbcMirror( aTop, aBottom );
1954  }
1955  if ( rNewRect.Top() > rNewRect.Bottom() )
1956  {
1957  Point aLeft( GetSnapRect().Left(), ( GetSnapRect().Top() + GetSnapRect().Bottom() ) >> 1 );
1958  Point aRight( aLeft.X() + 1000, aLeft.Y() );
1959  NbcMirror( aLeft, aRight );
1960  }
1961 
1962  for (const auto& rInteraction : aInteractionHandles)
1963  {
1964  try
1965  {
1966  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED )
1967  rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition );
1968  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_X ||
1969  rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX )
1970  {
1971  if (rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX)
1972  bOldMirroredX = !bOldMirroredX;
1973 
1974  sal_Int32 nX;
1975  if ( bOldMirroredX )
1976  {
1977  nX = ( rInteraction.aPosition.X - aOld.Right() );
1978  if ( rNewRect.Left() > rNewRect.Right() )
1979  nX = maRect.Left() - nX;
1980  else
1981  nX += maRect.Right();
1982  }
1983  else
1984  {
1985  nX = ( rInteraction.aPosition.X - aOld.Left() );
1986  if ( rNewRect.Left() > rNewRect.Right() )
1987  nX = maRect.Right() - nX;
1988  else
1989  nX += maRect.Left();
1990  }
1991  rInteraction.xInteraction->setControllerPosition( css::awt::Point( nX, rInteraction.xInteraction->getPosition().Y ) );
1992  }
1993  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_Y )
1994  {
1995  sal_Int32 nY;
1996  if ( bOldMirroredY )
1997  {
1998  nY = ( rInteraction.aPosition.Y - aOld.Bottom() );
1999  if ( rNewRect.Top() > rNewRect.Bottom() )
2000  nY = maRect.Top() - nY;
2001  else
2002  nY += maRect.Bottom();
2003  }
2004  else
2005  {
2006  nY = ( rInteraction.aPosition.Y - aOld.Top() );
2007  if ( rNewRect.Top() > rNewRect.Bottom() )
2008  nY = maRect.Bottom() - nY;
2009  else
2010  nY += maRect.Top();
2011  }
2012  rInteraction.xInteraction->setControllerPosition( css::awt::Point( rInteraction.xInteraction->getPosition().X, nY ) );
2013  }
2014  }
2015  catch ( const uno::RuntimeException& )
2016  {
2017  }
2018  }
2019 }
2020 
2021 void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point& rDestination,
2022  const sal_uInt16 nCustomShapeHdlNum, bool bMoveCalloutRectangle )
2023 {
2024  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
2025  if ( nCustomShapeHdlNum >= aInteractionHandles.size() )
2026  return;
2027 
2028  SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] );
2029  if ( !aInteractionHandle.xInteraction.is() )
2030  return;
2031 
2032  try
2033  {
2034  css::awt::Point aPt( rDestination.X(), rDestination.Y() );
2035  if ( aInteractionHandle.nMode & CustomShapeHandleModes::MOVE_SHAPE && bMoveCalloutRectangle )
2036  {
2037  sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X;
2038  sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y;
2039 
2040  maRect.Move( nXDiff, nYDiff );
2041  m_aOutRect.Move( nXDiff, nYDiff );
2042  maSnapRect.Move( nXDiff, nYDiff );
2043  SetBoundAndSnapRectsDirty(/*bNotMyself*/true);
2045 
2046  for (const auto& rInteraction : aInteractionHandles)
2047  {
2048  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED )
2049  {
2050  if ( rInteraction.xInteraction.is() )
2051  rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition );
2052  }
2053  }
2054  }
2055  aInteractionHandle.xInteraction->setControllerPosition( aPt );
2056  }
2057  catch ( const uno::RuntimeException& )
2058  {
2059  }
2060 }
2061 
2063 {
2064  const SdrHdl* pHdl = rDrag.GetHdl();
2065  const SdrHdlKind eHdl((pHdl == nullptr) ? SdrHdlKind::Move : pHdl->GetKind());
2066 
2067  switch(eHdl)
2068  {
2070  {
2072  DragMoveCustomShapeHdl( rDrag.GetNow(), static_cast<sal_uInt16>(pHdl->GetPointNum()), !rDrag.GetDragMethod()->IsShiftPressed() );
2075  SetChanged();
2076  break;
2077  }
2078 
2079  case SdrHdlKind::UpperLeft :
2080  case SdrHdlKind::Upper :
2081  case SdrHdlKind::UpperRight :
2082  case SdrHdlKind::Left :
2083  case SdrHdlKind::Right :
2084  case SdrHdlKind::LowerLeft :
2085  case SdrHdlKind::Lower :
2086  case SdrHdlKind::LowerRight :
2087  {
2089  break;
2090  }
2091  case SdrHdlKind::Move :
2092  {
2093  Move(Size(rDrag.GetDX(), rDrag.GetDY()));
2094  break;
2095  }
2096  default: break;
2097  }
2098 
2099  return true;
2100 }
2101 
2102 
2104 {
2105  tools::Rectangle aRect1;
2106  rStat.TakeCreateRect( aRect1 );
2107 
2108  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
2109 
2110  constexpr sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ?
2111  constexpr sal_uInt32 nDefaultObjectSizeHeight= 3000;
2112 
2113  if ( ImpVerticalSwitch( *this ) )
2114  {
2115  SetMirroredX( aRect1.Left() > aRect1.Right() );
2116 
2117  aRect1 = tools::Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) );
2118  // subtracting the horizontal difference of the latest handle from shape position
2119  if ( !aInteractionHandles.empty() )
2120  {
2121  sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X;
2122  aRect1.Move( maRect.Left() - nHandlePos, 0 );
2123  }
2124  }
2125  ImpJustifyRect( aRect1 );
2126  rStat.SetActionRect( aRect1 );
2127  maRect = aRect1;
2129 
2130  for (const auto& rInteraction : aInteractionHandles)
2131  {
2132  try
2133  {
2134  if ( rInteraction.nMode & CustomShapeHandleModes::CREATE_FIXED )
2135  rInteraction.xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) );
2136  }
2137  catch ( const uno::RuntimeException& )
2138  {
2139  }
2140  }
2141 
2143  m_bSnapRectDirty=true;
2144 }
2145 
2147 {
2148  SdrView* pView = rStat.GetView(); // #i37448#
2149  if( pView && pView->IsSolidDragging() )
2150  {
2152  }
2153  DragCreateObject( rStat );
2155  return true;
2156 }
2157 
2159 {
2160  DragCreateObject( rStat );
2161 
2162  AdaptTextMinSize();
2163 
2165  return ( eCmd == SdrCreateCmd::ForceEnd || rStat.GetPointCount() >= 2 );
2166 }
2167 
2169 {
2170  return GetLineGeometry( false );
2171 }
2172 
2173 
2174 // in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text,
2175 // the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape
2177 {
2178  const SfxItemSet& rSet = GetMergedItemSet();
2179  bool bIsAutoGrowHeight = rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
2180  if ( bIsAutoGrowHeight && IsVerticalWriting() )
2181  bIsAutoGrowHeight = !rSet.Get(SDRATTR_TEXT_WORDWRAP).GetValue();
2182  return bIsAutoGrowHeight;
2183 }
2185 {
2186  const SfxItemSet& rSet = GetMergedItemSet();
2187  bool bIsAutoGrowWidth = rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
2188  if ( bIsAutoGrowWidth && !IsVerticalWriting() )
2189  bIsAutoGrowWidth = !rSet.Get(SDRATTR_TEXT_WORDWRAP).GetValue();
2190  return bIsAutoGrowWidth;
2191 }
2192 
2193 /* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference
2194  is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing
2195  mode has been changed */
2196 
2198 {
2200 
2201  OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2202 
2203  DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" );
2204 
2205  if( !pOutlinerParaObject ||
2206  (pOutlinerParaObject->IsEffectivelyVertical() == bVertical) )
2207  return;
2208 
2209  // get item settings
2210  const SfxItemSet& rSet = GetObjectItemSet();
2211 
2212  // Also exchange horizontal and vertical adjust items
2213  SdrTextHorzAdjust eHorz = rSet.Get(SDRATTR_TEXT_HORZADJUST).GetValue();
2214  SdrTextVertAdjust eVert = rSet.Get(SDRATTR_TEXT_VERTADJUST).GetValue();
2215 
2216  // rescue object size, SetSnapRect below expects logic rect,
2217  // not snap rect.
2218  tools::Rectangle aObjectRect = GetLogicRect();
2219 
2220  // prepare ItemSet to set exchanged width and height items
2222  // Expanded item ranges to also support horizontal and vertical adjust.
2225 
2226  aNewSet.Put(rSet);
2227 
2228  // Exchange horizontal and vertical adjusts
2229  switch(eVert)
2230  {
2235  }
2236  switch(eHorz)
2237  {
2242  }
2243 
2244  pOutlinerParaObject = GetOutlinerParaObject();
2245  if ( pOutlinerParaObject )
2246  pOutlinerParaObject->SetVertical(bVertical);
2247  SetObjectItemSet( aNewSet );
2248 
2249  // restore object size
2250  SetSnapRect(aObjectRect);
2251 }
2252 
2253 void SdrObjCustomShape::SuggestTextFrameSize(Size aSuggestedTextFrameSize)
2254 {
2255  m_aSuggestedTextFrameSize = aSuggestedTextFrameSize;
2256 }
2257 
2259 {
2260  // Either we have text or the application has native text and suggested its size to us.
2261  bool bHasText = HasText() || !m_aSuggestedTextFrameSize.IsEmpty();
2262  if ( bHasText && !rR.IsEmpty() )
2263  {
2264  bool bWdtGrow=bWdt && IsAutoGrowWidth();
2265  bool bHgtGrow=bHgt && IsAutoGrowHeight();
2266  if ( bWdtGrow || bHgtGrow )
2267  {
2268  tools::Rectangle aR0(rR);
2269  tools::Long nHgt=0,nMinHgt=0,nMaxHgt=0;
2270  tools::Long nWdt=0,nMinWdt=0,nMaxWdt=0;
2271  Size aSiz(rR.GetSize()); aSiz.AdjustWidth( -1 ); aSiz.AdjustHeight( -1 );
2272  Size aMaxSiz(100000,100000);
2273  Size aTmpSiz(getSdrModelFromSdrObject().GetMaxObjSize());
2274  if (aTmpSiz.Width()!=0) aMaxSiz.setWidth(aTmpSiz.Width() );
2275  if (aTmpSiz.Height()!=0) aMaxSiz.setHeight(aTmpSiz.Height() );
2276  if (bWdtGrow)
2277  {
2278  nMinWdt=GetMinTextFrameWidth();
2279  nMaxWdt=GetMaxTextFrameWidth();
2280  if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width();
2281  if (nMinWdt<=0) nMinWdt=1;
2282  aSiz.setWidth(nMaxWdt );
2283  }
2284  if (bHgtGrow)
2285  {
2286  nMinHgt=GetMinTextFrameHeight();
2287  nMaxHgt=GetMaxTextFrameHeight();
2288  if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height();
2289  if (nMinHgt<=0) nMinHgt=1;
2290  aSiz.setHeight(nMaxHgt );
2291  }
2294  aSiz.AdjustWidth( -nHDist );
2295  aSiz.AdjustHeight( -nVDist );
2296  if ( aSiz.Width() < 2 )
2297  aSiz.setWidth( 2 ); // minimum size=2
2298  if ( aSiz.Height() < 2 )
2299  aSiz.setHeight( 2 ); // minimum size=2
2300 
2301  if (HasText())
2302  {
2303  if(mpEditingOutliner)
2304  {
2306  if (bWdtGrow)
2307  {
2309  nWdt=aSiz2.Width()+1; // a little more tolerance
2310  if (bHgtGrow) nHgt=aSiz2.Height()+1; // a little more tolerance
2311  } else
2312  {
2313  nHgt=mpEditingOutliner->GetTextHeight()+1; // a little more tolerance
2314  }
2315  }
2316  else
2317  {
2318  Outliner& rOutliner=ImpGetDrawOutliner();
2319  rOutliner.SetPaperSize(aSiz);
2320  rOutliner.SetUpdateLayout(true);
2321  // TODO: add the optimization with bPortionInfoChecked again.
2322  OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2323  if( pOutlinerParaObject != nullptr )
2324  {
2325  rOutliner.SetText(*pOutlinerParaObject);
2327  }
2328  if ( bWdtGrow )
2329  {
2330  Size aSiz2(rOutliner.CalcTextSize());
2331  nWdt=aSiz2.Width()+1; // a little more tolerance
2332  if ( bHgtGrow )
2333  nHgt=aSiz2.Height()+1; // a little more tolerance
2334  }
2335  else
2336  {
2337  nHgt = rOutliner.GetTextHeight()+1; // a little more tolerance
2338 
2339  sal_Int16 nColumns = GetMergedItem(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue();
2340  if (bHgtGrow && nColumns > 1)
2341  {
2342  // Both 'resize shape to fix text' and multiple columns are enabled. The
2343  // first means a dynamic height, the second expects a fixed height.
2344  // Resolve this conflict by going with the original height.
2345  nHgt = rR.getHeight();
2346  }
2347  }
2348  rOutliner.Clear();
2349  }
2350  }
2351  else
2352  {
2355  }
2356  if ( nWdt < nMinWdt )
2357  nWdt = nMinWdt;
2358  if ( nWdt > nMaxWdt )
2359  nWdt = nMaxWdt;
2360  nWdt += nHDist;
2361  if ( nWdt < 1 )
2362  nWdt = 1; // nHDist may also be negative
2363  if ( nHgt < nMinHgt )
2364  nHgt = nMinHgt;
2365  if ( nHgt > nMaxHgt )
2366  nHgt = nMaxHgt;
2367  nHgt+=nVDist;
2368  if ( nHgt < 1 )
2369  nHgt = 1; // nVDist may also be negative
2370  tools::Long nWdtGrow = nWdt-(rR.Right()-rR.Left());
2371  tools::Long nHgtGrow = nHgt-(rR.Bottom()-rR.Top());
2372  if ( nWdtGrow == 0 )
2373  bWdtGrow = false;
2374  if ( nHgtGrow == 0 )
2375  bHgtGrow=false;
2376  if ( bWdtGrow || bHgtGrow || !m_aSuggestedTextFrameSize.IsEmpty())
2377  {
2378  if ( bWdtGrow || m_aSuggestedTextFrameSize.Width() )
2379  {
2382  {
2384  }
2385  else if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2386  rR.AdjustRight(nWdtGrow );
2387  else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2388  rR.AdjustLeft( -nWdtGrow );
2389  else
2390  {
2391  tools::Long nWdtGrow2=nWdtGrow/2;
2392  rR.AdjustLeft( -nWdtGrow2 );
2393  rR.SetRight(rR.Left()+nWdt );
2394  }
2395  }
2396  if ( bHgtGrow || m_aSuggestedTextFrameSize.Height() )
2397  {
2400  {
2402  }
2403  else if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2404  rR.AdjustBottom(nHgtGrow );
2405  else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2406  rR.AdjustTop( -nHgtGrow );
2407  else
2408  {
2409  tools::Long nHgtGrow2=nHgtGrow/2;
2410  rR.AdjustTop( -nHgtGrow2 );
2411  rR.SetBottom(rR.Top()+nHgt );
2412  }
2413  }
2414  if ( maGeo.nRotationAngle )
2415  {
2416  Point aD1(rR.TopLeft());
2417  aD1-=aR0.TopLeft();
2418  Point aD2(aD1);
2420  aD2-=aD1;
2421  rR.Move(aD2.X(),aD2.Y());
2422  }
2423  return true;
2424  }
2425  }
2426  }
2427  return false;
2428 }
2429 
2431 {
2432  tools::Rectangle aReturnValue;
2433 
2434  tools::Rectangle aOldTextRect( maRect ); // <- initial text rectangle
2435 
2436  tools::Rectangle aNewTextRect( maRect ); // <- new text rectangle returned from the custom shape renderer,
2437  GetTextBounds( aNewTextRect ); // it depends to the current logical shape size
2438 
2439  tools::Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure
2440  if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner
2441  {
2442  if (aAdjustedTextRect != aNewTextRect && aOldTextRect != aAdjustedTextRect &&
2443  aNewTextRect.GetWidth() && aNewTextRect.GetHeight())
2444  {
2445  aReturnValue = maRect;
2446  double fXScale = static_cast<double>(aOldTextRect.GetWidth()) / static_cast<double>(aNewTextRect.GetWidth());
2447  double fYScale = static_cast<double>(aOldTextRect.GetHeight()) / static_cast<double>(aNewTextRect.GetHeight());
2448  double fRightDiff = static_cast<double>( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale;
2449  double fLeftDiff = static_cast<double>( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale;
2450  double fTopDiff = static_cast<double>( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale;
2451  double fBottomDiff= static_cast<double>( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale;
2452  aReturnValue.AdjustLeft(static_cast<sal_Int32>(fLeftDiff) );
2453  aReturnValue.AdjustRight(static_cast<sal_Int32>(fRightDiff) );
2454  aReturnValue.AdjustTop(static_cast<sal_Int32>(fTopDiff) );
2455  aReturnValue.AdjustBottom(static_cast<sal_Int32>(fBottomDiff) );
2456  }
2457  }
2458  return aReturnValue;
2459 }
2460 
2462 {
2463  tools::Rectangle aNewTextRect = ImpCalculateTextFrame(bHgt, bWdt);
2464  const bool bRet = !aNewTextRect.IsEmpty() && aNewTextRect != maRect;
2466  {
2468 
2469  // taking care of handles that should not been changed
2470  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
2471 
2472  maRect = aNewTextRect;
2474  SetChanged();
2475 
2476  for (const auto& rInteraction : aInteractionHandles)
2477  {
2478  try
2479  {
2480  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED )
2481  rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition );
2482  }
2483  catch ( const uno::RuntimeException& )
2484  {
2485  }
2486  }
2488 
2490  }
2491  return bRet;
2492 }
2493 
2495 {
2496  tools::Rectangle aNewTextRect = ImpCalculateTextFrame( true/*bHgt*/, true/*bWdt*/ );
2497  bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != maRect );
2498  if ( bRet )
2499  {
2500  tools::Rectangle aBoundRect0;
2501  if ( m_pUserCall )
2502  aBoundRect0 = GetCurrentBoundRect();
2503 
2504  // taking care of handles that should not been changed
2505  std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() );
2506 
2507  maRect = aNewTextRect;
2509 
2510  for (const auto& rInteraction : aInteractionHandles)
2511  {
2512  try
2513  {
2514  if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED )
2515  rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition );
2516  }
2517  catch ( const uno::RuntimeException& )
2518  {
2519  }
2520  }
2521 
2523  SetChanged();
2526  }
2527  return bRet;
2528 }
2529 void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, tools::Rectangle* pViewInit, tools::Rectangle* pViewMin) const
2530 {
2531  tools::Rectangle aViewInit;
2532  TakeTextAnchorRect( aViewInit );
2533  if (maGeo.nRotationAngle)
2534  {
2535  Point aCenter(aViewInit.Center());
2536  aCenter-=aViewInit.TopLeft();
2537  Point aCenter0(aCenter);
2539  aCenter-=aCenter0;
2540  aViewInit.Move(aCenter.X(),aCenter.Y());
2541  }
2542  Size aAnkSiz(aViewInit.GetSize());
2543  aAnkSiz.AdjustWidth( -1 ); aAnkSiz.AdjustHeight( -1 ); // because GetSize() adds 1
2544  Size aMaxSiz(1000000,1000000);
2545  {
2546  Size aTmpSiz(getSdrModelFromSdrObject().GetMaxObjSize());
2547  if (aTmpSiz.Width()!=0) aMaxSiz.setWidth(aTmpSiz.Width() );
2548  if (aTmpSiz.Height()!=0) aMaxSiz.setHeight(aTmpSiz.Height() );
2549  }
2552 
2553  tools::Long nMinWdt = GetMinTextFrameWidth();
2554  tools::Long nMinHgt = GetMinTextFrameHeight();
2555  tools::Long nMaxWdt = GetMaxTextFrameWidth();
2556  tools::Long nMaxHgt = GetMaxTextFrameHeight();
2557  if (nMinWdt<1) nMinWdt=1;
2558  if (nMinHgt<1) nMinHgt=1;
2559  if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() )
2560  nMaxWdt = aMaxSiz.Width();
2561  if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() )
2562  nMaxHgt=aMaxSiz.Height();
2563 
2565  {
2566  if ( IsVerticalWriting() )
2567  {
2568  nMaxHgt = aAnkSiz.Height();
2569  nMinHgt = nMaxHgt;
2570  }
2571  else
2572  {
2573  nMaxWdt = aAnkSiz.Width();
2574  nMinWdt = nMaxWdt;
2575  }
2576  }
2577  Size aPaperMax(nMaxWdt, nMaxHgt);
2578  Size aPaperMin(nMinWdt, nMinHgt);
2579 
2580  if ( pViewMin )
2581  {
2582  *pViewMin = aViewInit;
2583 
2584  tools::Long nXFree = aAnkSiz.Width() - aPaperMin.Width();
2585  if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2586  pViewMin->AdjustRight( -nXFree );
2587  else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2588  pViewMin->AdjustLeft(nXFree );
2589  else { pViewMin->AdjustLeft(nXFree / 2 ); pViewMin->SetRight( pViewMin->Left() + aPaperMin.Width() ); }
2590 
2591  tools::Long nYFree = aAnkSiz.Height() - aPaperMin.Height();
2592  if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2593  pViewMin->AdjustBottom( -nYFree );
2594  else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2595  pViewMin->AdjustTop(nYFree );
2596  else { pViewMin->AdjustTop(nYFree / 2 ); pViewMin->SetBottom( pViewMin->Top() + aPaperMin.Height() ); }
2597  }
2598 
2599  if( IsVerticalWriting() )
2600  aPaperMin.setWidth( 0 );
2601  else
2602  aPaperMin.setHeight( 0 );
2603 
2604  if( eHAdj != SDRTEXTHORZADJUST_BLOCK )
2605  aPaperMin.setWidth(0 );
2606 
2607  // For complete vertical adjust support, set paper min height to 0, here.
2608  if(SDRTEXTVERTADJUST_BLOCK != eVAdj )
2609  aPaperMin.setHeight( 0 );
2610 
2611  if (pPaperMin!=nullptr) *pPaperMin=aPaperMin;
2612  if (pPaperMax!=nullptr) *pPaperMax=aPaperMax;
2613  if (pViewInit!=nullptr) *pViewInit=aViewInit;
2614 }
2616 {
2617  SdrTextObj::EndTextEdit( rOutl );
2619 }
2621 {
2622  if ( GetTextBounds( rAnchorRect ) )
2623  {
2624  Point aRotateRef( maSnapRect.Center() );
2625  AdjustRectToTextDistance(rAnchorRect);
2626 
2627  if ( rAnchorRect.GetWidth() < 2 )
2628  rAnchorRect.SetRight( rAnchorRect.Left() + 1 ); // minimal width is 2
2629  if ( rAnchorRect.GetHeight() < 2 )
2630  rAnchorRect.SetBottom( rAnchorRect.Top() + 1 ); // minimal height is 2
2631  if (maGeo.nRotationAngle)
2632  {
2633  Point aP( rAnchorRect.TopLeft() );
2635  rAnchorRect.SetPos( aP );
2636  }
2637  }
2638  else
2639  SdrTextObj::TakeTextAnchorRect( rAnchorRect );
2640 }
2641 void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, tools::Rectangle& rTextRect, bool bNoEditText,
2642  tools::Rectangle* pAnchorRect, bool /*bLineWidth*/) const
2643 {
2644  tools::Rectangle aAnkRect; // Rect in which we anchor
2645  TakeTextAnchorRect(aAnkRect);
2648  EEControlBits nStat0=rOutliner.GetControlWord();
2649  Size aNullSize;
2650 
2651  rOutliner.SetControlWord(nStat0|EEControlBits::AUTOPAGESIZE);
2652  rOutliner.SetMinAutoPaperSize(aNullSize);
2653  sal_Int32 nMaxAutoPaperWidth = 1000000;
2654  sal_Int32 nMaxAutoPaperHeight= 1000000;
2655 
2656  tools::Long nAnkWdt=aAnkRect.GetWidth();
2657  tools::Long nAnkHgt=aAnkRect.GetHeight();
2658 
2660  {
2661  if ( IsVerticalWriting() )
2662  nMaxAutoPaperHeight = nAnkHgt;
2663  else
2664  nMaxAutoPaperWidth = nAnkWdt;
2665  }
2666  if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
2667  {
2668  rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
2669  }
2670 
2671  if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
2672  {
2673  rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
2674  }
2675  rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) );
2676  rOutliner.SetPaperSize( aNullSize );
2677 
2678  // put text into the Outliner - if necessary the use the text from the EditOutliner
2680  if (GetOutlinerParaObject())
2681  pPara = *GetOutlinerParaObject();
2682  if (mpEditingOutliner && !bNoEditText)
2684 
2685  if (pPara)
2686  {
2687  bool bHitTest(&getSdrModelFromSdrObject().GetHitTestOutliner() == &rOutliner);
2688  const SdrTextObj* pTestObj = rOutliner.GetTextObj();
2689 
2690  if( !pTestObj || !bHitTest || pTestObj != this ||
2691  pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() )
2692  {
2693  if( bHitTest )
2694  rOutliner.SetTextObj( this );
2695 
2696  rOutliner.SetUpdateLayout(true);
2697  rOutliner.SetText(*pPara);
2698  }
2699  }
2700  else
2701  {
2702  rOutliner.SetTextObj( nullptr );
2703  }
2704 
2705  rOutliner.SetUpdateLayout(true);
2706  rOutliner.SetControlWord(nStat0);
2707 
2708  SdrText* pText = getActiveText();
2709  if( pText )
2710  pText->CheckPortionInfo( rOutliner );
2711 
2712  Point aTextPos(aAnkRect.TopLeft());
2713  Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() has a little added tolerance, no?
2714 
2715  // For draw objects containing text correct horizontal/vertical alignment if text is bigger
2716  // than the object itself. Without that correction, the text would always be
2717  // formatted to the left edge (or top edge when vertical) of the draw object.
2718 
2719  if( !IsTextFrame() )
2720  {
2721  if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
2722  {
2723  // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
2724  // else the alignment is wanted.
2725  if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
2726  {
2727  SvxAdjust eAdjust = GetObjectItemSet().Get(EE_PARA_JUST).GetAdjust();
2728  switch (eAdjust)
2729  {
2730  case SvxAdjust::Left: eHAdj = SDRTEXTHORZADJUST_LEFT; break;
2731  case SvxAdjust::Right: eHAdj = SDRTEXTHORZADJUST_RIGHT; break;
2732  case SvxAdjust::Center: eHAdj = SDRTEXTHORZADJUST_CENTER; break;
2733  default: break;
2734  }
2735  }
2736  }
2737 
2738  if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
2739  {
2740  // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
2741  // else the alignment is wanted.
2742  if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
2743  {
2744  eVAdj = SDRTEXTVERTADJUST_CENTER;
2745  }
2746  }
2747  }
2748 
2750  {
2751  tools::Long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
2752  if (eHAdj==SDRTEXTHORZADJUST_CENTER)
2753  aTextPos.AdjustX(nFreeWdt/2 );
2754  if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
2755  aTextPos.AdjustX(nFreeWdt );
2756  }
2758  {
2759  tools::Long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
2760  if (eVAdj==SDRTEXTVERTADJUST_CENTER)
2761  aTextPos.AdjustY(nFreeHgt/2 );
2762  if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
2763  aTextPos.AdjustY(nFreeHgt );
2764  }
2765  if (maGeo.nRotationAngle != 0_deg100)
2767 
2768  if (pAnchorRect)
2769  *pAnchorRect=aAnkRect;
2770 
2771  // using rTextRect together with ContourFrame doesn't always work correctly
2772  rTextRect=tools::Rectangle(aTextPos,aTextSiz);
2773 }
2774 
2776 {
2777  SdrTextObj::NbcSetOutlinerParaObject( std::move(pTextObject) );
2781 }
2782 
2784 {
2785  return new SdrObjCustomShape(rTargetModel, *this);
2786 }
2787 
2789 {
2790  OUString sName(SvxResId(STR_ObjNameSingulCUSTOMSHAPE));
2791  OUString aNm(GetName());
2792  if (!aNm.isEmpty())
2793  sName += " '" + aNm + "'";
2794  return sName;
2795 }
2796 
2798 {
2799  return SvxResId(STR_ObjNamePluralCUSTOMSHAPE);
2800 }
2801 
2803 {
2804  return GetLineGeometry( false );
2805 }
2806 
2808 {
2809  const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
2810  if ( pSdrObject )
2811  return pSdrObject->TakeContour();
2812  return basegfx::B2DPolyPolygon();
2813 }
2814 
2816 {
2817  // #i37011#
2818  SdrObjectUniquePtr pRetval;
2819  SdrObject* pRenderedCustomShape = nullptr;
2820 
2821  if ( !mXRenderedCustomShape.is() )
2822  {
2823  // force CustomShape
2825  }
2826 
2827  if ( mXRenderedCustomShape.is() )
2828  {
2830  }
2831 
2832  if ( pRenderedCustomShape )
2833  {
2834  // Clone to same SdrModel
2835  SdrObject* pCandidate(pRenderedCustomShape->CloneSdrObject(pRenderedCustomShape->getSdrModelFromSdrObject()));
2836  DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)");
2837  pRetval = pCandidate->DoConvertToPolyObj(bBezier, bAddText);
2838  SdrObject::Free( pCandidate );
2839 
2840  if(pRetval)
2841  {
2842  const bool bShadow(GetMergedItem(SDRATTR_SHADOW).GetValue());
2843  if(bShadow)
2844  {
2845  pRetval->SetMergedItem(makeSdrShadowItem(true));
2846  }
2847  }
2848 
2849  if(bAddText && HasText() && !IsTextPath())
2850  {
2851  pRetval = ImpConvertAddText(std::move(pRetval), bBezier);
2852  }
2853  }
2854 
2855  return pRetval;
2856 }
2857 
2858 void SdrObjCustomShape::InternalSetStyleSheet( SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast )
2859 {
2860  // #i40944#
2862  SdrObject::InternalSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr, bBroadcast );
2863 }
2864 
2866 {
2867  // call parent
2868  SdrTextObj::handlePageChange(pOldPage, pNewPage);
2869 
2870  if(nullptr != pNewPage)
2871  {
2872  // invalidating rectangles by SetRectsDirty is not sufficient,
2873  // AdjustTextFrameWidthAndHeight() also has to be made, both
2874  // actions are done by NbcSetSnapRect
2875  tools::Rectangle aTmp( maRect ); //creating temporary rectangle #i61108#
2876  NbcSetSnapRect( aTmp );
2877  }
2878 }
2879 
2880 std::unique_ptr<SdrObjGeoData> SdrObjCustomShape::NewGeoData() const
2881 {
2882  return std::make_unique<SdrAShapeObjGeoData>();
2883 }
2884 
2886 {
2887  SdrTextObj::SaveGeoData( rGeo );
2888  SdrAShapeObjGeoData& rAGeo=static_cast<SdrAShapeObjGeoData&>(rGeo);
2890  rAGeo.bMirroredX = IsMirroredX();
2891  rAGeo.bMirroredY = IsMirroredY();
2892 
2893  const Any* pAny = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ).GetPropertyValueByName( "AdjustmentValues" );
2894  if ( pAny )
2895  *pAny >>= rAGeo.aAdjustmentSeq;
2896 }
2897 
2899 {
2901  const SdrAShapeObjGeoData& rAGeo=static_cast<const SdrAShapeObjGeoData&>(rGeo);
2903  SetMirroredX( rAGeo.bMirroredX );
2904  SetMirroredY( rAGeo.bMirroredY );
2905 
2907  PropertyValue aPropVal;
2908  aPropVal.Name = "AdjustmentValues";
2909  aPropVal.Value <<= rAGeo.aAdjustmentSeq;
2910  rGeometryItem.SetPropertyValue( aPropVal );
2911  SetMergedItem( rGeometryItem );
2912 
2914 }
2915 
2916 void SdrObjCustomShape::AdjustToMaxRect(const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */)
2917 {
2918  SAL_INFO_IF(bShrinkOnly, "svx", "Case bShrinkOnly == true is not implemented yet.");
2919 
2920  if (rMaxRect.IsEmpty() || rMaxRect == GetSnapRect())
2921  return;
2922 
2923  // Get a matrix, that would produce the existing shape, when applied to a unit square
2924  basegfx::B2DPolyPolygon aPolyPolygon; //not used, but formal needed
2925  basegfx::B2DHomMatrix aMatrix;
2926  TRGetBaseGeometry(aMatrix, aPolyPolygon);
2927  // Using TRSetBaseGeometry(aMatrix, aPolyPolygon) would regenerate the current shape. But
2928  // applying aMatrix to a unit square will not generate the current shape. Scaling,
2929  // rotation and translation are correct, but shear angle has wrong sign. So break up
2930  // matrix and create a mathematically correct new one.
2931  basegfx::B2DTuple aScale;
2932  basegfx::B2DTuple aTranslate;
2933  double fRotate, fShearX;
2934  aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
2935  basegfx::B2DHomMatrix aMathMatrix;
2937  aScale,
2938  basegfx::fTools::equalZero(fShearX) ? 0.0 : -fShearX,
2939  basegfx::fTools::equalZero(fRotate) ? 0.0 : fRotate,
2940  aTranslate);
2941 
2942  // Calculate scaling factors from size of the transformed unit polygon as ersatz for the not
2943  // usable current snap rectangle.
2945  aB2DPolygon.transform(aMathMatrix);
2946  basegfx::B2DRange aB2DRange(aB2DPolygon.getB2DRange());
2947  double fPolygonWidth = aB2DRange.getWidth();
2948  if (fPolygonWidth == 0)
2949  fPolygonWidth = 1;
2950  double fPolygonHeight = aB2DRange.getHeight();
2951  if (fPolygonHeight == 0)
2952  fPolygonHeight = 1;
2953  const double aFactorX = static_cast<double>(rMaxRect.GetWidth()) / fPolygonWidth;
2954  const double aFactorY = static_cast<double>(rMaxRect.GetHeight()) / fPolygonHeight;
2955 
2956  // Generate matrix, that would produce the desired rMaxRect when applied to unit square
2957  aMathMatrix.scale(aFactorX, aFactorY);
2958  aB2DPolygon = basegfx::utils::createUnitPolygon();
2959  aB2DPolygon.transform(aMathMatrix);
2960  aB2DRange = aB2DPolygon.getB2DRange();
2961  const double fPolygonLeft = aB2DRange.getMinX();
2962  const double fPolygonTop = aB2DRange.getMinY();
2963  aMathMatrix.translate(rMaxRect.Left() - fPolygonLeft, rMaxRect.Top() - fPolygonTop);
2964 
2965  // Create a Matrix from aMathMatrix, which is usable with TRSetBaseGeometry
2966  aMathMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
2968  aScale,
2969  basegfx::fTools::equalZero(fShearX) ? 0.0 : -fShearX,
2970  basegfx::fTools::equalZero(fRotate) ? 0.0 : fRotate,
2971  aTranslate);
2972 
2973  // Now use TRSetBaseGeometry to actually perform scale, shear, rotate and translate
2974  // on the shape. That considers gluepoints, interaction handles and text area, and includes
2975  // setting rectangles dirty and broadcast.
2976  TRSetBaseGeometry(aMatrix, aPolyPolygon);
2977 }
2978 
2980 {
2981  // The shape might have already flipping in its enhanced geometry. LibreOffice applies
2982  // such after all transformations. We remove it, but remember it to apply them later.
2983  bool bIsMirroredX = IsMirroredX();
2984  bool bIsMirroredY = IsMirroredY();
2985  if (bIsMirroredX || bIsMirroredY)
2986  {
2987  Point aCurrentCenter = GetSnapRect().Center();
2988  if (bIsMirroredX) // mirror on the y-axis
2989  {
2990  Mirror(aCurrentCenter, Point(aCurrentCenter.X(), aCurrentCenter.Y() + 1000));
2991  }
2992  if (bIsMirroredY) // mirror on the x-axis
2993  {
2994  Mirror(aCurrentCenter, Point(aCurrentCenter.X() + 1000, aCurrentCenter.Y()));
2995  }
2996  }
2997 
2998  // break up matrix
2999  basegfx::B2DTuple aScale;
3000  basegfx::B2DTuple aTranslate;
3001  double fRotate, fShearX;
3002  rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
3003 
3004  // reset object shear and rotations
3005  fObjectRotation = 0.0;
3006  maGeo.nRotationAngle = 0_deg100;
3007  maGeo.RecalcSinCos();
3008  maGeo.nShearAngle = 0_deg100;
3009  maGeo.RecalcTan();
3010 
3011  // if anchor is used, make position relative to it
3012  if(getSdrModelFromSdrObject().IsWriter())
3013  {
3014  if(GetAnchorPos().X() || GetAnchorPos().Y())
3015  {
3016  aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3017  }
3018  }
3019 
3020  // scale
3021  Size aSize(FRound(fabs(aScale.getX())), FRound(fabs(aScale.getY())));
3022  // fdo#47434 We need a valid rectangle here
3023  if( !aSize.Height() ) aSize.setHeight( 1 );
3024  if( !aSize.Width() ) aSize.setWidth( 1 );
3025  tools::Rectangle aBaseRect(Point(), aSize);
3026  SetLogicRect(aBaseRect);
3027 
3028  // Apply flipping from Matrix, which is a transformation relative to origin
3029  if (basegfx::fTools::less(aScale.getX(), 0.0))
3030  Mirror(Point(0, 0), Point(0, 1000)); // mirror on the y-axis
3031  if (basegfx::fTools::less(aScale.getY(), 0.0))
3032  Mirror(Point(0, 0), Point(1000, 0)); // mirror on the x-axis
3033 
3034  // shear?
3035  if(!basegfx::fTools::equalZero(fShearX))
3036  {
3037  GeoStat aGeoStat;
3038  // #i123181# The fix for #121932# here was wrong, the trunk version does not correct the
3039  // mirrored shear values, neither at the object level, nor on the API or XML level. Taking
3040  // back the mirroring of the shear angle
3041  aGeoStat.nShearAngle = Degree100(FRound(basegfx::rad2deg<100>(atan(fShearX))));
3042  aGeoStat.RecalcTan();
3043  Shear(Point(), aGeoStat.nShearAngle, aGeoStat.mfTanShearAngle, false);
3044  }
3045 
3046  // rotation?
3047  if(!basegfx::fTools::equalZero(fRotate))
3048  {
3049  GeoStat aGeoStat;
3050 
3051  // #i78696#
3052  // fRotate is mathematically correct, but aGeoStat.nRotationAngle is
3053  // mirrored -> mirror value here
3054  aGeoStat.nRotationAngle = NormAngle36000(Degree100(FRound(-basegfx::rad2deg<100>(fRotate))));
3055  aGeoStat.RecalcSinCos();
3056  Rotate(Point(), aGeoStat.nRotationAngle, aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle);
3057  }
3058 
3059  // translate?
3060  if(!aTranslate.equalZero())
3061  {
3062  Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
3063  }
3064 
3065  // Apply flipping from enhanced geometry at center of the shape.
3066  if (!(bIsMirroredX || bIsMirroredY))
3067  return;
3068 
3069  // create mathematically matrix for the applied transformations
3070  // aScale was in most cases built from a rectangle including edge
3071  // and is therefore mathematically too large by 1
3072  if (aScale.getX() > 2.0 && aScale.getY() > 2.0)
3073  aScale -= basegfx::B2DTuple(1.0, 1.0);
3075  aScale, -fShearX, basegfx::fTools::equalZero(fRotate) ? 0.0 : fRotate,
3076  aTranslate);
3077  // Use matrix to get current center
3078  basegfx::B2DPoint aCenter(0.5,0.5);
3079  aCenter = aMathMat * aCenter;
3080  double fCenterX = aCenter.getX();
3081  double fCenterY = aCenter.getY();
3082  if (bIsMirroredX) // vertical axis
3083  Mirror(Point(FRound(fCenterX),FRound(fCenterY)),
3084  Point(FRound(fCenterX), FRound(fCenterY + 1000.0)));
3085  if (bIsMirroredY) // horizontal axis
3086  Mirror(Point(FRound(fCenterX),FRound(fCenterY)),
3087  Point(FRound(fCenterX + 1000.0), FRound(fCenterY)));
3088 }
3089 
3090 // taking fObjectRotation instead of aGeo.nAngle
3092 {
3093  // get turn and shear
3094  double fRotate = basegfx::deg2rad(fObjectRotation);
3095  double fShearX = toRadians(maGeo.nShearAngle);
3096 
3097  // get aRect, this is the unrotated snaprect
3098  tools::Rectangle aRectangle(maRect);
3099 
3100  bool bMirroredX = IsMirroredX();
3101  bool bMirroredY = IsMirroredY();
3102  if ( bMirroredX || bMirroredY )
3103  { // we have to retrieve the unmirrored rect
3104 
3105  GeoStat aNewGeo(maGeo);
3106 
3107  if ( bMirroredX )
3108  {
3109  fShearX = -fShearX;
3110  tools::Polygon aPol = Rect2Poly(maRect, aNewGeo);
3111  tools::Rectangle aBoundRect( aPol.GetBoundRect() );
3112 
3113  Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() );
3114  Point aRef2( aRef1.X(), aRef1.Y() + 1000 );
3115  sal_uInt16 i;
3116  sal_uInt16 nPointCount=aPol.GetSize();
3117  for (i=0; i<nPointCount; i++)
3118  {
3119  MirrorPoint(aPol[i],aRef1,aRef2);
3120  }
3121  // mirror polygon and move it a bit
3122  tools::Polygon aPol0(aPol);
3123  aPol[0]=aPol0[1];
3124  aPol[1]=aPol0[0];
3125  aPol[2]=aPol0[3];
3126  aPol[3]=aPol0[2];
3127  aPol[4]=aPol0[1];
3128  Poly2Rect(aPol,aRectangle,aNewGeo);
3129  }
3130  if ( bMirroredY )
3131  {
3132  fShearX = -fShearX;
3133  tools::Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) );
3134  tools::Rectangle aBoundRect( aPol.GetBoundRect() );
3135 
3136  Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 );
3137  Point aRef2( aRef1.X() + 1000, aRef1.Y() );
3138  sal_uInt16 i;
3139  sal_uInt16 nPointCount=aPol.GetSize();
3140  for (i=0; i<nPointCount; i++)
3141  {
3142  MirrorPoint(aPol[i],aRef1,aRef2);
3143  }
3144  // mirror polygon and move it a bit
3145  tools::Polygon aPol0(aPol);
3146  aPol[0]=aPol0[1]; // This was WRONG for vertical (!)
3147  aPol[1]=aPol0[0]; // #i121932# Despite my own comment above
3148  aPol[2]=aPol0[3]; // it was *not* wrong even when the reordering
3149  aPol[3]=aPol0[2]; // *seems* to be specific for X-Mirrorings. Oh
3150  aPol[4]=aPol0[1]; // will I be happy when this old stuff is |gone| with aw080 (!)
3151  Poly2Rect(aPol,aRectangle,aNewGeo);
3152  }
3153  }
3154 
3155  // fill other values
3156  basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
3157  basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
3158 
3159  // position may be relative to anchorpos, convert
3161  {
3162  if(GetAnchorPos().X() || GetAnchorPos().Y())
3163  {
3164  aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3165  }
3166  }
3167 
3168  // build matrix
3170  aScale,
3171  basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
3172  basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
3173  aTranslate);
3174 
3175  return false;
3176 }
3177 
3178 std::unique_ptr<sdr::contact::ViewContact> SdrObjCustomShape::CreateObjectSpecificViewContact()
3179 {
3180  return std::make_unique<sdr::contact::ViewContactOfSdrObjCustomShape>(*this);
3181 }
3182 
3183 // #i33136#
3184 bool SdrObjCustomShape::doConstructOrthogonal(std::u16string_view rName)
3185 {
3186  bool bRetval(false);
3187 
3188  if(o3tl::equalsIgnoreAsciiCase(rName, u"quadrat"))
3189  {
3190  bRetval = true;
3191  }
3192  else if(o3tl::equalsIgnoreAsciiCase(rName, u"round-quadrat"))
3193  {
3194  bRetval = true;
3195  }
3196  else if(o3tl::equalsIgnoreAsciiCase(rName, u"circle"))
3197  {
3198  bRetval = true;
3199  }
3200  else if(o3tl::equalsIgnoreAsciiCase(rName, u"circle-pie"))
3201  {
3202  bRetval = true;
3203  }
3204  else if(o3tl::equalsIgnoreAsciiCase(rName, u"ring"))
3205  {
3206  bRetval = true;
3207  }
3208 
3209  return bRetval;
3210 }
3211 
3212 // #i37011# centralize throw-away of render geometry
3214 {
3215  mXRenderedCustomShape = nullptr;
3217  mpLastShadowGeometry = nullptr;
3218 }
3219 
3220 void SdrObjCustomShape::setUnoShape(const uno::Reference<drawing::XShape>& rxUnoShape)
3221 {
3222  SdrTextObj::setUnoShape(rxUnoShape);
3223 
3224  // The shape engine is created with _current_ shape. This means we
3225  // _must_ reset it when the shape changes.
3226  mxCustomShapeEngine.set(nullptr);
3227 }
3228 
3230 {
3231  OUString sShapeName;
3232  OUString aEngine( GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue() );
3233  if ( aEngine.isEmpty()
3234  || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" )
3235  {
3236  OUString sShapeType;
3238  const Any* pAny = rGeometryItem.GetPropertyValueByName( "Type" );
3239  if ( pAny && ( *pAny >>= sShapeType ) )
3240  sShapeName = EnhancedCustomShapeTypeNames::GetAccName( sShapeType );
3241  }
3242  return sShapeName;
3243 }
3244 
3245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void Shear(const Point &rRef, Degree100 nAngle, double tn, bool bVShear)
Definition: svdobj.cxx:1594
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_TEXT_AUTOGROWHEIGHT(SDRATTR_MISC_FIRST+2)
void SetPos(const Point &rPoint)
tools::Long GetTextLowerDistance() const
Bottom inner spacing to borders.
Definition: svdotext.cxx:1752
tools::Rectangle ImpCalculateTextFrame(const bool bHgt, const bool bWdt)
Definition: svdoashp.cxx:2430
double getY() const
virtual void NbcSetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject) override
Definition: svdotext.cxx:1339
void SetPropertyValue(const css::beans::PropertyValue &rPropVal)
uno::Reference< drawing::XShape > GetXShapeForSdrObject(SdrObject *pObj) noexcept
returns a StarOffice API wrapper for the given SdrObject
Definition: unoshape.cxx:4011
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const
Definition: svdobj.cxx:654
constexpr TypedWhichId< SdrTextHorzAdjustItem > SDRATTR_TEXT_HORZADJUST(SDRATTR_MISC_FIRST+13)
virtual void NbcResize(const Point &rRef, const Fraction &xFact, const Fraction &yFact) override
Definition: svdotxtr.cxx:102
SdrMetricItem makeSdrShadowYDistItem(tools::Long nDist)
Definition: sdsxyitm.hxx:30
constexpr TypedWhichId< SdrPercentItem > SDRATTR_SHADOWTRANSPARENCE(SDRATTR_SHADOW_FIRST+4)
virtual SdrObjCustomShape * CloneSdrObject(SdrModel &rTargetModel) const override
Definition: svdoashp.cxx:2783
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:949
SVX_DLLPRIVATE void DragCreateObject(SdrDragStat &rDrag)
Definition: svdoashp.cxx:2103
tools::Long GetDX() const
Definition: svddrag.hxx:158
void ShearPoint(Point &rPnt, const Point &rRef, double tn, bool bVShear=false)
Definition: svdtrans.hxx:109
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
void setWidth(tools::Long nWidth)
void ForceOutlinerParaObject()
Definition: svdotext.cxx:1449
B2DPolygon const & createUnitPolygon()
std::string GetValue
bool m_bClosedObj
Definition: svdobj.hxx:902
bool equalZero(const T &rfVal)
sal_Int32 ImpGetLineWdt() const
Detects the width of the line. No line ->0.
Definition: svdoattr.cxx:78
tools::Long GetDY() const
Definition: svddrag.hxx:159
constexpr double deg2rad(double v)
constexpr tools::Long Left() const
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_TEXT_AUTOGROWWIDTH(SDRATTR_MISC_FIRST+12)
const Point & GetStart() const
Definition: svddrag.hxx:102
SdrHdlKind
Definition: svdhdl.hxx:52
std::unique_ptr< sal_Int32[]> pData
constexpr Point RightCenter() const
void SetPaperSize(const Size &rSize)
tools::Long GetTextLeftDistance() const
Left inner spacing to borders.
Definition: svdotext.cxx:1737
SdrTextHorzAdjust
Definition: sdtaitm.hxx:53
void Poly2Rect(const tools::Polygon &rPol, tools::Rectangle &rRect, GeoStat &rGeo)
Definition: svdtrans.cxx:480
#define SAL_INFO_IF(condition, area, stream)
long Long
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
static bool doConstructOrthogonal(std::u16string_view rName)
Definition: svdoashp.cxx:3184
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterface > &xInt)
Definition: unoshape.cxx:4018
virtual std::unique_ptr< sdr::contact::ViewContact > CreateObjectSpecificViewContact() override
Definition: svdoashp.cxx:3178
constexpr TypedWhichId< XFillStyleItem > XATTR_FILLSTYLE(XATTR_FILL_FIRST)
virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const
Definition: svdobj.cxx:2638
bool IsTextFrame() const
Definition: svdotext.hxx:334
virtual void NbcShear(const Point &rRef, Degree100 nAngle, double tn, bool bVShear) override
Definition: svdoashp.cxx:1669
static sal_Int32 GetNumberOfProperties(const SvxMSDffHandle *pData)
Definition: svdoashp.cxx:655
sal_Int64 n
double mfSinRotationAngle
Definition: svdtrans.hxx:206
virtual void Move(const Size &rSiz) override
Definition: svdoashp.cxx:1465
SvxMSDffVertPair * pVertices
sal_uInt32 GetPointNum() const
Definition: svdhdl.hxx:222
virtual sal_uInt32 GetHdlCount() const override
Via GetHdlCount the number of Handles can be retrieved.
Definition: svdotxdr.cxx:36
virtual void SetBoundRectDirty()
Definition: svdobj.cxx:316
virtual void AdaptTextMinSize() override
Definition: svdoashp.cxx:1378
virtual basegfx::B2DPolyPolygon TakeContour() const override
contour for TextToContour
Definition: svdoashp.cxx:2807
virtual void SaveGeoData(SdrObjGeoData &rGeo) const override
Definition: svdoashp.cxx:2885
virtual void NbcSetLogicRect(const tools::Rectangle &rRect) override
Definition: svdoashp.cxx:1443
SdrObjectUniquePtr ImpConvertAddText(SdrObjectUniquePtr pObj, bool bBezier) const
Definition: svdotxtr.cxx:457
constexpr TypedWhichId< XLineStyleItem > XATTR_LINESTYLE(XATTR_LINE_FIRST)
virtual bool MovCreate(SdrDragStat &rStat) override
Definition: svdoashp.cxx:2146
sal_uInt32 GetTextHeight() const
tools::Long GetMinTextFrameHeight() const
Definition: svdotext.cxx:1699
constexpr Point BottomCenter() const
void CheckPortionInfo(const SdrOutliner &rOutliner)
Definition: svdtext.cxx:42
constexpr TypedWhichId< SvxAdjustItem > EE_PARA_JUST(EE_PARA_START+15)
virtual std::unique_ptr< SdrObjGeoData > NewGeoData() const override
A derived class must override these 3 methods if it has own geometric data that must be saved for Und...
Definition: svdoashp.cxx:2880
tools::Rectangle m_aOutRect
Definition: svdobj.hxx:882
constexpr TypedWhichId< XFillHatchItem > XATTR_FILLHATCH(XATTR_FILL_FIRST+3)
virtual bool EndCreate(SdrDragStat &rStat, SdrCreateCmd eCmd) override
Definition: svdoashp.cxx:2158
static void Free(SdrObject *&_rpObject)
Definition: svdobj.cxx:471
sal_uInt16 GetCount() const
Definition: svdglue.hxx:194
void RecalcTan()
Definition: svdtrans.cxx:456
virtual const tools::Rectangle & GetSnapRect() const override
Definition: svdoattr.cxx:49
EEControlBits
All geometrical data of an arbitrary object for use in undo/redo.
Definition: svdobj.hxx:173
virtual std::unique_ptr< sdr::properties::BaseProperties > CreateObjectSpecificProperties() override
Definition: svdoashp.cxx:787
virtual void EndTextEdit(SdrOutliner &rOutl)
Definition: svdotxed.cxx:264
SdrObjCustomShape(SdrModel &rSdrModel)
Definition: svdoashp.cxx:792
virtual bool HasText() const override
Definition: svdotxat.cxx:418
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const override
Definition: svdoashp.cxx:1313
virtual void NbcMirror(const Point &rRef1, const Point &rRef2) override
Definition: svdotxtr.cxx:232
SdrObjKind
Definition: svdobjkind.hxx:24
SVXCORE_DLLPUBLIC const OUString & GetAccName(const OUString &)
bool IsCustomShapeFilledByDefault(MSO_SPT eSpType)
bool equalZero() const
tools::Long getHeight() const
tools::Long GetMaxTextFrameHeight() const
Definition: svdotext.cxx:1704
constexpr tools::Long Width() const
Provides information about various ZObject properties.
Definition: svdobj.hxx:195
void SetColor(const Color &rColor)
Definition: xhatch.hxx:47
SvxMSDffVertPair * pGluePoints
const SdrHdl * GetHdl() const
Definition: svddrag.hxx:111
SdrMetricItem makeSdrTextMinFrameWidthItem(tools::Long mnWidth)
Definition: sdtmfitm.hxx:35
virtual bool hasSpecialDrag() const override
The standard transformations (Move,Resize,Rotate,Mirror,Shear) are taken over by the View (TakeXorPol...
Definition: svdoashp.cxx:1880
void SetControlWord(EEControlBits nWord)
bool IsMore() const
Definition: svditer.hxx:62
MSO_SPT
Definition: msdffdef.hxx:274
bool IsMirroredX() const
Definition: svdoashp.cxx:471
virtual void SaveGeoData(SdrObjGeoData &rGeo) const override
Definition: svdotext.cxx:1417
B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:201
int nCount
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
constexpr Point TopCenter() const
bool LineIsOutsideGeometry() const
Definition: svdobj.hxx:846
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
virtual void SetLogicRect(const tools::Rectangle &rRect) override
Definition: svdoashp.cxx:1455
const SfxItemSet & GetObjectItemSet() const
Definition: svdobj.cxx:1967
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_TEXT_WORDWRAP(SDRATTR_MISC_FIRST+24)
tools::Rectangle maRect
Definition: svdotext.hxx:170
constexpr TypedWhichId< XColorItem > SDRATTR_SHADOWCOLOR(SDRATTR_SHADOW_FIRST+1)
constexpr tools::Long GetWidth() const
void SetFixedCellHeight(bool bUseFixedCellHeight)
void GetOOXHandleAdjRelation(std::u16string_view sFullOOXShapeName, const sal_Int32 nHandleIndex, OUString &rFirstRefType, sal_Int32 &rFirstAdjValueIndex, OUString &rSecondRefType, sal_Int32 &rSecondAdjValueIndex)
void TakeCreateRect(tools::Rectangle &rRect) const
Definition: svddrag.cxx:115
tools::Long GetMaxTextFrameWidth() const
Definition: svdotext.cxx:1714
static SdrObject * ImpCreateShadowObjectClone(const SdrObject &rOriginal, const SfxItemSet &rOriginalSet)
Definition: svdoashp.cxx:210
virtual void NbcShear(const Point &rRef, Degree100 nAngle, double tn, bool bVShear) override
Definition: svdotxtr.cxx:210
EEControlBits GetControlWord() const
const GeoStat & GetGeoStat() const
Definition: svdotext.hxx:392
tools::Rectangle maSnapRect
Definition: svdoattr.hxx:41
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_SHADOW(SDRATTR_SHADOW_FIRST+0)
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
double GetExtraTextRotation(const bool bPreRotation=false) const
Definition: svdoashp.cxx:508
virtual bool IsAutoGrowWidth() const override
Definition: svdoashp.cxx:2184
void MergeDefaultAttributes(const OUString *pType=nullptr)
Definition: svdoashp.cxx:823
double mfTanShearAngle
Definition: svdtrans.hxx:205
virtual void handlePageChange(SdrPage *pOldPage, SdrPage *pNewPage) override
Definition: svdoashp.cxx:2865
virtual void SetBoundAndSnapRectsDirty(bool bNotMyself=false, bool bRecursive=true)
Definition: svdobj.cxx:510
css::awt::Point aPosition
Definition: svdoashp.hxx:70
tools::Rectangle ImpDragCalcRect(const SdrDragStat &rDrag) const
Definition: svdotxdr.cxx:72
constexpr bool IsEmpty() const
void Rotate(const Point &rCenter, double fSin, double fCos)
SvxMSDffTextRectangles * pTextRect
virtual void RestoreGeoData(const SdrObjGeoData &rGeo) override
Definition: svdoashp.cxx:2898
virtual bool IsAutoGrowHeight() const override
Definition: svdoashp.cxx:2176
SvxMSDffHandleFlags nFlags
static void lcl_ShapePropertiesFromDFF(const SvxMSDffHandle *pData, css::beans::PropertyValues &rPropValues)
Definition: svdoashp.cxx:692
const SfxPoolItem & GetObjectItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:2002
virtual SdrGluePoint GetVertexGluePoint(sal_uInt16 nNum) const override
Definition: svdoashp.cxx:1699
virtual void AdjustToMaxRect(const tools::Rectangle &rMaxRect, bool bShrinkOnly=false) override
Definition: svdoashp.cxx:2916
SdrTextHorzAdjust GetTextHorizontalAdjust() const
Definition: svdotext.cxx:356
bool mbTextFrame
Definition: svdotext.hxx:219
virtual void TakeTextRect(SdrOutliner &rOutliner, tools::Rectangle &rTextRect, bool bNoEditText, tools::Rectangle *pAnchorRect, bool bLineWidth=true) const override
Definition: svdoashp.cxx:2641
constexpr TypedWhichId< SvxWritingModeItem > SDRATTR_TEXTDIRECTION(SDRATTR_NOTPERSIST_FIRST+34)
void SetNoSnap(bool bOn=true)
Definition: svddrag.hxx:131
virtual void handlePageChange(SdrPage *pOldPage, SdrPage *pNewPage) override
Definition: svdotext.cxx:490
CustomShapeHandleModes
Definition: svdoashp.hxx:50
Right
void SetEndDragChangesGeoAndAttributes(bool bOn)
Definition: svddrag.hxx:145
SdrTextVertAdjust GetTextVerticalAdjust() const
Definition: svdotext.cxx:388
virtual const SdrGluePointList * GetGluePointList() const
Definition: svdobj.cxx:2310
OptionalString sType
bool IsEmpty() const
static OUString GetEquation(const sal_uInt16 nFlags, sal_Int32 nPara1, sal_Int32 nPara2, sal_Int32 nPara3)
void SetText(const OutlinerParaObject &)
constexpr TypedWhichId< XFillGradientItem > XATTR_FILLGRADIENT(XATTR_FILL_FIRST+2)
#define DBG_ASSERT(sCon, aError)
virtual void NbcSetSnapRect(const tools::Rectangle &rRect) override
Definition: svdoashp.cxx:1420
virtual void NbcSetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject) override
Definition: svdoashp.cxx:2775
SvxAdjust
constexpr TypedWhichId< SdrCustomShapeGeometryItem > SDRATTR_CUSTOMSHAPE_GEOMETRY(SDRATTR_CUSTOMSHAPE_FIRST+2)
int i
uno_Any a
virtual void TakeTextAnchorRect(tools::Rectangle &rAnchorRect) const override
Definition: svdoashp.cxx:2620
bool IsWriter() const
Definition: svdmodel.hxx:582
constexpr TypedWhichId< XFillBitmapItem > XATTR_FILLBITMAP(XATTR_FILL_FIRST+4)
virtual void InternalSetStyleSheet(SfxStyleSheet *pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast)
Definition: svdobj.cxx:2265
OUString sName
SdrOutliner * mpEditingOutliner
Definition: svdotext.hxx:184
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
tools::Long FRound(double fVal)
void SetVertical(bool bNew)
virtual void SetVerticalWriting(bool bVertical) override
Definition: svdoashp.cxx:2197
B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(const css::drawing::PolyPolygonBezierCoords &rPolyPolygonBezierCoordsSource)
virtual void NbcResize(const Point &rRef, const Fraction &xFact, const Fraction &yFact) override
Definition: svdoashp.cxx:1500
SvxMSDffCalculationData * pCalculation
virtual void TakeTextEditArea(Size *pPaperMin, Size *pPaperMax, tools::Rectangle *pViewInit, tools::Rectangle *pViewMin) const override
Definition: svdoashp.cxx:2529
void BroadcastObjectChange() const
Definition: svdobj.cxx:1001
constexpr TypedWhichId< SdrTextVertAdjustItem > SDRATTR_TEXT_VERTADJUST(SDRATTR_MISC_FIRST+8)
sal_Int32 GetPointCount() const
Definition: svddrag.hxx:101
void MirrorPoint(Point &rPnt, const Point &rRef1, const Point &rRef2)
Definition: svdtrans.cxx:105
void ActionChanged() const
Definition: svdobj.cxx:263
virtual void EndTextEdit(SdrOutliner &rOutl) override
Definition: svdoashp.cxx:2615
SdrView * GetView() const
Definition: svddrag.hxx:96
constexpr tools::Long Right() const
bool IsDefaultGeometry(const DefaultType eDefaultType) const
Definition: svdoashp.cxx:1098
float u
virtual basegfx::B2DPolyPolygon TakeContour() const
contour for TextToContour
Definition: svdobj.cxx:1128
Universal Network Object packed into SvDraw object.
void scale(double fX, double fY)
constexpr TypedWhichId< SdrMetricItem > SDRATTR_TEXT_MINFRAMEWIDTH(SDRATTR_MISC_FIRST+10)
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:279
virtual sal_uInt32 GetHdlCount() const override
Via GetHdlCount the number of Handles can be retrieved.
Definition: svdoashp.cxx:1849
SdrObjUserCall * m_pUserCall
Definition: svdobj.hxx:884
bool createItemIfMissing(const OUString &sKey, const TValueType &aValue)
void SetUserDefined(bool bNew)
Definition: svdglue.hxx:136
constexpr TypedWhichId< SdrMetricItem > SDRATTR_SHADOWYDIST(SDRATTR_SHADOW_FIRST+3)
virtual void TakeTextAnchorRect(::tools::Rectangle &rAnchorRect) const
Definition: svdotext.cxx:667
void SetPercent(bool bOn)
Definition: svdglue.hxx:124
constexpr tools::Long Top() const
virtual bool TRGetBaseGeometry(basegfx::B2DHomMatrix &rMatrix, basegfx::B2DPolyPolygon &rPolyPolygon) const override
Definition: svdoashp.cxx:3091
virtual basegfx::B2DPolyPolygon TakeXorPoly() const override
The Xor-Polygon is required by the View to drag the object.
Definition: svdoashp.cxx:2802
size
static void SetEnhancedCustomShapeParameter(css::drawing::EnhancedCustomShapeParameter &rParameter, const sal_Int32 nValue)
sal_uInt16 GetSize() const
virtual void AddToHdlList(SdrHdlList &rHdlList) const override
Definition: svdoashp.cxx:1855
tools::Polygon Rect2Poly(const tools::Rectangle &rRect, const GeoStat &rGeo)
Definition: svdtrans.cxx:467
double toRadians(D x)
constexpr void SetRight(tools::Long v)
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1982
const SdrObject * GetSdrObjectShadowFromCustomShape() const
Definition: svdoashp.cxx:423
virtual void NbcMove(const Size &rSiz) override
The methods Move, Resize, Rotate, Mirror, Shear, SetSnapRect and SetLogicRect call the corresponding ...
Definition: svdotxtr.cxx:94
void SetEndDragChangesAttributes(bool bOn)
Definition: svddrag.hxx:143
virtual void NbcRotate(const Point &rRef, Degree100 nAngle, double sn, double cs) override
Definition: svdotxtr.cxx:186
constexpr void SetBottom(tools::Long v)
constexpr TypedWhichId< SdrMetricItem > SDRATTR_TEXT_MINFRAMEHEIGHT(SDRATTR_MISC_FIRST+1)
virtual SdrText * getActiveText() const
returns the currently active text.
Definition: svdotext.cxx:2065
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:2007
std::optional< OutlinerParaObject > CreateParaObject(sal_Int32 nStartPara=0, sal_Int32 nParaCount=EE_PARA_ALL) const
bool IsShiftPressed() const
Definition: svddrgmt.hxx:195
Abstract DrawObject.
Definition: svdobj.hxx:259
css::uno::Reference< css::drawing::XCustomShapeHandle > xInteraction
Definition: svdoashp.hxx:69
SfxItemPool * GetPool() const
virtual void SetSnapRect(const tools::Rectangle &rRect) override
Definition: svdoashp.cxx:1433
void ImpCheckShear()
Definition: svdotext.cxx:430
virtual void setUnoShape(const css::uno::Reference< css::drawing::XShape > &_rxUnoShape)
Sets a new UNO representation of the shape.
Definition: svdobj.cxx:2823
constexpr Point LeftCenter() const
virtual bool applySpecialDrag(SdrDragStat &rDrag) override
Definition: svdoashp.cxx:2062
virtual void Mirror(const Point &rRef1, const Point &rRef2)
Definition: svdobj.cxx:1585
SdrObject * mpLastShadowGeometry
Definition: svdoashp.hxx:96
#define DEFAULT_MAXIMUM_SIGNED_COMPARE
Definition: svdoashp.cxx:653
static void lcl_ShapeSegmentFromBinary(EnhancedCustomShapeSegment &rSegInfo, sal_uInt16 nSDat)
Definition: svdoashp.cxx:96
#define Y
CustomShapeHandleModes nMode
Definition: svdoashp.hxx:71
Degree100 NormAngle36000(Degree100 a)
Normalize angle to -180.00..179.99.
Definition: svdtrans.cxx:408
tools::Long GetMinTextFrameWidth() const
Definition: svdotext.cxx:1709
constexpr Point Center() const
void transform(const basegfx::B2DHomMatrix &rMatrix)
constexpr Point TopLeft() const
void SuggestTextFrameSize(Size aSuggestedTextFrameSize)
Allows suggesting the text frame size: in case the application has its own text associated to the sha...
Definition: svdoashp.cxx:2253
tools::Long AdjustTop(tools::Long nVertMoveDelta)
css::uno::Reference< css::drawing::XShape > mXRenderedCustomShape
Definition: svdoashp.hxx:91
virtual void Shear(const Point &rRef, Degree100 nAngle, double tn, bool bVShear) override
Definition: svdoashp.cxx:1664
SdrDragMethod * GetDragMethod() const
Definition: svddrag.hxx:163
void DragMoveCustomShapeHdl(const Point &rDestination, const sal_uInt16 nCustomShapeHdlNum, bool bMoveCalloutRectangle)
Definition: svdoashp.cxx:2021
virtual bool NbcAdjustTextFrameWidthAndHeight(bool bHgt=true, bool bWdt=true) override
Definition: svdoashp.cxx:2461
sal_uInt16 Insert(const SdrGluePoint &rGP)
Definition: svdglue.cxx:295
constexpr tools::Long Bottom() const
tools::Long GetTextRightDistance() const
Right inner spacing to borders.
Definition: svdotext.cxx:1742
basegfx::B2DPolyPolygon GetLineGeometry(const bool bBezierAllowed) const
Definition: svdoashp.cxx:535
const SdrObject * GetSdrObjectFromCustomShape() const
Definition: svdoashp.cxx:408
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdoashp.cxx:1371
B2DRange const & getB2DRange() const
virtual const tools::Rectangle & GetLastBoundRect() const
Definition: svdobj.cxx:963
SdrObject * Next()
Definition: svditer.hxx:63
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
constexpr TypedWhichId< SdrMetricItem > SDRATTR_SHADOWXDIST(SDRATTR_SHADOW_FIRST+2)
OUString GetCustomShapeName() const
Definition: svdoashp.cxx:3229
void RotatePoint(Point &rPnt, const Point &rRef, double sn, double cs)
Definition: svdtrans.hxx:101
void SetActionRect(const tools::Rectangle &rR)
Definition: svddrag.hxx:167
virtual void NbcRotate(const Point &rRef, Degree100 nAngle, double sn, double cs) override
Definition: svdoashp.cxx:1575
bool IsEffectivelyVertical() const
constexpr Size GetSize() const
virtual bool IsVerticalWriting() const
Definition: svdotext.cxx:1470
tools::Long GetTextUpperDistance() const
Top inner spacing to borders.
Definition: svdotext.cxx:1747
void SetMaxAutoPaperSize(const Size &rSz)
void ImpCheckCustomGluePointsAreAdded()
Definition: svdoashp.cxx:1727
sal_Int32 GetDenominator() const
B2DPolygon adaptiveSubdivideByAngle(const B2DPolygon &rCandidate, double fAngleBound)
virtual SdrGluePointList * ForceGluePointList()
Definition: svdobj.cxx:2317
bool UseNoFillStyle() const
Definition: svdoashp.cxx:457
virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix &rMatrix, const basegfx::B2DPolyPolygon &rPolyPolygon) override
Definition: svdoashp.cxx:2979
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
constexpr tools::Long Height() const
unsigned char sal_uInt8
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1330
void RecalcSinCos()
Definition: svdtrans.cxx:444
SdrMetricItem makeSdrShadowXDistItem(tools::Long nDist)
Definition: sdsxyitm.hxx:25
void SetObjectItemSet(const SfxItemSet &rSet)
Definition: svdobj.cxx:1992
SdrMetricItem makeSdrTextMinFrameHeightItem(tools::Long mnHeight)
Definition: sdtmfitm.hxx:25
GeoStat maGeo
Definition: svdotext.hxx:173
bool less(const T &rfValA, const T &rfValB)
virtual void NbcMove(const Size &rSiz)
The methods Move, Resize, Rotate, Mirror, Shear, SetSnapRect and SetLogicRect call the corresponding ...
Definition: svdobj.cxx:1427
eFillStyle
Definition: fillctrl.cxx:53
State
Degree100 nRotationAngle
Definition: svdtrans.hxx:203
bool IsSolidDragging() const
Definition: svddrgv.cxx:912
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1972
void SetMirroredX(const bool bMirroredX)
Definition: svdoashp.cxx:489
void SetMinAutoPaperSize(const Size &rSz)
bool IsTextPath() const
Definition: svdoashp.cxx:446
tools::Long AdjustWidth(tools::Long n)
double mfCosRotationAngle
Definition: svdtrans.hxx:207
virtual bool beginSpecialDrag(SdrDragStat &rDrag) const override
Definition: svdoashp.cxx:1885
static MSO_SPT ImpGetCustomShapeType(const SdrObjCustomShape &rCustoShape)
Definition: svdoashp.cxx:174
virtual SdrObject * CloneSdrObject(SdrModel &rTargetModel) const
Definition: svdobj.cxx:1070
virtual const SdrGluePointList * GetGluePointList() const override
Definition: svdoashp.cxx:1828
virtual OUString TakeObjNameSingul() const override
Definition: svdoashp.cxx:2788
static void SetEnhancedCustomShapeHandleParameter(css::drawing::EnhancedCustomShapeParameter &rParameter, const sal_Int32 nPara, const bool bIsSpecialValue, bool bHorz)
Size m_aSuggestedTextFrameSize
Definition: svdoashp.hxx:129
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
#define DEFAULT_MINIMUM_SIGNED_COMPARE
Definition: svdoashp.cxx:652
void SetMirroredY(const bool bMirroredY)
Definition: svdoashp.cxx:498
sal_Int32 GetNumerator() const
bool GetTextBounds(tools::Rectangle &rTextBound) const
Definition: svdoashp.cxx:519
css::uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq
Definition: svdoashp.hxx:47
virtual void RestoreGeoData(const SdrObjGeoData &rGeo) override
Definition: svdotext.cxx:1425
std::unique_ptr< SdrObject, SdrObjectFreeOp > SdrObjectUniquePtr
Definition: svdobj.hxx:97
virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const override
Definition: svdoashp.cxx:2815
SdrOnOffItem makeSdrShadowItem(bool bShadow)
Definition: sdshitm.hxx:25
const Point & GetPos() const
Definition: svdglue.hxx:96
const Point & GetNow() const
Definition: svddrag.hxx:105
bool SetUpdateLayout(bool bUpdate)
void translate(double fX, double fY)
static bool ImpVerticalSwitch(const SdrObjCustomShape &rCustoShape)
Definition: svdoashp.cxx:190
virtual void InternalSetStyleSheet(SfxStyleSheet *pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast) override
Definition: svdoashp.cxx:2858
constexpr TypedWhichId< SdrTextFixedCellHeightItem > SDRATTR_TEXT_USEFIXEDCELLHEIGHT(SDRATTR_MISC_FIRST+23)
const Point & GetAnchorPos() const
Definition: svdobj.cxx:1651
constexpr TypedWhichId< SfxInt16Item > SDRATTR_TEXTCOLUMNS_NUMBER(SDRATTR_TEXTCOLUMNS_FIRST+0)
virtual OUString TakeObjNamePlural() const override
Definition: svdoashp.cxx:2797
css::uno::Any * GetPropertyValueByName(const OUString &rPropName)
virtual void Rotate(const Point &rRef, Degree100 nAngle, double sn, double cs)
Definition: svdobj.cxx:1574
void AdjustRectToTextDistance(tools::Rectangle &rAnchorRect) const
Definition: svdotext.cxx:634
virtual void setUnoShape(const css::uno::Reference< css::drawing::XShape > &rxUnoShape) override
Sets a new UNO representation of the shape.
Definition: svdoashp.cxx:3220
double toDegrees(D x)
void setHeight(tools::Long nHeight)
SVX_DLLPRIVATE void DragResizeCustomShape(const tools::Rectangle &rNewRect)
Definition: svdoashp.cxx:1923
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
virtual bool AdjustTextFrameWidthAndHeight() override
Definition: svdoashp.cxx:2494
void SetTextObj(const SdrTextObj *pObj)
Definition: svdoutl.cxx:40
bool IsUserDefined() const
Definition: svdglue.hxx:132
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
const mso_CustomShape * GetCustomShapeContent(MSO_SPT eSpType)
css::uno::Reference< css::drawing::XCustomShapeEngine > const & GetCustomShapeEngine() const
Definition: svdoashp.cxx:373
double getX() const
SVXCORE_DLLPUBLIC MSO_SPT Get(const OUString &)
bool m_bSnapRectDirty
Definition: svdobj.hxx:889
double fObjectRotation
Definition: svdoashp.hxx:45
tools::Rectangle GetBoundRect() const
css::uno::Reference< css::drawing::XCustomShapeEngine > mxCustomShapeEngine
Definition: svdoashp.hxx:93
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:373
Left
const SdrTextObj * GetTextObj() const
Definition: svdoutl.cxx:87
void Clear()
bool areControlPointsUsed() const
virtual SdrGluePointList * ForceGluePointList() override
Definition: svdoashp.cxx:1835
SdrCreateCmd
Definition: svdtypes.hxx:26
virtual void SetChanged()
Definition: svdobj.cxx:1025
std::unique_ptr< SdrObjPlusData > m_pPlusData
Definition: svdobj.hxx:886
virtual void NbcMove(const Size &rSiz) override
The methods Move, Resize, Rotate, Mirror, Shear, SetSnapRect and SetLogicRect call the corresponding ...
Definition: svdoashp.cxx:1478
bool IsMirroredY() const
Definition: svdoashp.cxx:480
static void ImpJustifyRect(tools::Rectangle &rRect)
Definition: svdotext.cxx:421
SdrOutliner & ImpGetDrawOutliner() const
Definition: svdotext.cxx:1164
const OUString & GetName() const
Definition: svdobj.cxx:792
Size CalcTextSize()
virtual void NbcMirror(const Point &rRef1, const Point &rRef2) override
Definition: svdoashp.cxx:1619
bool mbAdjustingTextFrameWidthAndHeight
Definition: svdoashp.hxx:79
Degree100 nShearAngle
Definition: svdtrans.hxx:204
virtual basegfx::B2DPolyPolygon TakeCreatePoly(const SdrDragStat &rDrag) const override
Polygon dragged by the user when creating the object.
Definition: svdoashp.cxx:2168
virtual void AddToHdlList(SdrHdlList &rHdlList) const override
Definition: svdotxdr.cxx:41
double fObjectRotation
Definition: svdoashp.hxx:78
SdrTextVertAdjust
Definition: sdtaitm.hxx:29
void SendUserCall(SdrUserCallType eUserCall, const tools::Rectangle &rBoundRect) const
Definition: svdobj.cxx:2762
void SetPos(const Point &rNewPos)
Definition: svdglue.hxx:100
constexpr TypedWhichId< SfxStringItem > SDRATTR_CUSTOMSHAPE_ENGINE(SDRATTR_CUSTOMSHAPE_FIRST+0)
void AddHdl(std::unique_ptr< SdrHdl > pHdl)
Definition: svdhdl.cxx:2290
std::vector< SdrCustomShapeInteraction > GetInteractionHandles() const
Definition: svdoashp.cxx:557
SdrHdlKind GetKind() const
Definition: svdhdl.hxx:194
bool m_bDetectedRangeSegmentation false
constexpr tools::Long GetHeight() const
virtual const tools::Rectangle & GetLogicRect() const override
Definition: svdotxtr.cxx:69
virtual ~SdrObjCustomShape() override
Definition: svdoashp.cxx:817
const Size & GetPaperSize() const
void InvalidateRenderGeometry()
Definition: svdoashp.cxx:3213