Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/svx/source/svdraw/svdobj.cxx
Line
Count
Source (jump to first uncovered line)
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/svdobj.hxx>
21
#include <config_features.h>
22
23
#include <sal/config.h>
24
25
#include <com/sun/star/text/RelOrientation.hpp>
26
#include <com/sun/star/frame/XTerminateListener.hpp>
27
#include <com/sun/star/frame/Desktop.hpp>
28
29
#include <basegfx/matrix/b2dhommatrix.hxx>
30
#include <basegfx/matrix/b2dhommatrixtools.hxx>
31
#include <basegfx/polygon/b2dpolygon.hxx>
32
#include <basegfx/polygon/b2dpolygontools.hxx>
33
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
34
#include <basegfx/polygon/b2dpolypolygontools.hxx>
35
#include <basegfx/range/b2drange.hxx>
36
#include <drawinglayer/processor2d/contourextractor2d.hxx>
37
#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
38
#include <comphelper/processfactory.hxx>
39
#include <editeng/editeng.hxx>
40
#include <editeng/outlobj.hxx>
41
#include <o3tl/deleter.hxx>
42
#include <math.h>
43
#include <svl/grabbagitem.hxx>
44
#include <tools/bigint.hxx>
45
#include <tools/helpers.hxx>
46
#include <comphelper/configuration.hxx>
47
#include <vcl/canvastools.hxx>
48
#include <vcl/ptrstyle.hxx>
49
#include <vector>
50
51
#include <svx/svdotable.hxx>
52
53
#include <svx/sdr/contact/displayinfo.hxx>
54
#include <sdr/contact/objectcontactofobjlistpainter.hxx>
55
#include <svx/sdr/contact/viewcontactofsdrobj.hxx>
56
#include <sdr/properties/emptyproperties.hxx>
57
#include <svx/annotation/ObjectAnnotationData.hxx>
58
#include <svx/sdrhittesthelper.hxx>
59
#include <svx/sdrobjectuser.hxx>
60
#include <svx/sdrobjectfilter.hxx>
61
#include <svx/svddrag.hxx>
62
#include <svx/svdetc.hxx>
63
#include <svx/svdhdl.hxx>
64
#include <svx/svditer.hxx>
65
#include <svx/svdmodel.hxx>
66
#include <svx/svdoashp.hxx>
67
#include <svx/svdocapt.hxx>
68
#include <svx/svdocirc.hxx>
69
#include <svx/svdoedge.hxx>
70
#include <svx/svdograf.hxx>
71
#include <svx/svdogrp.hxx>
72
#include <svx/svdomeas.hxx>
73
#include <svx/svdomedia.hxx>
74
#include <svx/svdoole2.hxx>
75
#include <svx/svdopage.hxx>
76
#include <svx/svdopath.hxx>
77
#include <svx/svdorect.hxx>
78
#include <svx/svdotext.hxx>
79
#include <svx/svdouno.hxx>
80
#include <svx/svdovirt.hxx>
81
#include <svx/svdpage.hxx>
82
#include <svx/svdpool.hxx>
83
#include <svx/strings.hrc>
84
#include <svx/dialmgr.hxx>
85
#include <svx/svdtrans.hxx>
86
#include <svx/svdundo.hxx>
87
#include <svx/svdview.hxx>
88
#include <sxlayitm.hxx>
89
#include <sxlogitm.hxx>
90
#include <sxmovitm.hxx>
91
#include <sxoneitm.hxx>
92
#include <sxopitm.hxx>
93
#include <sxreoitm.hxx>
94
#include <sxrooitm.hxx>
95
#include <sxsaitm.hxx>
96
#include <sxsoitm.hxx>
97
#include <sxtraitm.hxx>
98
#include <svx/unopage.hxx>
99
#include <svx/unoshape.hxx>
100
#include <svx/xfillit0.hxx>
101
#include <svx/xflclit.hxx>
102
#include <svx/xfltrit.hxx>
103
#include <svx/xlineit0.hxx>
104
#include <svx/xlnclit.hxx>
105
#include <svx/xlnedwit.hxx>
106
#include <svx/xlnstwit.hxx>
107
#include <svx/xlntrit.hxx>
108
#include <svx/xlnwtit.hxx>
109
#include <svx/svdglue.hxx>
110
#include <svx/svdsob.hxx>
111
#include <svdobjplusdata.hxx>
112
#include <svdobjuserdatalist.hxx>
113
114
#include <optional>
115
#include <libxml/xmlwriter.h>
116
#include <memory>
117
118
#include <svx/scene3d.hxx>
119
#include <rtl/character.hxx>
120
#include <tools/UnitConversion.hxx>
121
#include <o3tl/string_view.hxx>
122
#include <tools/lazydelete.hxx>
123
124
using namespace ::com::sun::star;
125
126
127
SdrObjUserCall::~SdrObjUserCall()
128
1.22M
{
129
1.22M
}
130
131
void SdrObjUserCall::Changed(const SdrObject& /*rObj*/, SdrUserCallType /*eType*/, const tools::Rectangle& /*rOldBoundRect*/)
132
775k
{
133
775k
}
134
135
void const* SdrObjUserCall::GetPDFAnchorStructureElementKey(SdrObject const&)
136
0
{
137
0
    return nullptr;
138
0
}
139
140
SdrObjMacroHitRec::SdrObjMacroHitRec() :
141
0
    pVisiLayer(nullptr),
142
0
    pPageView(nullptr),
143
0
    nTol(0) {}
144
145
146
SdrObjUserData::SdrObjUserData(SdrInventor nInv, sal_uInt16 nId) :
147
1.73M
    m_nInventor(nInv),
148
1.73M
    m_nIdentifier(nId) {}
149
150
SdrObjUserData::SdrObjUserData(const SdrObjUserData& rData) :
151
9.74k
    m_nInventor(rData.m_nInventor),
152
9.74k
    m_nIdentifier(rData.m_nIdentifier) {}
153
154
1.74M
SdrObjUserData::~SdrObjUserData() {}
155
156
SdrObjGeoData::SdrObjGeoData():
157
46.3k
    bMovProt(false),
158
46.3k
    bSizProt(false),
159
46.3k
    bNoPrint(false),
160
46.3k
    bClosedObj(false),
161
46.3k
    mbVisible(true),
162
46.3k
    mnLayerID(0)
163
46.3k
{
164
46.3k
}
165
166
SdrObjGeoData::~SdrObjGeoData()
167
46.3k
{
168
46.3k
}
169
170
SdrObjTransformInfoRec::SdrObjTransformInfoRec() :
171
0
    bMoveAllowed(true),
172
0
    bResizeFreeAllowed(true),
173
0
    bResizePropAllowed(true),
174
0
    bRotateFreeAllowed(true),
175
0
    bRotate90Allowed(true),
176
0
    bMirrorFreeAllowed(true),
177
0
    bMirror45Allowed(true),
178
0
    bMirror90Allowed(true),
179
0
    bTransparenceAllowed(true),
180
0
    bShearAllowed(true),
181
0
    bEdgeRadiusAllowed(true),
182
0
    bNoOrthoDesired(true),
183
0
    bNoContortion(true),
184
0
    bCanConvToPath(true),
185
0
    bCanConvToPoly(true),
186
0
    bCanConvToContour(false),
187
0
    bCanConvToPathLineToArea(true),
188
0
    bCanConvToPolyLineToArea(true) {}
189
190
struct SdrObject::Impl
191
{
192
    sdr::ObjectUserVector maObjectUsers;
193
    std::optional<double> mnRelativeWidth;
194
    std::optional<double> mnRelativeHeight;
195
    sal_Int16               meRelativeWidthRelation;
196
    sal_Int16               meRelativeHeightRelation;
197
198
    Impl() :
199
2.67M
        meRelativeWidthRelation(text::RelOrientation::PAGE_FRAME),
200
2.67M
        meRelativeHeightRelation(text::RelOrientation::PAGE_FRAME) {}
201
};
202
203
const std::shared_ptr< svx::diagram::IDiagramHelper >& SdrObject::getDiagramHelper() const
204
846
{
205
846
    static std::shared_ptr< svx::diagram::IDiagramHelper > aEmpty;
206
846
    return aEmpty;
207
846
}
208
209
// BaseProperties section
210
211
sdr::properties::BaseProperties& SdrObject::GetProperties() const
212
65.6M
{
213
65.6M
    if(!mpProperties)
214
1.91M
    {
215
        // CAUTION(!) Do *not* call this during SdrObject construction,
216
        // that will lead to wrong type-casts (dependent on constructor-level)
217
        // and thus eventually create the wrong sdr::properties (!). Is there
218
        // a way to check if on the stack is a SdrObject-constructor (?)
219
1.91M
        const_cast< SdrObject* >(this)->mpProperties =
220
1.91M
            const_cast< SdrObject* >(this)->CreateObjectSpecificProperties();
221
1.91M
    }
222
223
65.6M
    return *mpProperties;
224
65.6M
}
225
226
227
// ObjectUser section
228
229
void SdrObject::AddObjectUser(sdr::ObjectUser& rNewUser)
230
2.24M
{
231
2.24M
    mpImpl->maObjectUsers.push_back(&rNewUser);
232
2.24M
}
233
234
void SdrObject::RemoveObjectUser(sdr::ObjectUser& rOldUser)
235
2.76M
{
236
2.76M
    const sdr::ObjectUserVector::iterator aFindResult =
237
2.76M
        std::find(mpImpl->maObjectUsers.begin(), mpImpl->maObjectUsers.end(), &rOldUser);
238
2.76M
    if (aFindResult != mpImpl->maObjectUsers.end())
239
2.24M
    {
240
2.24M
        mpImpl->maObjectUsers.erase(aFindResult);
241
2.24M
    }
242
2.76M
}
243
244
245
// DrawContact section
246
247
std::unique_ptr<sdr::contact::ViewContact> SdrObject::CreateObjectSpecificViewContact()
248
0
{
249
0
    return std::make_unique<sdr::contact::ViewContactOfSdrObj>(*this);
250
0
}
251
252
sdr::contact::ViewContact& SdrObject::GetViewContact() const
253
30.5M
{
254
30.5M
    if(!mpViewContact)
255
2.66M
    {
256
2.66M
        const_cast< SdrObject* >(this)->mpViewContact =
257
2.66M
            const_cast< SdrObject* >(this)->CreateObjectSpecificViewContact();
258
2.66M
    }
259
260
30.5M
    return *mpViewContact;
261
30.5M
}
262
263
// DrawContact support: Methods for handling Object changes
264
void SdrObject::ActionChanged() const
265
21.6M
{
266
    // Do necessary ViewContact actions
267
21.6M
    GetViewContact().ActionChanged();
268
21.6M
}
269
270
SdrPage* SdrObject::getSdrPageFromSdrObject() const
271
62.3M
{
272
62.3M
    if (SdrObjList* pParentList = getParentSdrObjListFromSdrObject())
273
48.4M
    {
274
48.4M
        return pParentList->getSdrPageFromSdrObjList();
275
48.4M
    }
276
277
13.9M
    return nullptr;
278
62.3M
}
279
280
SdrModel& SdrObject::getSdrModelFromSdrObject() const
281
108M
{
282
108M
    return mrSdrModelFromSdrObject;
283
108M
}
284
285
void SdrObject::setParentOfSdrObject(SdrObjList* pNewObjList)
286
4.99M
{
287
4.99M
    assert(!pNewObjList || mpParentOfSdrObject != pNewObjList);
288
4.99M
    if(mpParentOfSdrObject == pNewObjList)
289
0
        return;
290
    // we need to be removed from the old parent before we are attached to the new parent
291
4.99M
    assert(bool(mpParentOfSdrObject) != bool(pNewObjList) && "may only transition empty->full or full->empty");
292
293
    // remember current page
294
4.99M
    SdrPage* pOldPage(getSdrPageFromSdrObject());
295
296
    // set new parent
297
4.99M
    mpParentOfSdrObject = pNewObjList;
298
299
    // get new page
300
4.99M
    SdrPage* pNewPage(getSdrPageFromSdrObject());
301
302
    // broadcast page change over objects if needed
303
4.99M
    if(pOldPage != pNewPage)
304
2.82M
    {
305
2.82M
        handlePageChange(pOldPage, pNewPage);
306
2.82M
    }
307
4.99M
}
308
309
SdrObjList* SdrObject::getParentSdrObjListFromSdrObject() const
310
164M
{
311
164M
    return mpParentOfSdrObject;
312
164M
}
313
314
SdrObjList* SdrObject::getChildrenOfSdrObject() const
315
7.22M
{
316
    // default has no children
317
7.22M
    return nullptr;
318
7.22M
}
319
320
void SdrObject::SetBoundRectDirty()
321
20.7M
{
322
20.7M
    resetOutRectangle();
323
20.7M
}
324
325
void impAddIncarnatedSdrObjectToSdrModel(SdrObject& rSdrObject, SdrModel& rSdrModel)
326
2.67M
{
327
2.67M
    rSdrModel.maAllIncarnatedObjects.insert(&rSdrObject);
328
2.67M
}
329
void impRemoveIncarnatedSdrObjectToSdrModel(SdrObject& rSdrObject, SdrModel& rSdrModel)
330
2.67M
{
331
2.67M
    if(!rSdrModel.maAllIncarnatedObjects.erase(&rSdrObject))
332
0
    {
333
0
        assert(false && "SdrObject::~SdrObject: Destructed incarnation of SdrObject not member of this SdrModel (!)");
334
0
    }
335
2.67M
}
336
337
SdrObject::SdrObject(SdrModel& rSdrModel)
338
2.64M
    : mpFillGeometryDefiningShape(nullptr)
339
2.64M
    , mrSdrModelFromSdrObject(rSdrModel)
340
2.64M
    , m_pUserCall(nullptr)
341
2.64M
    , mpImpl(new Impl)
342
2.64M
    , mpParentOfSdrObject(nullptr)
343
2.64M
    , m_nOrdNum(0)
344
2.64M
    , mnNavigationPosition(SAL_MAX_UINT32)
345
2.64M
    , mnLayerID(0)
346
2.64M
    , mpSvxShape( nullptr )
347
2.64M
    , mbDoNotInsertIntoPageAutomatically(false)
348
2.64M
{
349
2.64M
    m_bVirtObj         =false;
350
2.64M
    m_bSnapRectDirty   =true;
351
2.64M
    m_bMovProt         =false;
352
2.64M
    m_bSizProt         =false;
353
2.64M
    m_bNoPrint         =false;
354
2.64M
    m_bEmptyPresObj    =false;
355
2.64M
    m_bNotVisibleAsMaster=false;
356
2.64M
    m_bClosedObj       =false;
357
2.64M
    mbVisible        = true;
358
359
    // #i25616#
360
2.64M
    mbLineIsOutsideGeometry = false;
361
362
    // #i25616#
363
2.64M
    mbSupportTextIndentingOnLineWidthChange = false;
364
365
2.64M
    m_bIsEdge=false;
366
2.64M
    m_bIs3DObj=false;
367
2.64M
    m_bMarkProt=false;
368
2.64M
    m_bIsUnoObj=false;
369
2.64M
    impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
370
2.64M
}
371
372
SdrObject::SdrObject(SdrModel& rSdrModel, SdrObject const & rSource)
373
26.4k
    : mpFillGeometryDefiningShape(nullptr)
374
26.4k
    , mrSdrModelFromSdrObject(rSdrModel)
375
26.4k
    , m_pUserCall(nullptr)
376
26.4k
    , mpImpl(new Impl)
377
26.4k
    , mpParentOfSdrObject(nullptr)
378
26.4k
    , m_nOrdNum(0)
379
26.4k
    , mnNavigationPosition(SAL_MAX_UINT32)
380
26.4k
    , mnLayerID(0)
381
26.4k
    , mpSvxShape( nullptr )
382
26.4k
    , mbDoNotInsertIntoPageAutomatically(false)
