Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdobj.cxx
Warning:line 2498, column 16
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

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