LibreOffice Module svx (master)  1
svdedtv2.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 
20 #include <svx/svdedtv.hxx>
21 #include <svx/svdundo.hxx>
22 #include <svx/svdogrp.hxx>
23 #include <svx/svdoutl.hxx>
24 #include <svx/svdopath.hxx>
25 #include <svx/svdpage.hxx>
26 #include <svx/svdpagv.hxx>
27 #include <svx/svditer.hxx>
28 #include <svx/svdograf.hxx>
29 #include <svx/svdoole2.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <svx/sdooitm.hxx>
32 #include <svx/sdshitm.hxx>
33 #include <svx/xfillit0.hxx>
34 #include <svx/xlineit0.hxx>
35 #include <svx/xtextit0.hxx>
36 #include "svdfmtf.hxx"
37 #include "svdpdf.hxx"
38 #include <svx/svdetc.hxx>
39 #include <editeng/outlobj.hxx>
40 #include <editeng/eeitem.hxx>
43 #include <svx/svxdlg.hxx>
44 #include <svx/strings.hrc>
45 #include <svx/svdoashp.hxx>
47 #include <i18nutil/unicode.hxx>
48 #include <sal/log.hxx>
49 #include <tools/debug.hxx>
50 #include <memory>
51 #include <vector>
52 
53 using ::std::vector;
54 using namespace com::sun::star;
55 
57 {
58  return nullptr;
59 }
60 
62 {
63  return nullptr;
64 }
65 
66 void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, size_t /*nOldPos*/, size_t /*nNewPos*/)
67 {
68 }
69 
71 {
72  const size_t nCount=GetMarkedObjectCount();
73  if (nCount!=0)
74  {
75  const bool bUndo = IsUndoEnabled();
76 
77  if( bUndo )
78  BegUndo(SvxResId(STR_EditMovToTop),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToTop);
79 
80  SortMarkedObjects();
81  for (size_t nm=0; nm<nCount; ++nm)
82  { // All Ordnums have to be correct!
83  GetMarkedObjectByIndex(nm)->GetOrdNum();
84  }
85  bool bChg=false;
86  SdrObjList* pOL0=nullptr;
87  size_t nNewPos=0;
88  for (size_t nm=nCount; nm>0;)
89  {
90  --nm;
91  SdrMark* pM=GetSdrMarkByIndex(nm);
92  SdrObject* pObj=pM->GetMarkedSdrObj();
94  if (pOL!=pOL0)
95  {
96  nNewPos = pOL->GetObjCount()-1;
97  pOL0=pOL;
98  }
99  const size_t nNowPos = pObj->GetOrdNumDirect();
100  const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
101  size_t nCmpPos = nNowPos+1;
102  SdrObject* pMaxObj=GetMaxToTopObj(pObj);
103  if (pMaxObj!=nullptr)
104  {
105  size_t nMaxPos=pMaxObj->GetOrdNum();
106  if (nMaxPos!=0)
107  nMaxPos--;
108  if (nNewPos>nMaxPos)
109  nNewPos=nMaxPos; // neither go faster...
110  if (nNewPos<nNowPos)
111  nNewPos=nNowPos; // nor go in the other direction
112  }
113  bool bEnd=false;
114  while (nCmpPos<nNewPos && !bEnd)
115  {
116  SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
117  if (pCmpObj==nullptr)
118  {
119  OSL_FAIL("MovMarkedToTop(): Reference object not found.");
120  bEnd=true;
121  }
122  else if (pCmpObj==pMaxObj)
123  {
124  nNewPos=nCmpPos;
125  nNewPos--;
126  bEnd=true;
127  }
128  else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
129  {
130  nNewPos=nCmpPos;
131  bEnd=true;
132  }
133  else
134  {
135  nCmpPos++;
136  }
137  }
138  if (nNowPos!=nNewPos)
139  {
140  bChg=true;
141  pOL->SetObjectOrdNum(nNowPos,nNewPos);
142  if( bUndo )
143  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
144  ObjOrderChanged(pObj,nNowPos,nNewPos);
145  }
146  nNewPos--;
147  }
148 
149  if( bUndo )
150  EndUndo();
151 
152  if (bChg)
153  MarkListHasChanged();
154  }
155 }
156 
158 {
159  const size_t nCount=GetMarkedObjectCount();
160  if (nCount!=0)
161  {
162  const bool bUndo = IsUndoEnabled();
163 
164  if( bUndo )
165  BegUndo(SvxResId(STR_EditMovToBtm),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToBottom);
166 
167  SortMarkedObjects();
168  for (size_t nm=0; nm<nCount; ++nm)
169  { // All Ordnums have to be correct!
170  GetMarkedObjectByIndex(nm)->GetOrdNum();
171  }
172 
173  bool bChg=false;
174  SdrObjList* pOL0=nullptr;
175  size_t nNewPos=0;
176  for (size_t nm=0; nm<nCount; ++nm)
177  {
178  SdrMark* pM=GetSdrMarkByIndex(nm);
179  SdrObject* pObj=pM->GetMarkedSdrObj();
181  if (pOL!=pOL0)
182  {
183  nNewPos=0;
184  pOL0=pOL;
185  }
186  const size_t nNowPos = pObj->GetOrdNumDirect();
187  const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
188  size_t nCmpPos = nNowPos;
189  if (nCmpPos>0)
190  --nCmpPos;
191  SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
192  if (pMaxObj!=nullptr)
193  {
194  const size_t nMinPos=pMaxObj->GetOrdNum()+1;
195  if (nNewPos<nMinPos)
196  nNewPos=nMinPos; // neither go faster...
197  if (nNewPos>nNowPos)
198  nNewPos=nNowPos; // nor go in the other direction
199  }
200  bool bEnd=false;
201  // nNewPos in this case is the "maximum" position
202  // the object may reach without going faster than the object before
203  // it (multiple selection).
204  while (nCmpPos>nNewPos && !bEnd)
205  {
206  SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
207  if (pCmpObj==nullptr)
208  {
209  OSL_FAIL("MovMarkedToBtm(): Reference object not found.");
210  bEnd=true;
211  }
212  else if (pCmpObj==pMaxObj)
213  {
214  nNewPos=nCmpPos;
215  nNewPos++;
216  bEnd=true;
217  }
218  else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
219  {
220  nNewPos=nCmpPos;
221  bEnd=true;
222  }
223  else
224  {
225  nCmpPos--;
226  }
227  }
228  if (nNowPos!=nNewPos)
229  {
230  bChg=true;
231  pOL->SetObjectOrdNum(nNowPos,nNewPos);
232  if( bUndo )
233  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
234  ObjOrderChanged(pObj,nNowPos,nNewPos);
235  }
236  nNewPos++;
237  }
238 
239  if(bUndo)
240  EndUndo();
241 
242  if(bChg)
243  MarkListHasChanged();
244  }
245 }
246 
248 {
249  PutMarkedInFrontOfObj(nullptr);
250 }
251 
253 {
254  const size_t nCount=GetMarkedObjectCount();
255  if (nCount==0)
256  return;
257 
258  const bool bUndo = IsUndoEnabled();
259  if( bUndo )
260  BegUndo(SvxResId(STR_EditPutToTop),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToTop);
261 
262  SortMarkedObjects();
263 
264  if (pRefObj!=nullptr)
265  {
266  // Make "in front of the object" work, even if the
267  // selected objects are already in front of the other object
268  const size_t nRefMark=TryToFindMarkedObject(pRefObj);
269  SdrMark aRefMark;
270  if (nRefMark!=SAL_MAX_SIZE)
271  {
272  aRefMark=*GetSdrMarkByIndex(nRefMark);
273  GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
274  }
275  PutMarkedToBtm();
276  if (nRefMark!=SAL_MAX_SIZE)
277  {
278  GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
279  SortMarkedObjects();
280  }
281  }
282  for (size_t nm=0; nm<nCount; ++nm)
283  { // All Ordnums have to be correct!
284  GetMarkedObjectByIndex(nm)->GetOrdNum();
285  }
286  bool bChg=false;
287  SdrObjList* pOL0=nullptr;
288  size_t nNewPos=0;
289  for (size_t nm=nCount; nm>0;)
290  {
291  --nm;
292  SdrMark* pM=GetSdrMarkByIndex(nm);
293  SdrObject* pObj=pM->GetMarkedSdrObj();
294  if (pObj!=pRefObj)
295  {
297  if (pOL!=pOL0)
298  {
299  nNewPos=pOL->GetObjCount()-1;
300  pOL0=pOL;
301  }
302  const size_t nNowPos=pObj->GetOrdNumDirect();
303  SdrObject* pMaxObj=GetMaxToTopObj(pObj);
304  if (pMaxObj!=nullptr)
305  {
306  size_t nMaxOrd=pMaxObj->GetOrdNum(); // sadly doesn't work any other way
307  if (nMaxOrd>0)
308  nMaxOrd--;
309  if (nNewPos>nMaxOrd)
310  nNewPos=nMaxOrd; // neither go faster...
311  if (nNewPos<nNowPos)
312  nNewPos=nNowPos; // nor go into the other direction
313  }
314  if (pRefObj!=nullptr)
315  {
317  {
318  const size_t nMaxOrd=pRefObj->GetOrdNum(); // sadly doesn't work any other way
319  if (nNewPos>nMaxOrd)
320  nNewPos=nMaxOrd; // neither go faster...
321  if (nNewPos<nNowPos)
322  nNewPos=nNowPos; // nor go into the other direction
323  }
324  else
325  {
326  nNewPos=nNowPos; // different PageView, so don't change
327  }
328  }
329  if (nNowPos!=nNewPos)
330  {
331  bChg=true;
332  pOL->SetObjectOrdNum(nNowPos,nNewPos);
333  if( bUndo )
334  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
335  ObjOrderChanged(pObj,nNowPos,nNewPos);
336  }
337  nNewPos--;
338  } // if (pObj!=pRefObj)
339  } // for loop over all selected objects
340 
341  if( bUndo )
342  EndUndo();
343 
344  if(bChg)
345  MarkListHasChanged();
346 }
347 
349 {
350  PutMarkedBehindObj(nullptr);
351 }
352 
354 {
355  const size_t nCount=GetMarkedObjectCount();
356  if (nCount==0)
357  return;
358 
359  const bool bUndo = IsUndoEnabled();
360 
361  if( bUndo )
362  BegUndo(SvxResId(STR_EditPutToBtm),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToBottom);
363 
364  SortMarkedObjects();
365  if (pRefObj!=nullptr)
366  {
367  // Make "behind the object" work, even if the
368  // selected objects are already behind the other object
369  const size_t nRefMark=TryToFindMarkedObject(pRefObj);
370  SdrMark aRefMark;
371  if (nRefMark!=SAL_MAX_SIZE)
372  {
373  aRefMark=*GetSdrMarkByIndex(nRefMark);
374  GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
375  }
376  PutMarkedToTop();
377  if (nRefMark!=SAL_MAX_SIZE)
378  {
379  GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
380  SortMarkedObjects();
381  }
382  }
383  for (size_t nm=0; nm<nCount; ++nm) { // All Ordnums have to be correct!
384  GetMarkedObjectByIndex(nm)->GetOrdNum();
385  }
386  bool bChg=false;
387  SdrObjList* pOL0=nullptr;
388  size_t nNewPos=0;
389  for (size_t nm=0; nm<nCount; ++nm) {
390  SdrMark* pM=GetSdrMarkByIndex(nm);
391  SdrObject* pObj=pM->GetMarkedSdrObj();
392  if (pObj!=pRefObj) {
394  if (pOL!=pOL0) {
395  nNewPos=0;
396  pOL0=pOL;
397  }
398  const size_t nNowPos=pObj->GetOrdNumDirect();
399  SdrObject* pMinObj=GetMaxToBtmObj(pObj);
400  if (pMinObj!=nullptr) {
401  const size_t nMinOrd=pMinObj->GetOrdNum()+1; // sadly doesn't work any differently
402  if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
403  if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
404  }
405  if (pRefObj!=nullptr) {
407  const size_t nMinOrd=pRefObj->GetOrdNum(); // sadly doesn't work any differently
408  if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
409  if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
410  } else {
411  nNewPos=nNowPos; // different PageView, so don't change
412  }
413  }
414  if (nNowPos!=nNewPos) {
415  bChg=true;
416  pOL->SetObjectOrdNum(nNowPos,nNewPos);
417  if( bUndo )
418  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
419  ObjOrderChanged(pObj,nNowPos,nNewPos);
420  }
421  nNewPos++;
422  } // if (pObj!=pRefObj)
423  } // for loop over all selected objects
424 
425  if(bUndo)
426  EndUndo();
427 
428  if(bChg)
429  MarkListHasChanged();
430 
431 }
432 
434 {
435  SortMarkedObjects();
436  const size_t nMarkCount=GetMarkedObjectCount();
437  if (nMarkCount>0)
438  {
439  bool bChg=false;
440 
441  bool bUndo = IsUndoEnabled();
442  if( bUndo )
443  BegUndo(SvxResId(STR_EditRevOrder),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ReverseOrder);
444 
445  size_t a=0;
446  do {
447  // take into account selection across multiple PageViews
448  size_t b=a+1;
449  while (b<nMarkCount && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) ++b;
450  --b;
451  SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
452  size_t c=b;
453  if (a<c) { // make sure OrdNums aren't dirty
454  GetMarkedObjectByIndex(a)->GetOrdNum();
455  }
456  while (a<c) {
457  SdrObject* pObj1=GetMarkedObjectByIndex(a);
458  SdrObject* pObj2=GetMarkedObjectByIndex(c);
459  const size_t nOrd1=pObj1->GetOrdNumDirect();
460  const size_t nOrd2=pObj2->GetOrdNumDirect();
461  if( bUndo )
462  {
463  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
464  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
465  }
466  pOL->SetObjectOrdNum(nOrd1,nOrd2);
467  // Obj 2 has moved forward by one position, so now nOrd2-1
468  pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
469  // use Replace instead of SetOrdNum for performance reasons (recalculation of Ordnums)
470  ++a;
471  --c;
472  bChg=true;
473  }
474  a=b+1;
475  } while (a<nMarkCount);
476 
477  if(bUndo)
478  EndUndo();
479 
480  if(bChg)
481  MarkListHasChanged();
482  }
483 }
484 
486 {
487  const size_t nCount=GetMarkedObjectCount();
488  if (nCount==0)
489  return;
490  if (nCount==1)
491  { // special-casing for single selection
492  SdrObject* pObj=GetMarkedObjectByIndex(0);
494  SAL_WARN_IF(!pOL, "svx", "Object somehow has no ObjList");
495  size_t nMax = pOL ? pOL->GetObjCount() : 0;
496  size_t nMin = 0;
497  const size_t nObjNum=pObj->GetOrdNum();
498  SdrObject* pRestrict=GetMaxToTopObj(pObj);
499  if (pRestrict!=nullptr) {
500  const size_t nRestrict=pRestrict->GetOrdNum();
501  if (nRestrict<nMax) nMax=nRestrict;
502  }
503  pRestrict=GetMaxToBtmObj(pObj);
504  if (pRestrict!=nullptr) {
505  const size_t nRestrict=pRestrict->GetOrdNum();
506  if (nRestrict>nMin) nMin=nRestrict;
507  }
508  m_bToTopPossible=nObjNum<nMax-1;
509  m_bToBtmPossible=nObjNum>nMin;
510  } else { // multiple selection
511  SdrObjList* pOL0=nullptr;
512  size_t nPos0 = 0;
513  for (size_t nm = 0; !m_bToBtmPossible && nm<nCount; ++nm) { // check 'send to background'
514  SdrObject* pObj=GetMarkedObjectByIndex(nm);
516  if (pOL!=pOL0) {
517  nPos0 = 0;
518  pOL0=pOL;
519  }
520  const size_t nPos = pObj->GetOrdNum();
521  m_bToBtmPossible = nPos && (nPos-1 > nPos0);
522  nPos0 = nPos;
523  }
524 
525  pOL0=nullptr;
526  nPos0 = SAL_MAX_SIZE;
527  for (size_t nm=nCount; !m_bToTopPossible && nm>0; ) { // check 'bring to front'
528  --nm;
529  SdrObject* pObj=GetMarkedObjectByIndex(nm);
531  if (pOL!=pOL0) {
532  nPos0=pOL->GetObjCount();
533  pOL0=pOL;
534  }
535  const size_t nPos = pObj->GetOrdNum();
536  m_bToTopPossible = nPos+1 < nPos0;
537  nPos0=nPos;
538  }
539  }
540 }
541 
542 
543 // Combine
544 
545 
546 void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
547 {
548  if (pSource!=nullptr) {
549  SdrObjList* pOL=pSource->GetSubList();
550  if (pOL!=nullptr && !pSource->Is3DObj()) { // get first non-group object from group
552  pSource=aIter.Next();
553  }
554  }
555 
556  if(pSource && pDest)
557  {
558  SfxItemSet aSet(mpModel->GetItemPool(),
562 
563  aSet.Put(pSource->GetMergedItemSet());
564 
565  pDest->ClearMergedItem();
566  pDest->SetMergedItemSet(aSet);
567 
568  pDest->NbcSetLayer(pSource->GetLayer());
569  pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), true);
570  }
571 }
572 
574 {
575  // new condition IsLine() to be able to combine simple Lines
576  bool bIsLine(false);
577 
578  const SdrPathObj* pPath = dynamic_cast< const SdrPathObj*>( pObj );
579 
580  if(pPath)
581  {
582  bIsLine = pPath->IsLine();
583  }
584 
586  pObj->TakeObjInfo(aInfo);
587 
588  return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
589 }
590 
592 {
593  SdrObjList* pOL = pObj->GetSubList();
594 
595  if(pOL && !pObj->Is3DObj())
596  {
598 
599  while(aIter.IsMore())
600  {
601  SdrObject* pObj1 = aIter.Next();
602 
603  // all members of a group have to be convertible
604  if(!ImpCanConvertForCombine1(pObj1))
605  {
606  return false;
607  }
608  }
609  }
610  else
611  {
612  if(!ImpCanConvertForCombine1(pObj))
613  {
614  return false;
615  }
616  }
617 
618  return true;
619 }
620 
622 {
623  basegfx::B2DPolyPolygon aRetval;
624  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj );
625 
626  if(pPath && !pObj->GetOutlinerParaObject())
627  {
628  aRetval = pPath->GetPathPoly();
629  }
630  else
631  {
632  SdrObjectUniquePtr pConvObj = pObj->ConvertToPolyObj(true/*bCombine*/, false);
633 
634  if(pConvObj)
635  {
636  SdrObjList* pOL = pConvObj->GetSubList();
637 
638  if(pOL)
639  {
641 
642  while(aIter.IsMore())
643  {
644  SdrObject* pObj1 = aIter.Next();
645  pPath = dynamic_cast<SdrPathObj*>( pObj1 );
646 
647  if(pPath)
648  {
649  aRetval.append(pPath->GetPathPoly());
650  }
651  }
652  }
653  else
654  {
655  pPath = dynamic_cast<SdrPathObj*>( pConvObj.get() );
656 
657  if(pPath)
658  {
659  aRetval = pPath->GetPathPoly();
660  }
661  }
662  }
663  }
664 
665  return aRetval;
666 }
667 
669 {
670  SdrObjList* pOL = pObj->GetSubList();
671 
672  if(pOL && !pObj->Is3DObj())
673  {
674  basegfx::B2DPolyPolygon aRetval;
676 
677  while(aIter.IsMore())
678  {
679  SdrObject* pObj1 = aIter.Next();
680  aRetval.append(ImpGetPolyPolygon1(pObj1));
681  }
682 
683  return aRetval;
684  }
685  else
686  {
687  return ImpGetPolyPolygon1(pObj);
688  }
689 }
690 
692 {
693  const sal_uInt32 nPolyCount(rPolyPolygon.count());
694 
695  if(0 == nPolyCount)
696  {
697  return basegfx::B2DPolygon();
698  }
699  else if(1 == nPolyCount)
700  {
701  return rPolyPolygon.getB2DPolygon(0);
702  }
703  else
704  {
705  basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0));
706 
707  for(sal_uInt32 a(1); a < nPolyCount; a++)
708  {
709  basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
710 
711  if(aRetval.count())
712  {
713  if(aCandidate.count())
714  {
715  const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0));
716  const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1));
717  const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0));
718  const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1));
719 
720  const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
721  const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
722  const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
723  const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
724 
725  const double fSmallestRA(std::min(fRACA, fRACB));
726  const double fSmallestRB(std::min(fRBCA, fRBCB));
727 
728  if(fSmallestRA < fSmallestRB)
729  {
730  // flip result
731  aRetval.flip();
732  }
733 
734  const double fSmallestCA(std::min(fRACA, fRBCA));
735  const double fSmallestCB(std::min(fRACB, fRBCB));
736 
737  if(fSmallestCB < fSmallestCA)
738  {
739  // flip candidate
740  aCandidate.flip();
741  }
742 
743  // append candidate to retval
744  aRetval.append(aCandidate);
745  }
746  }
747  else
748  {
749  aRetval = aCandidate;
750  }
751  }
752 
753  return aRetval;
754  }
755 }
756 
757 namespace {
758 
759 // for distribution dialog function
760 struct ImpDistributeEntry
761 {
762  SdrObject* mpObj;
763  sal_Int32 mnPos;
764  sal_Int32 mnLength;
765 };
766 
767 }
768 
769 typedef vector<ImpDistributeEntry> ImpDistributeEntryList;
770 
772 {
773  const size_t nMark(GetMarkedObjectCount());
774 
775  if(nMark > 2)
776  {
777  SfxItemSet aNewAttr(mpModel->GetItemPool());
778 
780  ScopedVclPtr<AbstractSvxDistributeDialog> pDlg(pFact->CreateSvxDistributeDialog(pParent, aNewAttr));
781 
782  sal_uInt16 nResult = pDlg->Execute();
783 
784  if(nResult == RET_OK)
785  {
786  SvxDistributeHorizontal eHor = pDlg->GetDistributeHor();
787  SvxDistributeVertical eVer = pDlg->GetDistributeVer();
788  ImpDistributeEntryList aEntryList;
789  ImpDistributeEntryList::iterator itEntryList;
790  sal_uInt32 nFullLength;
791 
792  const bool bUndo = IsUndoEnabled();
793  if( bUndo )
794  BegUndo();
795 
797  {
798  // build sorted entry list
799  nFullLength = 0;
800 
801  for( size_t a = 0; a < nMark; ++a )
802  {
803  SdrMark* pMark = GetSdrMarkByIndex(a);
804  ImpDistributeEntry aNew;
805 
806  aNew.mpObj = pMark->GetMarkedSdrObj();
807 
808  switch(eHor)
809  {
811  {
812  aNew.mnPos = aNew.mpObj->GetSnapRect().Left();
813  break;
814  }
816  {
817  aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
818  break;
819  }
821  {
822  aNew.mnLength = aNew.mpObj->GetSnapRect().GetWidth() + 1;
823  nFullLength += aNew.mnLength;
824  aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
825  break;
826  }
828  {
829  aNew.mnPos = aNew.mpObj->GetSnapRect().Right();
830  break;
831  }
832  default: break;
833  }
834 
835  itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
836  [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
837  if ( itEntryList < aEntryList.end() )
838  aEntryList.insert( itEntryList, aNew );
839  else
840  aEntryList.push_back( aNew );
841  }
842 
844  {
845  // calculate room in-between
846  sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
847  double fStepWidth = (static_cast<double>(nWidth) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
848  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
849  fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
850 
851  // move entries 1..n-1
852  for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i )
853  {
854  ImpDistributeEntry& rCurr = aEntryList[ i ];
855  ImpDistributeEntry& rNext = aEntryList[ i + 1];
856  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
857  if( bUndo )
858  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
859  rCurr.mpObj->Move(Size(nDelta, 0));
860  fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
861  }
862  }
863  else
864  {
865  // calculate distances
866  sal_Int32 nWidth = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
867  double fStepWidth = static_cast<double>(nWidth) / static_cast<double>(aEntryList.size() - 1);
868  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
869  fStepStart += fStepWidth;
870 
871  // move entries 1..n-1
872  for( size_t i = 1 ; i < aEntryList.size()-1 ; ++i )
873  {
874  ImpDistributeEntry& rCurr = aEntryList[ i ];
875  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
876  if( bUndo )
877  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
878  rCurr.mpObj->Move(Size(nDelta, 0));
879  fStepStart += fStepWidth;
880  }
881  }
882 
883  // clear list
884  aEntryList.clear();
885  }
886 
887  if(eVer != SvxDistributeVertical::NONE)
888  {
889  // build sorted entry list
890  nFullLength = 0;
891 
892  for( size_t a = 0; a < nMark; ++a )
893  {
894  SdrMark* pMark = GetSdrMarkByIndex(a);
895  ImpDistributeEntry aNew;
896 
897  aNew.mpObj = pMark->GetMarkedSdrObj();
898 
899  switch(eVer)
900  {
902  {
903  aNew.mnPos = aNew.mpObj->GetSnapRect().Top();
904  break;
905  }
907  {
908  aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
909  break;
910  }
912  {
913  aNew.mnLength = aNew.mpObj->GetSnapRect().GetHeight() + 1;
914  nFullLength += aNew.mnLength;
915  aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
916  break;
917  }
919  {
920  aNew.mnPos = aNew.mpObj->GetSnapRect().Bottom();
921  break;
922  }
923  default: break;
924  }
925 
926  itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
927  [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
928  if ( itEntryList < aEntryList.end() )
929  aEntryList.insert( itEntryList, aNew );
930  else
931  aEntryList.push_back( aNew );
932  }
933 
935  {
936  // calculate room in-between
937  sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
938  double fStepWidth = (static_cast<double>(nHeight) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
939  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
940  fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
941 
942  // move entries 1..n-1
943  for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
944  {
945  ImpDistributeEntry& rCurr = aEntryList[ i ];
946  ImpDistributeEntry& rNext = aEntryList[ i + 1 ];
947  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
948  if( bUndo )
949  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
950  rCurr.mpObj->Move(Size(0, nDelta));
951  fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
952  }
953  }
954  else
955  {
956  // calculate distances
957  sal_Int32 nHeight = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
958  double fStepWidth = static_cast<double>(nHeight) / static_cast<double>(aEntryList.size() - 1);
959  double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
960  fStepStart += fStepWidth;
961 
962  // move entries 1..n-1
963  for(size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
964  {
965  ImpDistributeEntry& rCurr = aEntryList[ i ];
966  sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
967  if( bUndo )
968  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
969  rCurr.mpObj->Move(Size(0, nDelta));
970  fStepStart += fStepWidth;
971  }
972  }
973 
974  // clear list
975  aEntryList.clear();
976  }
977 
978  // UNDO-Comment and end of UNDO
979  mpModel->SetUndoComment(SvxResId(STR_DistributeMarkedObjects));
980 
981  if( bUndo )
982  EndUndo();
983  }
984  }
985 }
986 
988 {
989  // #i73441# check content
990  if(!AreObjectsMarked())
991  return;
992 
993  SdrMarkList aRemove;
994  SortMarkedObjects();
995 
996  const bool bUndo = IsUndoEnabled();
997 
998  if( bUndo )
999  BegUndo();
1000 
1001  size_t nInsPos = SAL_MAX_SIZE;
1002  const SdrObject* pAttrObj = nullptr;
1003  basegfx::B2DPolyPolygon aMergePolyPolygonA;
1004  basegfx::B2DPolyPolygon aMergePolyPolygonB;
1005 
1006  SdrObjList* pInsOL = nullptr;
1007  SdrPageView* pInsPV = nullptr;
1008  bool bFirstObjectComplete(false);
1009 
1010  // make sure selected objects are contour objects
1011  // since now basegfx::utils::adaptiveSubdivide() is used, it is no longer
1012  // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1013  // mechanisms. In a next step the polygon clipper will even be able to clip curves...
1014  // ConvertMarkedToPolyObj(true);
1015  ConvertMarkedToPathObj(true);
1016  OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)");
1017 
1018  for(size_t a=0; a<GetMarkedObjectCount(); ++a)
1019  {
1020  SdrMark* pM = GetSdrMarkByIndex(a);
1021  SdrObject* pObj = pM->GetMarkedSdrObj();
1022 
1023  if(ImpCanConvertForCombine(pObj))
1024  {
1025  if(!pAttrObj)
1026  pAttrObj = pObj;
1027 
1028  nInsPos = pObj->GetOrdNum() + 1;
1029  pInsPV = pM->GetPageView();
1030  pInsOL = pObj->getParentSdrObjListFromSdrObject();
1031 
1032  // #i76891# use single iteration from SJ here which works on SdrObjects and takes
1033  // groups into account by itself
1035 
1036  while(aIter.IsMore())
1037  {
1038  SdrObject* pCandidate = aIter.Next();
1039  SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>( pCandidate );
1040  if(pPathObj)
1041  {
1042  basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1043 
1044  // #i76891# unfortunately ConvertMarkedToPathObj has converted all
1045  // involved polygon data to curve segments, even if not necessary.
1046  // It is better to try to reduce to more simple polygons.
1047  aTmpPoly = basegfx::utils::simplifyCurveSegments(aTmpPoly);
1048 
1049  // for each part polygon as preparation, remove self-intersections
1050  // correct orientations and get rid of possible neutral polygons.
1051  aTmpPoly = basegfx::utils::prepareForPolygonOperation(aTmpPoly);
1052 
1053  if(!bFirstObjectComplete)
1054  {
1055  // #i111987# Also need to collect ORed source shape when more than
1056  // a single polygon is involved
1057  if(aMergePolyPolygonA.count())
1058  {
1059  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1060  }
1061  else
1062  {
1063  aMergePolyPolygonA = aTmpPoly;
1064  }
1065  }
1066  else
1067  {
1068  if(aMergePolyPolygonB.count())
1069  {
1070  // to topologically correctly collect the 2nd polygon
1071  // group it is necessary to OR the parts (each is seen as
1072  // XOR-FillRule polygon and they are drawn over each-other)
1073  aMergePolyPolygonB = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1074  }
1075  else
1076  {
1077  aMergePolyPolygonB = aTmpPoly;
1078  }
1079  }
1080  }
1081  }
1082 
1083  // was there something added to the first polygon?
1084  if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1085  {
1086  bFirstObjectComplete = true;
1087  }
1088 
1089  // move object to temporary delete list
1090  aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1091  }
1092  }
1093 
1094  switch(eMode)
1095  {
1096  case SdrMergeMode::Merge:
1097  {
1098  // merge all contained parts (OR)
1099  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1100  break;
1101  }
1103  {
1104  // Subtract B from A
1105  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1106  break;
1107  }
1109  {
1110  // AND B and A
1111  aMergePolyPolygonA = basegfx::utils::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1112  break;
1113  }
1114  }
1115 
1116  // #i73441# check insert list before taking actions
1117  if(pInsOL)
1118  {
1119  SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), OBJ_PATHFILL, aMergePolyPolygonA);
1120  ImpCopyAttributes(pAttrObj, pPath);
1121  pInsOL->InsertObject(pPath, nInsPos);
1122  if( bUndo )
1123  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1124 
1125  // #i124760# To have a correct selection with only the new object it is necessary to
1126  // unmark all objects first. If not doing so, there may remain invalid pointers to objects
1127  // TTTT:Not needed for aw080 (!)
1128  UnmarkAllObj(pInsPV);
1129 
1130  MarkObj(pPath, pInsPV, false, true);
1131  }
1132 
1133  aRemove.ForceSort();
1134  switch(eMode)
1135  {
1136  case SdrMergeMode::Merge:
1137  {
1138  SetUndoComment(
1139  SvxResId(STR_EditMergeMergePoly),
1140  aRemove.GetMarkDescription());
1141  break;
1142  }
1144  {
1145  SetUndoComment(
1146  SvxResId(STR_EditMergeSubstractPoly),
1147  aRemove.GetMarkDescription());
1148  break;
1149  }
1151  {
1152  SetUndoComment(
1153  SvxResId(STR_EditMergeIntersectPoly),
1154  aRemove.GetMarkDescription());
1155  break;
1156  }
1157  }
1158  DeleteMarkedList(aRemove);
1159 
1160  if( bUndo )
1161  EndUndo();
1162 }
1163 
1165 {
1166  const SdrMarkList& rMarkList = GetMarkedObjectList();
1167  size_t nMarked = rMarkList.GetMarkCount();
1168 
1169  if (nMarked < 2)
1170  return;
1171 
1172  size_t nLastSelected = 0;
1173  sal_Int64 nLastSelectedTime = rMarkList.GetMark(0)->getTimeStamp();
1174  for (size_t a = 1; a < nMarked; ++a)
1175  {
1176  sal_Int64 nCandidateTime = rMarkList.GetMark(a)->getTimeStamp();
1177  if (nCandidateTime > nLastSelectedTime)
1178  {
1179  nLastSelectedTime = nCandidateTime;
1180  nLastSelected = a;
1181  }
1182  }
1183 
1184  SdrObject* pLastSelectedObj = rMarkList.GetMark(nLastSelected)->GetMarkedSdrObj();
1185  Size aLastRectSize(pLastSelectedObj->GetLogicRect().GetSize());
1186 
1187  const bool bUndo = IsUndoEnabled();
1188 
1189  if (bUndo)
1190  BegUndo();
1191 
1192  for (size_t a = 0; a < nMarked; ++a)
1193  {
1194  if (a == nLastSelected)
1195  continue;
1196  SdrMark* pM = rMarkList.GetMark(a);
1197  SdrObject* pObj = pM->GetMarkedSdrObj();
1198  tools::Rectangle aLogicRect(pObj->GetLogicRect());
1199  Size aLogicRectSize(aLogicRect.GetSize());
1200  if (bWidth)
1201  aLogicRectSize.setWidth( aLastRectSize.Width() );
1202  else
1203  aLogicRectSize.setHeight( aLastRectSize.Height() );
1204  aLogicRect.SetSize(aLogicRectSize);
1205  if (bUndo)
1206  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1207  pObj->SetLogicRect(aLogicRect);
1208  }
1209 
1210  SetUndoComment(
1211  SvxResId(bWidth ? STR_EqualizeWidthMarkedObjects : STR_EqualizeHeightMarkedObjects),
1212  rMarkList.GetMarkDescription());
1213 
1214  if (bUndo)
1215  EndUndo();
1216 }
1217 
1219 {
1220  SdrPageView* pPageView = GetSdrPageView();
1221  if ( !pPageView || pPageView->IsLayerLocked( GetActiveLayer() ) )
1222  return;
1223 
1224  bool bUndo = IsUndoEnabled();
1225 
1226  // Undo-String will be set later
1227  if ( bUndo )
1228  BegUndo();
1229 
1230  SdrOutliner& rDrawOutliner = getSdrModelFromSdrView().GetDrawOutliner();
1231 
1232  SdrObjListIter aIter( GetMarkedObjectList(), SdrIterMode::Flat);
1233  while ( aIter.IsMore() )
1234  {
1235  SdrObject* pObj = aIter.Next();
1236  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( pObj );
1237  const OutlinerParaObject* pOPO = pTextObj ? pTextObj->GetOutlinerParaObject() : nullptr;
1238  if ( pOPO && pTextObj->IsTextFrame()
1239  && pTextObj->GetObjIdentifier() == OBJ_TEXT // not callouts (OBJ_CAPTION)
1240  && !pTextObj->IsOutlText() // not impress presentation objects
1241  && pTextObj->GetMergedItem(XATTR_FORMTXTSTYLE).GetValue() == XFormTextStyle::NONE // not Fontwork
1242  )
1243  {
1244  // if the last paragraph does not end in paragraph-end punctuation (ignoring whitespace),
1245  // assume this text should be added to the end of the last paragraph, instead of starting a new paragraph.
1246  const sal_Int32 nPara = rDrawOutliner.GetParagraphCount();
1247  const OUString sLastPara = nPara ? rDrawOutliner.GetText( rDrawOutliner.GetParagraph( nPara - 1 ) ) : "";
1248  sal_Int32 n = sLastPara.getLength();
1249  while ( n && unicode::isWhiteSpace( sLastPara[--n] ) )
1250  ;
1251  //TODO: find way to use Locale to identify sentence final punctuation. Copied IsSentenceAtEnd() from autofmt.cxx
1252  const bool bAppend = !n || ( sLastPara[n] != '.' && sLastPara[n] != '?' && sLastPara[n] != '!' );
1253  rDrawOutliner.AddText( *pOPO, bAppend );
1254  }
1255  else
1256  {
1257  // Unmark non-textboxes, because all marked objects are deleted at the end. AdjustMarkHdl later.
1258  MarkObj(pObj, pPageView, /*bUnmark=*/true, /*bImpNoSetMarkHdl=*/true);
1259  }
1260  }
1261 
1262  MarkListHasChanged();
1263  AdjustMarkHdl();
1264 
1265  if ( GetMarkedObjectCount() > 1 )
1266  {
1267  SdrRectObj* pReplacement = new SdrRectObj( getSdrModelFromSdrView(), OBJ_TEXT );
1268  pReplacement->SetOutlinerParaObject( rDrawOutliner.CreateParaObject() );
1269  pReplacement->SetSnapRect( GetMarkedObjRect() );
1270 
1272  if ( InsertObjectAtView( pReplacement, *pPageView, nFlags ) )
1273  DeleteMarkedObj();
1274  }
1275 
1276  if ( bUndo )
1277  EndUndo();
1278 
1279  return;
1280 }
1281 
1283 {
1284  // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1285  // create a 2nd Undo-action and Undo-Comment.
1286 
1287  bool bUndo = IsUndoEnabled();
1288 
1289  // Undo-String will be set later
1290  if( bUndo )
1291  BegUndo("", "", bNoPolyPoly ? SdrRepeatFunc::CombineOnePoly : SdrRepeatFunc::CombinePolyPoly);
1292 
1293  // #105899# First, guarantee that all objects are converted to polyobjects,
1294  // especially for SdrGrafObj with bitmap filling this is necessary to not
1295  // lose the bitmap filling.
1296 
1297  // #i12392#
1298  // ConvertMarkedToPolyObj was too strong here, it will lose quality and
1299  // information when curve objects are combined. This can be replaced by
1300  // using ConvertMarkedToPathObj without changing the previous fix.
1301 
1302  // #i21250#
1303  // Instead of simply passing true as LineToArea, use bNoPolyPoly as info
1304  // if this command is a 'Combine' or a 'Connect' command. On Connect it's true.
1305  // To not concert line segments with a set line width to polygons in that case,
1306  // use this info. Do not convert LineToArea on Connect commands.
1307  // ConvertMarkedToPathObj(!bNoPolyPoly);
1308 
1309  // This is used for Combine and Connect. In no case it is necessary to force
1310  // the content to curve, but it is also not good to force to polygons. Thus,
1311  // curve is the less information losing one. Remember: This place is not
1312  // used for merge.
1313  // LineToArea is never necessary, both commands are able to take over the
1314  // set line style and to display it correctly. Thus, i will use a
1315  // ConvertMarkedToPathObj with a false in any case. Only drawback is that
1316  // simple polygons will be changed to curves, but with no information loss.
1317  ConvertMarkedToPathObj(false /* bLineToArea */);
1318 
1319  // continue as before
1320  basegfx::B2DPolyPolygon aPolyPolygon;
1321  SdrObjList* pCurrentOL = nullptr;
1322  SdrMarkList aRemoveBuffer;
1323 
1324  SortMarkedObjects();
1325  size_t nInsPos = SAL_MAX_SIZE;
1326  SdrObjList* pInsOL = nullptr;
1327  SdrPageView* pInsPV = nullptr;
1328  const SdrObject* pAttrObj = nullptr;
1329 
1330  for(size_t a = GetMarkedObjectCount(); a; )
1331  {
1332  --a;
1333  SdrMark* pM = GetSdrMarkByIndex(a);
1334  SdrObject* pObj = pM->GetMarkedSdrObj();
1335  SdrObjList* pThisOL = pObj->getParentSdrObjListFromSdrObject();
1336 
1337  if(pCurrentOL != pThisOL)
1338  {
1339  pCurrentOL = pThisOL;
1340  }
1341 
1342  if(ImpCanConvertForCombine(pObj))
1343  {
1344  // remember objects to be able to copy attributes
1345  pAttrObj = pObj;
1346 
1347  // unfortunately ConvertMarkedToPathObj has converted all
1348  // involved polygon data to curve segments, even if not necessary.
1349  // It is better to try to reduce to more simple polygons.
1350  basegfx::B2DPolyPolygon aTmpPoly(basegfx::utils::simplifyCurveSegments(ImpGetPolyPolygon(pObj)));
1351  aPolyPolygon.insert(0, aTmpPoly);
1352 
1353  if(!pInsOL)
1354  {
1355  nInsPos = pObj->GetOrdNum() + 1;
1356  pInsPV = pM->GetPageView();
1357  pInsOL = pObj->getParentSdrObjListFromSdrObject();
1358  }
1359 
1360  aRemoveBuffer.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1361  }
1362  }
1363 
1364  if(bNoPolyPoly)
1365  {
1366  basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1367  aPolyPolygon.clear();
1368  aPolyPolygon.append(aCombinedPolygon);
1369  }
1370 
1371  const sal_uInt32 nPolyCount(aPolyPolygon.count());
1372 
1373  if (nPolyCount && pAttrObj)
1374  {
1375  SdrObjKind eKind = OBJ_PATHFILL;
1376 
1377  if(nPolyCount > 1)
1378  {
1379  aPolyPolygon.setClosed(true);
1380  }
1381  else
1382  {
1383  // check for Polyline
1384  const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0));
1385  const sal_uInt32 nPointCount(aPolygon.count());
1386 
1387  if(nPointCount <= 2)
1388  {
1389  eKind = OBJ_PATHLINE;
1390  }
1391  else
1392  {
1393  if(!aPolygon.isClosed())
1394  {
1395  const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0));
1396  const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1));
1397  const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1398  const double fJoinTolerance(10.0);
1399 
1400  if(fDistance < fJoinTolerance)
1401  {
1402  aPolyPolygon.setClosed(true);
1403  }
1404  else
1405  {
1406  eKind = OBJ_PATHLINE;
1407  }
1408  }
1409  }
1410  }
1411 
1412  SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), eKind, aPolyPolygon);
1413 
1414  // attributes of the lowest object
1415  ImpCopyAttributes(pAttrObj, pPath);
1416 
1417  // If LineStyle of pAttrObj is drawing::LineStyle_NONE force to drawing::LineStyle_SOLID to make visible.
1418  const drawing::LineStyle eLineStyle = pAttrObj->GetMergedItem(XATTR_LINESTYLE).GetValue();
1419  const drawing::FillStyle eFillStyle = pAttrObj->GetMergedItem(XATTR_FILLSTYLE).GetValue();
1420 
1421  // Take fill style/closed state of pAttrObj in account when deciding to change the line style
1422  bool bIsClosedPathObj(dynamic_cast<const SdrPathObj*>( pAttrObj) != nullptr && static_cast<const SdrPathObj*>(pAttrObj)->IsClosed());
1423 
1424  if(drawing::LineStyle_NONE == eLineStyle && (drawing::FillStyle_NONE == eFillStyle || !bIsClosedPathObj))
1425  {
1426  pPath->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
1427  }
1428 
1429  pInsOL->InsertObject(pPath,nInsPos);
1430  if( bUndo )
1431  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1432 
1433  // Here was a severe error: Without UnmarkAllObj, the new object was marked
1434  // additionally to the two ones which are deleted below. As long as those are
1435  // in the UNDO there is no problem, but as soon as they get deleted, the
1436  // MarkList will contain deleted objects -> GPF.
1437  UnmarkAllObj(pInsPV);
1438  MarkObj(pPath, pInsPV, false, true);
1439  }
1440 
1441  // build an UndoComment from the objects actually used
1442  aRemoveBuffer.ForceSort(); // important for remove (see below)
1443  if( bUndo )
1444  SetUndoComment(SvxResId(bNoPolyPoly?STR_EditCombine_OnePoly:STR_EditCombine_PolyPoly),aRemoveBuffer.GetMarkDescription());
1445 
1446  // remove objects actually used from the list
1447  DeleteMarkedList(aRemoveBuffer);
1448  if( bUndo )
1449  EndUndo();
1450 }
1451 
1452 
1453 // Dismantle
1454 
1455 
1456 bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, bool bMakeLines)
1457 {
1458  bool bCan(false);
1459  const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1460 
1461  if(nPolygonCount >= 2)
1462  {
1463  // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1464  bCan = true;
1465  }
1466  else if(bMakeLines && 1 == nPolygonCount)
1467  {
1468  // #i69172# ..or with at least 2 edges (curves or lines)
1469  const basegfx::B2DPolygon& aPolygon(rPpolyPolygon.getB2DPolygon(0));
1470  const sal_uInt32 nPointCount(aPolygon.count());
1471 
1472  if(nPointCount > 2)
1473  {
1474  bCan = true;
1475  }
1476  }
1477 
1478  return bCan;
1479 }
1480 
1481 bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, bool bMakeLines)
1482 {
1483  bool bOtherObjs(false); // true=objects other than PathObj's existent
1484  bool bMin1PolyPoly(false); // true=at least 1 tools::PolyPolygon with more than one Polygon existent
1485  SdrObjList* pOL = pObj->GetSubList();
1486 
1487  if(pOL)
1488  {
1489  // group object -- check all members if they're PathObjs
1491 
1492  while(aIter.IsMore() && !bOtherObjs)
1493  {
1494  const SdrObject* pObj1 = aIter.Next();
1495  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj1 );
1496 
1497  if(pPath)
1498  {
1499  if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1500  {
1501  bMin1PolyPoly = true;
1502  }
1503 
1504  SdrObjTransformInfoRec aInfo;
1505  pObj1->TakeObjInfo(aInfo);
1506 
1507  if(!aInfo.bCanConvToPath)
1508  {
1509  // happens e. g. in the case of FontWork
1510  bOtherObjs = true;
1511  }
1512  }
1513  else
1514  {
1515  bOtherObjs = true;
1516  }
1517  }
1518  }
1519  else
1520  {
1521  const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>(pObj);
1522  const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>(pObj);
1523 
1524  // #i37011#
1525  if(pPath)
1526  {
1527  if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1528  {
1529  bMin1PolyPoly = true;
1530  }
1531 
1532  SdrObjTransformInfoRec aInfo;
1533  pObj->TakeObjInfo(aInfo);
1534 
1535  // new condition IsLine() to be able to break simple Lines
1536  if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1537  {
1538  // happens e. g. in the case of FontWork
1539  bOtherObjs = true;
1540  }
1541  }
1542  else if(pCustomShape)
1543  {
1544  if(bMakeLines)
1545  {
1546  // allow break command
1547  bMin1PolyPoly = true;
1548  }
1549  }
1550  else
1551  {
1552  bOtherObjs = true;
1553  }
1554  }
1555  return bMin1PolyPoly && !bOtherObjs;
1556 }
1557 
1558 void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, size_t& rPos, SdrPageView* pPV, bool bMakeLines)
1559 {
1560  const SdrPathObj* pSrcPath = dynamic_cast<const SdrPathObj*>( pObj );
1561  const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>( pObj );
1562 
1563  const bool bUndo = IsUndoEnabled();
1564 
1565  if(pSrcPath)
1566  {
1567  // #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1568  SdrObject* pLast = nullptr; // to be able to apply OutlinerParaObject
1569  const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1570  const sal_uInt32 nPolyCount(rPolyPolygon.count());
1571 
1572  for(sal_uInt32 a(0); a < nPolyCount; a++)
1573  {
1574  const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1575  const sal_uInt32 nPointCount(rCandidate.count());
1576 
1577  if(!bMakeLines || nPointCount < 2)
1578  {
1579  SdrPathObj* pPath = new SdrPathObj(
1580  pSrcPath->getSdrModelFromSdrObject(),
1581  static_cast<SdrObjKind>(pSrcPath->GetObjIdentifier()),
1582  basegfx::B2DPolyPolygon(rCandidate));
1583  ImpCopyAttributes(pSrcPath, pPath);
1584  pLast = pPath;
1585  rOL.InsertObject(pPath, rPos);
1586  if( bUndo )
1587  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1588  MarkObj(pPath, pPV, false, true);
1589  rPos++;
1590  }
1591  else
1592  {
1593  const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1594 
1595  for(sal_uInt32 b(0); b < nLoopCount; b++)
1596  {
1597  SdrObjKind eKind(OBJ_PLIN);
1598  basegfx::B2DPolygon aNewPolygon;
1599  const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1600 
1601  aNewPolygon.append(rCandidate.getB2DPoint(b));
1602 
1603  if(rCandidate.areControlPointsUsed())
1604  {
1605  aNewPolygon.appendBezierSegment(
1606  rCandidate.getNextControlPoint(b),
1607  rCandidate.getPrevControlPoint(nNextIndex),
1608  rCandidate.getB2DPoint(nNextIndex));
1609  eKind = OBJ_PATHLINE;
1610  }
1611  else
1612  {
1613  aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1614  }
1615 
1616  SdrPathObj* pPath = new SdrPathObj(
1617  pSrcPath->getSdrModelFromSdrObject(),
1618  eKind,
1619  basegfx::B2DPolyPolygon(aNewPolygon));
1620  ImpCopyAttributes(pSrcPath, pPath);
1621  pLast = pPath;
1622  rOL.InsertObject(pPath, rPos);
1623  if( bUndo )
1624  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1625  MarkObj(pPath, pPV, false, true);
1626  rPos++;
1627  }
1628  }
1629  }
1630 
1631  if(pLast && pSrcPath->GetOutlinerParaObject())
1632  {
1633  pLast->SetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pSrcPath->GetOutlinerParaObject()));
1634  }
1635  }
1636  else if(pCustomShape)
1637  {
1638  if(bMakeLines)
1639  {
1640  // break up custom shape
1641  const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1642 
1643  if(pReplacement)
1644  {
1645  SdrObject* pCandidate(pReplacement->CloneSdrObject(pReplacement->getSdrModelFromSdrObject()));
1646  DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)");
1647 
1648  if(pCustomShape->GetMergedItem(SDRATTR_SHADOW).GetValue())
1649  {
1650  if(dynamic_cast<const SdrObjGroup*>( pReplacement) != nullptr)
1651  {
1652  pCandidate->SetMergedItem(makeSdrShadowItem(true));
1653  }
1654  }
1655 
1656  rOL.InsertObject(pCandidate, rPos);
1657  if( bUndo )
1658  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1659  MarkObj(pCandidate, pPV, false, true);
1660 
1661  if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1662  {
1663  // #i37011# also create a text object and add at rPos + 1
1665  pCustomShape->getSdrModelFromSdrObject(),
1666  pCustomShape->GetObjInventor(),
1667  OBJ_TEXT);
1668 
1669  // Copy text content
1670  OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1671  if(pParaObj)
1672  {
1673  pTextObj->NbcSetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pParaObj));
1674  }
1675 
1676  // copy all attributes
1677  SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1678 
1679  // clear fill and line style
1680  aTargetItemSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
1681  aTargetItemSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
1682 
1683  // get the text bounds and set at text object
1684  tools::Rectangle aTextBounds = pCustomShape->GetSnapRect();
1685  if(pCustomShape->GetTextBounds(aTextBounds))
1686  {
1687  pTextObj->SetSnapRect(aTextBounds);
1688  }
1689 
1690  // if rotated, copy GeoStat, too.
1691  const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1692  if(rSourceGeo.nRotationAngle)
1693  {
1694  pTextObj->NbcRotate(
1695  pCustomShape->GetSnapRect().Center(), rSourceGeo.nRotationAngle,
1696  rSourceGeo.nSin, rSourceGeo.nCos);
1697  }
1698 
1699  // set modified ItemSet at text object
1700  pTextObj->SetMergedItemSet(aTargetItemSet);
1701 
1702  // insert object
1703  rOL.InsertObject(pTextObj, rPos + 1);
1704  if( bUndo )
1705  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1706  MarkObj(pTextObj, pPV, false, true);
1707  }
1708  }
1709  }
1710  }
1711 }
1712 
1714 {
1715  // temporary MarkList
1716  SdrMarkList aRemoveBuffer;
1717 
1718  SortMarkedObjects();
1719 
1720  const bool bUndo = IsUndoEnabled();
1721 
1722  if( bUndo )
1723  {
1724  // comment is constructed later
1725  BegUndo("", "", bMakeLines ? SdrRepeatFunc::DismantleLines : SdrRepeatFunc::DismantlePolys);
1726  }
1727 
1728  SdrObjList* pOL0=nullptr;
1729  for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1730  --nm;
1731  SdrMark* pM=GetSdrMarkByIndex(nm);
1732  SdrObject* pObj=pM->GetMarkedSdrObj();
1733  SdrPageView* pPV=pM->GetPageView();
1735  if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // make sure OrdNums are correct!
1736  if (ImpCanDismantle(pObj,bMakeLines)) {
1737  aRemoveBuffer.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1738  const size_t nPos0=pObj->GetOrdNumDirect();
1739  size_t nPos=nPos0+1;
1740  SdrObjList* pSubList=pObj->GetSubList();
1741  if (pSubList!=nullptr && !pObj->Is3DObj()) {
1742  SdrObjListIter aIter(pSubList,SdrIterMode::DeepNoGroups);
1743  while (aIter.IsMore()) {
1744  const SdrObject* pObj1=aIter.Next();
1745  ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1746  }
1747  } else {
1748  ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1749  }
1750  if( bUndo )
1751  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,true));
1752  pOL->RemoveObject(nPos0);
1753 
1754  if( !bUndo )
1755  SdrObject::Free(pObj);
1756  }
1757  }
1758 
1759  if( bUndo )
1760  {
1761  // construct UndoComment from objects actually used
1762  SetUndoComment(SvxResId(bMakeLines?STR_EditDismantle_Lines:STR_EditDismantle_Polys),aRemoveBuffer.GetMarkDescription());
1763  // remove objects actually used from the list
1764  EndUndo();
1765  }
1766 }
1767 
1768 
1769 // Group
1770 
1771 
1773 {
1774  if (AreObjectsMarked())
1775  {
1776  SortMarkedObjects();
1777 
1778  const bool bUndo = IsUndoEnabled();
1779  if( bUndo )
1780  {
1781  BegUndo(SvxResId(STR_EditGroup),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Group);
1782 
1783  for(size_t nm = GetMarkedObjectCount(); nm>0; )
1784  {
1785  // add UndoActions for all affected objects
1786  --nm;
1787  SdrMark* pM=GetSdrMarkByIndex(nm);
1788  SdrObject* pObj = pM->GetMarkedSdrObj();
1789  AddUndoActions( CreateConnectorUndo( *pObj ) );
1790  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1791  }
1792  }
1793 
1794  SdrMarkList aNewMark;
1795  SdrPageView* pPV = GetSdrPageView();
1796 
1797  if(pPV)
1798  {
1799  SdrObjList* pCurrentLst=pPV->GetObjList();
1800  SdrObjList* pSrcLst=pCurrentLst;
1801  SdrObjList* pSrcLst0=pSrcLst;
1802  // make sure OrdNums are correct
1803  if (pSrcLst->IsObjOrdNumsDirty())
1804  pSrcLst->RecalcObjOrdNums();
1805  SdrObject* pGrp=nullptr;
1806  SdrObjList* pDstLst=nullptr;
1807  // if all selected objects come from foreign object lists.
1808  // the group object is the last one in the list.
1809  size_t nInsPos=pSrcLst->GetObjCount();
1810  bool bNeedInsPos=true;
1811  for (size_t nm=GetMarkedObjectCount(); nm>0;)
1812  {
1813  --nm;
1814  SdrMark* pM=GetSdrMarkByIndex(nm);
1815  if (pM->GetPageView()==pPV)
1816  {
1817  SdrObject* pObj=pM->GetMarkedSdrObj();
1818  if (nullptr==pGrp)
1819  {
1820  pGrp = new SdrObjGroup(pObj->getSdrModelFromSdrObject());
1821  pDstLst=pGrp->GetSubList();
1822  DBG_ASSERT(pDstLst!=nullptr,"Alleged group object doesn't return object list.");
1823  }
1824  pSrcLst=pObj->getParentSdrObjListFromSdrObject();
1825  if (pSrcLst!=pSrcLst0)
1826  {
1827  if (pSrcLst->IsObjOrdNumsDirty())
1828  pSrcLst->RecalcObjOrdNums();
1829  }
1830  bool bForeignList=pSrcLst!=pCurrentLst;
1831  if (!bForeignList && bNeedInsPos)
1832  {
1833  nInsPos=pObj->GetOrdNum(); // this way, all ObjOrdNum of the page are set
1834  nInsPos++;
1835  bNeedInsPos=false;
1836  }
1837  pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1838  if (!bForeignList)
1839  nInsPos--; // correct InsertPos
1840  pDstLst->InsertObject(pObj,0);
1841  GetMarkedObjectListWriteAccess().DeleteMark(nm);
1842  pSrcLst0=pSrcLst;
1843  }
1844  }
1845  if (pGrp!=nullptr)
1846  {
1847  aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1848  const size_t nCount=pDstLst->GetObjCount();
1849  pCurrentLst->InsertObject(pGrp,nInsPos);
1850  if( bUndo )
1851  {
1852  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // no recalculation!
1853  for (size_t no=0; no<nCount; ++no)
1854  {
1855  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1856  }
1857  }
1858  }
1859  }
1860  GetMarkedObjectListWriteAccess().Merge(aNewMark);
1861  MarkListHasChanged();
1862 
1863  if( bUndo )
1864  EndUndo();
1865  }
1866 }
1867 
1868 
1869 // Ungroup
1870 
1871 
1873 {
1874  SdrMarkList aNewMark;
1875 
1876  const bool bUndo = IsUndoEnabled();
1877  if( bUndo )
1878  BegUndo("", "", SdrRepeatFunc::Ungroup);
1879 
1880  size_t nCount=0;
1881  OUString aName1;
1882  OUString aName;
1883  bool bNameOk=false;
1884  for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1885  --nm;
1886  SdrMark* pM=GetSdrMarkByIndex(nm);
1887  SdrObject* pGrp=pM->GetMarkedSdrObj();
1888  SdrObjList* pSrcLst=pGrp->GetSubList();
1889  if (pSrcLst!=nullptr) {
1890  nCount++;
1891  if (nCount==1) {
1892  aName = pGrp->TakeObjNameSingul(); // retrieve name of group
1893  aName1 = pGrp->TakeObjNamePlural(); // retrieve name of group
1894  bNameOk=true;
1895  } else {
1896  if (nCount==2) aName=aName1; // set plural name
1897  if (bNameOk) {
1898  OUString aStr(pGrp->TakeObjNamePlural()); // retrieve name of group
1899 
1900  if (aStr != aName)
1901  bNameOk = false;
1902  }
1903  }
1904  size_t nDstCnt=pGrp->GetOrdNum();
1905  SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1906 
1907  // FIRST move contained objects to parent of group, so that
1908  // the contained objects are NOT migrated to the UNDO-ItemPool
1909  // when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1910  const size_t nObjCount=pSrcLst->GetObjCount();
1911 
1912  if( bUndo )
1913  {
1914  for (size_t no=nObjCount; no>0;)
1915  {
1916  no--;
1917  SdrObject* pObj=pSrcLst->GetObj(no);
1918  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1919  }
1920  }
1921  for (size_t no=0; no<nObjCount; ++no)
1922  {
1923  SdrObject* pObj=pSrcLst->RemoveObject(0);
1924  pDstLst->InsertObject(pObj,nDstCnt);
1925  if( bUndo )
1926  AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1927  nDstCnt++;
1928  // No SortCheck when inserting into MarkList, because that would
1929  // provoke a RecalcOrdNums() each time because of pObj->GetOrdNum():
1930  aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),false);
1931  }
1932 
1933  if( bUndo )
1934  {
1935  // Now it is safe to add the delete-UNDO which triggers the
1936  // MigrateItemPool now only for itself, not for the sub-objects.
1937  // nDstCnt is right, because previous inserts move group
1938  // object deeper and increase nDstCnt.
1939  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1940  }
1941  pDstLst->RemoveObject(nDstCnt);
1942 
1943  if( !bUndo )
1944  SdrObject::Free(pGrp);
1945 
1946  GetMarkedObjectListWriteAccess().DeleteMark(nm);
1947  }
1948  }
1949  if (nCount!=0)
1950  {
1951  if (!bNameOk)
1952  aName=SvxResId(STR_ObjNamePluralGRUP); // Use the term "Group Objects," if different objects are grouped.
1953  SetUndoComment(SvxResId(STR_EditUngroup),aName);
1954  }
1955 
1956  if( bUndo )
1957  EndUndo();
1958 
1959  if (nCount!=0)
1960  {
1961  GetMarkedObjectListWriteAccess().Merge(aNewMark,true); // Because of the sorting above, aNewMark is reversed
1962  MarkListHasChanged();
1963  }
1964 }
1965 
1966 
1967 // ConvertToPoly
1968 
1969 
1970 SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, bool bPath, bool bLineToArea)
1971 {
1972  SdrObjectUniquePtr pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
1973  if (pNewObj)
1974  {
1976  const bool bUndo = IsUndoEnabled();
1977  if( bUndo )
1978  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
1979 
1980  pOL->ReplaceObject(pNewObj.get(), pObj->GetOrdNum());
1981 
1982  if( !bUndo )
1983  SdrObject::Free(pObj);
1984  }
1985  return pNewObj.release();
1986 }
1987 
1988 void SdrEditView::ImpConvertTo(bool bPath, bool bLineToArea)
1989 {
1990  if (AreObjectsMarked()) {
1991  bool bMrkChg = false;
1992  const size_t nMarkCount=GetMarkedObjectCount();
1993  const char* pDscrID = nullptr;
1994  if(bLineToArea)
1995  {
1996  if(nMarkCount == 1)
1997  pDscrID = STR_EditConvToContour;
1998  else
1999  pDscrID = STR_EditConvToContours;
2000 
2001  BegUndo(SvxResId(pDscrID), GetDescriptionOfMarkedObjects());
2002  }
2003  else
2004  {
2005  if (bPath) {
2006  if (nMarkCount==1) pDscrID=STR_EditConvToCurve;
2007  else pDscrID=STR_EditConvToCurves;
2008  BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPath);
2009  } else {
2010  if (nMarkCount==1) pDscrID=STR_EditConvToPoly;
2011  else pDscrID=STR_EditConvToPolys;
2012  BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPoly);
2013  }
2014  }
2015  for (size_t nm=nMarkCount; nm>0;) {
2016  --nm;
2017  SdrMark* pM=GetSdrMarkByIndex(nm);
2018  SdrObject* pObj=pM->GetMarkedSdrObj();
2019  SdrPageView* pPV=pM->GetPageView();
2020  if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
2021  SdrObject* pGrp=pObj;
2023  while (aIter.IsMore()) {
2024  pObj=aIter.Next();
2025  ImpConvertOneObj(pObj,bPath,bLineToArea);
2026  }
2027  } else {
2028  SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
2029  if (pNewObj!=nullptr) {
2030  bMrkChg=true;
2031  GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
2032  }
2033  }
2034  }
2035  EndUndo();
2036  if (bMrkChg)
2037  {
2038  AdjustMarkHdl();
2039  MarkListHasChanged();
2040  }
2041  }
2042 }
2043 
2045 {
2046  ImpConvertTo(true, bLineToArea);
2047 }
2048 
2050 {
2051  ImpConvertTo(false, false/*bLineToArea*/);
2052 }
2053 
2054 namespace
2055 {
2056  GDIMetaFile GetMetaFile(SdrGrafObj const * pGraf)
2057  {
2058  if (pGraf->HasGDIMetaFile())
2060  assert(pGraf->isEmbeddedVectorGraphicData());
2062  }
2063 }
2064 
2065 // Metafile Import
2067 {
2068  const bool bUndo = IsUndoEnabled();
2069 
2070  if( bUndo )
2071  BegUndo("", "", SdrRepeatFunc::ImportMtf);
2072 
2073  SortMarkedObjects();
2074  SdrMarkList aForTheDescription;
2075  SdrMarkList aNewMarked;
2076  for (size_t nm =GetMarkedObjectCount(); nm > 0; )
2077  {
2078  // create Undo objects for all new objects
2079  // check for cancellation between the metafiles
2080  if (pProgrInfo != nullptr)
2081  {
2082  pProgrInfo->SetNextObject();
2083  if (!pProgrInfo->ReportActions(0))
2084  break;
2085  }
2086 
2087  --nm;
2088  SdrMark* pM=GetSdrMarkByIndex(nm);
2089  SdrObject* pObj=pM->GetMarkedSdrObj();
2090  SdrPageView* pPV=pM->GetPageView();
2092  const size_t nInsPos=pObj->GetOrdNum()+1;
2093  size_t nInsCnt=0;
2094  tools::Rectangle aLogicRect;
2095 
2096  SdrGrafObj* pGraf = dynamic_cast<SdrGrafObj*>( pObj );
2097  if (pGraf != nullptr)
2098  {
2099  if (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedVectorGraphicData())
2100  {
2101  GDIMetaFile aMetaFile(GetMetaFile(pGraf));
2102  if (aMetaFile.GetActionSize())
2103  {
2104  aLogicRect = pGraf->GetLogicRect();
2105  ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2106  nInsCnt = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
2107  }
2108  }
2109  }
2110 
2111  SdrOle2Obj* pOle2 = dynamic_cast<SdrOle2Obj*>(pObj);
2112  if (pOle2 != nullptr && pOle2->GetGraphic())
2113  {
2114  aLogicRect = pOle2->GetLogicRect();
2115  ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2116  nInsCnt = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
2117  }
2118 
2119  if (nInsCnt != 0)
2120  {
2121  // transformation
2122  GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
2123  size_t nObj = nInsPos;
2124 
2125  if (aGeoStat.nShearAngle)
2126  aGeoStat.RecalcTan();
2127 
2128  if (aGeoStat.nRotationAngle)
2129  aGeoStat.RecalcSinCos();
2130 
2131  for (size_t i = 0; i < nInsCnt; i++)
2132  {
2133  if (bUndo)
2134  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2135 
2136  // update new MarkList
2137  SdrObject* pCandidate = pOL->GetObj(nObj);
2138 
2139  // apply original transformation
2140  if (aGeoStat.nShearAngle)
2141  pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
2142 
2143  if (aGeoStat.nRotationAngle)
2144  pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
2145 
2146  SdrMark aNewMark(pCandidate, pPV);
2147  aNewMarked.InsertEntry(aNewMark);
2148 
2149  nObj++;
2150  }
2151 
2152  aForTheDescription.InsertEntry(*pM);
2153 
2154  if (bUndo)
2155  AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2156 
2157  // remove object from selection and delete
2158  GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2159  pOL->RemoveObject(nInsPos-1);
2160 
2161  if (!bUndo)
2162  SdrObject::Free(pObj);
2163  }
2164  }
2165 
2166  if (aNewMarked.GetMarkCount())
2167  {
2168  // create new selection
2169  for (size_t a = 0; a < aNewMarked.GetMarkCount(); ++a)
2170  {
2171  GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2172  }
2173 
2174  SortMarkedObjects();
2175  }
2176 
2177  if (bUndo)
2178  {
2179  SetUndoComment(SvxResId(STR_EditImportMtf),aForTheDescription.GetMarkDescription());
2180  EndUndo();
2181  }
2182 }
2183 
2184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ImpCheckToTopBtmPossible()
Definition: svdedtv2.cxx:485
Point TopLeft() const
void MovMarkedToBtm()
Definition: svdedtv2.cxx:157
GDIMetaFile getMetafileFromEmbeddedVectorGraphicData() const
Definition: svdograf.cxx:843
#define EE_ITEMS_START
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const
Definition: svdobj.cxx:562
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
size_t GetMarkCount() const
Definition: svdmark.hxx:180
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:853
void PutMarkedInFrontOfObj(const SdrObject *pRefObj)
Definition: svdedtv2.cxx:252
static bool ImpCanDismantle(const basegfx::B2DPolyPolygon &rPpolyPpolygon, bool bMakeLines)
Definition: svdedtv2.cxx:1456
void EqualizeMarkedObjects(bool bWidth)
Definition: svdedtv2.cxx:1164
static bool ImpCanConvertForCombine1(const SdrObject *pObj)
Definition: svdedtv2.cxx:573
static basegfx::B2DPolyPolygon ImpGetPolyPolygon1(const SdrObject *pObj)
Definition: svdedtv2.cxx:621
void setClosed(bool bNew)
double nSin
Definition: svdtrans.hxx:219
periodic cubic Spline (ni)
Definition: svdobj.hxx:133
static bool ImpCanConvertForCombine(const SdrObject *pObj)
Definition: svdedtv2.cxx:591
static SvxAbstractDialogFactory * Create()
Definition: svxdlg.cxx:23
bool IsTextFrame() const
Definition: svdotext.hxx:343
void SetNextObject()
Definition: svdetc.cxx:489
long nRotationAngle
Definition: svdtrans.hxx:216
B2DPolyPolygon solvePolygonOperationOr(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
sal_Int64 n
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:766
void RecalcObjOrdNums()
recalculate order numbers / ZIndex
Definition: svdpage.cxx:252
size_t GetObjCount() const
Definition: svdpage.cxx:760
void PutMarkedBehindObj(const SdrObject *pRefObj)
Definition: svdedtv2.cxx:353
void appendBezierSegment(const basegfx::B2DPoint &rNextControlPoint, const basegfx::B2DPoint &rPrevControlPoint, const basegfx::B2DPoint &rPoint)
bool IsOver(const tools::Rectangle &rRect) const
static bool isWhiteSpace(const sal_Unicode ch)
void PutMarkedToTop()
Definition: svdedtv2.cxx:247
vector< ImpDistributeEntry > ImpDistributeEntryList
Definition: svdedtv2.cxx:769
#define SDRATTR_NOTPERSIST_LAST
Definition: svddef.hxx:309
virtual OUString TakeObjNameSingul() const
Definition: svdobj.cxx:1017
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:229
sal_Int32 GetParagraphCount() const
#define SDRATTR_END
Definition: svddef.hxx:417
sal_Int64 getTimeStamp() const
Definition: svdmark.hxx:130
static void Free(SdrObject *&_rpObject)
Definition: svdobj.cxx:395
void RecalcTan()
Definition: svdtrans.cxx:462
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
Definition: svdpage.cxx:351
virtual const tools::Rectangle & GetSnapRect() const override
Definition: svdoattr.cxx:48
virtual SdrObjList * GetSubList() const
Definition: svdobj.cxx:646
polygon, PolyPolygon
Definition: svdobj.hxx:126
virtual bool HasText() const override
Definition: svdotxat.cxx:412
static basegfx::B2DPolyPolygon ImpGetPolyPolygon(const SdrObject *pObj)
Definition: svdedtv2.cxx:668
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:39
bool IsObjOrdNumsDirty() const
Definition: svdpage.hxx:108
Provides information about various ZObject properties.
Definition: svdobj.hxx:248
virtual SdrObject * GetMaxToBtmObj(SdrObject *pObj) const
Definition: svdedtv2.cxx:61
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void ClearMergedItem(const sal_uInt16 nWhich=0)
Definition: svdobj.cxx:1898
#define SDRATTR_NOTPERSIST_FIRST
Definition: svddef.hxx:272
bool IsMore() const
Definition: svditer.hxx:62
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
void MovMarkedToTop()
Definition: svdedtv2.cxx:70
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:214
int nCount
void ConvertMarkedToPolyObj()
Definition: svdedtv2.cxx:2049
SfxStyleSheet * GetStyleSheet() const
Definition: svdobj.cxx:2134
const GDIMetaFile & GetGDIMetaFile() const
void SetMergedItemSet(const SfxItemSet &rSet, bool bClearAllItems=false)
Definition: svdobj.cxx:1908
PolyLine.
Definition: svdobj.hxx:127
static SdrObject * MakeNewObject(SdrModel &rSdrModel, SdrInventor nInventor, sal_uInt16 nObjIdentifier, const tools::Rectangle *pSnapRect=nullptr)
Definition: svdobj.cxx:3043
B2DPolyPolygon solvePolygonOperationAnd(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
const GeoStat & GetGeoStat() const
Definition: svdotext.hxx:399
virtual void NbcRotate(const Point &rRef, long nAngle, double sn, double cs)
Definition: svdobj.cxx:1400
B2DPolyPolygon solvePolygonOperationDiff(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
sal_uInt32 GetOrdNumDirect() const
Definition: svdobj.hxx:891
void ConvertMarkedToPathObj(bool bLineToArea)
Definition: svdedtv2.cxx:2044
SdrObjList * GetObjList() const
Return current List.
Definition: svdpagv.hxx:174
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
Everything a View needs to know about a selected object.
Definition: svdmark.hxx:44
Graphic GetTransformedGraphic(SdrGrafObjTransformsAttrs nTransformFlags=SdrGrafObjTransformsAttrs::ALL) const
Definition: svdograf.cxx:334
double nCos
Definition: svdtrans.hxx:220
#define DBG_ASSERT(sCon, aError)
int i
uno_Any a
bool IsLayerLocked(const OUString &rName) const
Definition: svdpagv.hxx:198
void ImpCopyAttributes(const SdrObject *pSource, SdrObject *pDest) const
Definition: svdedtv2.cxx:546
SdrPageView * GetPageView() const
Definition: svdmark.hxx:70
size_t DoImport(const GDIMetaFile &rMtf, SdrObjList &rDestList, size_t nInsPos, SvdProgressInfo *pProgrInfo=nullptr)
Definition: svdfmtf.cxx:210
Helper class for the communication between the dialog In order to break open Metafiles (sd/source/ui/...
Definition: svdetc.hxx:111
void CombineMarkedObjects(bool bNoPolyPoly=true)
Definition: svdedtv2.cxx:1282
SvxDistributeVertical
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:272
sal_uInt32 GetOrdNum() const
The order number (aka ZOrder, aka z-index) determines whether a SdrObject is located above or below a...
Definition: svdobj.cxx:795
#define SDRATTR_SHADOW
Definition: svddef.hxx:176
virtual sal_uInt16 GetObjIdentifier() const override
Definition: svdotext.cxx:415
bool IsGroupObject() const
Definition: svdobj.cxx:641
#define XATTR_LINESTYLE
Definition: xdef.hxx:90
virtual void SetLogicRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1630
void DistributeMarkedObjects(weld::Window *pParent)
Definition: svdedtv2.cxx:771
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1893
#define SDRATTR_START
Definition: svddef.hxx:173
OUString GetText(Paragraph const *pPara, sal_Int32 nParaCount=1) const
#define XATTR_FILLSTYLE
Definition: xdef.hxx:107
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:1918
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:79
Abstract DrawObject.
Definition: svdobj.hxx:312
bool ReportActions(size_t nActionCount)
Definition: svdetc.cxx:455
virtual SdrObject * RemoveObject(size_t nObjNum)
Definition: svdpage.cxx:429
virtual void ObjOrderChanged(SdrObject *pObj, size_t nOldPos, size_t nNewPos)
Definition: svdedtv2.cxx:66
void UnGroupMarked()
Definition: svdedtv2.cxx:1872
SdrInsertFlags
Definition: svdedtv.hxx:58
Size GetSize() const
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:552
void CombineMarkedTextObjects()
Definition: svdedtv2.cxx:1218
Paragraph * GetParagraph(sal_Int32 nAbsPos) const
virtual SdrLayerID GetLayer() const
Definition: svdobj.cxx:576
const SdrObject * GetSdrObjectFromCustomShape() const
Definition: svdoashp.cxx:402
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
virtual void NbcShear(const Point &rRef, long nAngle, double tn, bool bVShear)
Definition: svdobj.cxx:1459
bool IsLine() const
Definition: svdopath.hxx:145
SdrObject * Next()
Definition: svditer.hxx:63
std::unique_ptr< OutlinerParaObject > CreateParaObject(sal_Int32 nStartPara=0, sal_Int32 nParaCount=EE_PARA_ALL) const
SdrObjectUniquePtr ConvertToPolyObj(bool bBezier, bool bLineToArea) const
Definition: svdobj.cxx:2504
void ForceSort() const
Definition: svdmark.cxx:141
sal_uInt32 count() const
virtual void NbcSetOutlinerParaObject(std::unique_ptr< OutlinerParaObject > pTextObject)
Definition: svdobj.cxx:1738
virtual SdrObject * ReplaceObject(SdrObject *pNewObj, size_t nObjNum)
Replace existing object by different one.
Definition: svdpage.cxx:485
SdrObjKind
Definition: svdobj.hxx:116
#define SAL_WARN_IF(condition, area, stream)
void GroupMarked()
Definition: svdedtv2.cxx:1772
void DismantleMarkedObjects(bool bMakeLines=false)
Definition: svdedtv2.cxx:1713
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1354
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svddrgmt.hxx:168
OUString aName
static basegfx::B2DPolygon ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon &rPolyPolygon)
Definition: svdedtv2.cxx:691
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1883
bool HasGDIMetaFile() const
Definition: svdograf.cxx:833
RET_OK
bool IsTextPath() const
Definition: svdoashp.cxx:440
void insert(sal_uInt32 nIndex, const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
void AddText(const OutlinerParaObject &, bool bAppend=false)
virtual SdrObject * CloneSdrObject(SdrModel &rTargetModel) const
Definition: svdobj.cxx:973
void SetOutlinerParaObject(std::unique_ptr< OutlinerParaObject > pTextObject)
Definition: svdobj.cxx:1727
virtual sal_uInt16 GetObjIdentifier() const override
Definition: svdopath.cxx:1813
size_t GetActionSize() const
bool GetTextBounds(tools::Rectangle &rTextBound) const
Definition: svdoashp.cxx:536
std::unique_ptr< SdrObject, SdrObjectFreeOp > SdrObjectUniquePtr
Definition: svdobj.hxx:114
SdrOnOffItem makeSdrShadowItem(bool bShadow)
Definition: sdshitm.hxx:25
double getLength(const B2DPolygon &rCandidate)
const basegfx::B2DPolyPolygon & GetPathPoly() const
Definition: svdopath.hxx:139
virtual OUString TakeObjNamePlural() const
Definition: svdobj.cxx:1032
bool IsOutlText() const
Definition: svdotext.hxx:344
virtual void SetSnapRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1621
#define XATTR_FORMTXTSTYLE
Definition: xdef.hxx:131
void ImpConvertTo(bool bPath, bool bLineToArea)
Definition: svdedtv2.cxx:1988
virtual SdrObject * GetMaxToTopObj(SdrObject *pObj) const
Definition: svdedtv2.cxx:56
void ImpDismantleOneObject(const SdrObject *pObj, SdrObjList &rOL, size_t &rPos, SdrPageView *pPV, bool bMakeLines)
Definition: svdedtv2.cxx:1558
virtual SdrObject * SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
Modify ZOrder of an SdrObject.
Definition: svdpage.cxx:549
void ReverseOrderOfMarked()
Definition: svdedtv2.cxx:433
virtual const tools::Rectangle & GetLogicRect() const
Definition: svdobj.cxx:1606
void PutMarkedToBtm()
Definition: svdedtv2.cxx:348
B2DPolygon simplifyCurveSegments(const B2DPolygon &rCandidate)
SdrObjList * getParentSdrObjListFromSdrObject() const
Definition: svdobj.cxx:298
virtual void NbcSetStyleSheet(SfxStyleSheet *pNewStyleSheet, bool bDontRemoveHardAttr)
Definition: svdobj.cxx:2152
SvxDistributeHorizontal
const OUString & GetMarkDescription() const
Definition: svdmark.cxx:415
SdrMergeMode
Definition: svdedtv.hxx:51
B2DPolyPolygon prepareForPolygonOperation(const B2DPolygon &rCandidate)
void DoImportMarkedMtf(SvdProgressInfo *pProgrInfo=nullptr)
Definition: svdedtv2.cxx:2066
void MergeMarkedObjects(SdrMergeMode eMode)
Definition: svdedtv2.cxx:987
void InsertEntry(const SdrMark &rMark, bool bChkSort=true)
Definition: svdmark.cxx:259
void setWidth(long nWidth)
bool isEmbeddedVectorGraphicData() const
Definition: svdograf.cxx:838
virtual OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdobj.cxx:1742
bool Is3DObj() const
Definition: svdobj.hxx:795
aStr
SdrObject * ImpConvertOneObj(SdrObject *pObj, bool bPath, bool bLineToArea)
Definition: svdedtv2.cxx:1970
open Bezier-curve
Definition: svdobj.hxx:128
Point Center() const
sal_uInt16 nPos
const Graphic * GetGraphic() const
Definition: svdoole2.cxx:1648
virtual const tools::Rectangle & GetLogicRect() const override
Definition: svdotxtr.cxx:69
virtual void NbcSetLayer(SdrLayerID nLayer)
Definition: svdobj.cxx:593
#define EE_ITEMS_END