383
26.4k
{
384
26.4k
    m_bVirtObj         =false;
385
26.4k
    m_bSnapRectDirty   =true;
386
26.4k
    m_bMovProt         =false;
387
26.4k
    m_bSizProt         =false;
388
26.4k
    m_bNoPrint         =false;
389
26.4k
    m_bEmptyPresObj    =false;
390
26.4k
    m_bNotVisibleAsMaster=false;
391
26.4k
    m_bClosedObj       =false;
392
26.4k
    mbVisible        = true;
393
394
    // #i25616#
395
26.4k
    mbLineIsOutsideGeometry = false;
396
397
    // #i25616#
398
26.4k
    mbSupportTextIndentingOnLineWidthChange = false;
399
400
26.4k
    m_bIsEdge=false;
401
26.4k
    m_bIs3DObj=false;
402
26.4k
    m_bMarkProt=false;
403
26.4k
    m_bIsUnoObj=false;
404
405
26.4k
    mpProperties.reset();
406
26.4k
    mpViewContact.reset();
407
408
    // The CloneSdrObject() method uses the local copy constructor from the individual
409
    // sdr::properties::BaseProperties class. Since the target class maybe for another
410
    // draw object, an SdrObject needs to be provided, as in the normal constructor.
411
26.4k
    mpProperties = rSource.GetProperties().Clone(*this);
412
413
26.4k
    setOutRectangle(rSource.getOutRectangle());
414
26.4k
    mnLayerID = rSource.mnLayerID;
415
26.4k
    m_aAnchor =rSource.m_aAnchor;
416
26.4k
    m_bVirtObj=rSource.m_bVirtObj;
417
26.4k
    m_bSizProt=rSource.m_bSizProt;
418
26.4k
    m_bMovProt=rSource.m_bMovProt;
419
26.4k
    m_bNoPrint=rSource.m_bNoPrint;
420
26.4k
    mbVisible=rSource.mbVisible;
421
26.4k
    m_bMarkProt=rSource.m_bMarkProt;
422
26.4k
    m_bEmptyPresObj =rSource.m_bEmptyPresObj;
423
26.4k
    m_bNotVisibleAsMaster=rSource.m_bNotVisibleAsMaster;
424
26.4k
    m_bSnapRectDirty=true;
425
26.4k
    m_pPlusData.reset();
426
26.4k
    if (rSource.m_pPlusData!=nullptr) {
427
22.9k
        m_pPlusData.reset(rSource.m_pPlusData->Clone(this));
428
22.9k
    }
429
26.4k
    if (m_pPlusData!=nullptr && m_pPlusData->pBroadcast!=nullptr) {
430
0
        m_pPlusData->pBroadcast.reset(); // broadcaster isn't copied
431
0
    }
432
433
26.4k
    m_pGrabBagItem.reset();
434
26.4k
    if (rSource.m_pGrabBagItem!=nullptr)
435
10.5k
        m_pGrabBagItem.reset(rSource.m_pGrabBagItem->Clone());
436
26.4k
    impAddIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
437
26.4k
}
438
439
SdrObject::~SdrObject()
440
2.67M
{
441
#ifdef DBG_UTIL
442
    // see logic in SdrObject::release
443
    assert(m_refCount == -1);
444
#endif
445
    // Tell all the registered ObjectUsers that the page is in destruction.
446
    // And clear the vector. This means that user do not need to call RemoveObjectUser()
447
    // when they get called from ObjectInDestruction().
448
2.67M
    sdr::ObjectUserVector aList;
449
2.67M
    aList.swap(mpImpl->maObjectUsers);
450
2.67M
    for(sdr::ObjectUser* pObjectUser : aList)
451
3.88k
    {
452
3.88k
        DBG_ASSERT(pObjectUser, "SdrObject::~SdrObject: corrupt ObjectUser list (!)");
453
3.88k
        pObjectUser->ObjectInDestruction(*this);
454
3.88k
    }
455
456
    // UserCall
457
2.67M
    SendUserCall(SdrUserCallType::Delete, GetLastBoundRect());
458
2.67M
    o3tl::reset_preserve_ptr_during(m_pPlusData);
459
460
2.67M
    m_pGrabBagItem.reset();
461
2.67M
    mpProperties.reset();
462
2.67M
    mpViewContact.reset();
463
2.67M
    impRemoveIncarnatedSdrObjectToSdrModel(*this, getSdrModelFromSdrObject());
464
2.67M
}
465
466
void SdrObject::acquire() noexcept
467
33.0M
{
468
#ifdef DBG_UTIL
469
    assert(m_refCount != -1);
470
#endif
471
33.0M
    osl_atomic_increment( &m_refCount );
472
33.0M
}
473
474
void SdrObject::release() noexcept
475
33.0M
{
476
33.0M
    oslInterlockedCount x = osl_atomic_decrement( &m_refCount );
477
33.0M
    if ( x == 0 )
478
2.67M
    {
479
2.67M
        disposeWeakConnectionPoint();
480
#ifdef DBG_UTIL
481
        // make sure it doesn't accidentally come back to life, see assert in acquire()
482
        osl_atomic_decrement( &m_refCount );
483
#endif
484
2.67M
        delete this;
485
2.67M
    }
486
33.0M
}
487
488
void SdrObject::SetBoundAndSnapRectsDirty(bool bNotMyself, bool bRecursive)
489
46.4M
{
490
46.4M
    if (!bNotMyself)
491
33.4M
    {
492
33.4M
        SetBoundRectDirty();
493
33.4M
        m_bSnapRectDirty=true;
494
33.4M
    }
495
496
46.4M
    if (bRecursive && nullptr != getParentSdrObjListFromSdrObject())
497
35.4M
    {
498
35.4M
        getParentSdrObjListFromSdrObject()->SetSdrObjListRectsDirty();
499
35.4M
    }
500
46.4M
}
501
502
void SdrObject::handlePageChange(SdrPage*, SdrPage* )
503
2.95M
{
504
2.95M
}
505
506
507
// init global static itempool
508
SdrItemPool& SdrObject::GetGlobalDrawObjectItemPool()
509
426k
{
510
426k
    static tools::DeleteRtlReferenceOnDeinit<SdrItemPool> xGlobalItemPool( []() {
511
14
        rtl::Reference<SdrItemPool> xNewPool(new SdrItemPool());
512
14
        rtl::Reference<SfxItemPool> pGlobalOutlPool = EditEngine::CreatePool();
513
14
        xNewPool->SetSecondaryPool(pGlobalOutlPool.get());
514
14
        xNewPool->SetDefaultMetric(SdrEngineDefaults::GetMapUnit());
515
14
        if (comphelper::IsFuzzing())
516
14
            xNewPool->acquire();
517
14
        return xNewPool;
518
14
    }() );
519
520
426k
    return *xGlobalItemPool.get();
521
426k
}
522
523
void SdrObject::SetRelativeWidth( double nValue )
524
180
{
525
180
    mpImpl->mnRelativeWidth = nValue;
526
180
}
527
528
void SdrObject::SetRelativeWidthRelation( sal_Int16 eValue )
529
197
{
530
197
    mpImpl->meRelativeWidthRelation = eValue;
531
197
}
532
533
void SdrObject::SetRelativeHeight( double nValue )
534
169
{
535
169
    mpImpl->mnRelativeHeight = nValue;
536
169
}
537
538
void SdrObject::SetRelativeHeightRelation( sal_Int16 eValue )
539
197
{
540
197
    mpImpl->meRelativeHeightRelation = eValue;
541
197
}
542
543
const double* SdrObject::GetRelativeWidth( ) const
544
33.6k
{
545
33.6k
    if (!mpImpl->mnRelativeWidth)
546
33.6k
        return nullptr;
547
548
0
    return &*mpImpl->mnRelativeWidth;
549
33.6k
}
550
551
sal_Int16 SdrObject::GetRelativeWidthRelation() const
552
0
{
553
0
    return mpImpl->meRelativeWidthRelation;
554
0
}
555
556
const double* SdrObject::GetRelativeHeight( ) const
557
33.6k
{
558
33.6k
    if (!mpImpl->mnRelativeHeight)
559
33.6k
        return nullptr;
560
561
0
    return &*mpImpl->mnRelativeHeight;
562
33.6k
}
563
564
sal_Int16 SdrObject::GetRelativeHeightRelation() const
565
0
{
566
0
    return mpImpl->meRelativeHeightRelation;
567
0
}
568
569
SfxItemPool& SdrObject::GetObjectItemPool() const
570
1.94M
{
571
1.94M
    return getSdrModelFromSdrObject().GetItemPool();
572
1.94M
}
573
574
SdrInventor SdrObject::GetObjInventor()   const
575
6.72M
{
576
6.72M
    return SdrInventor::Default;
577
6.72M
}
578
579
SdrObjKind SdrObject::GetObjIdentifier() const
580
0
{
581
0
    return SdrObjKind::NONE;
582
0
}
583
584
void SdrObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
585
0
{
586
0
    rInfo.bRotateFreeAllowed=false;
587
0
    rInfo.bMirrorFreeAllowed=false;
588
0
    rInfo.bTransparenceAllowed = false;
589
0
    rInfo.bShearAllowed     =false;
590
0
    rInfo.bEdgeRadiusAllowed=false;
591
0
    rInfo.bCanConvToPath    =false;
592
0
    rInfo.bCanConvToPoly    =false;
593
0
    rInfo.bCanConvToContour = false;
594
0
    rInfo.bCanConvToPathLineToArea=false;
595
0
    rInfo.bCanConvToPolyLineToArea=false;
596
0
}
597
598
SdrLayerID SdrObject::GetLayer() const
599
3.36M
{
600
3.36M
    return mnLayerID;
601
3.36M
}
602
603
bool SdrObject::isVisibleOnAnyOfTheseLayers(const SdrLayerIDSet& rSet) const
604
208
{
605
208
    if (rSet.IsSet(GetLayer()))
606
207
        return true;
607
1
    SdrObjList* pOL=GetSubList();
608
1
    if (!pOL)
609
1
        return false;
610
0
    for (const rtl::Reference<SdrObject>& pObject : *pOL)
611
0
        if (pObject->isVisibleOnAnyOfTheseLayers(rSet))
612
0
            return true;
613
0
    return false;
614
0
}
615
616
void SdrObject::NbcSetLayer(SdrLayerID nLayer)
617
3.11M
{
618
3.11M
    mnLayerID = nLayer;
619
3.11M
}
620
621
void SdrObject::SetLayer(SdrLayerID nLayer)
622
1.60M
{
623
1.60M
    NbcSetLayer(nLayer);
624
1.60M
    SetChanged();
625
1.60M
    BroadcastObjectChange();
626
1.60M
}
627
628
void SdrObject::AddListener(SfxListener& rListener)
629
990k
{
630
990k
    ImpForcePlusData();
631
990k
    if (m_pPlusData->pBroadcast==nullptr) m_pPlusData->pBroadcast.reset(new SfxBroadcaster);
632
633
    // SdrEdgeObj may be connected to same SdrObject on both ends so allow it
634
    // to listen twice
635
990k
    SdrEdgeObj const*const pEdge(dynamic_cast<SdrEdgeObj const*>(&rListener));
636
990k
    rListener.StartListening(*m_pPlusData->pBroadcast, pEdge ? DuplicateHandling::Allow : DuplicateHandling::Unexpected);
637
990k
}
638
639
void SdrObject::RemoveListener(SfxListener& rListener)
640
982k
{
641
982k
    if (m_pPlusData!=nullptr && m_pPlusData->pBroadcast!=nullptr) {
642
982k
        rListener.EndListening(*m_pPlusData->pBroadcast);
643
982k
        if (!m_pPlusData->pBroadcast->HasListeners()) {
644
424k
            m_pPlusData->pBroadcast.reset();
645
424k
        }
646
982k
    }
647
982k
}
648
649
SfxBroadcaster* SdrObject::GetBroadcaster() const
650
50.7k
{
651
50.7k
    return m_pPlusData!=nullptr ? m_pPlusData->pBroadcast.get() : nullptr;
652
50.7k
}
653
654
void SdrObject::AddReference(SdrVirtObj& rVrtObj)
655
24.0k
{
656
24.0k
    AddListener(rVrtObj);
657
24.0k
}
658
659
void SdrObject::DelReference(SdrVirtObj& rVrtObj)
660
24.0k
{
661
24.0k
    RemoveListener(rVrtObj);
662
24.0k
}
663
664
bool SdrObject::IsGroupObject() const
665
3.13M
{
666
3.13M
    return GetSubList()!=nullptr;
667
3.13M
}
668
669
SdrObjList* SdrObject::GetSubList() const
670
6.83M
{
671
6.83M
    return nullptr;
672
6.83M
}
673
674
SdrObject* SdrObject::getParentSdrObjectFromSdrObject() const
675
13.7M
{
676
13.7M
    SdrObjList* pParent(getParentSdrObjListFromSdrObject());
677
678
13.7M
    if(nullptr == pParent)
679
6.16M
    {
680
6.16M
        return nullptr;
681
6.16M
    }
682
683
7.54M
    return pParent->getSdrObjectFromSdrObjList();
684
13.7M
}
685
686
void SdrObject::SetName(const OUString& rStr, const bool bSetChanged)
687
179k
{
688
179k
    if (!rStr.isEmpty() && !m_pPlusData)
689
51.8k
    {
690
51.8k
        ImpForcePlusData();
691
51.8k
    }
692
693
179k
    if(!(m_pPlusData && m_pPlusData->aObjName != rStr))
694
22.6k
        return;
695
696
    // Undo/Redo for setting object's name (#i73249#)
697
157k
    bool bUndo( false );
698
157k
    if ( getSdrModelFromSdrObject().IsUndoEnabled() )
699
0
    {
700
0
        bUndo = true;
701
0
        std::unique_ptr<SdrUndoAction> pUndoAction =
702
0
                SdrUndoFactory::CreateUndoObjectStrAttr(
703
0
                                                *this,
704
0
                                                SdrUndoObjStrAttr::ObjStrAttrType::Name,
705
0
                                                GetName(),
706
0
                                                rStr );
707
0
        getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
708
0
        getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
709
0
    }
710
157k
    m_pPlusData->aObjName = rStr;
711
    // Undo/Redo for setting object's name (#i73249#)
712
157k
    if ( bUndo )
713
0
    {
714
0
        getSdrModelFromSdrObject().EndUndo();
715
0
    }
716
157k
    if (bSetChanged)
717
157k
    {
718
157k
        SetChanged();
719
157k
        BroadcastObjectChange();
720
157k
    }
721
157k
}
722
723
const OUString & SdrObject::GetName() const
724
388k
{
725
388k
    if(m_pPlusData)
726
245k
    {
727
245k
        return m_pPlusData->aObjName;
728
245k
    }
729
730
143k
    return EMPTY_OUSTRING;
731
388k
}
732
733
void SdrObject::SetTitle(const OUString& rStr)
734
6.19k
{
735
6.19k
    if (!rStr.isEmpty() && !m_pPlusData)
736
12
    {
737
12
        ImpForcePlusData();
738
12
    }
739
740
6.19k
    if(!(m_pPlusData && m_pPlusData->aObjTitle != rStr))
741
6.17k
        return;
742
743
    // Undo/Redo for setting object's title (#i73249#)
744
13
    bool bUndo( false );
745
13
    if ( getSdrModelFromSdrObject().IsUndoEnabled() )
746
0
    {
747
0
        bUndo = true;
748
0
        std::unique_ptr<SdrUndoAction> pUndoAction =
749
0
                SdrUndoFactory::CreateUndoObjectStrAttr(
750
0
                                                *this,
751
0
                                                SdrUndoObjStrAttr::ObjStrAttrType::Title,
752
0
                                                GetTitle(),
753
0
                                                rStr );
754
0
        getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
755
0
        getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
756
0
    }
757
13
    m_pPlusData->aObjTitle = rStr;
758
    // Undo/Redo for setting object's title (#i73249#)
759
13
    if ( bUndo )
760
0
    {
761
0
        getSdrModelFromSdrObject().EndUndo();
762
0
    }
763
13
    SetChanged();
764
13
    BroadcastObjectChange();
765
13
}
766
767
OUString SdrObject::GetTitle() const
768
12.3k
{
769
12.3k
    if(m_pPlusData)
770
5.28k
    {
771
5.28k
        return m_pPlusData->aObjTitle;
772
5.28k
    }
773
774
7.05k
    return OUString();
775
12.3k
}
776
777
void SdrObject::SetDescription(const OUString& rStr)
778
9.73k
{
779
9.73k
    if (!rStr.isEmpty() && !m_pPlusData)
780
1.45k
    {
781
1.45k
        ImpForcePlusData();
782
1.45k
    }
783
784
9.73k
    if(!(m_pPlusData && m_pPlusData->aObjDescription != rStr))
785
5.03k
        return;
786
787
    // Undo/Redo for setting object's description (#i73249#)
788
4.70k
    bool bUndo( false );
789
4.70k
    if ( getSdrModelFromSdrObject().IsUndoEnabled() )
790
0
    {
791
0
        bUndo = true;
792
0
        std::unique_ptr<SdrUndoAction> pUndoAction =
793
0
                SdrUndoFactory::CreateUndoObjectStrAttr(
794
0
                                                *this,
795
0
                                                SdrUndoObjStrAttr::ObjStrAttrType::Description,
796
0
                                                GetDescription(),
797
0
                                                rStr );
798
0
        getSdrModelFromSdrObject().BegUndo( pUndoAction->GetComment() );
799
0
        getSdrModelFromSdrObject().AddUndo( std::move(pUndoAction) );
800
0
    }
801
4.70k
    m_pPlusData->aObjDescription = rStr;
802
    // Undo/Redo for setting object's description (#i73249#)
803
4.70k
    if ( bUndo )
804
0
    {
805
0
        getSdrModelFromSdrObject().EndUndo();
806
0
    }
807
4.70k
    SetChanged();
808
4.70k
    BroadcastObjectChange();
809
4.70k
}
810
811
OUString SdrObject::GetDescription() const
812
8.40k
{
813
8.40k
    if(m_pPlusData)
814
6.45k
    {
815
6.45k
        return m_pPlusData->aObjDescription;
816
6.45k
    }
817
818
1.95k
    return OUString();
819
8.40k
}
820
821
void SdrObject::SetDecorative(bool const isDecorative)
822
0
{
823
0
    ImpForcePlusData();
824
825
0
    if (m_pPlusData->isDecorative == isDecorative)
826
0
    {
827
0
        return;
828
0
    }
829
830
0
    if (getSdrModelFromSdrObject().IsUndoEnabled())
831
0
    {
832
0
        std::unique_ptr<SdrUndoAction> pUndoAction(
833
0
            SdrUndoFactory::CreateUndoObjectDecorative(
834
0
                    *this, m_pPlusData->isDecorative));
835
0
        getSdrModelFromSdrObject().BegUndo(pUndoAction->GetComment());
836
0
        getSdrModelFromSdrObject().AddUndo(std::move(pUndoAction));
837
0
    }
838
839
0
    m_pPlusData->isDecorative = isDecorative;
840
841
0
    if (getSdrModelFromSdrObject().IsUndoEnabled())
842
0
    {
843
0
        getSdrModelFromSdrObject().EndUndo();
844
0
    }
845
846
0
    SetChanged();
847
0
    BroadcastObjectChange();
848
0
}
849
850
bool SdrObject::IsDecorative() const
851
0
{
852
0
    return m_pPlusData == nullptr ? false : m_pPlusData->isDecorative;
853
0
}
854
855
void SdrObject::setAsAnnotationObject()
856
0
{
857
0
    if (!mpAnnotationData)
858
0
        mpAnnotationData = std::make_unique<sdr::annotation::ObjectAnnotationData>();
859
0
}
860
861
std::unique_ptr<sdr::annotation::ObjectAnnotationData>& SdrObject::getAnnotationData()
862
0
{
863
0
    return mpAnnotationData;
864
0
}
865
866
sal_uInt32 SdrObject::GetOrdNum() const
867
652k
{
868
652k
    if (SdrObjList* pParentList = getParentSdrObjListFromSdrObject())
869
651k
    {
870
651k
        if (pParentList->IsObjOrdNumsDirty())
871
532k
        {
872
532k
            pParentList->RecalcObjOrdNums();
873
532k
        }
874
651k
    } else const_cast<SdrObject*>(this)->m_nOrdNum=0;
875
652k
    return m_nOrdNum;
876
652k
}
877
878
void SdrObject::SetOrdNum(sal_uInt32 nNum)
879
160M
{
880
160M
    m_nOrdNum = nNum;
881
160M
}
882
883
/// Try to ensure the desired result __without__ triggering RecalcObjOrdNums
884
void SdrObject::ensureSortedImmediatelyAfter(const SdrObject& rFirst)
885
6.55k
{
886
6.55k
    SdrObjList* pParentList = getParentSdrObjListFromSdrObject();
887
6.55k
    assert(pParentList == rFirst.getParentSdrObjListFromSdrObject());
888
6.55k
    bool bDirty = pParentList->IsObjOrdNumsDirty();
889
6.55k
    if (!bDirty)
890
0
    {
891
0
        pParentList->SetObjectOrdNum(GetOrdNum(), rFirst.GetOrdNum() + 1);
892
0
    }
893
6.55k
    else
894
6.55k
    {
895
6.55k
        std::optional<decltype(pParentList->begin())> itFound1, itFound2;
896
35.3k
        for (auto it = pParentList->begin(), itEnd = pParentList->end(); it != itEnd; ++it)
897
35.3k
        {
898
35.3k
            if (*it == this)
899
6.55k
                itFound1 = it;
900
28.7k
            else if (*it == &rFirst)
901
6.55k
                itFound2 = it;
902
35.3k
            if (itFound1 && itFound2)
903
6.55k
            {
904
6.55k
                auto ord1 = std::distance(pParentList->begin(), *itFound1);
905
6.55k
                auto ord2 = std::distance(pParentList->begin(), *itFound2);
906
6.55k
                pParentList->SetObjectOrdNum(ord1, ord2 + 1);
907
6.55k
                break;
908
6.55k
            }
909
35.3k
        }
910
6.55k
    }
911
6.55k
}
912
913
void SdrObject::GetGrabBagItem(css::uno::Any& rVal) const
914
82.9k
{
915
82.9k
    if (m_pGrabBagItem != nullptr)
916
50.5k
        m_pGrabBagItem->QueryValue(rVal);
917
32.3k
    else
918
32.3k
        rVal <<= uno::Sequence<beans::PropertyValue>();
919
82.9k
}
920
921
void SdrObject::SetGrabBagItem(const css::uno::Any& rVal)
922
78.6k
{
923
78.6k
    if (m_pGrabBagItem == nullptr)
924
31.8k
        m_pGrabBagItem.reset(new SfxGrabBagItem);
925
926
78.6k
    m_pGrabBagItem->PutValue(rVal, 0);
927
928
78.6k
    SetChanged();
929
78.6k
    BroadcastObjectChange();
930
78.6k
}
931
932
sal_uInt32 SdrObject::GetNavigationPosition() const
933
0
{
934
0
    if (nullptr != getParentSdrObjListFromSdrObject() && getParentSdrObjListFromSdrObject()->RecalcNavigationPositions())
935
0
    {
936
0
        return mnNavigationPosition;
937
0
    }
938
0
    else
939
0
        return GetOrdNum();
940
0
}
941
942
943
void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition)
944
0
{
945
0
    mnNavigationPosition = nNewPosition;
946
0
}
947
948
949
// To make clearer that this method may trigger RecalcBoundRect and thus may be
950
// expensive and sometimes problematic (inside a bigger object change you will get
951
// non-useful BoundRects sometimes) I rename that method from GetBoundRect() to
952
// GetCurrentBoundRect().
953
const tools::Rectangle& SdrObject::GetCurrentBoundRect() const
954
13.1M
{
955
13.1M
    auto const& rRectangle = getOutRectangle();
956
13.1M
    if (rRectangle.IsEmpty())
957
13.1M
    {
958
13.1M
        const_cast< SdrObject* >(this)->RecalcBoundRect();
959
13.1M
    }
960
961
13.1M
    return rRectangle;
962
13.1M
}
963
964
// To have a possibility to get the last calculated BoundRect e.g for producing
965
// the first rectangle for repaints (old and new need to be used) without forcing
966
// a RecalcBoundRect (which may be problematical and expensive sometimes) I add here
967
// a new method for accessing the last BoundRect.
968
const tools::Rectangle& SdrObject::GetLastBoundRect() const
969
7.85M
{
970
7.85M
    return getOutRectangle();
971
7.85M
}
972
973
void SdrObject::RecalcBoundRect()
974
14.7M
{
975
    // #i101680# suppress BoundRect calculations on import(s)
976
14.7M
    if ((getSdrModelFromSdrObject().isLocked()) || comphelper::IsFuzzing())
977
14.7M
        return;
978
979
980
0
    auto const& rRectangle = getOutRectangle();
981
    // central new method which will calculate the BoundRect using primitive geometry
982
0
    if (!rRectangle.IsEmpty())
983
0
        return;
984
985
    // Use view-independent data - we do not want any connections
986
    // to e.g. GridOffset in SdrObject-level
987
0
    drawinglayer::primitive2d::Primitive2DContainer xPrimitives;
988
0
    GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives);
