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