989
990
0
    if (xPrimitives.empty())
991
0
        return;
992
993
    // use neutral ViewInformation and get the range of the primitives
994
0
    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
995
0
    const basegfx::B2DRange aRange(xPrimitives.getB2DRange(aViewInformation2D));
996
997
0
    if (!aRange.isEmpty())
998
0
    {
999
0
        tools::Rectangle aNewRectangle(
1000
0
            tools::Long(floor(aRange.getMinX())),
1001
0
            tools::Long(floor(aRange.getMinY())),
1002
0
            tools::Long(ceil(aRange.getMaxX())),
1003
0
            tools::Long(ceil(aRange.getMaxY())));
1004
0
        setOutRectangle(aNewRectangle);
1005
0
        return;
1006
0
    }
1007
0
}
1008
1009
void SdrObject::BroadcastObjectChange() const
1010
10.1M
{
1011
10.1M
    if ((getSdrModelFromSdrObject().isLocked()) || getSdrModelFromSdrObject().IsInDestruction() || comphelper::IsFuzzing())
1012
10.1M
        return;
1013
1014
0
    bool bPlusDataBroadcast(m_pPlusData && m_pPlusData->pBroadcast);
1015
0
    bool bObjectChange(IsInserted());
1016
1017
0
    if(!(bPlusDataBroadcast || bObjectChange))
1018
0
        return;
1019
1020
0
    SdrHint aHint(SdrHintKind::ObjectChange, *this);
1021
1022
0
    if(bPlusDataBroadcast)
1023
0
    {
1024
0
        m_pPlusData->pBroadcast->Broadcast(aHint);
1025
0
    }
1026
1027
0
    if(bObjectChange)
1028
0
    {
1029
0
        getSdrModelFromSdrObject().Broadcast(aHint);
1030
0
    }
1031
0
}
1032
1033
void SdrObject::SetChanged()
1034
17.9M
{
1035
    // For testing purposes, use the new ViewContact for change
1036
    // notification now.
1037
17.9M
    ActionChanged();
1038
1039
    // TTTT Need to check meaning/usage of IsInserted in one
1040
    // of the next changes. It should not mean to have a SdrModel
1041
    // set (this is guaranteed now), but should be connected to
1042
    // being added to a SdrPage (?)
1043
    // TTTT tdf#120066 Indeed - This triggers e.g. by CustomShape
1044
    // geometry-presenting SdrObjects that are in a SdrObjGroup,
1045
    // but the SdrObjGroup is *by purpose* not inserted.
1046
    // Need to check deeper and maybe identify all ::IsInserted()
1047
    // calls by rename and let the compiler work...
1048
17.9M
    if(nullptr != getSdrPageFromSdrObject())
1049
9.52M
    {
1050
9.52M
        getSdrModelFromSdrObject().SetChanged();
1051
9.52M
    }
1052
17.9M
}
1053
1054
// tooling for painting a single object to an OutputDevice.
1055
void SdrObject::SingleObjectPainter(OutputDevice& rOut) const
1056
0
{
1057
0
    sdr::contact::SdrObjectVector aObjectVector;
1058
0
    aObjectVector.push_back(const_cast< SdrObject* >(this));
1059
1060
0
    sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, std::move(aObjectVector), getSdrPageFromSdrObject());
1061
0
    sdr::contact::DisplayInfo aDisplayInfo;
1062
1063
0
    aPainter.ProcessDisplay(aDisplayInfo);
1064
0
}
1065
1066
bool SdrObject::LineGeometryUsageIsNecessary() const
1067
0
{
1068
0
    drawing::LineStyle eXLS = GetMergedItem(XATTR_LINESTYLE).GetValue();
1069
0
    return (eXLS != drawing::LineStyle_NONE);
1070
0
}
1071
1072
bool SdrObject::HasLimitedRotation() const
1073
0
{
1074
    // RotGrfFlyFrame: Default is false, support full rotation
1075
0
    return false;
1076
0
}
1077
1078
OUString SdrObject::TakeObjNameSingul() const
1079
0
{
1080
0
    OUString sName(SvxResId(STR_ObjNameSingulNONE));
1081
1082
0
    OUString aName(GetName());
1083
0
    if (!aName.isEmpty())
1084
0
        sName += " '" + aName + "'";
1085
0
    return sName;
1086
0
}
1087
1088
OUString SdrObject::TakeObjNamePlural() const
1089
0
{
1090
0
    return SvxResId(STR_ObjNamePluralNONE);
1091
0
}
1092
1093
OUString SdrObject::ImpGetDescriptionStr(TranslateId pStrCacheID) const
1094
0
{
1095
0
    OUString aStr = SvxResId(pStrCacheID);
1096
0
    sal_Int32 nPos = aStr.indexOf("%1");
1097
0
    if (nPos >= 0)
1098
0
    {
1099
        // Replace '%1' with the object name.
1100
0
        OUString aObjName(TakeObjNameSingul());
1101
0
        aStr = aStr.replaceAt(nPos, 2, aObjName);
1102
0
    }
1103
1104
0
    nPos = aStr.indexOf("%2");
1105
0
    if (nPos >= 0)
1106
        // Replace '%2' with the passed value.
1107
0
        aStr = aStr.replaceAt(nPos, 2, u"0");
1108
0
    return aStr;
1109
0
}
1110
1111
void SdrObject::ImpForcePlusData()
1112
3.08M
{
1113
3.08M
    if (!m_pPlusData)
1114
2.05M
        m_pPlusData.reset( new SdrObjPlusData );
1115
3.08M
}
1116
1117
OUString SdrObject::GetMetrStr(tools::Long nVal) const
1118
0
{
1119
0
    return getSdrModelFromSdrObject().GetMetricString(nVal);
1120
0
}
1121
1122
basegfx::B2DPolyPolygon SdrObject::TakeXorPoly() const
1123
0
{
1124
0
    basegfx::B2DPolyPolygon aRetval;
1125
0
    const tools::Rectangle aR(GetCurrentBoundRect());
1126
0
    aRetval.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aR)));
1127
1128
0
    return aRetval;
1129
0
}
1130
1131
basegfx::B2DPolyPolygon SdrObject::TakeContour() const
1132
0
{
1133
0
    basegfx::B2DPolyPolygon aRetval;
1134
1135
    // create cloned object without text, but with drawing::LineStyle_SOLID,
1136
    // COL_BLACK as line color and drawing::FillStyle_NONE
1137
0
    rtl::Reference<SdrObject> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
1138
1139
0
    if(pClone)
1140
0
    {
1141
0
        const SdrTextObj* pTextObj = DynCastSdrTextObj(this);
1142
1143
0
        if(pTextObj)
1144
0
        {
1145
            // no text and no text animation
1146
0
            pClone->SetMergedItem(SdrTextAniKindItem(SdrTextAniKind::NONE));
1147
0
            pClone->SetOutlinerParaObject(std::nullopt);
1148
0
        }
1149
1150
0
        const SdrEdgeObj* pEdgeObj = dynamic_cast< const SdrEdgeObj* >(this);
1151
1152
0
        if(pEdgeObj)
1153
0
        {
1154
            // create connections if connector, will be cleaned up when
1155
            // deleting the connector again
1156
0
            SdrObject* pLeft = pEdgeObj->GetConnectedNode(true);
1157
0
            SdrObject* pRight = pEdgeObj->GetConnectedNode(false);
1158
1159
0
            if(pLeft)
1160
0
            {
1161
0
                pClone->ConnectToNode(true, pLeft);
1162
0
            }
1163
1164
0
            if(pRight)
1165
0
            {
1166
0
                pClone->ConnectToNode(false, pRight);
1167
0
            }
1168
0
        }
1169
1170
0
        SfxItemSet aNewSet(GetObjectItemPool());
1171
1172
        // #i101980# ignore LineWidth; that's what the old implementation
1173
        // did. With line width, the result may be huge due to fat/thick
1174
        // line decompositions
1175
0
        aNewSet.Put(XLineWidthItem(0));
1176
1177
        // solid black lines and no fill
1178
0
        aNewSet.Put(XLineStyleItem(drawing::LineStyle_SOLID));
1179
0
        aNewSet.Put(XLineColorItem(OUString(), COL_BLACK));
1180
0
        aNewSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
1181
0
        pClone->SetMergedItemSet(aNewSet);
1182
1183
        // get sequence from clone
1184
0
        const sdr::contact::ViewContact& rVC(pClone->GetViewContact());
1185
0
        drawinglayer::primitive2d::Primitive2DContainer xSequence;
1186
0
        rVC.getViewIndependentPrimitive2DContainer(xSequence);
1187
1188
0
        if(!xSequence.empty())
1189
0
        {
1190
            // use neutral ViewInformation
1191
0
            const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
1192
1193
            // create extractor, process and get result (with hairlines as opened polygons)
1194
0
            drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D, false);
1195
0
            aExtractor.process(xSequence);
1196
0
            const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
1197
0
            const sal_uInt32 nSize(rResult.size());
1198
1199
            // when count is one, it is implied that the object has only its normal
1200
            // contour anyways and TakeContour() is to return an empty PolyPolygon
1201
            // (see old implementation for historical reasons)
1202
0
            if(nSize > 1)
1203
0
            {
1204
                // the topology for contour is correctly a vector of PolyPolygons; for
1205
                // historical reasons cut it back to a single tools::PolyPolygon here
1206
0
                for(sal_uInt32 a(0); a < nSize; a++)
1207
0
                {
1208
0
                    aRetval.append(rResult[a]);
1209
0
                }
1210
0
            }
1211
0
        }
1212
0
    }
1213
1214
0
    return aRetval;
1215
0
}
1216
1217
sal_uInt32 SdrObject::GetHdlCount() const
1218
0
{
1219
0
    return 8;
1220
0
}
1221
1222
void SdrObject::AddToHdlList(SdrHdlList& rHdlList) const
1223
0
{
1224
0
    const tools::Rectangle& rR=GetSnapRect();
1225
0
    for (sal_uInt32 nHdlNum=0; nHdlNum<8; ++nHdlNum)
1226
0
    {
1227
0
        std::unique_ptr<SdrHdl> pH;
1228
0
        switch (nHdlNum) {
1229
0
            case 0: pH.reset(new SdrHdl(rR.TopLeft(),     SdrHdlKind::UpperLeft)); break;
1230
0
            case 1: pH.reset(new SdrHdl(rR.TopCenter(),   SdrHdlKind::Upper)); break;
1231
0
            case 2: pH.reset(new SdrHdl(rR.TopRight(),    SdrHdlKind::UpperRight)); break;
1232
0
            case 3: pH.reset(new SdrHdl(rR.LeftCenter(),  SdrHdlKind::Left )); break;
1233
0
            case 4: pH.reset(new SdrHdl(rR.RightCenter(), SdrHdlKind::Right)); break;
1234
0
            case 5: pH.reset(new SdrHdl(rR.BottomLeft(),  SdrHdlKind::LowerLeft)); break;
1235
0
            case 6: pH.reset(new SdrHdl(rR.BottomCenter(),SdrHdlKind::Lower)); break;
1236
0
            case 7: pH.reset(new SdrHdl(rR.BottomRight(), SdrHdlKind::LowerRight)); break;
1237
0
        }
1238
0
        rHdlList.AddHdl(std::move(pH));
1239
0
    }
1240
0
}
1241
1242
void SdrObject::AddToPlusHdlList(SdrHdlList&, SdrHdl&) const
1243
0
{
1244
0
}
1245
1246
void SdrObject::addCropHandles(SdrHdlList& /*rTarget*/) const
1247
0
{
1248
    // Default implementation, does nothing. Overloaded in
1249
    // SdrGrafObj and SwVirtFlyDrawObj
1250
0
}
1251
1252
void SdrObject::ImpCommonDragCalcRect(const SdrDragStat& rDrag, tools::Rectangle& rTmpRect)
1253
0
{
1254
0
    const tools::Rectangle aRect(rTmpRect);
1255
0
    const SdrHdl* pHdl = rDrag.GetHdl();
1256
0
    SdrHdlKind eHdl = (pHdl==nullptr ? SdrHdlKind::Move : pHdl->GetKind());
1257
0
    bool bCorner = (eHdl==SdrHdlKind::UpperLeft || eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::LowerLeft || eHdl==SdrHdlKind::LowerRight);
1258
0
    bool bOrtho = rDrag.GetView()!=nullptr && rDrag.GetView()->IsOrtho();
1259
0
    bool bBigOrtho = bCorner && bOrtho && rDrag.GetView()->IsBigOrtho();
1260
0
    Point aPos(rDrag.GetNow());
1261
0
    bool bLft = (eHdl==SdrHdlKind::UpperLeft  || eHdl==SdrHdlKind::Left  || eHdl==SdrHdlKind::LowerLeft);
1262
0
    bool bRgt = (eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::Right || eHdl==SdrHdlKind::LowerRight);
1263
0
    bool bTop = (eHdl==SdrHdlKind::UpperRight || eHdl==SdrHdlKind::Upper || eHdl==SdrHdlKind::UpperLeft);
1264
0
    bool bBtm = (eHdl==SdrHdlKind::LowerRight || eHdl==SdrHdlKind::Lower || eHdl==SdrHdlKind::LowerLeft);
1265
0
    if (bLft)
1266
0
        rTmpRect.SetLeft(aPos.X() );
1267
0
    else if (bRgt)
1268
0
        rTmpRect.SetRight(aPos.X() );
1269
0
    if (bTop)
1270
0
        rTmpRect.SetTop(aPos.Y() );
1271
0
    else if (bBtm)
1272
0
        rTmpRect.SetBottom(aPos.Y() );
1273
0
    if (bOrtho)  // Ortho
1274
0
    {
1275
0
        tools::Long nWdt0 = aRect.Right() - aRect.Left();
1276
0
        tools::Long nHgt0 = aRect.Bottom()- aRect.Top();
1277
0
        tools::Long nXMul = rTmpRect.Right() - rTmpRect.Left();
1278
0
        tools::Long nYMul = rTmpRect.Bottom()- rTmpRect.Top();
1279
0
        tools::Long nXDiv = nWdt0;
1280
0
        tools::Long nYDiv = nHgt0;
1281
0
        bool bXNeg = ((nXMul<0) != (nXDiv<0));
1282
0
        bool bYNeg = ((nYMul<0) != (nYDiv<0));
1283
0
        nXMul = std::abs(nXMul);
1284
0
        nYMul = std::abs(nYMul);
1285
0
        nXDiv = std::abs(nXDiv);
1286
0
        nYDiv = std::abs(nYDiv);
1287
0
        Fraction aXFact(nXMul, nXDiv); // fractions for canceling
1288
0
        Fraction aYFact(nYMul, nYDiv); // and for comparing
1289
0
        nXMul = aXFact.GetNumerator();
1290
0
        nYMul = aYFact.GetNumerator();
1291
0
        nXDiv = aXFact.GetDenominator();
1292
0
        nYDiv = aYFact.GetDenominator();
1293
0
        if (bCorner) // corner point handles
1294
0
        {
1295
0
            bool bUseX = ((aXFact<aYFact) != bBigOrtho);
1296
0
            if (bUseX)
1297
0
            {
1298
0
                tools::Long nNeed = tools::Long( BigInt(nHgt0) * BigInt(nXMul) / BigInt(nXDiv) );
1299
0
                if (bYNeg)
1300
0
                    nNeed = -nNeed;
1301
0
                if (bTop)
1302
0
                    rTmpRect.SetTop( rTmpRect.Bottom() - nNeed );
1303
0
                else if (bBtm)
1304
0
                    rTmpRect.SetBottom( rTmpRect.Top() + nNeed );
1305
0
            }
1306
0
            else
1307
0
            {
1308
0
                tools::Long nNeed = tools::Long( BigInt(nWdt0) * BigInt(nYMul) / BigInt(nYDiv) );
1309
0
                if (bXNeg)
1310
0
                    nNeed = -nNeed;
1311
0
                if (bLft)
1312
0
                    rTmpRect.SetLeft(rTmpRect.Right()-nNeed );
1313
0
                else if (bRgt)
1314
0
                    rTmpRect.SetRight(rTmpRect.Left()+nNeed );
1315
0
            }
1316
0
        }
1317
0
        else // apex handles
1318
0
        {
1319
0
            if ((bLft || bRgt) && nXDiv!=0)
1320
0
            {
1321
0
                tools::Long nHgt0b = aRect.Bottom() - aRect.Top();
1322
0
                tools::Long nNeed = tools::Long( BigInt(nHgt0b) * BigInt(nXMul) / BigInt(nXDiv) ) ;
1323
0
                rTmpRect.AdjustTop( -((nNeed-nHgt0b)/2) );
1324
0
                rTmpRect.SetBottom( rTmpRect.Top() + nNeed );
1325
0
            }
1326
0
            else if ((bTop || bBtm) && nYDiv!=0)
1327
0
            {
1328
0
                tools::Long nWdt0b = aRect.Right() - aRect.Left();
1329
0
                tools::Long nNeed = tools::Long( BigInt(nWdt0b) * BigInt(nYMul) / BigInt(nYDiv) );
1330
0
                rTmpRect.AdjustLeft( -((nNeed-nWdt0b)/2) );
1331
0
                rTmpRect.SetRight( rTmpRect.Left() + nNeed );
1332
0
            }
1333
0
        }
1334
0
    }
1335
0
}
1336
1337
tools::Rectangle SdrObject::ImpDragCalcRect(const SdrDragStat& rDrag) const
1338
0
{
1339
0
    tools::Rectangle aTmpRect(GetSnapRect());
1340
0
    ImpCommonDragCalcRect( rDrag, aTmpRect );
1341
0
    aTmpRect.Normalize();
1342
0
    return aTmpRect;
1343
0
}
1344
1345
1346
bool SdrObject::hasSpecialDrag() const
1347
0
{
1348
0
    return false;
1349
0
}
1350
1351
bool SdrObject::supportsFullDrag() const
1352
0
{
1353
0
    return true;
1354
0
}
1355
1356
rtl::Reference<SdrObject> SdrObject::getFullDragClone() const
1357
0
{
1358
    // default uses simple clone
1359
0
    return CloneSdrObject(getSdrModelFromSdrObject());
1360
0
}
1361
1362
bool SdrObject::beginSpecialDrag(SdrDragStat& rDrag) const
1363
0
{
1364
0
    const SdrHdl* pHdl = rDrag.GetHdl();
1365
1366
0
    SdrHdlKind eHdl = (pHdl == nullptr) ? SdrHdlKind::Move : pHdl->GetKind();
1367
1368
0
    return eHdl==SdrHdlKind::UpperLeft || eHdl==SdrHdlKind::Upper || eHdl==SdrHdlKind::UpperRight ||
1369
0
        eHdl==SdrHdlKind::Left || eHdl==SdrHdlKind::Right || eHdl==SdrHdlKind::LowerLeft ||
1370
0
        eHdl==SdrHdlKind::Lower || eHdl==SdrHdlKind::LowerRight;
1371
0
}
1372
1373
bool SdrObject::applySpecialDrag(SdrDragStat& rDrag)
1374
0
{
1375
0
    tools::Rectangle aNewRect(ImpDragCalcRect(rDrag));
1376
1377
0
    if(aNewRect != GetSnapRect())
1378
0
    {
1379
0
           NbcSetSnapRect(aNewRect);
1380
0
    }
1381
1382
0
    return true;
1383
0
}
1384
1385
OUString SdrObject::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
1386
0
{
1387
0
    return OUString();
1388
0
}
1389
1390
basegfx::B2DPolyPolygon SdrObject::getSpecialDragPoly(const SdrDragStat& /*rDrag*/) const
1391
0
{
1392
    // default has nothing to add
1393
0
    return basegfx::B2DPolyPolygon();
1394
0
}
1395
1396
1397
// Create
1398
bool SdrObject::BegCreate(SdrDragStat& rStat)
1399
0
{
1400
0
    rStat.SetOrtho4Possible();
1401
0
    tools::Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
1402
0
    aRect1.Normalize();
1403
0
    rStat.SetActionRect(aRect1);
1404
0
    setOutRectangle(aRect1);
1405
0
    return true;
1406
0
}
1407
1408
bool SdrObject::MovCreate(SdrDragStat& rStat)
1409
0
{
1410
0
    tools::Rectangle aRectangle;
1411
0
    rStat.TakeCreateRect(aRectangle);
1412
0
    rStat.SetActionRect(aRectangle);
1413
0
    aRectangle.Normalize();
1414
0
    setOutRectangle(aRectangle);
1415
0
    return true;
1416
0
}
1417
1418
bool SdrObject::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
1419
0
{
1420
0
    tools::Rectangle aRectangle;
1421
0
    rStat.TakeCreateRect(aRectangle);
1422
0
    aRectangle.Normalize();
1423
0
    setOutRectangle(aRectangle);
1424
1425
0
    return (eCmd==SdrCreateCmd::ForceEnd || rStat.GetPointCount()>=2);
1426
0
}
1427
1428
void SdrObject::BrkCreate(SdrDragStat& /*rStat*/)
1429
0
{
1430
0
}
1431
1432
bool SdrObject::BckCreate(SdrDragStat& /*rStat*/)
1433
0
{
1434
0
    return false;
1435
0
}
1436
1437
basegfx::B2DPolyPolygon SdrObject::TakeCreatePoly(const SdrDragStat& rDrag) const
1438
0
{
1439
0
    tools::Rectangle aRect1;
1440
0
    rDrag.TakeCreateRect(aRect1);
1441
0
    aRect1.Normalize();
1442
1443
0
    basegfx::B2DPolyPolygon aRetval;
1444
0
    aRetval.append(basegfx::utils::createPolygonFromRect(vcl::unotools::b2DRectangleFromRectangle(aRect1)));
1445
0
    return aRetval;
1446
0
}
1447
1448
PointerStyle SdrObject::GetCreatePointer() const
1449
0
{
1450
0
    return PointerStyle::Cross;
1451
0
}
1452
1453
// transformations
1454
void SdrObject::NbcMove(const Size& rSize)
1455
152k
{
1456
152k
    moveOutRectangle(rSize.Width(), rSize.Height());
1457
152k
    SetBoundAndSnapRectsDirty();
1458
152k
}
1459
1460
void SdrObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
1461
0
{
1462
0
    bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
1463
0
    bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
1464
0
    if (bXMirr || bYMirr) {
1465
0
        Point aRef1(GetSnapRect().Center());
1466
0
        if (bXMirr) {
1467
0
            Point aRef2(aRef1);
1468
0
            aRef2.AdjustY( 1 );
1469
0
            NbcMirrorGluePoints(aRef1,aRef2);
1470
0
        }
1471
0
        if (bYMirr) {
1472
0
            Point aRef2(aRef1);
1473
0
            aRef2.AdjustX( 1 );
1474
0
            NbcMirrorGluePoints(aRef1,aRef2);
1475
0
        }
1476
0
    }
1477
0
    auto aRectangle = getOutRectangle();
1478
0
    ResizeRect(aRectangle, rRef, xFact, yFact);
1479
0
    setOutRectangle(aRectangle);
1480
1481
0
    SetBoundAndSnapRectsDirty();
1482
0
}
1483
1484
bool SdrObject::IsSizeValid(Size /* aTargetSize */)
1485
0
{
1486
0
    return true;
1487
0
}
1488
1489
void SdrObject::NbcRotate(const Point& rRef, Degree100 nAngle)
1490
31.9k
{
1491
31.9k
    if (nAngle)
1492
31.9k
    {
1493
31.9k
        double a = toRadians(nAngle);
1494
31.9k
        NbcRotate( rRef, nAngle, sin( a ), cos( a ) );
1495
31.9k
    }
1496
31.9k
}
1497
1498
namespace
1499
{
1500
tools::Rectangle lclMirrorRectangle(tools::Rectangle const& rRectangle, Point const& rRef1, Point const& rRef2)
1501
0
{
1502
0
    tools::Rectangle aRectangle(rRectangle);
1503
0
    aRectangle.Move(-rRef1.X(),-rRef1.Y());
1504
0
    tools::Rectangle R(aRectangle);
1505
0
    tools::Long dx=rRef2.X()-rRef1.X();
1506
0
    tools::Long dy=rRef2.Y()-rRef1.Y();
1507
0
    if (dx==0) {          // vertical axis
1508
0
        aRectangle.SetLeft(-R.Right() );
1509
0
        aRectangle.SetRight(-R.Left() );
1510
0
    } else if (dy==0) {   // horizontal axis
1511
0
        aRectangle.SetTop(-R.Bottom() );
1512
0
        aRectangle.SetBottom(-R.Top() );
1513
0
    } else if (dx==dy) {  // 45deg axis
1514
0
        aRectangle.SetLeft(R.Top() );
1515
0
        aRectangle.SetRight(R.Bottom() );
1516
0
        aRectangle.SetTop(R.Left() );
1517
0
        aRectangle.SetBottom(R.Right() );
1518
0
    } else if (dx==-dy) { // 45deg axis
1519
0
        aRectangle.SetLeft(-R.Bottom() );
1520
0
        aRectangle.SetRight(-R.Top() );
1521
0
        aRectangle.SetTop(-R.Right() );
1522
0
        aRectangle.SetBottom(-R.Left() );
1523
0
    }
1524
0
    aRectangle.Move(rRef1.X(),rRef1.Y());
1525
0
    aRectangle.Normalize(); // just in case
1526
0
    return aRectangle;
1527
0
}
1528
1529
} // end anonymous namespace
1530
1531
void SdrObject::NbcMirror(const Point& rRef1, const Point& rRef2)
1532
0
{
1533
0
    SetGlueReallyAbsolute(true);
1534
1535
0
    tools::Rectangle aRectangle = getOutRectangle();
1536
0
    aRectangle = lclMirrorRectangle(aRectangle, rRef1, rRef2);
1537
0
    setOutRectangle(aRectangle);
1538
1539
0
    SetBoundAndSnapRectsDirty();
1540
0
    NbcMirrorGluePoints(rRef1,rRef2);
1541
0
    SetGlueReallyAbsolute(false);
1542
0
}
1543
1544
void SdrObject::NbcShear(const Point& rRef, Degree100 /*nAngle*/, double tn, bool bVShear)
1545
0
{
1546
0
    SetGlueReallyAbsolute(true);
1547
0
    NbcShearGluePoints(rRef,tn,bVShear);
1548
0
    SetGlueReallyAbsolute(false);
1549
0
}
1550
1551
void SdrObject::Move(const Size& rSize)
1552
236k
{
1553
236k
    if (rSize.Width() == 0 && rSize.Height() == 0)
1554
126k
        return;
1555
1556
109k
    tools::Rectangle aBoundRect0;
1557
109k
    if (m_pUserCall != nullptr)
1558
61.4k
        aBoundRect0 = GetLastBoundRect();
1559
109k
    NbcMove(rSize);
1560
109k
    if (isAnnotationObject())
1561
0
    {
1562
0
        css::geometry::RealPoint2D aNewPosition(
1563
0
            GetLogicRect().Left() / 100.0,
1564
0
            GetLogicRect().Top() / 100.0);
1565
1566
0
        getAnnotationData()->mxAnnotation->SetPosition(aNewPosition);
1567
0
    }
1568
109k
    SetChanged();
1569
109k
    BroadcastObjectChange();
1570
109k
    SendUserCall(SdrUserCallType::MoveOnly, aBoundRect0);
1571
109k
}
1572
1573
void SdrObject::NbcCrop(const basegfx::B2DPoint& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
1574
0
{
1575
    // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
1576
    // Where SwVirtFlyDrawObj is the only real user of it to do something local
1577
0
}
1578
1579
void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative)
1580
2.79k
{
1581
2.79k
    if (xFact.GetNumerator() == xFact.GetDenominator() && yFact.GetNumerator() == yFact.GetDenominator())
1582
0
        return;
1583
1584
2.79k
    if (bUnsetRelative)
1585
2.79k
    {
1586
2.79k
        mpImpl->mnRelativeWidth.reset();
1587
2.79k
        mpImpl->meRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
1588
2.79k
        mpImpl->meRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
1589
2.79k
        mpImpl->mnRelativeHeight.reset();
1590
2.79k
    }
1591
2.79k
    tools::Rectangle aBoundRect0;
1592
1593
2.79k
    if (m_pUserCall != nullptr)
1594
0
        aBoundRect0 = GetLastBoundRect();
1595
1596
2.79k
    NbcResize(rRef, xFact, yFact);
1597
1598
2.79k
    if (isAnnotationObject())
1599
0
    {
1600
0
        auto& rRect = GetCurrentBoundRect();
1601
0
        css::geometry::RealSize2D aNewSize(rRect.GetWidth() / 100.0, rRect.GetHeight() / 100.0);
1602
0
        getAnnotationData()->mxAnnotation->SetSize(aNewSize);
1603
0
    }
1604
1605
2.79k
    SetChanged();
1606
2.79k
    BroadcastObjectChange();
1607
2.79k
    SendUserCall(SdrUserCallType::Resize, aBoundRect0);
1608
2.79k
}
1609
1610
void SdrObject::Crop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact)
1611
0
{
1612
0
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1613
0
    NbcCrop(rRef, fxFact, fyFact);
1614
0
    SetChanged();
1615
0
    BroadcastObjectChange();
1616
0
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1617
0
}
1618
1619
void SdrObject::Rotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
1620
6.69k
{
1621
6.69k
    if (nAngle) {
1622
6.69k
        tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1623
6.69k
        NbcRotate(rRef,nAngle,sn,cs);
1624
6.69k
        SetChanged();
1625
6.69k
        BroadcastObjectChange();
1626
6.69k
        SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1627
6.69k
    }
1628
6.69k
}
1629
1630
void SdrObject::Mirror(const Point& rRef1, const Point& rRef2)
1631
226
{
1632
226
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1633
226
    NbcMirror(rRef1,rRef2);
1634
226
    SetChanged();
1635
226
    BroadcastObjectChange();
1636
226
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1637
226
}
1638
1639
void SdrObject::Shear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
1640
0
{
1641
0
    if (nAngle) {
1642
0
        tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1643
0
        NbcShear(rRef,nAngle,tn,bVShear);
1644
0
        SetChanged();
1645
0
        BroadcastObjectChange();
1646
0
        SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1647
0
    }
1648
0
}
1649
1650
void SdrObject::NbcSetRelativePos(const Point& rPnt)
1651
61
{
1652
61
    Point aRelPos0(GetSnapRect().TopLeft()-m_aAnchor);
1653
61
    Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
1654
61
    NbcMove(aSiz); // This also calls SetRectsDirty()
1655
61
}
1656
1657
void SdrObject::SetRelativePos(const Point& rPnt)
1658
156
{
1659
156
    if (rPnt!=GetRelativePos()) {
1660
61
        tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1661
61
        NbcSetRelativePos(rPnt);
1662
61
        SetChanged();
1663
61
        BroadcastObjectChange();
1664
61
        SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
1665
61
    }
1666
156
}
1667
1668
Point SdrObject::GetRelativePos() const
1669
7.16k
{
1670
7.16k
    return GetSnapRect().TopLeft()-m_aAnchor;
1671
7.16k
}
1672
1673
void SdrObject::ImpSetAnchorPos(const Point& rPnt)
1674
1.42k
{
1675
1.42k
    m_aAnchor = rPnt;
1676
1.42k
}
1677
1678
void SdrObject::NbcSetAnchorPos(const Point& rPnt)
1679
78.2k
{
1680
78.2k
    Size aSiz(rPnt.X()-m_aAnchor.X(),rPnt.Y()-m_aAnchor.Y());
1681
78.2k
    m_aAnchor=rPnt;
1682
78.2k
    NbcMove(aSiz); // This also calls SetRectsDirty()
1683
78.2k
}
1684
1685
void SdrObject::SetAnchorPos(const Point& rPnt)
1686
78.4k
{
1687
78.4k
    if (rPnt!=m_aAnchor) {
1688
78.2k
        tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1689
78.2k
        NbcSetAnchorPos(rPnt);
1690
78.2k
        SetChanged();
1691
78.2k
        BroadcastObjectChange();
1692
78.2k
        SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
1693
78.2k
    }
1694
78.4k
}
1695
1696
const Point& SdrObject::GetAnchorPos() const
1697
206k
{
1698
206k
    return m_aAnchor;
1699
206k
}
1700
1701
void SdrObject::RecalcSnapRect()
1702
0
{
1703
0
}
1704
1705
const tools::Rectangle& SdrObject::GetSnapRect() const
1706
7.10k
{
1707
7.10k
    return getOutRectangle();
1708
7.10k
}
1709
1710
void SdrObject::NbcSetSnapRect(const tools::Rectangle& rRect)
1711
723k
{
1712
723k
    setOutRectangle(rRect);
1713
723k
}
1714
1715
const tools::Rectangle& SdrObject::GetLogicRect() const
1716
7.25k
{
1717
7.25k
    return GetSnapRect();
1718
7.25k
}
1719
1720
void SdrObject::NbcSetLogicRect(const tools::Rectangle& rRect, bool /*bAdaptTextMinSize*/)
1721
717k
{
1722
717k
    NbcSetSnapRect(rRect);
1723
717k
}
1724
1725
void SdrObject::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool /* bShrinkOnly = false */ )
1726
527k
{
1727
527k
    SetLogicRect( rMaxRect );
1728
527k
}
1729
1730
void SdrObject::SetSnapRect(const tools::Rectangle& rRect)
1731
154k
{
1732
154k
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1733
154k
    NbcSetSnapRect(rRect);
1734
154k
    SetChanged();
1735
154k
    BroadcastObjectChange();
1736
154k
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1737
154k
}
1738
1739
void SdrObject::SetLogicRect(const tools::Rectangle& rRect)
1740
3.64M
{
1741
3.64M
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1742
3.64M
    NbcSetLogicRect(rRect);
1743
3.64M
    SetChanged();
1744
3.64M
    BroadcastObjectChange();
1745
3.64M
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1746
3.64M
}
1747
1748
Degree100 SdrObject::GetRotateAngle() const
1749
0
{
1750
0
    return 0_deg100;
1751
0
}
1752
1753
Degree100 SdrObject::GetShearAngle(bool /*bVertical*/) const
1754
0
{
1755
0
    return 0_deg100;
1756
0
}
1757
1758
sal_uInt32 SdrObject::GetSnapPointCount() const
1759
0
{
1760
0
    return GetPointCount();
1761
0
}
1762
1763
Point SdrObject::GetSnapPoint(sal_uInt32 i) const
1764
0
{
1765
0
    return GetPoint(i);
1766
0
}
1767
1768
bool SdrObject::IsPolyObj() const
1769
30
{
1770
30
    return false;
1771
30
}
1772
1773
sal_uInt32 SdrObject::GetPointCount() const
1774
0
{
1775
0
    return 0;
1776
0
}
1777
1778
Point SdrObject::GetPoint(sal_uInt32 /*i*/) const
1779
0
{
1780
0
    return Point();
1781
0
}
1782
1783
void SdrObject::SetPoint(const Point& rPnt, sal_uInt32 i)
1784
0
{
1785
0
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1786
0
    NbcSetPoint(rPnt, i);
1787
0
    SetChanged();
1788
0
    BroadcastObjectChange();
1789
0
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1790
0
}
1791
1792
void SdrObject::NbcSetPoint(const Point& /*rPnt*/, sal_uInt32 /*i*/)
1793
0
{
1794
0
}
1795
1796
bool SdrObject::HasTextEdit() const
1797
0
{
1798
0
    return false;
1799
0
}
1800
1801
bool SdrObject::Equals(const SdrObject& rOtherObj) const
1802
0
{
1803
0
    return (m_aAnchor.X() == rOtherObj.m_aAnchor.X() && m_aAnchor.Y() == rOtherObj.m_aAnchor.Y() &&
1804
0
            m_nOrdNum == rOtherObj.m_nOrdNum && mnNavigationPosition == rOtherObj.mnNavigationPosition &&
1805
0
            mbSupportTextIndentingOnLineWidthChange == rOtherObj.mbSupportTextIndentingOnLineWidthChange &&
1806
0
            mbLineIsOutsideGeometry == rOtherObj.mbLineIsOutsideGeometry && m_bMarkProt == rOtherObj.m_bMarkProt &&
1807
0
            m_bIs3DObj == rOtherObj.m_bIs3DObj && m_bIsEdge == rOtherObj.m_bIsEdge && m_bClosedObj == rOtherObj.m_bClosedObj &&
1808
0
            m_bNotVisibleAsMaster == rOtherObj.m_bNotVisibleAsMaster && m_bEmptyPresObj == rOtherObj.m_bEmptyPresObj &&
1809
0
            mbVisible == rOtherObj.mbVisible && m_bNoPrint == rOtherObj.m_bNoPrint && m_bSizProt == rOtherObj.m_bSizProt &&
1810
0
            m_bMovProt == rOtherObj.m_bMovProt && m_bVirtObj == rOtherObj.m_bVirtObj &&
1811
0
            mnLayerID == rOtherObj.mnLayerID && GetMergedItemSet().Equals(rOtherObj.GetMergedItemSet(), false) );
1812
0
}
1813
1814
void SdrObject::dumpAsXml(xmlTextWriterPtr pWriter) const
1815
0
{
1816
0
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrObject"));
1817
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1818
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
1819
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("name"), "%s", BAD_CAST(GetName().toUtf8().getStr()));
1820
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("title"), "%s", BAD_CAST(GetTitle().toUtf8().getStr()));
1821
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("description"), "%s", BAD_CAST(GetDescription().toUtf8().getStr()));
1822
0
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("nOrdNum"), "%" SAL_PRIuUINT32, GetOrdNumDirect());
1823
0
    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("aOutRect"), BAD_CAST(getOutRectangle().toString().getStr()));
1824
1825
0
    if (m_pGrabBagItem)
1826
0
    {
1827
0
        m_pGrabBagItem->dumpAsXml(pWriter);
1828
0
    }
1829
1830
0
    if (mpProperties)
1831
0
    {
1832
0
        mpProperties->dumpAsXml(pWriter);
1833
0
    }
1834
1835
0
    if (const OutlinerParaObject* pOutliner = GetOutlinerParaObject())
1836
0
        pOutliner->dumpAsXml(pWriter);
1837
1838
0
    (void)xmlTextWriterEndElement(pWriter);
1839
0
}
1840
1841
void SdrObject::SetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObject)
1842
1.27M
{
1843
1.27M
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1844
1.27M
    NbcSetOutlinerParaObject(std::move(pTextObject));
1845
1.27M
    SetChanged();
1846
1.27M
    BroadcastObjectChange();
1847
1.27M
    if (GetCurrentBoundRect()!=aBoundRect0) {
1848
0
        SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1849
0
    }
1850
1851
1.27M
    if (!getSdrModelFromSdrObject().IsUndoEnabled())
1852
789k
        return;
1853
1854
    // Don't do this during import.
1855
485k
    if (SdrObject* pTopGroupObj = getParentSdrObjectFromSdrObject())
1856
0
    {
1857
0
        while (SdrObject* pParent = pTopGroupObj->getParentSdrObjectFromSdrObject())
1858
0
            pTopGroupObj = pParent;
1859
        // A shape was modified, which is in a group shape. Empty the group shape's grab-bag,
1860
        // which potentially contains the old text of the shapes in case of diagrams.
1861
0
        pTopGroupObj->SetGrabBagItem(uno::Any(uno::Sequence<beans::PropertyValue>()));
1862
0
    }
1863
485k
}
1864
1865
void SdrObject::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> /*pTextObject*/, bool /*bAdjustTextFrameWidthAndHeight = true*/)
1866
0
{
1867
0
}
1868
1869
OutlinerParaObject* SdrObject::GetOutlinerParaObject() const
1870
4
{
1871
4
    return nullptr;
1872
4
}
1873
1874
void SdrObject::NbcReformatText()
1875
0
{
1876
0
}
1877
1878
void SdrObject::BurnInStyleSheetAttributes()
1879
0
{
1880
0
    GetProperties().ForceStyleToHardAttributes();
1881
0
}
1882
1883
bool SdrObject::HasMacro() const
1884
0
{
1885
0
    return false;
1886
0
}
1887
1888
SdrObject* SdrObject::CheckMacroHit(const SdrObjMacroHitRec& rRec) const
1889
0
{
1890
0
    if(rRec.pPageView)
1891
0
    {
1892
0
        return SdrObjectPrimitiveHit(*this, rRec.aPos, {static_cast<double>(rRec.nTol), static_cast<double>(rRec.nTol)}, *rRec.pPageView, rRec.pVisiLayer, false);
1893
0
    }
1894
1895
0
    return nullptr;
1896
0
}
1897
1898
PointerStyle SdrObject::GetMacroPointer(const SdrObjMacroHitRec&) const
1899
0
{
1900
0
    return PointerStyle::RefHand;
1901
0
}
1902
1903
void SdrObject::PaintMacro(OutputDevice& rOut, const tools::Rectangle& , const SdrObjMacroHitRec& ) const
1904
0
{
1905
0
    const RasterOp eRop(rOut.GetRasterOp());
1906
0
    const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
1907
1908
0
    rOut.SetLineColor(COL_BLACK);
1909
0
    rOut.SetFillColor();
1910
0
    rOut.SetRasterOp(RasterOp::Invert);
1911
1912
0
    for(auto const& rPolygon : aPolyPolygon)
1913
0
    {
1914
0
        rOut.DrawPolyLine(rPolygon);
1915
0
    }
1916
1917
0
    rOut.SetRasterOp(eRop);
1918
0
}
1919
1920
bool SdrObject::DoMacro(const SdrObjMacroHitRec&)
1921
0
{
1922
0
    return false;
1923
0
}
1924
1925
bool SdrObject::IsMacroHit(const SdrObjMacroHitRec& rRec) const
1926
0
{
1927
0
    return CheckMacroHit(rRec) != nullptr;
1928
0
}
1929
1930
1931
std::unique_ptr<SdrObjGeoData> SdrObject::NewGeoData() const
1932
0
{
1933
0
    return std::make_unique<SdrObjGeoData>();
1934
0
}
1935
1936
void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const
1937
46.3k
{
1938
46.3k
    rGeo.aBoundRect    =GetCurrentBoundRect();
1939
46.3k
    rGeo.aAnchor       =m_aAnchor       ;
1940
46.3k
    rGeo.bMovProt      =m_bMovProt      ;
1941
46.3k
    rGeo.bSizProt      =m_bSizProt      ;
1942
46.3k
    rGeo.bNoPrint      =m_bNoPrint      ;
1943
46.3k
    rGeo.mbVisible     =mbVisible     ;
1944
46.3k
    rGeo.bClosedObj    =m_bClosedObj    ;
1945
46.3k
    rGeo.mnLayerID = mnLayerID;
1946
1947
    // user-defined gluepoints
1948
46.3k
    if (m_pPlusData!=nullptr && m_pPlusData->pGluePoints!=nullptr) {
1949
0
        rGeo.moGluePoints = *m_pPlusData->pGluePoints;
1950
46.3k
    } else {
1951
46.3k
        rGeo.moGluePoints.reset();
1952
46.3k
    }
1953
46.3k
}
1954
1955
void SdrObject::RestoreGeoData(const SdrObjGeoData& rGeo)
1956
0
{
1957
0
    SetBoundAndSnapRectsDirty();
1958
0
    setOutRectangle(rGeo.aBoundRect);
1959
0
    m_aAnchor       =rGeo.aAnchor       ;
1960
0
    m_bMovProt      =rGeo.bMovProt      ;
1961
0
    m_bSizProt      =rGeo.bSizProt      ;
1962
0
    m_bNoPrint      =rGeo.bNoPrint      ;
1963
0
    mbVisible     =rGeo.mbVisible     ;
1964
0
    m_bClosedObj    =rGeo.bClosedObj    ;
1965
0
    mnLayerID = rGeo.mnLayerID;
1966
1967
    // user-defined gluepoints
1968
0
    if (rGeo.moGluePoints) {
1969
0
        ImpForcePlusData();
1970
0
        if (m_pPlusData->pGluePoints!=nullptr) {
1971
0
            *m_pPlusData->pGluePoints=*rGeo.moGluePoints;
1972
0
        } else {
1973
0
            m_pPlusData->pGluePoints.reset(new SdrGluePointList(*rGeo.moGluePoints));
1974
0
        }
1975
0
    } else {
1976
0
        if (m_pPlusData!=nullptr && m_pPlusData->pGluePoints!=nullptr) {
1977
0
            m_pPlusData->pGluePoints.reset();
1978
0
        }
1979
0
    }
1980
0
}
1981
1982
std::unique_ptr<SdrObjGeoData> SdrObject::GetGeoData() const
1983
45.5k
{
1984
45.5k
    std::unique_ptr<SdrObjGeoData> pGeo = NewGeoData();
1985
45.5k
    SaveGeoData(*pGeo);
1986
45.5k
    return pGeo;
1987
45.5k
}
1988
1989
void SdrObject::SetGeoData(const SdrObjGeoData& rGeo)
1990
0
{
1991
0
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
1992
0
    RestoreGeoData(rGeo);
1993
0
    SetChanged();
1994
0
    BroadcastObjectChange();
1995
0
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
1996
0
}
1997
1998
1999
// ItemSet access
2000
2001
const SfxItemSet& SdrObject::GetObjectItemSet() const
2002
42.2M
{
2003
42.2M
    return GetProperties().GetObjectItemSet();
2004
42.2M
}
2005
2006
const SfxItemSet& SdrObject::GetMergedItemSet() const
2007
7.15M
{
2008
7.15M
    return GetProperties().GetMergedItemSet();
2009
7.15M
}
2010
2011
void SdrObject::SetObjectItem(const SfxPoolItem& rItem)
2012
4.99k
{
2013
4.99k
    GetProperties().SetObjectItem(rItem);
2014
4.99k
}
2015
2016
void SdrObject::SetMergedItem(const SfxPoolItem& rItem)
2017
2.43M
{
2018
2.43M
    GetProperties().SetMergedItem(rItem);
2019
2.43M
}
2020
2021
void SdrObject::ClearMergedItem(const sal_uInt16 nWhich)
2022
20.4k
{
2023
20.4k
    GetProperties().ClearMergedItem(nWhich);
2024
20.4k
}
2025
2026
void SdrObject::SetObjectItemSet(const SfxItemSet& rSet)
2027
1.96M
{
2028
1.96M
    GetProperties().SetObjectItemSet(rSet);
2029
1.96M
}
2030
2031
void SdrObject::SetMergedItemSet(const SfxItemSet& rSet, bool bClearAllItems, bool bAdjustTextFrameWidthAndHeight)
2032
2.26M
{
2033
2.26M
    GetProperties().SetMergedItemSet(rSet, bClearAllItems, bAdjustTextFrameWidthAndHeight);
2034
2.26M
}
2035
2036
const SfxPoolItem& SdrObject::GetObjectItem(const sal_uInt16 nWhich) const
2037
716k
{
2038
716k
    return GetObjectItemSet().Get(nWhich);
2039
716k
}
2040
2041
const SfxPoolItem& SdrObject::GetMergedItem(const sal_uInt16 nWhich) const
2042
6.08M
{
2043
6.08M
    return GetMergedItemSet().Get(nWhich);
2044
6.08M
}
2045
2046
void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, bool bClearAllItems)
2047
565k
{
2048
565k
    GetProperties().SetMergedItemSetAndBroadcast(rSet, bClearAllItems);
2049
565k
}
2050
2051
void SdrObject::ApplyNotPersistAttr(const SfxItemSet& rAttr)
2052
3.52k
{
2053
3.52k
    tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
2054
3.52k
    NbcApplyNotPersistAttr(rAttr);
2055
3.52k
    SetChanged();
2056
3.52k
    BroadcastObjectChange();
2057
3.52k
    SendUserCall(SdrUserCallType::Resize,aBoundRect0);
2058
3.52k
}
2059
2060
void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet& rAttr)
2061
3.52k
{
2062
3.52k
    const tools::Rectangle& rSnap=GetSnapRect();
2063
3.52k
    const tools::Rectangle& rLogic=GetLogicRect();
2064
3.52k
    Point aRef1(rSnap.Center());
2065
2066
3.52k
    if (const SdrTransformRef1XItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1X))
2067
0
    {
2068
0
        aRef1.setX(pPoolItem->GetValue() );
2069
0
    }
2070
3.52k
    if (const SdrTransformRef1YItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_TRANSFORMREF1Y))
2071
0
    {
2072
0
        aRef1.setY(pPoolItem->GetValue() );
2073
0
    }
2074
2075
3.52k
    tools::Rectangle aNewSnap(rSnap);
2076
3.52k
    if (const SdrMoveXItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_MOVEX))
2077
0
    {
2078
0
        tools::Long n = pPoolItem->GetValue();
2079
0
        aNewSnap.Move(n,0);
2080
0
    }
2081
3.52k
    if (const SdrMoveYItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_MOVEY))
2082
0
    {
2083
0
        tools::Long n = pPoolItem->GetValue();
2084
0
        aNewSnap.Move(0,n);
2085
0
    }
2086
3.52k
    if (const SdrOnePositionXItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONEPOSITIONX))
2087
0
    {
2088
0
        tools::Long n = pPoolItem->GetValue();
2089
0
        aNewSnap.Move(n-aNewSnap.Left(),0);
2090
0
    }
2091
3.52k
    if (const SdrOnePositionYItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONEPOSITIONY))
2092
0
    {
2093
0
        tools::Long n = pPoolItem->GetValue();
2094
0
        aNewSnap.Move(0,n-aNewSnap.Top());
2095
0
    }
2096
3.52k
    if (const SdrOneSizeWidthItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONESIZEWIDTH))
2097
0
    {
2098
0
        tools::Long n = pPoolItem->GetValue();
2099
0
        aNewSnap.SetRight(aNewSnap.Left()+n );
2100
0
    }
2101
3.52k
    if (const SdrOneSizeHeightItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ONESIZEHEIGHT))
2102
0
    {
2103
0
        tools::Long n = pPoolItem->GetValue();
2104
0
        aNewSnap.SetBottom(aNewSnap.Top()+n );
2105
0
    }
2106
3.52k
    if (aNewSnap!=rSnap) {
2107
0
        if (aNewSnap.GetSize()==rSnap.GetSize()) {
2108
0
            NbcMove(Size(aNewSnap.Left()-rSnap.Left(),aNewSnap.Top()-rSnap.Top()));
2109
0
        } else {
2110
0
            NbcSetSnapRect(aNewSnap);
2111
0
        }
2112
0
    }
2113
2114
3.52k
    if (const SdrShearAngleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_SHEARANGLE))
2115
0
    {
2116
0
        Degree100 n = pPoolItem->GetValue();
2117
0
        n-=GetShearAngle();
2118
0
        if (n) {
2119
0
            double nTan = tan(toRadians(n));
2120
0
            NbcShear(aRef1,n,nTan,false);
2121
0
        }
2122
0
    }
2123
3.52k
    if (const SdrAngleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ROTATEANGLE))
2124
6
    {
2125
6
        Degree100 n = pPoolItem->GetValue();
2126
6
        n-=GetRotateAngle();
2127
6
        if (n) {
2128
0
            NbcRotate(aRef1,n);
2129
0
        }
2130
6
    }
2131
3.52k
    if (const SdrRotateOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_ROTATEONE))
2132
0
    {
2133
0
        Degree100 n = pPoolItem->GetValue();
2134
0
        NbcRotate(aRef1,n);
2135
0
    }
2136
3.52k
    if (const SdrHorzShearOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_HORZSHEARONE))
2137
0
    {
2138
0
        Degree100 n = pPoolItem->GetValue();
2139
0
        double nTan = tan(toRadians(n));
2140
0
        NbcShear(aRef1,n,nTan,false);
2141
0
    }
2142
3.52k
    if (const SdrVertShearOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_VERTSHEARONE))
2143
0
    {
2144
0
        Degree100 n = pPoolItem->GetValue();
2145
0
        double nTan = tan(toRadians(n));
2146
0
        NbcShear(aRef1,n,nTan,true);
2147
0
    }
2148
2149
3.52k
    if (const SdrYesNoItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJMOVEPROTECT))
2150
68
    {
2151
68
        bool b = pPoolItem->GetValue();
2152
68
        SetMoveProtect(b);
2153
68
    }
2154
3.52k
    if (const SdrYesNoItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJSIZEPROTECT))
2155
165
    {
2156
165
        bool b = pPoolItem->GetValue();
2157
165
        SetResizeProtect(b);
2158
165
    }
2159
2160
    /* move protect always sets size protect */
2161
3.52k
    if( IsMoveProtect() )
2162
68
        SetResizeProtect( true );
2163
2164
3.52k
    if (const SdrObjPrintableItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJPRINTABLE))
2165
0
    {
2166
0
        bool b = pPoolItem->GetValue();
2167
0
        SetPrintable(b);
2168
0
    }
2169
2170
3.52k
    if (const SdrObjVisibleItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJVISIBLE))
2171
0
    {
2172
0
        bool b = pPoolItem->GetValue();
2173
0
        SetVisible(b);
2174
0
    }
2175
2176
3.52k
    SdrLayerID nLayer=SDRLAYER_NOTFOUND;
2177
3.52k
    if (const SdrLayerIdItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERID))
2178
0
    {
2179
0
        nLayer = pPoolItem->GetValue();
2180
0
    }
2181
3.52k
    if (const SdrLayerNameItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERNAME))
2182
0
    {
2183
0
        OUString aLayerName = pPoolItem->GetValue();
2184
0
        const SdrLayerAdmin& rLayAd(nullptr != getSdrPageFromSdrObject()
2185
0
            ? getSdrPageFromSdrObject()->GetLayerAdmin()
2186
0
            : getSdrModelFromSdrObject().GetLayerAdmin());
2187
0
        const SdrLayer* pLayer = rLayAd.GetLayer(aLayerName);
2188
2189
0
        if(nullptr != pLayer)
2190
0
        {
2191
0
            nLayer=pLayer->GetID();
2192
0
        }
2193
0
    }
2194
3.52k
    if (nLayer!=SDRLAYER_NOTFOUND) {
2195
0
        NbcSetLayer(nLayer);
2196
0
    }
2197
2198
3.52k
    if (const SfxStringItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_OBJECTNAME))
2199
179
    {
2200
179
        OUString aName = pPoolItem->GetValue();
2201
179
        SetName(aName);
2202
179
    }
2203
3.52k
    tools::Rectangle aNewLogic(rLogic);
2204
3.52k
    if (const SdrLogicSizeWidthItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LOGICSIZEWIDTH))
2205
0
    {
2206
0
        tools::Long n = pPoolItem->GetValue();
2207
0
        aNewLogic.SetRight(aNewLogic.Left()+n );
2208
0
    }
2209
3.52k
    if (const SdrLogicSizeHeightItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LOGICSIZEHEIGHT))
2210
0
    {
2211
0
        tools::Long n = pPoolItem->GetValue();
2212
0
        aNewLogic.SetBottom(aNewLogic.Top()+n );
2213
0
    }
2214
3.52k
    if (aNewLogic!=rLogic) {
2215
0
        NbcSetLogicRect(aNewLogic);
2216
0
    }
2217
3.52k
    Fraction aResizeX(1,1);
2218
3.52k
    Fraction aResizeY(1,1);
2219
3.52k
    if (const SdrResizeXOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEXONE))
2220
0
    {
2221
0
        aResizeX *= pPoolItem->GetValue();
2222
0
    }
2223
3.52k
    if (const SdrResizeYOneItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_RESIZEYONE))
2224
0
    {
2225
0
        aResizeY *= pPoolItem->GetValue();
2226
0
    }
2227
3.52k
    if (aResizeX!=Fraction(1,1) || aResizeY!=Fraction(1,1)) {
2228
0
        NbcResize(aRef1,aResizeX,aResizeY);
2229
0
    }
2230
3.52k
}
2231
2232
void SdrObject::TakeNotPersistAttr(SfxItemSet& rAttr) const
2233
0
{
2234
0
    const tools::Rectangle& rSnap=GetSnapRect();
2235
0
    const tools::Rectangle& rLogic=GetLogicRect();
2236
0
    rAttr.Put(SdrYesNoItem(SDRATTR_OBJMOVEPROTECT, IsMoveProtect()));
2237
0
    rAttr.Put(SdrYesNoItem(SDRATTR_OBJSIZEPROTECT, IsResizeProtect()));
2238
0
    rAttr.Put(SdrObjPrintableItem(IsPrintable()));
2239
0
    rAttr.Put(SdrObjVisibleItem(IsVisible()));
2240
0
    rAttr.Put(SdrAngleItem(SDRATTR_ROTATEANGLE, GetRotateAngle()));
2241
0
    rAttr.Put(SdrShearAngleItem(GetShearAngle()));
2242
0
    rAttr.Put(SdrOneSizeWidthItem(rSnap.GetWidth()-1));
2243
0
    rAttr.Put(SdrOneSizeHeightItem(rSnap.GetHeight()-1));
2244
0
    rAttr.Put(SdrOnePositionXItem(rSnap.Left()));
2245
0
    rAttr.Put(SdrOnePositionYItem(rSnap.Top()));
2246
0
    if (rLogic.GetWidth()!=rSnap.GetWidth()) {
2247
0
        rAttr.Put(SdrLogicSizeWidthItem(rLogic.GetWidth()-1));
2248
0
    }
2249
0
    if (rLogic.GetHeight()!=rSnap.GetHeight()) {
2250
0
        rAttr.Put(SdrLogicSizeHeightItem(rLogic.GetHeight()-1));
2251
0
    }
2252
0
    OUString aName(GetName());
2253
2254
0
    if (!aName.isEmpty())
2255
0
    {
2256
0
        rAttr.Put(SfxStringItem(SDRATTR_OBJECTNAME, aName));
2257
0
    }
2258
2259
0
    rAttr.Put(SdrLayerIdItem(GetLayer()));
2260
0
    const SdrLayerAdmin& rLayAd(nullptr != getSdrPageFromSdrObject()
2261
0
        ? getSdrPageFromSdrObject()->GetLayerAdmin()
2262
0
        : getSdrModelFromSdrObject().GetLayerAdmin());
2263
0
    const SdrLayer* pLayer = rLayAd.GetLayerPerID(GetLayer());
2264
0
    if(nullptr != pLayer)
2265
0
    {
2266
0
        rAttr.Put(SdrLayerNameItem(pLayer->GetName()));
2267
0
    }
2268
0
    Point aRef1(rSnap.Center());
2269
0
    Point aRef2(aRef1); aRef2.AdjustY( 1 );
2270
0
    rAttr.Put(SdrTransformRef1XItem(aRef1.X()));
2271
0
    rAttr.Put(SdrTransformRef1YItem(aRef1.Y()));
2272
0
    rAttr.Put(SdrTransformRef2XItem(aRef2.X()));
2273
0
    rAttr.Put(SdrTransformRef2YItem(aRef2.Y()));
2274
0
}
2275
2276
SfxStyleSheet* SdrObject::GetStyleSheet() const
2277
1.79M
{
2278
1.79M
    return GetProperties().GetStyleSheet();
2279
1.79M
}
2280
2281
void SdrObject::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr)
2282
629k
{
2283
629k
    tools::Rectangle aBoundRect0;
2284
2285
629k
    if(m_pUserCall)
2286
9.75k
        aBoundRect0 = GetLastBoundRect();
2287
2288
629k
    InternalSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, true);
2289
629k
    SetChanged();
2290
629k
    BroadcastObjectChange();
2291
629k
    SendUserCall(SdrUserCallType::ChangeAttr, aBoundRect0);
2292
629k
}
2293
2294
void SdrObject::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bAdjustTextFrameWidthAndHeight)
2295
97.1k
{
2296
97.1k
    InternalSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, false, bAdjustTextFrameWidthAndHeight);
2297
97.1k
}
2298
2299
void SdrObject::InternalSetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast, bool bAdjustTextFrameWidthAndHeight)
2300
726k
{
2301
726k
    GetProperties().SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr, bBroadcast, bAdjustTextFrameWidthAndHeight);
2302
726k
}
2303
2304
// Broadcasting while setting attributes is managed by the AttrObj.
2305
2306
2307
SdrGluePoint SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum) const
2308
0
{
2309
    // #i41936# Use SnapRect for default GluePoints
2310
0
    const tools::Rectangle aR(GetSnapRect());
2311
0
    Point aPt;
2312
2313
0
    switch(nPosNum)
2314
0
    {
2315
0
        case 0 : aPt = aR.TopCenter();    break;
2316
0
        case 1 : aPt = aR.RightCenter();  break;
2317
0
        case 2 : aPt = aR.BottomCenter(); break;
2318
0
        case 3 : aPt = aR.LeftCenter();   break;
2319
0
    }
2320
2321
0
    aPt -= aR.Center();
2322
0
    SdrGluePoint aGP(aPt);
2323
0
    aGP.SetPercent(false);
2324
2325
0
    return aGP;
2326
0
}
2327
2328
SdrGluePoint SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum) const
2329
0
{
2330
0
    tools::Rectangle aR(GetCurrentBoundRect());
2331
0
    Point aPt;
2332
0
    switch (nPosNum) {
2333
0
        case 0 : aPt=aR.TopLeft();     break;
2334
0
        case 1 : aPt=aR.TopRight();    break;
2335
0
        case 2 : aPt=aR.BottomRight(); break;
2336
0
        case 3 : aPt=aR.BottomLeft();  break;
2337
0
    }
2338
0
    aPt-=GetSnapRect().Center();
2339
0
    SdrGluePoint aGP(aPt);
2340
0
    aGP.SetPercent(false);
2341
0
    return aGP;
2342
0
}
2343
2344
const SdrGluePointList* SdrObject::GetGluePointList() const
2345
953k
{
2346
953k
    if (m_pPlusData!=nullptr) return m_pPlusData->pGluePoints.get();
2347
269k
    return nullptr;
2348
953k
}
2349
2350
2351
SdrGluePointList* SdrObject::ForceGluePointList()
2352
317k
{
2353
317k
    ImpForcePlusData();
2354
317k
    if (m_pPlusData->pGluePoints==nullptr) {
2355
19.7k
        m_pPlusData->pGluePoints.reset(new SdrGluePointList);
2356
19.7k
    }
2357
317k
    return m_pPlusData->pGluePoints.get();
2358
317k
}
2359
2360
void SdrObject::SetGlueReallyAbsolute(bool bOn)
2361
353k
{
2362
    // First a const call to see whether there are any gluepoints.
2363
    // Force const call!
2364
353k
    if (GetGluePointList()!=nullptr) {
2365
26.6k
        SdrGluePointList* pGPL=ForceGluePointList();
2366
26.6k
        pGPL->SetReallyAbsolute(bOn,*this);
2367
26.6k
    }
2368
353k
}
2369
2370
void SdrObject::NbcRotateGluePoints(const Point& rRef, Degree100 nAngle, double sn, double cs)
2371
91.2k
{
2372
    // First a const call to see whether there are any gluepoints.
2373
    // Force const call!
2374
91.2k
    if (GetGluePointList()!=nullptr) {
2375
10.3k
        SdrGluePointList* pGPL=ForceGluePointList();
2376
10.3k
        pGPL->Rotate(rRef,nAngle,sn,cs,this);
2377
10.3k
    }
2378
91.2k
}
2379
2380
void SdrObject::NbcMirrorGluePoints(const Point& rRef1, const Point& rRef2)
2381
86.5k
{
2382
    // First a const call to see whether there are any gluepoints.
2383
    // Force const call!
2384
86.5k
    if (GetGluePointList()!=nullptr) {
2385
2.97k
        SdrGluePointList* pGPL=ForceGluePointList();
2386
2.97k
        pGPL->Mirror(rRef1,rRef2,this);
2387
2.97k
    }
2388
86.5k
}
2389
2390
void SdrObject::NbcShearGluePoints(const Point& rRef, double tn, bool bVShear)
2391
0
{
2392
    // First a const call to see whether there are any gluepoints.
2393
    // Force const call!
2394
0
    if (GetGluePointList()!=nullptr) {
2395
0
        SdrGluePointList* pGPL=ForceGluePointList();
2396
0
        pGPL->Shear(rRef,tn,bVShear,this);
2397
0
    }
2398
0
}
2399
2400
void SdrObject::ConnectToNode(bool /*bTail1*/, SdrObject* /*pObj*/)
2401
0
{
2402
0
}
2403
2404
void SdrObject::DisconnectFromNode(bool /*bTail1*/)
2405
0
{
2406
0
}
2407
2408
SdrObject* SdrObject::GetConnectedNode(bool /*bTail1*/) const
2409
0
{
2410
0
    return nullptr;
2411
0
}
2412
2413
2414
static void extractLineContourFromPrimitive2DSequence(
2415
    const drawinglayer::primitive2d::Primitive2DContainer& rxSequence,
2416
    basegfx::B2DPolygonVector& rExtractedHairlines,
2417
    basegfx::B2DPolyPolygonVector& rExtractedLineFills)
2418
0
{
2419
0
    rExtractedHairlines.clear();
2420
0
    rExtractedLineFills.clear();
2421
2422
0
    if(rxSequence.empty())
2423
0
        return;
2424
2425
    // use neutral ViewInformation
2426
0
    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
2427
2428
    // create extractor, process and get result
2429
0
    drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D);
2430
0
    aExtractor.process(rxSequence);
2431
2432
    // copy line results
2433
0
    rExtractedHairlines = aExtractor.getExtractedHairlines();
2434
2435
    // copy fill rsults
2436
0
    rExtractedLineFills = aExtractor.getExtractedLineFills();
2437
0
}
2438
2439
2440
rtl::Reference<SdrObject> SdrObject::ImpConvertToContourObj(bool bForceLineDash)
2441
0
{
2442
0
    rtl::Reference<SdrObject> pRetval;
2443
2444
0
    if(LineGeometryUsageIsNecessary())
2445
0
    {
2446
0
        basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon;
2447
0
        basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon;
2448
0
        drawinglayer::primitive2d::Primitive2DContainer xSequence;
2449
0
        GetViewContact().getViewIndependentPrimitive2DContainer(xSequence);
2450
2451
0
        if(!xSequence.empty())
2452
0
        {
2453
0
            basegfx::B2DPolygonVector aExtractedHairlines;
2454
0
            basegfx::B2DPolyPolygonVector aExtractedLineFills;
2455
2456
0
            extractLineContourFromPrimitive2DSequence(xSequence, aExtractedHairlines, aExtractedLineFills);
2457
2458
            // for SdrObject creation, just copy all to a single Hairline-PolyPolygon
2459
0
            for(const basegfx::B2DPolygon & rExtractedHairline : aExtractedHairlines)
2460
0
            {
2461
0
                aMergedHairlinePolyPolygon.append(rExtractedHairline);
2462
0
            }
2463
2464
            // check for fill rsults
2465
0
            if (!aExtractedLineFills.empty() && !comphelper::IsFuzzing())
2466
0
            {
2467
                // merge to a single tools::PolyPolygon (OR)
2468
0
                aMergedLineFillPolyPolygon = basegfx::utils::mergeToSinglePolyPolygon(std::move(aExtractedLineFills));
2469
0
            }
2470
0
        }
2471
2472
0
        if(aMergedLineFillPolyPolygon.count() || (bForceLineDash && aMergedHairlinePolyPolygon.count()))
2473
0
        {
2474
0
            SfxItemSet aSet(GetMergedItemSet());
2475
0
            drawing::FillStyle eOldFillStyle = aSet.Get(XATTR_FILLSTYLE).GetValue();
2476
0
            rtl::Reference<SdrPathObj> aLinePolygonPart;
2477
0
            rtl::Reference<SdrPathObj> aLineHairlinePart;
2478
0
            bool bBuildGroup(false);
2479
2480
0
            if(aMergedLineFillPolyPolygon.count())
2481
0
            {
2482
                // create SdrObject for filled line geometry
2483
0
                aLinePolygonPart = new SdrPathObj(
2484
0
                    getSdrModelFromSdrObject(),
2485
0
                    SdrObjKind::PathFill,
2486
0
                    std::move(aMergedLineFillPolyPolygon));
2487
2488
                // correct item properties
2489
0
                aSet.Put(XLineWidthItem(0));
2490
0
                aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
2491
0
                Color aColorLine = aSet.Get(XATTR_LINECOLOR).GetColorValue();
2492
0
                sal_uInt16 nTransLine = aSet.Get(XATTR_LINETRANSPARENCE).GetValue();
2493
0
                aSet.Put(XFillColorItem(OUString(), aColorLine));
2494
0
                aSet.Put(XFillStyleItem(drawing::FillStyle_SOLID));
2495
0
                aSet.Put(XFillTransparenceItem(nTransLine));
2496
2497
0
                aLinePolygonPart->SetMergedItemSet(aSet);
2498
0
            }
2499
2500
0
            if(aMergedHairlinePolyPolygon.count())
2501
0
            {
2502
                // create SdrObject for hairline geometry
2503
                // OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
2504
                // to get a non-filled object. If the poly is closed, the PathObj takes care for
2505
                // the correct closed state.
2506
0
                aLineHairlinePart = new SdrPathObj(
2507
0
                    getSdrModelFromSdrObject(),
2508
0
                    SdrObjKind::PathLine,
2509
0
                    std::move(aMergedHairlinePolyPolygon));
2510
2511
0
                aSet.Put(XLineWidthItem(0));
2512
0
                aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
2513
0
                aSet.Put(XLineStyleItem(drawing::LineStyle_SOLID));
2514
2515
                // it is also necessary to switch off line start and ends here
2516
0
                aSet.Put(XLineStartWidthItem(0));
2517
0
                aSet.Put(XLineEndWidthItem(0));
2518
2519
0
                aLineHairlinePart->SetMergedItemSet(aSet);
2520
2521
0
                if(aLinePolygonPart)
2522
0
                {
2523
0
                    bBuildGroup = true;
2524
0
                }
2525
0
            }
2526
2527
            // check if original geometry should be added (e.g. filled and closed)
2528
0
            bool bAddOriginalGeometry(false);
2529
0
            SdrPathObj* pPath = dynamic_cast<SdrPathObj*>(this);
2530
2531
0
            if(pPath && pPath->IsClosed())
2532
0
            {
2533
0
                if(eOldFillStyle != drawing::FillStyle_NONE)
2534
0
                {
2535
0
                    bAddOriginalGeometry = true;
2536
0
                }
2537
0
            }
2538
2539
            // do we need a group?
2540
0
            if(bBuildGroup || bAddOriginalGeometry)
2541
0
            {
2542
0
                rtl::Reference<SdrObject> xGroup = new SdrObjGroup(getSdrModelFromSdrObject());
2543
2544
0
                if(bAddOriginalGeometry)
2545
0
                {
2546
                    // Add a clone of the original geometry.
2547
0
                    aSet.ClearItem();
2548
0
                    aSet.Put(GetMergedItemSet());
2549
0
                    aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
2550
0
                    aSet.Put(XLineWidthItem(0));
2551
2552
0
                    rtl::Reference<SdrObject> pClone(CloneSdrObject(getSdrModelFromSdrObject()));
2553
0
                    pClone->SetMergedItemSet(aSet);
2554
2555
0
                    xGroup->GetSubList()->NbcInsertObject(pClone.get());
2556
0
                }
2557
2558
0
                if(aLinePolygonPart)
2559
0
                {
2560
0
                    xGroup->GetSubList()->NbcInsertObject(aLinePolygonPart.get());
2561
0
                }
2562
2563
0
                if(aLineHairlinePart)
2564
0
                {
2565
0
                    xGroup->GetSubList()->NbcInsertObject(aLineHairlinePart.get());
2566
0
                }
2567
2568
0
                pRetval = std::move(xGroup);
2569
0
            }
2570
0
            else
2571
0
            {
2572
0
                if(aLinePolygonPart)
2573
0
                {
2574
0
                    pRetval = aLinePolygonPart;
2575
0
                }
2576
0
                else if(aLineHairlinePart)
2577
0
                {
2578
0
                    pRetval = aLineHairlinePart;
2579
0
                }
2580
0
            }
2581
0
        }
2582
0
    }
2583
2584
0
    if(!pRetval)
2585
0
    {
2586
        // due to current method usage, create and return a clone when nothing has changed
2587
0
        pRetval = CloneSdrObject(getSdrModelFromSdrObject());
2588
0
    }
2589
2590
0
    return pRetval;
2591
0
}
2592
2593
2594
void SdrObject::SetMarkProtect(bool bProt)
2595
23.8k
{
2596
23.8k
    m_bMarkProt = bProt;
2597
23.8k
}
2598
2599
2600
void SdrObject::SetEmptyPresObj(bool bEpt)
2601
1.67M
{
2602
1.67M
    m_bEmptyPresObj = bEpt;
2603
1.67M
}
2604
2605
2606
void SdrObject::SetNotVisibleAsMaster(bool bFlg)
2607
287k
{
2608
287k
    m_bNotVisibleAsMaster=bFlg;
2609
287k
}
2610
2611
2612
// convert this path object to contour object, even when it is a group
2613
rtl::Reference<SdrObject> SdrObject::ConvertToContourObj(SdrObject* pRet1, bool bForceLineDash) const
2614
0
{
2615
0
    rtl::Reference<SdrObject> pRet = pRet1;
2616
0
    if(dynamic_cast<const SdrObjGroup*>( pRet.get()) !=  nullptr)
2617
0
    {
2618
0
        SdrObjList* pObjList2 = pRet->GetSubList();
2619
0
        rtl::Reference<SdrObject> pGroup = new SdrObjGroup(getSdrModelFromSdrObject());
2620
2621
0
        for (const rtl::Reference<SdrObject>& pIterObj : *pObjList2)
2622
0
            pGroup->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj.get(), bForceLineDash).get());
2623
2624
0
        pRet = std::move(pGroup);
2625
0
    }
2626
0
    else
2627
0
    {
2628
0
        if (SdrPathObj *pPathObj = dynamic_cast<SdrPathObj*>(pRet.get()))
2629
0
        {
2630
            // bezier geometry got created, even for straight edges since the given
2631
            // object is a result of DoConvertToPolyObj. For conversion to contour
2632
            // this is not really needed and can be reduced again AFAP
2633
0
            pPathObj->SetPathPoly(basegfx::utils::simplifyCurveSegments(pPathObj->GetPathPoly()));
2634
0
        }
2635
2636
0
        pRet = pRet->ImpConvertToContourObj(bForceLineDash);
2637
0
    }
2638
2639
    // #i73441# preserve LayerID
2640
0
    if(pRet && pRet->GetLayer() != GetLayer())
2641
0
    {
2642
0
        pRet->SetLayer(GetLayer());
2643
0
    }
2644
2645
0
    return pRet;
2646
0
}
2647
2648
2649
rtl::Reference<SdrObject> SdrObject::ConvertToPolyObj(bool bBezier, bool bLineToArea) const
2650
313
{
2651
313
    rtl::Reference<SdrObject> pRet = DoConvertToPolyObj(bBezier, true);
2652
2653
313
    if(pRet && bLineToArea)
2654
0
    {
2655
0
        pRet = ConvertToContourObj(pRet.get());
2656
0
    }
2657
2658
    // #i73441# preserve LayerID
2659
313
    if(pRet && pRet->GetLayer() != GetLayer())
2660
0
    {
2661
0
        pRet->SetLayer(GetLayer());
2662
0
    }
2663
2664
313
    return pRet;
2665
313
}
2666
2667
2668
rtl::Reference<SdrObject> SdrObject::DoConvertToPolyObj(bool /*bBezier*/, bool /*bAddText*/) const
2669
0
{
2670
0
    return nullptr;
2671
0
}
2672
2673
2674
void SdrObject::InsertedStateChange()
2675
3.01M
{
2676
3.01M
    const bool bIsInserted(nullptr != getParentSdrObjListFromSdrObject());
2677
3.01M
    const tools::Rectangle aBoundRect0(GetLastBoundRect());
2678
2679
3.01M
    if(bIsInserted)
2680
2.49M
    {
2681
2.49M
        SendUserCall(SdrUserCallType::Inserted, aBoundRect0);
2682
2.49M
    }
2683
512k
    else
2684
512k
    {
2685
512k
        SendUserCall(SdrUserCallType::Removed, aBoundRect0);
2686
512k
    }
2687
2688
3.01M
    if(nullptr != m_pPlusData && nullptr != m_pPlusData->pBroadcast)
2689
139k
    {
2690
139k
        SdrHint aHint(bIsInserted ? SdrHintKind::ObjectInserted : SdrHintKind::ObjectRemoved, *this);
2691
139k
        m_pPlusData->pBroadcast->Broadcast(aHint);
2692
139k
    }
2693
3.01M
}
2694
2695
void SdrObject::SetMoveProtect(bool bProt)
2696
40.5k
{
2697
40.5k
    if(IsMoveProtect() != bProt)
2698
24.3k
    {
2699
        // #i77187# secured and simplified
2700
24.3k
        m_bMovProt = bProt;
2701
24.3k
        SetChanged();
2702
24.3k
        BroadcastObjectChange();
2703
24.3k
    }
2704
40.5k
}
2705
2706
void SdrObject::SetResizeProtect(bool bProt)
2707
249k
{
2708
249k
    if(IsResizeProtect() != bProt)
2709
249k
    {
2710
        // #i77187# secured and simplified
2711
249k
        m_bSizProt = bProt;
2712
249k
        SetChanged();
2713
249k
        BroadcastObjectChange();
2714
249k
    }
2715
249k
}
2716
2717
bool SdrObject::IsPrintable() const
2718
0
{
2719
0
    return !m_bNoPrint;
2720
0
}
2721
2722
void SdrObject::SetPrintable(bool bPrn)
2723
258k
{
2724
258k
    if( bPrn == m_bNoPrint )
2725
1.44k
    {
2726
1.44k
        m_bNoPrint=!bPrn;
2727
1.44k
        SetChanged();
2728
1.44k
        if (IsInserted())
2729
1.26k
        {
2730
1.26k
            SdrHint aHint(SdrHintKind::ObjectChange, *this);
2731
1.26k
            getSdrModelFromSdrObject().Broadcast(aHint);
2732
1.26k
        }
2733
1.44k
    }
2734
258k
}
2735
2736
bool SdrObject::IsVisible() const
2737
36.0k
{
2738
36.0k
    return mbVisible;
2739
36.0k
}
2740
2741
void SdrObject::SetVisible(bool bVisible)
2742
258k
{
2743
258k
    if( bVisible != mbVisible )
2744
1.41k
    {
2745
1.41k
        mbVisible = bVisible;
2746
1.41k
        SetChanged();
2747
1.41k
        if (IsInserted())
2748
1.26k
        {
2749
1.26k
            SdrHint aHint(SdrHintKind::ObjectChange, *this);
2750
1.26k
            getSdrModelFromSdrObject().Broadcast(aHint);
2751
1.26k
        }
2752
1.41k
    }
2753
258k
}
2754
2755
2756
sal_uInt16 SdrObject::GetUserDataCount() const
2757
18.7M
{
2758
18.7M
    if (m_pPlusData==nullptr || m_pPlusData->pUserDataList==nullptr) return 0;
2759
16.1M
    return m_pPlusData->pUserDataList->GetUserDataCount();
2760
18.7M
}
2761
2762
SdrObjUserData* SdrObject::GetUserData(sal_uInt16 nNum) const
2763
16.1M
{
2764
16.1M
    if (m_pPlusData==nullptr || m_pPlusData->pUserDataList==nullptr) return nullptr;
2765
16.1M
    return &m_pPlusData->pUserDataList->GetUserData(nNum);
2766
16.1M
}
2767
2768
void SdrObject::AppendUserData(std::unique_ptr<SdrObjUserData> pData)
2769
1.72M
{
2770
1.72M
    if (!pData)
2771
0
    {
2772
0
        OSL_FAIL("SdrObject::AppendUserData(): pData is NULL pointer.");
2773
0
        return;
2774
0
    }
2775
2776
1.72M
    ImpForcePlusData();
2777
1.72M
    if (!m_pPlusData->pUserDataList)
2778
1.71M
        m_pPlusData->pUserDataList.reset( new SdrObjUserDataList );
2779
2780
1.72M
    m_pPlusData->pUserDataList->AppendUserData(std::move(pData));
2781
1.72M
}
2782
2783
void SdrObject::DeleteUserData(sal_uInt16 nNum)
2784
0
{
2785
0
    sal_uInt16 nCount=GetUserDataCount();
2786
0
    if (nNum<nCount) {
2787
0
        m_pPlusData->pUserDataList->DeleteUserData(nNum);
2788
0
        if (nCount==1)  {
2789
0
            m_pPlusData->pUserDataList.reset();
2790
0
        }
2791
0
    } else {
2792
0
        OSL_FAIL("SdrObject::DeleteUserData(): Invalid Index.");
2793
0
    }
2794
0
}
2795
2796
void SdrObject::SetUserCall(SdrObjUserCall* pUser)
2797
4.54M
{
2798
4.54M
    m_pUserCall = pUser;
2799
4.54M
}
2800
2801
2802
void SdrObject::SendUserCall(SdrUserCallType eUserCall, const tools::Rectangle& rBoundRect) const
2803
12.1M
{
2804
12.1M
    SdrObject* pGroup(getParentSdrObjectFromSdrObject());
2805
2806
12.1M
    if ( m_pUserCall )
2807
1.91M
    {
2808
1.91M
        m_pUserCall->Changed( *this, eUserCall, rBoundRect );
2809
1.91M
    }
2810
2811
12.1M
    if(nullptr != pGroup && pGroup->GetUserCall())
2812
20.3k
    {
2813
        // broadcast to group
2814
20.3k
        SdrUserCallType eChildUserType = SdrUserCallType::ChildChangeAttr;
2815
2816
20.3k
        switch( eUserCall )
2817
20.3k
        {
2818
1.18k
            case SdrUserCallType::MoveOnly:
2819
1.18k
                eChildUserType = SdrUserCallType::ChildMoveOnly;
2820
1.18k
            break;
2821
2822
5.30k
            case SdrUserCallType::Resize:
2823
5.30k
                eChildUserType = SdrUserCallType::ChildResize;
2824
5.30k
            break;
2825
2826
12.3k
            case SdrUserCallType::ChangeAttr:
2827
12.3k
                eChildUserType = SdrUserCallType::ChildChangeAttr;
2828
12.3k
            break;
2829
2830
0
            case SdrUserCallType::Delete:
2831
0
                eChildUserType = SdrUserCallType::ChildDelete;
2832
0
            break;
2833
2834
1.52k
            case SdrUserCallType::Inserted:
2835
1.52k
                eChildUserType = SdrUserCallType::ChildInserted;
2836
1.52k
            break;
2837
2838
0
            case SdrUserCallType::Removed:
2839
0
                eChildUserType = SdrUserCallType::ChildRemoved;
2840
0
            break;
2841
2842
0
            default: break;
2843
20.3k
        }
2844
2845
20.3k
        pGroup->GetUserCall()->Changed( *this, eChildUserType, rBoundRect );
2846
20.3k
    }
2847
2848
    // notify our UNO shape listeners
2849
12.1M
    switch ( eUserCall )
2850
12.1M
    {
2851
4.24M
    case SdrUserCallType::Resize:
2852
4.24M
        notifyShapePropertyChange( u"Size"_ustr );
2853
4.24M
        [[fallthrough]]; // RESIZE might also imply a change of the position
2854
4.45M
    case SdrUserCallType::MoveOnly:
2855
4.45M
        notifyShapePropertyChange( u"Position"_ustr );
2856
4.45M
        break;
2857
7.71M
    default:
2858
        // not interested in
2859
7.71M
        break;
2860
12.1M
    }
2861
12.1M
}
2862
2863
void SdrObject::setUnoShape( const uno::Reference< drawing::XShape >& _rxUnoShape )
2864
861k
{
2865
861k
    const uno::Reference< uno::XInterface> xOldUnoShape( maWeakUnoShape );
2866
    // the UNO shape would be gutted by the following code; return early
2867
861k
    if ( _rxUnoShape == xOldUnoShape )
2868
409k
    {
2869
409k
        if ( !xOldUnoShape.is() )
2870
207k
        {
2871
            // make sure there is no stale impl. pointer if the UNO
2872
            // shape was destroyed meanwhile (remember we only hold weak
2873
            // reference to it!)
2874
207k
            mpSvxShape = nullptr;
2875
207k
        }
2876
409k
        return;
2877
409k
    }
2878
2879
451k
    if ( xOldUnoShape.is() )
2880
6.38k
    {
2881
        // Remove yourself from the current UNO shape. Its destructor
2882
        // will reset our UNO shape otherwise.
2883
6.38k
        mpSvxShape->InvalidateSdrObject();
2884
6.38k
    }
2885
2886
451k
    maWeakUnoShape = _rxUnoShape;
2887
451k
    mpSvxShape = comphelper::getFromUnoTunnel<SvxShape>( _rxUnoShape );
2888
451k
}
2889
2890
/** only for internal use! */
2891
SvxShape* SdrObject::getSvxShape()
2892
8.69M
{
2893
8.69M
    DBG_TESTSOLARMUTEX();
2894
        // retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be
2895
        // guarded by the SolarMutex
2896
2897
8.69M
    uno::Reference< uno::XInterface > xShape( maWeakUnoShape );
2898
    //#113608#, make sure mpSvxShape is always synchronized with maWeakUnoShape
2899
8.69M
    if ( mpSvxShape && !xShape )
2900
0
        mpSvxShape = nullptr;
2901
2902
8.69M
    return mpSvxShape;
2903
8.69M
}
2904
2905
css::uno::Reference< css::drawing::XShape > SdrObject::getUnoShape()
2906
425k
{
2907
    // try weak reference first
2908
425k
    uno::Reference< css::drawing::XShape > xShape = maWeakUnoShape;
2909
425k
    if (xShape)
2910
132k
        return xShape;
2911
2912
    // try to access SdrPage from this SdrObject. This will only exist if the SdrObject is
2913
    // inserted in a SdrObjList (page/group/3dScene)
2914
293k
    SdrPage* pPageCandidate(getSdrPageFromSdrObject());
2915
2916
    // tdf#12152, tdf#120728
2917
    //
2918
    // With the paradigm change to only get a SdrPage for a SdrObject when the SdrObject
2919
    // is *inserted*, the functionality for creating 1:1 associated UNO API implementation
2920
    // SvxShapes was partially broken: The used ::CreateShape relies on the SvxPage being
2921
    // derived and the CreateShape method overloaded, implementing additional SdrInventor
2922
    // types as needed.
2923
    //
2924
    // The fallback to use SvxDrawPage::CreateShapeByTypeAndInventor is a trap: It's only
2925
    // a static fallback that handles the SdrInventor types SdrInventor::E3d and
2926
    // SdrInventor::Default. Due to that, e.g. the ReportDesigner broke in various conditions.
2927
    //
2928
    // That again has to do with the ReportDesigner being implemented using the UNO API
2929
    // aspects of SdrObjects early during their construction, not just after these are
2930
    // inserted to a SdrPage - but that is not illegal or wrong, the SdrObject exists already.
2931
    //
2932
    // As a current solution, use the (now always available) SdrModel and any of the
2933
    // existing SdrPages. The only important thing is to get a SdrPage where ::CreateShape is
2934
    // overloaded and implemented as needed.
2935
    //
2936
    // Note for the future:
2937
    // In a more ideal world there would be only one factory method for creating SdrObjects (not
2938
    // ::CreateShape and ::CreateShapeByTypeAndInventor). This also would not be placed at
2939
    // SdrPage/SvxPage at all, but at the Model where it belongs - where else would you expect
2940
    // objects for the current Model to be constructed? To have this at the Page only would make
2941
    // sense if different shapes would need to be constructed for different Pages in the same Model
2942
    // - this is never the case.
2943
    // At that Model extended functionality for that factory (or overloads and implementations)
2944
    // should be placed. But to be realistic, migrating the factories to Model now is too much
2945
    // work - maybe over time when melting SdrObject/SvxObject one day...
2946
    //
2947
    // More Note (added by noel grandin)
2948
    // Except that sd/ is being naughty and doing all kinds of magic during CreateShape that
2949
    // requires knowing which page the object is being created for. Fixing that would require
2950
    // moving a bunch of nasty logic from object creation time, to the point in time when
2951
    // it is actually added to a page.
2952
293k
    if(nullptr == pPageCandidate)
2953
177k
    {
2954
        // If not inserted, alternatively access a SdrPage using the SdrModel. There is
2955
        // no reason not to create and return a UNO API XShape when the SdrObject is not
2956
        // inserted - it may be in construction. Main paradigm is that it exists.
2957
177k
        if(0 != getSdrModelFromSdrObject().GetPageCount())
2958
106k
        {
2959
            // Take 1st SdrPage. That may be e.g. a special page (in SD), but the
2960
            // to-be-used method ::CreateShape will be correctly overloaded in
2961
            // all cases
2962
106k
            pPageCandidate = getSdrModelFromSdrObject().GetPage(0);
2963
106k
        }
2964
177k
    }
2965
2966
293k
    if(nullptr != pPageCandidate)
2967
221k
    {
2968
221k
        uno::Reference< uno::XInterface > xPage(pPageCandidate->getUnoPage());
2969
221k
        if( xPage.is() )
2970
221k
        {
2971
221k
            SvxDrawPage* pDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>(xPage);
2972
221k
            if( pDrawPage )
2973
221k
            {
2974
                // create one
2975
221k
                xShape = pDrawPage->CreateShape( this );
2976
221k
                assert(xShape);
2977
221k
                setUnoShape( xShape );
2978
221k
            }
2979
221k
        }
2980
221k
    }
2981
71.1k
    else
2982
71.1k
    {
2983
        // Fallback to static base functionality. CAUTION: This will only support
2984
        // the most basic stuff like SdrInventor::E3d and SdrInventor::Default. All
2985
        // the other SdrInventor enum entries are from overloads and are *not accessible*
2986
        // using this fallback (!) - what a bad trap
2987
71.1k
        rtl::Reference<SvxShape> xNewShape = SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this );
2988
71.1k
        mpSvxShape = xNewShape.get();
2989
71.1k
        maWeakUnoShape = xShape = mpSvxShape;
2990
71.1k
    }
2991
2992
293k
    return xShape;
2993
425k
}
2994
2995
void SdrObject::notifyShapePropertyChange( const OUString& rPropName ) const
2996
8.69M
{
2997
8.69M
    DBG_TESTSOLARMUTEX();
2998
2999
8.69M
    SvxShape* pSvxShape = const_cast< SdrObject* >( this )->getSvxShape();
3000
8.69M
    if ( pSvxShape )
3001
887k
        return pSvxShape->notifyPropertyChange( rPropName );
3002
8.69M
}
3003
3004
// transformation interface for StarOfficeAPI. This implements support for
3005
// homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
3006
// moment it contains a shearX, rotation and translation, but for setting all linear
3007
// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
3008
3009
3010
// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
3011
// with the base geometry and returns TRUE. Otherwise it returns FALSE.
3012
bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
3013
2.35k
{
3014
    // any kind of SdrObject, just use SnapRect
3015
2.35k
    tools::Rectangle aRectangle(GetSnapRect());
3016
3017
    // convert to transformation values
3018
2.35k
    basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
3019
2.35k
    basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
3020
3021
    // position maybe relative to anchorpos, convert
3022
2.35k
    if(getSdrModelFromSdrObject().IsWriter())
3023
0
    {
3024
0
        if(GetAnchorPos().X() || GetAnchorPos().Y())
3025
0
        {
3026
0
            aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3027
0
        }
3028
0
    }
3029
3030
    // build matrix
3031
2.35k
    rMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(aScale, aTranslate);
3032
3033
2.35k
    return false;
3034
2.35k
}
3035
3036
// sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
3037
// If it's an SdrPathObj it will use the provided geometry information. The Polygon has
3038
// to use (0,0) as upper left and will be scaled to the given size in the matrix.
3039
void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
3040
2.35k
{
3041
    // break up matrix
3042
2.35k
    basegfx::B2DTuple aScale;
3043
2.35k
    basegfx::B2DTuple aTranslate;
3044
2.35k
    double fRotate, fShearX;
3045
2.35k
    rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
3046
3047
    // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
3048
    // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
3049
2.35k
    if(aScale.getX() < 0.0 && aScale.getY() < 0.0)
3050
0
    {
3051
0
        aScale.setX(fabs(aScale.getX()));
3052
0
        aScale.setY(fabs(aScale.getY()));
3053
0
    }
3054
3055
    // if anchor is used, make position relative to it
3056
2.35k
    if(getSdrModelFromSdrObject().IsWriter())
3057
0
    {
3058
0
        if(GetAnchorPos().X() || GetAnchorPos().Y())
3059
0
        {
3060
0
            aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3061
0
        }
3062
0
    }
3063
3064
    // build BaseRect
3065
2.35k
    Point aPoint(basegfx::fround<tools::Long>(aTranslate.getX()),
3066
2.35k
                 basegfx::fround<tools::Long>(aTranslate.getY()));
3067
2.35k
    tools::Rectangle aBaseRect(aPoint, Size(basegfx::fround<tools::Long>(aScale.getX()),
3068
2.35k
                                            basegfx::fround<tools::Long>(aScale.getY())));
3069
3070
    // set BaseRect
3071
2.35k
    SetSnapRect(aBaseRect);
3072
2.35k
}
3073
3074
// Give info if object is in destruction
3075
bool SdrObject::IsInDestruction() const
3076
0
{
3077
0
    return getSdrModelFromSdrObject().IsInDestruction();
3078
0
}
3079
3080
// return if fill is != drawing::FillStyle_NONE
3081
bool SdrObject::HasFillStyle() const
3082
0
{
3083
0
    return GetObjectItem(XATTR_FILLSTYLE).GetValue() != drawing::FillStyle_NONE;
3084
0
}
3085
3086
bool SdrObject::HasLineStyle() const
3087
0
{
3088
0
    return GetObjectItem(XATTR_LINESTYLE).GetValue() != drawing::LineStyle_NONE;
3089
0
}
3090
3091
3092
// #i52224#
3093
// on import of OLE object from MS documents the BLIP size might be retrieved,
3094
// the following four methods are used to control it;
3095
// usually this data makes no sense after the import is finished, since the object
3096
// might be resized
3097
3098
3099
void SdrObject::SetBLIPSizeRectangle( const tools::Rectangle& aRect )
3100
3.15k
{
3101
3.15k
    maBLIPSizeRectangle = aRect;
3102
3.15k
}
3103
3104
void SdrObject::SetContextWritingMode( const sal_Int16 /*_nContextWritingMode*/ )
3105
763
{
3106
    // this base class does not support different writing modes, so ignore the call
3107
763
}
3108
3109
void SdrObject::SetDoNotInsertIntoPageAutomatically(const bool bSet)
3110
0
{
3111
0
    mbDoNotInsertIntoPageAutomatically = bSet;
3112
0
}
3113
3114
3115
// #i121917#
3116
bool SdrObject::HasText() const
3117
0
{
3118
0
    return false;
3119
0
}
3120
3121
bool SdrObject::IsTextBox() const
3122
12.7k
{
3123
12.7k
    return false;
3124
12.7k
}
3125
3126
void SdrObject::MakeNameUnique()
3127
0
{
3128
0
    if (GetName().isEmpty())
3129
0
    {
3130
0
        OUString aName;
3131
0
        if (const E3dScene* pE3dObj = DynCastE3dScene(this))
3132
0
        {
3133
0
            SdrObjList* pObjList = pE3dObj->GetSubList();
3134
0
            if (pObjList)
3135
0
            {
3136
0
                SdrObject* pObj0 = pObjList->GetObj(0);
3137
0
                if (pObj0)
3138
0
                    aName = pObj0->TakeObjNameSingul();
3139
0
            }
3140
0
        }
3141
0
        else
3142
0
            aName = TakeObjNameSingul();
3143
0
        SetName(aName + " 1");
3144
0
    }
3145
3146
0
    std::unordered_set<OUString> aNameSet;
3147
0
    MakeNameUnique(aNameSet);
3148
0
}
3149
3150
void SdrObject::MakeNameUnique(std::unordered_set<OUString>& rNameSet)
3151
10.1k
{
3152
10.1k
    if (GetName().isEmpty())
3153
4.29k
        return;
3154
3155
5.90k
    if (rNameSet.empty())
3156
5.90k
    {
3157
5.90k
        SdrPage* pPage;
3158
5.90k
        SdrObject* pObj;
3159
11.8k
        for (sal_uInt16 nPage(0); nPage < mrSdrModelFromSdrObject.GetPageCount(); ++nPage)
3160
5.90k
        {
3161
5.90k
            pPage = mrSdrModelFromSdrObject.GetPage(nPage);
3162
5.90k
            SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
3163
68.8k
            while (aIter.IsMore())
3164
62.9k
            {
3165
62.9k
                pObj = aIter.Next();
3166
62.9k
                if (pObj != this)
3167
57.0k
                    rNameSet.insert(pObj->GetName());
3168
62.9k
            }
3169
5.90k
        }
3170
5.90k
    }
3171
3172
5.90k
    OUString sName(GetName().trim());
3173
5.90k
    OUString sRootName(sName);
3174
3175
5.90k
    if (!sName.isEmpty() && rtl::isAsciiDigit(sName[sName.getLength() - 1]))
3176
5.90k
    {
3177
5.90k
        sal_Int32 nPos(sName.getLength() - 1);
3178
9.68k
        while (nPos > 0 && rtl::isAsciiDigit(sName[--nPos]));
3179
5.90k
        sRootName = o3tl::trim(sName.subView(0, nPos + 1));
3180
5.90k
    }
3181
3182
14.1k
    for (sal_uInt32 n = 1; rNameSet.find(sName) != rNameSet.end(); n++)
3183
8.26k
        sName = sRootName + " " + OUString::number(n);
3184
5.90k
    rNameSet.insert(sName);
3185
3186
5.90k
    SetName(sName);
3187
5.90k
}
3188
3189
void SdrObject::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept
3190
3.51k
{
3191
3.51k
    MapUnit eMapUnit(getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3192
3.51k
    if(eMapUnit == MapUnit::Map100thMM)
3193
1.83k
        return;
3194
3195
1.67k
    if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid)
3196
1.67k
    {
3197
1.67k
        const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100, eTo));
3198
1.67k
        rPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert, fConvert));
3199
1.67k
    }
3200
0
    else
3201
0
    {
3202
0
        OSL_FAIL("Missing unit translation to PoolMetric!");
3203
0
    }
3204
1.67k
}
3205
3206
const tools::Rectangle& SdrObject::getOutRectangle() const
3207
44.6M
{
3208
44.6M
    return m_aOutRect;
3209
44.6M
}
3210
3211
void SdrObject::setOutRectangleConst(tools::Rectangle const& rRectangle) const
3212
723
{
3213
723
    m_aOutRect = rRectangle;
3214
723
}
3215
3216
void SdrObject::setOutRectangle(tools::Rectangle const& rRectangle)
3217
6.41M
{
3218
6.41M
    m_aOutRect = rRectangle;
3219
6.41M
}
3220
3221
void SdrObject::resetOutRectangle()
3222
20.7M
{
3223
20.7M
    m_aOutRect = tools::Rectangle();
3224
20.7M
}
3225
3226
void SdrObject::moveOutRectangle(sal_Int32 nXDelta, sal_Int32 nYDelta)
3227
321k
{
3228
321k
    m_aOutRect.Move(nXDelta, nYDelta);
3229
321k
}
3230
3231
E3dScene* DynCastE3dScene(SdrObject* pObj)
3232
791k
{
3233
791k
    if( pObj && pObj->GetObjInventor() == SdrInventor::E3d && pObj->GetObjIdentifier() == SdrObjKind::E3D_Scene )
3234
23.3k
        return static_cast<E3dScene*>(pObj);
3235
767k
    return nullptr;
3236
791k
}
3237
3238
E3dObject* DynCastE3dObject(SdrObject* pObj)
3239
1.40M
{
3240
1.40M
    if( pObj && pObj->GetObjInventor() == SdrInventor::E3d )
3241
1.40M
        return static_cast<E3dObject*>(pObj);
3242
400
    return nullptr;
3243
1.40M
}
3244
3245
SdrTextObj* DynCastSdrTextObj(SdrObject* pObj)
3246
26.6M
{
3247
    // SdrTextObj has a lot of subclasses, with lots of SdrObjKind identifiers, so use a virtual method
3248
    // to be safer.
3249
26.6M
    if( pObj && pObj->IsSdrTextObj() )
3250
23.9M
        return static_cast<SdrTextObj*>(pObj);
3251
2.64M
    return nullptr;
3252
26.6M
}
3253
3254
SdrOle2Obj* DynCastSdrOle2Obj(SdrObject* pObj)
3255
0
{
3256
    // SdrTextObj has subclasses, with lots of SdrObjKind identifiers, so use a virtual method
3257
    // to be safer.
3258
0
    if( pObj && pObj->IsSdrOle2Obj() )
3259
0
        return static_cast<SdrOle2Obj*>(pObj);
3260
0
    return nullptr;
3261
0
}
3262
3263
rtl::Reference<SdrObject> SdrObjFactory::CreateObjectFromFactory(SdrModel& rSdrModel, SdrInventor nInventor, SdrObjKind nObjIdentifier)
3264
0
{
3265
0
    SdrObjCreatorParams aParams { nInventor, nObjIdentifier, rSdrModel };
3266
0
    for (const auto & i : ImpGetUserMakeObjHdl()) {
3267
0
        rtl::Reference<SdrObject> pObj = i.Call(aParams);
3268
0
        if (pObj) {
3269
0
            return pObj;
3270
0
        }
3271
0
    }
3272
0
    return nullptr;
3273
0
}
3274
3275
namespace
3276
{
3277
3278
// SdrObject subclass, which represents an empty object of a
3279
// certain type (kind).
3280
template <SdrObjKind OBJECT_KIND, SdrInventor OBJECT_INVENTOR>
3281
class EmptyObject final : public SdrObject
3282
{
3283
private:
3284
    virtual ~EmptyObject() override
3285
    {}
3286
3287
public:
3288
    EmptyObject(SdrModel& rSdrModel)
3289
0
        : SdrObject(rSdrModel)
3290
0
    {
3291
0
    }
3292
3293
    EmptyObject(SdrModel& rSdrModel, EmptyObject const& rSource)
3294
0
        : SdrObject(rSdrModel, rSource)
3295
0
    {
3296
0
    }
3297
3298
    rtl::Reference<SdrObject> CloneSdrObject(SdrModel& rTargetModel) const override
3299
0
    {
3300
0
        return new EmptyObject(rTargetModel, *this);
3301
0
    }
3302
3303
    virtual std::unique_ptr<sdr::properties::BaseProperties> CreateObjectSpecificProperties() override
3304
0
    {
3305
0
        return std::make_unique<sdr::properties::EmptyProperties>(*this);
3306
0
    }
3307
3308
    SdrInventor GetObjInventor() const override
3309
0
    {
3310
0
        return OBJECT_INVENTOR;
3311
0
    }
3312
3313
    SdrObjKind GetObjIdentifier() const override
3314
0
    {
3315
0
        return OBJECT_KIND;
3316
0
    }
3317
3318
    void NbcRotate(const Point& /*rRef*/, Degree100 /*nAngle*/, double /*sinAngle*/, double /*cosAngle*/) override
3319
0
    {
3320
0
        assert(false); // should not be called for this kind of objects
3321
0
    }
3322
};
3323
3324
} // end anonymous namespace
3325
3326
rtl::Reference<SdrObject> SdrObjFactory::MakeNewObject(
3327
    SdrModel& rSdrModel,
3328
    SdrInventor nInventor,
3329
    SdrObjKind nIdentifier,
3330
    const tools::Rectangle* pSnapRect)
3331
189k
{
3332
189k
    rtl::Reference<SdrObject> pObj;
3333
189k
    bool bSetSnapRect(nullptr != pSnapRect);
3334
3335
189k
    if (nInventor == SdrInventor::Default)
3336
189k
    {
3337
189k
        switch (nIdentifier)
3338
189k
        {
3339
0
            case SdrObjKind::Measure:
3340
0
            {
3341
0
                if(nullptr != pSnapRect)
3342
0
                {
3343
0
                    pObj = new SdrMeasureObj(
3344
0
                        rSdrModel,
3345
0
                        pSnapRect->TopLeft(),
3346
0
                        pSnapRect->BottomRight());
3347
0
                }
3348
0
                else
3349
0
                {
3350
0
                    pObj = new SdrMeasureObj(rSdrModel);
3351
0
                }
3352
0
            }
3353
0
            break;
3354
712
            case SdrObjKind::Line:
3355
712
            {
3356
712
                if(nullptr != pSnapRect)
3357
712
                {
3358
712
                    basegfx::B2DPolygon aPoly;
3359
3360
712
                    aPoly.append(
3361
712
                        basegfx::B2DPoint(
3362
712
                            pSnapRect->Left(),
3363
712
                            pSnapRect->Top()));
3364
712
                    aPoly.append(
3365
712
                        basegfx::B2DPoint(
3366
712
                            pSnapRect->Right(),
3367
712
                            pSnapRect->Bottom()));
3368
712
                    pObj = new SdrPathObj(
3369
712
                        rSdrModel,
3370
712
                        SdrObjKind::Line,
3371
712
                        basegfx::B2DPolyPolygon(aPoly));
3372
712
                }
3373
0
                else
3374
0
                {
3375
0
                    pObj = new SdrPathObj(
3376
0
                        rSdrModel,
3377
0
                        SdrObjKind::Line);
3378
0
                }
3379
712
            }
3380
712
            break;
3381
148k
            case SdrObjKind::Text:
3382
148k
            case SdrObjKind::TitleText:
3383
148k
            case SdrObjKind::OutlineText:
3384
148k
            {
3385
148k
                if(nullptr != pSnapRect)
3386
8.11k
                {
3387
8.11k
                    pObj = new SdrRectObj(
3388
8.11k
                        rSdrModel, *pSnapRect, nIdentifier);
3389
8.11k
                    bSetSnapRect = false;
3390
8.11k
                }
3391
140k
                else
3392
140k
                {
3393
140k
                    pObj = new SdrRectObj(
3394
140k
                        rSdrModel, tools::Rectangle(), nIdentifier);
3395
140k
                }
3396
148k
            }
3397
148k
            break;
3398
214
            case SdrObjKind::CircleOrEllipse:
3399
214
            case SdrObjKind::CircleSection:
3400
214
            case SdrObjKind::CircleArc:
3401
214
            case SdrObjKind::CircleCut:
3402
214
            {
3403
214
                SdrCircKind eCircKind = ToSdrCircKind(nIdentifier);
3404
214
                if(nullptr != pSnapRect)
3405
214
                {
3406
214
                    pObj = new SdrCircObj(rSdrModel, eCircKind, *pSnapRect);
3407
214
                    bSetSnapRect = false;
3408
214
                }
3409
0
                else
3410
0
                {
3411
0
                    pObj = new SdrCircObj(rSdrModel, eCircKind);
3412
0
                }
3413
214
            }
3414
214
            break;
3415
0
            case SdrObjKind::NONE: pObj = nullptr; break;
3416
1.80k
            case SdrObjKind::Group       : pObj=new SdrObjGroup(rSdrModel);                 break;
3417
103
            case SdrObjKind::Polygon       : pObj=new SdrPathObj(rSdrModel, SdrObjKind::Polygon       ); break;
3418
2.32k
            case SdrObjKind::PolyLine       : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PolyLine       ); break;
3419
849
            case SdrObjKind::PathLine   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PathLine   ); break;
3420
5
            case SdrObjKind::PathFill   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PathFill   ); break;
3421
0
            case SdrObjKind::FreehandLine   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::FreehandLine   ); break;
3422
0
            case SdrObjKind::FreehandFill   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::FreehandFill   ); break;
3423
0
            case SdrObjKind::PathPoly   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::Polygon       ); break;
3424
0
            case SdrObjKind::PathPolyLine   : pObj=new SdrPathObj(rSdrModel, SdrObjKind::PolyLine       ); break;
3425
1.90k
            case SdrObjKind::Edge       : pObj=new SdrEdgeObj(rSdrModel);                  break;
3426
2.58k
            case SdrObjKind::Rectangle       : pObj=new SdrRectObj(rSdrModel);                  break;
3427
5.75k
            case SdrObjKind::Graphic       : pObj=new SdrGrafObj(rSdrModel);                  break;
3428
597
            case SdrObjKind::OLE2       : pObj=new SdrOle2Obj(rSdrModel);                  break;
3429
0
            case SdrObjKind::OLEPluginFrame      : pObj=new SdrOle2Obj(rSdrModel, true);            break;
3430
0
            case SdrObjKind::Caption    : pObj=new SdrCaptionObj(rSdrModel);               break;
3431
107
            case SdrObjKind::Page       : pObj=new SdrPageObj(rSdrModel);                  break;
3432
0
            case SdrObjKind::UNO        : pObj=new SdrUnoObj(rSdrModel, OUString());       break;
3433
23.0k
            case SdrObjKind::CustomShape: pObj=new SdrObjCustomShape(rSdrModel);       break;
3434
0
#if HAVE_FEATURE_AVMEDIA
3435
0
            case SdrObjKind::Media      : pObj=new SdrMediaObj(rSdrModel);               break;
3436
0
#endif
3437
1.11k
            case SdrObjKind::Table      : pObj=new sdr::table::SdrTableObj(rSdrModel);   break;
3438
0
            case SdrObjKind::NewFrame: // used for frame creation in writer
3439
0
                pObj = new EmptyObject<SdrObjKind::NewFrame, SdrInventor::Default>(rSdrModel);
3440
0
                break;
3441
0
            default:
3442
0
                break;
3443
189k
        }
3444
189k
    }
3445
3446
189k
    if (!pObj)
3447
0
    {
3448
0
        pObj = CreateObjectFromFactory(rSdrModel, nInventor, nIdentifier);
3449
0
    }
3450
3451
189k
    if (!pObj)
3452
0
    {
3453
        // Well, if no one wants it...
3454
0
        return nullptr;
3455
0
    }
3456
3457
189k
    if(bSetSnapRect && nullptr != pSnapRect)
3458
40.9k
    {
3459
40.9k
        pObj->NbcSetSnapRect(*pSnapRect);
3460
40.9k
    }
3461
3462
189k
    return pObj;
3463
189k
}
3464
3465
void SdrObjFactory::InsertMakeObjectHdl(Link<SdrObjCreatorParams, rtl::Reference<SdrObject>> const & rLink)
3466
59
{
3467
59
    std::vector<Link<SdrObjCreatorParams, rtl::Reference<SdrObject>>>& rLL=ImpGetUserMakeObjHdl();
3468
59
    auto it = std::find(rLL.begin(), rLL.end(), rLink);
3469
59
    if (it != rLL.end()) {
3470
0
        OSL_FAIL("SdrObjFactory::InsertMakeObjectHdl(): Link already in place.");
3471
59
    } else {
3472
59
        rLL.push_back(rLink);
3473
59
    }
3474
59
}
3475
3476
void SdrObjFactory::RemoveMakeObjectHdl(Link<SdrObjCreatorParams, rtl::Reference<SdrObject>> const & rLink)
3477
9
{
3478
9
    std::vector<Link<SdrObjCreatorParams, rtl::Reference<SdrObject>>>& rLL=ImpGetUserMakeObjHdl();
3479
9
    auto it = std::find(rLL.begin(), rLL.end(), rLink);
3480
9
    if (it != rLL.end())
3481
9
        rLL.erase(it);
3482
9
}
3483
3484
namespace svx
3485
{
3486
    ISdrObjectFilter::~ISdrObjectFilter()
3487
0
    {
3488
0
    }
3489
}
3490
3491
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */