Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

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 svdograf.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/svdograf.cxx

/home/maarten/src/libreoffice/core/svx/source/svdraw/svdograf.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 <unotools/streamwrap.hxx>
21
22#include <sfx2/lnkbase.hxx>
23#include <rtl/ustrbuf.hxx>
24#include <tools/helpers.hxx>
25#include <tools/stream.hxx>
26#include <sot/exchange.hxx>
27#include <sot/formats.hxx>
28#include <vcl/GraphicObject.hxx>
29#include <vcl/svapp.hxx>
30
31#include <sfx2/linkmgr.hxx>
32#include <svx/dialmgr.hxx>
33#include <svx/strings.hrc>
34#include <svx/svdhdl.hxx>
35#include <svx/svdmodel.hxx>
36#include <svx/svdpage.hxx>
37#include <svx/svdograf.hxx>
38#include <svx/svdogrp.hxx>
39#include <svx/xbtmpit.hxx>
40#include <svx/xfillit0.hxx>
41#include <svx/xflbmtit.hxx>
42#include "svdfmtf.hxx"
43#include <sdgcoitm.hxx>
44#include <svx/sdgcpitm.hxx>
45#include <svx/sdggaitm.hxx>
46#include <sdginitm.hxx>
47#include <svx/sdgluitm.hxx>
48#include <svx/sdgmoitm.hxx>
49#include <sdgtritm.hxx>
50#include <sdr/properties/graphicproperties.hxx>
51#include <sdr/contact/viewcontactofgraphic.hxx>
52#include <basegfx/matrix/b2dhommatrixtools.hxx>
53#include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
54#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
55#include <memory>
56
57using namespace ::com::sun::star;
58using namespace ::com::sun::star::uno;
59using namespace ::com::sun::star::io;
60
61class SdrGraphicLink : public sfx2::SvBaseLink
62{
63 SdrGrafObj& rGrafObj;
64
65public:
66 explicit SdrGraphicLink(SdrGrafObj& rObj);
67
68 virtual void Closed() override;
69
70 virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
71 const OUString& rMimeType, const css::uno::Any & rValue ) override;
72
73 void Connect() { GetRealObject(); }
74};
75
76SdrGraphicLink::SdrGraphicLink(SdrGrafObj& rObj)
77: ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB )
78, rGrafObj( rObj )
79{
80 SetSynchron( false );
81}
82
83::sfx2::SvBaseLink::UpdateResult SdrGraphicLink::DataChanged(
84 const OUString& rMimeType, const css::uno::Any & rValue )
85{
86 SdrModel& rModel(rGrafObj.getSdrModelFromSdrObject());
87 sfx2::LinkManager* pLinkManager(rModel.GetLinkManager());
88
89 if( pLinkManager && rValue.hasValue() )
90 {
91 sfx2::LinkManager::GetDisplayNames( this, nullptr, &rGrafObj.aFileName, nullptr, &rGrafObj.aFilterName );
92
93 Graphic aGraphic;
94 if (pLinkManager->GetGraphicFromAny(rMimeType, rValue, aGraphic, nullptr))
95 {
96 rGrafObj.ImpSetLinkedGraphic(aGraphic);
97 }
98 else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
99 {
100 // broadcasting, to update slide sorter
101 rGrafObj.BroadcastObjectChange();
102 }
103 }
104 return SUCCESS;
105}
106
107void SdrGraphicLink::Closed()
108{
109 // close connection; set pLink of the object to NULL, as link instance is just about getting destructed.
110 rGrafObj.ForceSwapIn();
111 rGrafObj.pGraphicLink=nullptr;
112 rGrafObj.ReleaseGraphicLink();
113 SvBaseLink::Closed();
114}
115
116std::unique_ptr<sdr::properties::BaseProperties> SdrGrafObj::CreateObjectSpecificProperties()
117{
118 return std::make_unique<sdr::properties::GraphicProperties>(*this);
119}
120
121
122// DrawContact section
123
124std::unique_ptr<sdr::contact::ViewContact> SdrGrafObj::CreateObjectSpecificViewContact()
125{
126 return std::make_unique<sdr::contact::ViewContactOfGraphic>(*this);
127}
128
129
130// check if SVG and if try to get ObjectInfoPrimitive2D and extract info
131
132void SdrGrafObj::onGraphicChanged()
133{
134 if (!mpGraphicObject || !mpGraphicObject->GetGraphic().isAvailable())
135 return;
136
137 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
138
139 if (!rVectorGraphicDataPtr)
140 return;
141
142 // Skip for PDF as it is only a bitmap primitive in a sequence and
143 // doesn't contain metadata. However getting the primitive sequence
144 // will also trigger a premature rendering of the PDF.
145 if (rVectorGraphicDataPtr->getVectorGraphicDataType() == VectorGraphicDataType::Pdf)
146 return;
147
148 const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVectorGraphicDataPtr->getPrimitive2DSequence());
149
150 if (aSequence.empty())
151 return;
152
153 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
154 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
155
156 aProcessor.process(aSequence);
157
158 const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
159
160 if (!pResult)
161 return;
162
163 OUString aName = pResult->getName();
164 OUString aTitle = pResult->getTitle();
165 OUString aDesc = pResult->getDesc();
166
167 if(!aName.isEmpty())
168 {
169 SetName(aName);
170 }
171
172 if(!aTitle.isEmpty())
173 {
174 SetTitle(aTitle);
175 }
176
177 if(!aDesc.isEmpty())
178 {
179 SetDescription(aDesc);
180 }
181}
182
183SdrGrafObj::SdrGrafObj(SdrModel& rSdrModel)
184: SdrRectObj(rSdrModel)
185 ,mpGraphicObject(new GraphicObject)
186 ,pGraphicLink(nullptr)
187 ,bMirrored(false)
188 ,mbIsSignatureLine(false)
189 ,mbIsSignatureLineShowSignDate(true)
190 ,mbIsSignatureLineCanAddComment(false)
191 ,mbSignatureLineIsSigned(false)
192{
193 onGraphicChanged();
194
195 // #i118485# Shear allowed and possible now
196 bNoShear = false;
197
198 mbGrafAnimationAllowed = true;
199
200 // #i25616#
201 mbLineIsOutsideGeometry = true;
202
203 // #i25616#
204 mbSupportTextIndentingOnLineWidthChange = false;
205}
206
207SdrGrafObj::SdrGrafObj(
208 SdrModel& rSdrModel,
209 const Graphic& rGraphic,
210 const tools::Rectangle& rRect)
211: SdrRectObj(rSdrModel, rRect)
212 ,mpGraphicObject(new GraphicObject(rGraphic))
213 ,pGraphicLink(nullptr)
214 ,bMirrored(false)
215 ,mbIsSignatureLine(false)
216 ,mbIsSignatureLineShowSignDate(true)
217 ,mbIsSignatureLineCanAddComment(false)
218 ,mbSignatureLineIsSigned(false)
219{
220 onGraphicChanged();
221
222 // #i118485# Shear allowed and possible now
223 bNoShear = false;
224
225 mbGrafAnimationAllowed = true;
226
227 // #i25616#
228 mbLineIsOutsideGeometry = true;
229
230 // #i25616#
231 mbSupportTextIndentingOnLineWidthChange = false;
232}
233
234SdrGrafObj::SdrGrafObj(
235 SdrModel& rSdrModel,
236 const Graphic& rGraphic)
237: SdrRectObj(rSdrModel)
238 ,mpGraphicObject(new GraphicObject(rGraphic))
239 ,pGraphicLink(nullptr)
240 ,bMirrored(false)
241 ,mbIsSignatureLine(false)
242 ,mbIsSignatureLineShowSignDate(true)
243 ,mbIsSignatureLineCanAddComment(false)
244 ,mbSignatureLineIsSigned(false)
245{
246 onGraphicChanged();
247
248 // #i118485# Shear allowed and possible now
249 bNoShear = false;
250
251 mbGrafAnimationAllowed = true;
252
253 // #i25616#
254 mbLineIsOutsideGeometry = true;
255
256 // #i25616#
257 mbSupportTextIndentingOnLineWidthChange = false;
258}
259
260SdrGrafObj::~SdrGrafObj()
261{
262 ImpDeregisterLink();
263}
264
265void SdrGrafObj::SetGraphicObject(const GraphicObject& rGraphicObject)
266{
267 mpGraphicObject.reset(new GraphicObject(rGraphicObject));
268 mpReplacementGraphicObject.reset();
269 mpGraphicObject->SetUserData();
270 SetChanged();
271 BroadcastObjectChange();
272 onGraphicChanged();
273}
274
275const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const
276{
277 if (bForceSwapIn)
278 ForceSwapIn();
279 return *mpGraphicObject;
280}
281
282const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const
283{
284 if (!mpReplacementGraphicObject && mpGraphicObject)
285 {
286 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
287
288 if (rVectorGraphicDataPtr)
289 {
290 const_cast< SdrGrafObj* >(this)->mpReplacementGraphicObject.reset(new GraphicObject(rVectorGraphicDataPtr->getReplacement()));
291 }
292 else if (mpGraphicObject->GetGraphic().GetType() == GraphicType::GdiMetafile)
293 {
294 // Replacement graphic for PDF and metafiles is just the bitmap.
295 const_cast<SdrGrafObj*>(this)->mpReplacementGraphicObject.reset(new GraphicObject(mpGraphicObject->GetGraphic().GetBitmapEx()));
296 }
297 }
298
299 return mpReplacementGraphicObject.get();
300}
301
302void SdrGrafObj::NbcSetGraphic(const Graphic& rGraphic)
303{
304 mpGraphicObject->SetGraphic(rGraphic);
305 mpReplacementGraphicObject.reset();
306 mpGraphicObject->SetUserData();
307 onGraphicChanged();
308}
309
310void SdrGrafObj::SetGraphic( const Graphic& rGraphic )
311{
312 if (!rGraphic.getOriginURL().isEmpty())
313 {
314 ImpDeregisterLink();
315 aFileName = rGraphic.getOriginURL();
316 aReferer = "";
317 aFilterName = "";
318 }
319 NbcSetGraphic(rGraphic);
320 if (!rGraphic.getOriginURL().isEmpty())
321 {
322 ImpRegisterLink();
323 mpGraphicObject->SetUserData();
324 }
325 SetChanged();
326 BroadcastObjectChange();
327 ForceSwapIn();
328}
329
330const Graphic& SdrGrafObj::GetGraphic() const
331{
332 return mpGraphicObject->GetGraphic();
333}
334
335Graphic SdrGrafObj::GetTransformedGraphic( SdrGrafObjTransformsAttrs nTransformFlags ) const
336{
337 // Refactored most of the code to GraphicObject, where
338 // everybody can use e.g. the cropping functionality
339 MapMode aDestMap(
340 getSdrModelFromSdrObject().GetScaleUnit(),
341 Point(),
342 getSdrModelFromSdrObject().GetScaleFraction(),
343 getSdrModelFromSdrObject().GetScaleFraction());
344 const Size aDestSize( GetLogicRect().GetSize() );
345 GraphicAttr aActAttr = GetGraphicAttr(nTransformFlags);
346
347 // Delegate to moved code in GraphicObject
348 return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr );
349}
350
351GraphicType SdrGrafObj::GetGraphicType() const
352{
353 return mpGraphicObject->GetType();
354}
355
356GraphicAttr SdrGrafObj::GetGraphicAttr( SdrGrafObjTransformsAttrs nTransformFlags ) const
357{
358 GraphicAttr aActAttr;
359
360 GraphicType eType = GetGraphicType();
361 if( SdrGrafObjTransformsAttrs::NONE != nTransformFlags &&
362 GraphicType::NONE != eType )
363 {
364 const bool bMirror = bool( nTransformFlags & SdrGrafObjTransformsAttrs::MIRROR );
365 const bool bRotate = bool( nTransformFlags & SdrGrafObjTransformsAttrs::ROTATE ) &&
366 (aGeo.nRotationAngle && aGeo.nRotationAngle != 18000);
367
368 // Need cropping info earlier
369 const_cast<SdrGrafObj*>(this)->ImpSetAttrToGrafInfo();
370
371 // Actually transform the graphic only in this case.
372 // Cropping always happens, though.
373 aActAttr = aGrafInfo;
374
375 if( bMirror )
376 {
377 sal_uInt16 nMirrorCase = ( aGeo.nRotationAngle == 18000 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 );
378 bool bHMirr = nMirrorCase == 2 || nMirrorCase == 4;
379 bool bVMirr = nMirrorCase == 3 || nMirrorCase == 4;
380
381 aActAttr.SetMirrorFlags( ( bHMirr ? BmpMirrorFlags::Horizontal : BmpMirrorFlags::NONE ) | ( bVMirr ? BmpMirrorFlags::Vertical : BmpMirrorFlags::NONE ) );
382 }
383
384 if( bRotate )
385 aActAttr.SetRotation( sal_uInt16(aGeo.nRotationAngle / 10) );
386 }
387
388 return aActAttr;
389}
390
391bool SdrGrafObj::IsAnimated() const
392{
393 return mpGraphicObject->IsAnimated();
394}
395
396bool SdrGrafObj::IsEPS() const
397{
398 return mpGraphicObject->IsEPS();
399}
400
401MapMode SdrGrafObj::GetGrafPrefMapMode() const
402{
403 return mpGraphicObject->GetPrefMapMode();
404}
405
406Size SdrGrafObj::GetGrafPrefSize() const
407{
408 return mpGraphicObject->GetPrefSize();
409}
410
411void SdrGrafObj::SetGrafStreamURL( const OUString& rGraphicStreamURL )
412{
413 if( rGraphicStreamURL.isEmpty() )
414 {
415 mpGraphicObject->SetUserData();
416 }
417 else if(getSdrModelFromSdrObject().IsSwapGraphics() )
418 {
419 mpGraphicObject->SetUserData( rGraphicStreamURL );
420 }
421}
422
423OUString const & SdrGrafObj::GetGrafStreamURL() const
424{
425 return mpGraphicObject->GetUserData();
426}
427
428Size SdrGrafObj::getOriginalSize() const
429{
430 Size aSize = GetGrafPrefSize();
431
432 if (aGrafInfo.IsCropped())
433 {
434 const long aCroppedTop(OutputDevice::LogicToLogic(aGrafInfo.GetTopCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
435 const long aCroppedBottom(OutputDevice::LogicToLogic(aGrafInfo.GetBottomCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
436 const long aCroppedLeft(OutputDevice::LogicToLogic(aGrafInfo.GetLeftCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
437 const long aCroppedRight(OutputDevice::LogicToLogic(aGrafInfo.GetRightCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
438 const long aCroppedWidth(aSize.getWidth() - aCroppedLeft + aCroppedRight);
439 const long aCroppedHeight(aSize.getHeight() - aCroppedTop + aCroppedBottom);
440
441 aSize = Size ( aCroppedWidth, aCroppedHeight);
442 }
443
444 if ( GetGrafPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
445 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
446 else
447 aSize = OutputDevice::LogicToLogic(aSize, GetGrafPrefMapMode(), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
448
449 return aSize;
450}
451
452// TODO Remove
453void SdrGrafObj::ForceSwapIn() const
454{
455 if (pGraphicLink && (mpGraphicObject->GetType() == GraphicType::NONE ||
456 mpGraphicObject->GetType() == GraphicType::Default) )
457 {
458 pGraphicLink->Update();
459 }
460}
461
462void SdrGrafObj::ImpRegisterLink()
463{
464 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
465
466 if( pLinkManager != nullptr && pGraphicLink == nullptr )
467 {
468 if (!aFileName.isEmpty())
469 {
470 pGraphicLink = new SdrGraphicLink( *this );
471 pLinkManager->InsertFileLink(
472 *pGraphicLink, sfx2::SvBaseLinkObjectType::ClientGraphic, aFileName, (aFilterName.isEmpty() ? nullptr : &aFilterName));
473 pGraphicLink->Connect();
474 }
475 }
476}
477
478void SdrGrafObj::ImpDeregisterLink()
479{
480 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
481
482 if( pLinkManager != nullptr && pGraphicLink!=nullptr)
483 {
484 // When using Remove, the *pGraphicLink is implicitly deleted
485 pLinkManager->Remove( pGraphicLink );
486 pGraphicLink=nullptr;
487 }
488}
489
490void SdrGrafObj::SetGraphicLink(const OUString& rFileName, const OUString& /*rReferer*/, const OUString& /*rFilterName*/)
491{
492 Graphic aGraphic;
493 aGraphic.setOriginURL(rFileName);
494 SetGraphic(aGraphic);
495}
496
497void SdrGrafObj::ReleaseGraphicLink()
498{
499 ImpDeregisterLink();
500 aFileName.clear();
501 aReferer.clear();
502 aFilterName.clear();
503}
504
505bool SdrGrafObj::IsLinkedGraphic() const
506{
507 return !mpGraphicObject->GetGraphic().getOriginURL().isEmpty();
508}
509
510void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
511{
512 bool bNoPresGrf = ( mpGraphicObject->GetType() != GraphicType::NONE ) && !bEmptyPresObj;
513
514 rInfo.bResizeFreeAllowed = aGeo.nRotationAngle % 9000 == 0 ||
515 aGeo.nRotationAngle % 18000 == 0 ||
516 aGeo.nRotationAngle % 27000 == 0;
517
518 rInfo.bResizePropAllowed = true;
519 rInfo.bRotateFreeAllowed = bNoPresGrf;
520 rInfo.bRotate90Allowed = bNoPresGrf;
521 rInfo.bMirrorFreeAllowed = bNoPresGrf;
522 rInfo.bMirror45Allowed = bNoPresGrf;
523 rInfo.bMirror90Allowed = !bEmptyPresObj;
524 rInfo.bTransparenceAllowed = false;
525
526 // #i118485# Shear allowed and possible now
527 rInfo.bShearAllowed = true;
528
529 rInfo.bEdgeRadiusAllowed=false;
530 rInfo.bCanConvToPath = !IsEPS();
531 rInfo.bCanConvToPathLineToArea = false;
532 rInfo.bCanConvToPolyLineToArea = false;
533 rInfo.bCanConvToPoly = !IsEPS();
534 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
535}
536
537sal_uInt16 SdrGrafObj::GetObjIdentifier() const
538{
539 return sal_uInt16( OBJ_GRAF );
540}
541
542void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic )
543{
544 const bool bIsChanged(getSdrModelFromSdrObject().IsChanged());
545 NbcSetGraphic( rGraphic );
546 ActionChanged();
547 BroadcastObjectChange();
548 getSdrModelFromSdrObject().SetChanged(bIsChanged);
549}
550
551OUString SdrGrafObj::TakeObjNameSingul() const
552{
553 if (!mpGraphicObject)
554 return OUString();
555
556 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
557
558 OUStringBuffer sName;
559
560 if (rVectorGraphicDataPtr)
561 {
562 switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
563 {
564 case VectorGraphicDataType::Wmf:
565 {
566 sName.append(SvxResId(STR_ObjNameSingulGRAFWMFreinterpret_cast<char const *>("STR_ObjNameSingulGRAFWMF"
"\004" u8"WMF")
));
567 break;
568 }
569 case VectorGraphicDataType::Emf:
570 {
571 sName.append(SvxResId(STR_ObjNameSingulGRAFEMFreinterpret_cast<char const *>("STR_ObjNameSingulGRAFEMF"
"\004" u8"EMF")
));
572 break;
573 }
574 default: // case VectorGraphicDataType::Svg:
575 {
576 sName.append(SvxResId(STR_ObjNameSingulGRAFSVGreinterpret_cast<char const *>("STR_ObjNameSingulGRAFSVG"
"\004" u8"SVG")
));
577 break;
578 }
579 }
580 }
581 else
582 {
583 switch( mpGraphicObject->GetType() )
584 {
585 case GraphicType::Bitmap:
586 {
587 const char* pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
588 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNKreinterpret_cast<char const *>("STR_ObjNameSingulGRAFBMPTRANSLNK"
"\004" u8"Linked image with transparency")
: STR_ObjNameSingulGRAFBMPTRANSreinterpret_cast<char const *>("STR_ObjNameSingulGRAFBMPTRANS"
"\004" u8"Image with transparency")
) :
589 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNKreinterpret_cast<char const *>("STR_ObjNameSingulGRAFBMPLNK"
"\004" u8"Linked Image")
: STR_ObjNameSingulGRAFBMPreinterpret_cast<char const *>("STR_ObjNameSingulGRAFBMP"
"\004" u8"Image")
) );
590
591 sName.append(SvxResId(pId));
592 }
593 break;
594
595 case GraphicType::GdiMetafile:
596 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNKreinterpret_cast<char const *>("STR_ObjNameSingulGRAFMTFLNK"
"\004" u8"Linked Metafile")
: STR_ObjNameSingulGRAFMTFreinterpret_cast<char const *>("STR_ObjNameSingulGRAFMTF"
"\004" u8"Metafile")
));
597 break;
598
599 case GraphicType::NONE:
600 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNKreinterpret_cast<char const *>("STR_ObjNameSingulGRAFNONELNK"
"\004" u8"Blank linked image")
: STR_ObjNameSingulGRAFNONEreinterpret_cast<char const *>("STR_ObjNameSingulGRAFNONE"
"\004" u8"Blank image object")
));
601 break;
602
603 default:
604 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNKreinterpret_cast<char const *>("STR_ObjNameSingulGRAFLNK"
"\004" u8"Linked image")
: STR_ObjNameSingulGRAFreinterpret_cast<char const *>("STR_ObjNameSingulGRAF" "\004"
u8"Image")
));
605 break;
606 }
607 }
608
609 const OUString aName(GetName());
610
611 if (!aName.isEmpty())
612 {
613 sName.append(" '");
614 sName.append(aName);
615 sName.append('\'' );
616 }
617
618 return sName.makeStringAndClear();
619}
620
621OUString SdrGrafObj::TakeObjNamePlural() const
622{
623 if (!mpGraphicObject)
624 return OUString();
625
626 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
627
628 OUStringBuffer sName;
629
630 if (rVectorGraphicDataPtr)
631 {
632 switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
633 {
634 case VectorGraphicDataType::Wmf:
635 {
636 sName.append(SvxResId(STR_ObjNamePluralGRAFWMFreinterpret_cast<char const *>("STR_ObjNamePluralGRAFWMF"
"\004" u8"WMFs")
));
637 break;
638 }
639 case VectorGraphicDataType::Emf:
640 {
641 sName.append(SvxResId(STR_ObjNamePluralGRAFEMFreinterpret_cast<char const *>("STR_ObjNamePluralGRAFEMF"
"\004" u8"EMFs")
));
642 break;
643 }
644 default: // case VectorGraphicDataType::Svg:
645 {
646 sName.append(SvxResId(STR_ObjNamePluralGRAFSVGreinterpret_cast<char const *>("STR_ObjNamePluralGRAFSVG"
"\004" u8"SVGs")
));
647 break;
648 }
649 }
650 }
651 else
652 {
653 switch(mpGraphicObject->GetType())
654 {
655 case GraphicType::Bitmap:
656 {
657 const char* pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
658 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNKreinterpret_cast<char const *>("STR_ObjNamePluralGRAFBMPTRANSLNK"
"\004" u8"Linked images with transparency")
: STR_ObjNamePluralGRAFBMPTRANSreinterpret_cast<char const *>("STR_ObjNamePluralGRAFBMPTRANS"
"\004" u8"Images with transparency")
) :
659 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNKreinterpret_cast<char const *>("STR_ObjNamePluralGRAFBMPLNK"
"\004" u8"Linked images")
: STR_ObjNamePluralGRAFBMPreinterpret_cast<char const *>("STR_ObjNamePluralGRAFBMP"
"\004" u8"Images")
) );
660
661 sName.append(SvxResId(pId));
662 }
663 break;
664
665 case GraphicType::GdiMetafile:
666 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNKreinterpret_cast<char const *>("STR_ObjNamePluralGRAFMTFLNK"
"\004" u8"Linked Metafiles")
: STR_ObjNamePluralGRAFMTFreinterpret_cast<char const *>("STR_ObjNamePluralGRAFMTF"
"\004" u8"Metafiles")
));
667 break;
668
669 case GraphicType::NONE:
670 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNKreinterpret_cast<char const *>("STR_ObjNamePluralGRAFNONELNK"
"\004" u8"Blank linked images")
: STR_ObjNamePluralGRAFNONEreinterpret_cast<char const *>("STR_ObjNamePluralGRAFNONE"
"\004" u8"Blank image objects")
));
671 break;
672
673 default:
674 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNKreinterpret_cast<char const *>("STR_ObjNamePluralGRAFLNK"
"\004" u8"Linked images")
: STR_ObjNamePluralGRAFreinterpret_cast<char const *>("STR_ObjNamePluralGRAF" "\004"
u8"Images")
));
675 break;
676 }
677 }
678
679 const OUString aName(GetName());
680
681 if (!aName.isEmpty())
682 {
683 sName.append(" '");
684 sName.append(aName);
685 sName.append('\'');
686 }
687
688 return sName.makeStringAndClear();
689}
690
691SdrObjectUniquePtr SdrGrafObj::getFullDragClone() const
692{
693 // call parent
694 SdrObjectUniquePtr pRetval = SdrRectObj::getFullDragClone();
695
696 // #i103116# the full drag clone leads to problems
697 // with linked graphics, so reset the link in this
698 // temporary interaction object and load graphic
699 if(pRetval && IsLinkedGraphic())
700 {
701 static_cast< SdrGrafObj* >(pRetval.get())->ReleaseGraphicLink();
702 }
703
704 return pRetval;
705}
706
707SdrGrafObj* SdrGrafObj::CloneSdrObject(SdrModel& rTargetModel) const
708{
709 return CloneHelper< SdrGrafObj >(rTargetModel);
710}
711
712SdrGrafObj& SdrGrafObj::operator=( const SdrGrafObj& rObj )
713{
714 if( this == &rObj )
715 return *this;
716 SdrRectObj::operator=( rObj );
717
718 aFileName = rObj.aFileName;
719 aFilterName = rObj.aFilterName;
720 bMirrored = rObj.bMirrored;
721
722 mbIsSignatureLine = rObj.mbIsSignatureLine;
723 maSignatureLineId = rObj.maSignatureLineId;
724 maSignatureLineSuggestedSignerName = rObj.maSignatureLineSuggestedSignerName;
725 maSignatureLineSuggestedSignerTitle = rObj.maSignatureLineSuggestedSignerTitle;
726 maSignatureLineSuggestedSignerEmail = rObj.maSignatureLineSuggestedSignerEmail;
727 maSignatureLineSigningInstructions = rObj.maSignatureLineSigningInstructions;
728 mbIsSignatureLineShowSignDate = rObj.mbIsSignatureLineShowSignDate;
729 mbIsSignatureLineCanAddComment = rObj.mbIsSignatureLineCanAddComment;
730 mbSignatureLineIsSigned = false;
731 mpSignatureLineUnsignedGraphic = rObj.mpSignatureLineUnsignedGraphic;
732
733 if(rObj.mpQrCode)
734 {
735 mpQrCode = std::make_unique<css::drawing::QRCode>(*rObj.mpQrCode);
736 }
737 else
738 {
739 mpQrCode.reset();
740 }
741
742 if (mbIsSignatureLine && rObj.mpSignatureLineUnsignedGraphic)
743 mpGraphicObject->SetGraphic(rObj.mpSignatureLineUnsignedGraphic);
744 else
745 mpGraphicObject->SetGraphic( rObj.GetGraphic(), &rObj.GetGraphicObject() );
746
747 if( rObj.IsLinkedGraphic() )
748 {
749 SetGraphicLink( aFileName, rObj.aReferer, aFilterName );
750 }
751
752 ImpSetAttrToGrafInfo();
753 return *this;
754}
755
756sal_uInt32 SdrGrafObj::GetHdlCount() const
757{
758 return 8;
759}
760
761void SdrGrafObj::AddToHdlList(SdrHdlList& rHdlList) const
762{
763 SdrHdlList tempList(nullptr);
764 SdrRectObj::AddToHdlList( tempList );
765 tempList.RemoveHdl(0);
766 tempList.MoveTo(rHdlList);
767}
768
769void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
770{
771 SdrRectObj::NbcResize( rRef, xFact, yFact );
772
773 bool bMirrX = xFact.GetNumerator() < 0;
774 bool bMirrY = yFact.GetNumerator() < 0;
775
776 if( bMirrX != bMirrY )
777 bMirrored = !bMirrored;
778}
779
780void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2)
781{
782 SdrRectObj::NbcMirror(rRef1,rRef2);
783 bMirrored = !bMirrored;
784}
785
786SdrObjGeoData* SdrGrafObj::NewGeoData() const
787{
788 return new SdrGrafObjGeoData;
789}
790
791void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const
792{
793 SdrRectObj::SaveGeoData(rGeo);
794 SdrGrafObjGeoData& rGGeo=static_cast<SdrGrafObjGeoData&>(rGeo);
795 rGGeo.bMirrored=bMirrored;
796}
797
798void SdrGrafObj::RestGeoData(const SdrObjGeoData& rGeo)
799{
800 SdrRectObj::RestGeoData(rGeo);
801 const SdrGrafObjGeoData& rGGeo=static_cast<const SdrGrafObjGeoData&>(rGeo);
802 bMirrored=rGGeo.bMirrored;
803}
804
805void SdrGrafObj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
806{
807 const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
808 const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
809
810 if( bRemove )
811 {
812 // No SwapIn necessary here, because if something's not loaded, it can't be animated either.
813 if( mpGraphicObject->IsAnimated())
814 mpGraphicObject->StopAnimation();
815
816 if( pGraphicLink != nullptr )
817 ImpDeregisterLink();
818 }
819
820 // call parent
821 SdrRectObj::handlePageChange(pOldPage, pNewPage);
822
823 if (!aFileName.isEmpty() && bInsert)
824 {
825 ImpRegisterLink();
826 }
827}
828
829void SdrGrafObj::StartAnimation()
830{
831 SetGrafAnimationAllowed(true);
832}
833
834bool SdrGrafObj::HasGDIMetaFile() const
835{
836 return( mpGraphicObject->GetType() == GraphicType::GdiMetafile );
837}
838
839bool SdrGrafObj::isEmbeddedVectorGraphicData() const
840{
841 return GraphicType::Bitmap == GetGraphicType() && GetGraphic().getVectorGraphicData();
842}
843
844GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedVectorGraphicData() const
845{
846 GDIMetaFile aRetval;
847
848 if(isEmbeddedVectorGraphicData())
849 {
850 ScopedVclPtrInstance< VirtualDevice > pOut;
851 const tools::Rectangle aBoundRect(GetCurrentBoundRect());
852 const MapMode aMap(
853 getSdrModelFromSdrObject().GetScaleUnit(),
854 Point(),
855 getSdrModelFromSdrObject().GetScaleFraction(),
856 getSdrModelFromSdrObject().GetScaleFraction());
857
858 pOut->EnableOutput(false);
859 pOut->SetMapMode(aMap);
860 aRetval.Record(pOut);
861 SingleObjectPainter(*pOut);
862 aRetval.Stop();
863 aRetval.WindStart();
864 aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top());
865 aRetval.SetPrefMapMode(aMap);
866 aRetval.SetPrefSize(aBoundRect.GetSize());
867 }
868
869 return aRetval;
870}
871
872GDIMetaFile SdrGrafObj::GetMetaFile(GraphicType &rGraphicType) const
873{
874 if (isEmbeddedVectorGraphicData())
875 {
876 // Embedded Vector Graphic Data
877 // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
878 // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
879 // use the old converter path over the MetaFile mechanism. Create Metafile from Svg
880 // primitives here pretty directly
881 rGraphicType = GraphicType::GdiMetafile;
882 return getMetafileFromEmbeddedVectorGraphicData();
883 }
884 else if (GraphicType::GdiMetafile == rGraphicType)
885 {
886 return GetTransformedGraphic(SdrGrafObjTransformsAttrs::MIRROR).GetGDIMetaFile();
887 }
888 return GDIMetaFile();
889}
890
891SdrObjectUniquePtr SdrGrafObj::DoConvertToPolyObj(bool bBezier, bool bAddText ) const
892{
893 SdrObject* pRetval = nullptr;
894 GraphicType aGraphicType(GetGraphicType());
895 GDIMetaFile aMtf(GetMetaFile(aGraphicType));
896 switch(aGraphicType)
1
Control jumps to 'case GdiMetafile:' at line 898
897 {
898 case GraphicType::GdiMetafile:
899 {
900 // Sort into group and return ONLY those objects that can be created from the MetaFile.
901 ImpSdrGDIMetaFileImport aFilter(
902 getSdrModelFromSdrObject(),
903 GetLayer(),
904 maRect);
905 SdrObjGroup* pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
906
907 if(aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0))
2
Assuming the condition is false
3
Taking false branch
908 {
909 {
910 // copy transformation
911 GeoStat aGeoStat(GetGeoStat());
912
913 if(aGeoStat.nShearAngle)
914 {
915 aGeoStat.RecalcTan();
916 pGrp->NbcShear(maRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
917 }
918
919 if(aGeoStat.nRotationAngle)
920 {
921 aGeoStat.RecalcSinCos();
922 pGrp->NbcRotate(maRect.TopLeft(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
923 }
924 }
925
926 pRetval = pGrp;
927 pGrp->NbcSetLayer(GetLayer());
928
929 if(bAddText)
930 {
931 pRetval = ImpConvertAddText(SdrObjectUniquePtr(pRetval), bBezier).release();
932 }
933
934 // convert all children
935 if( pRetval )
936 {
937 SdrObject* pHalfDone = pRetval;
938 pRetval = pRetval->DoConvertToPolyObj(bBezier, bAddText).release();
939 SdrObject::Free( pHalfDone ); // resulting object is newly created
940
941 if( pRetval )
942 {
943 // flatten subgroups. As we call
944 // DoConvertToPolyObj() on the resulting group
945 // objects, subgroups can exist (e.g. text is
946 // a group object for every line).
947 SdrObjList* pList = pRetval->GetSubList();
948 if( pList )
949 pList->FlattenGroups();
950 }
951 }
952 }
953 else
954 {
955 // always use SdrObject::Free(...) for SdrObjects (!)
956 SdrObject* pTemp(pGrp);
957 SdrObject::Free(pTemp);
958 }
959
960 // #i118485# convert line and fill
961 SdrObjectUniquePtr pLineFill = SdrRectObj::DoConvertToPolyObj(bBezier, false);
962
963 if(pLineFill)
4
Taking false branch
964 {
965 if(pRetval)
966 {
967 pGrp = dynamic_cast< SdrObjGroup* >(pRetval);
968
969 if(!pGrp)
970 {
971 pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
972 pGrp->NbcSetLayer(GetLayer());
973 pGrp->GetSubList()->NbcInsertObject(pRetval);
974 }
975
976 pGrp->GetSubList()->NbcInsertObject(pLineFill.release(), 0);
977 }
978 else
979 {
980 pRetval = pLineFill.release();
981 }
982 }
983
984 break;
5
Calling implicit destructor for 'ImpSdrGDIMetaFileImport'
6
Calling '~ScopedVclPtr'
985 }
986 case GraphicType::Bitmap:
987 {
988 // create basic object and add fill
989 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText).release();
990
991 // save bitmap as an attribute
992 if(pRetval)
993 {
994 // retrieve bitmap for the fill
995 SfxItemSet aSet(GetObjectItemSet());
996
997 aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
998 const BitmapEx aBitmapEx(GetTransformedGraphic().GetBitmapEx());
999 aSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
1000 aSet.Put(XFillBmpTileItem(false));
1001
1002 pRetval->SetMergedItemSet(aSet);
1003 }
1004 break;
1005 }
1006 case GraphicType::NONE:
1007 case GraphicType::Default:
1008 {
1009 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText).release();
1010 break;
1011 }
1012 }
1013
1014 return SdrObjectUniquePtr(pRetval);
1015}
1016
1017void SdrGrafObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1018{
1019 SetXPolyDirty();
1020 SdrRectObj::Notify( rBC, rHint );
1021 ImpSetAttrToGrafInfo();
1022}
1023
1024
1025void SdrGrafObj::SetMirrored( bool _bMirrored )
1026{
1027 bMirrored = _bMirrored;
1028}
1029
1030void SdrGrafObj::ImpSetAttrToGrafInfo()
1031{
1032 const SfxItemSet& rSet = GetObjectItemSet();
1033 const sal_uInt16 nTrans = rSet.Get( SDRATTR_GRAFTRANSPARENCE ).GetValue();
1034 const SdrGrafCropItem& rCrop = rSet.Get( SDRATTR_GRAFCROP );
1035
1036 aGrafInfo.SetLuminance( rSet.Get( SDRATTR_GRAFLUMINANCE ).GetValue() );
1037 aGrafInfo.SetContrast( rSet.Get( SDRATTR_GRAFCONTRAST ).GetValue() );
1038 aGrafInfo.SetChannelR( rSet.Get( SDRATTR_GRAFRED ).GetValue() );
1039 aGrafInfo.SetChannelG( rSet.Get( SDRATTR_GRAFGREEN ).GetValue() );
1040 aGrafInfo.SetChannelB( rSet.Get( SDRATTR_GRAFBLUE ).GetValue() );
1041 aGrafInfo.SetGamma( rSet.Get( SDRATTR_GRAFGAMMA ).GetValue() * 0.01 );
1042 aGrafInfo.SetTransparency( static_cast<sal_uInt8>(FRound( std::min( nTrans, sal_uInt16(100) ) * 2.55 )) );
1043 aGrafInfo.SetInvert( rSet.Get( SDRATTR_GRAFINVERT ).GetValue() );
1044 aGrafInfo.SetDrawMode( rSet.Get( SDRATTR_GRAFMODE ).GetValue() );
1045 aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() );
1046
1047 SetXPolyDirty();
1048 SetRectsDirty();
1049}
1050
1051void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly )
1052{
1053 Size aSize;
1054 Size aMaxSize( rMaxRect.GetSize() );
1055 if (mpGraphicObject->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
1056 aSize = Application::GetDefaultDevice()->PixelToLogic(mpGraphicObject->GetPrefSize(), MapMode(MapUnit::Map100thMM));
1057 else
1058 aSize = OutputDevice::LogicToLogic( mpGraphicObject->GetPrefSize(),
1059 mpGraphicObject->GetPrefMapMode(),
1060 MapMode( MapUnit::Map100thMM ) );
1061
1062 if( aSize.IsEmpty() )
1063 return;
1064
1065 Point aPos( rMaxRect.TopLeft() );
1066
1067 // if the graphic is too large, fit it to page
1068 if ( (!bShrinkOnly ||
1069 ( aSize.Height() > aMaxSize.Height() ) ||
1070 ( aSize.Width() > aMaxSize.Width() ) )&&
1071 aSize.Height() && aMaxSize.Height() )
1072 {
1073 float fGrfWH = static_cast<float>(aSize.Width()) /
1074 static_cast<float>(aSize.Height());
1075 float fWinWH = static_cast<float>(aMaxSize.Width()) /
1076 static_cast<float>(aMaxSize.Height());
1077
1078 // Scale graphic to page size
1079 if ( fGrfWH < fWinWH )
1080 {
1081 aSize.setWidth( static_cast<long>(aMaxSize.Height() * fGrfWH) );
1082 aSize.setHeight( aMaxSize.Height() );
1083 }
1084 else if ( fGrfWH > 0.F )
1085 {
1086 aSize.setWidth( aMaxSize.Width() );
1087 aSize.setHeight( static_cast<long>(aMaxSize.Width() / fGrfWH) );
1088 }
1089
1090 aPos = rMaxRect.Center();
1091 }
1092
1093 if( bShrinkOnly )
1094 aPos = maRect.TopLeft();
1095
1096 aPos.AdjustX( -(aSize.Width() / 2) );
1097 aPos.AdjustY( -(aSize.Height() / 2) );
1098 SetLogicRect( tools::Rectangle( aPos, aSize ) );
1099}
1100
1101void SdrGrafObj::SetGrafAnimationAllowed(bool bNew)
1102{
1103 if(mbGrafAnimationAllowed != bNew)
1104 {
1105 mbGrafAnimationAllowed = bNew;
1106 ActionChanged();
1107 }
1108}
1109
1110Reference< XInputStream > SdrGrafObj::getInputStream() const
1111{
1112 Reference< XInputStream > xStream;
1113
1114 if (mpGraphicObject && GetGraphic().IsGfxLink())
1115 {
1116 Graphic aGraphic( GetGraphic() );
1117 GfxLink aLink( aGraphic.GetGfxLink() );
1118 sal_uInt32 nSize = aLink.GetDataSize();
1119 const void* pSourceData = static_cast<const void*>(aLink.GetData());
1120 if( nSize && pSourceData )
1121 {
1122 sal_uInt8 * pBuffer = new sal_uInt8[ nSize ];
1123 memcpy( pBuffer, pSourceData, nSize );
1124
1125 SvMemoryStream* pStream = new SvMemoryStream( static_cast<void*>(pBuffer), static_cast<std::size_t>(nSize), StreamMode::READ );
1126 pStream->ObjectOwnsMemory( true );
1127 xStream.set( new utl::OInputStreamWrapper( pStream, true ) );
1128 }
1129 }
1130
1131 if (!xStream.is() && !aFileName.isEmpty())
1132 {
1133 SvFileStream* pStream = new SvFileStream( aFileName, StreamMode::READ );
1134 xStream.set( new utl::OInputStreamWrapper( pStream ) );
1135 }
1136
1137 return xStream;
1138}
1139
1140// moved crop handle creation here; this is the object type using them
1141void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
1142{
1143 basegfx::B2DHomMatrix aMatrix;
1144 basegfx::B2DPolyPolygon aPolyPolygon;
1145
1146 // get object transformation
1147 TRGetBaseGeometry(aMatrix, aPolyPolygon);
1148
1149 // part of object transformation correction, but used later, so defined outside next scope
1150 double fShearX(0.0), fRotate(0.0);
1151
1152 { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
1153 basegfx::B2DTuple aScale;
1154 basegfx::B2DTuple aTranslate;
1155
1156 aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1157
1158 if(!basegfx::fTools::equalZero(fShearX))
1159 {
1160 // shearX is used, correct it
1161 fShearX = -fShearX;
1162 }
1163
1164 aMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
1165 aScale,
1166 fShearX,
1167 fRotate,
1168 aTranslate);
1169 }
1170
1171 // get crop values
1172 const SdrGrafCropItem& rCrop = GetMergedItem(SDRATTR_GRAFCROP);
1173
1174 if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom())
1175 {
1176 // decompose object transformation to have current translate and scale
1177 basegfx::B2DVector aScale, aTranslate;
1178 double fLclRotate, fLclShearX;
1179
1180 aMatrix.decompose(aScale, aTranslate, fLclRotate, fLclShearX);
1181
1182 if(!aScale.equalZero())
1183 {
1184 // get crop scale
1185 const basegfx::B2DVector aCropScaleFactor(
1186 GetGraphicObject().calculateCropScaling(
1187 aScale.getX(),
1188 aScale.getY(),
1189 rCrop.GetLeft(),
1190 rCrop.GetTop(),
1191 rCrop.GetRight(),
1192 rCrop.GetBottom()));
1193
1194 // apply crop scale
1195 const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX());
1196 const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY());
1197 const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX());
1198 const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY());
1199 basegfx::B2DHomMatrix aMatrixForCropViewHdl(aMatrix);
1200
1201 if(IsMirrored())
1202 {
1203 // create corrected new matrix, TTTT can be removed with aw080
1204 // the old mirror only can mirror horizontally; the vertical mirror
1205 // is faked by using the horizontal and 180 degree rotation. Since
1206 // the object can be rotated differently from 180 degree, this is
1207 // not safe to detect. Just correct horizontal mirror (which is
1208 // in IsMirrored()) and keep the rotation angle
1209 // caution: Do not modify aMatrix, it is used below to calculate
1210 // the exact handle positions
1211 basegfx::B2DHomMatrix aPreMultiply;
1212
1213 // mirrored X, apply
1214 aPreMultiply.translate(-0.5, 0.0);
1215 aPreMultiply.scale(-1.0, 1.0);
1216 aPreMultiply.translate(0.5, 0.0);
1217
1218 aMatrixForCropViewHdl = aMatrixForCropViewHdl * aPreMultiply;
1219 }
1220
1221 rTarget.AddHdl(
1222 std::make_unique<SdrCropViewHdl>(
1223 aMatrixForCropViewHdl,
1224 GetGraphicObject().GetGraphic(),
1225 fCropLeft,
1226 fCropTop,
1227 fCropRight,
1228 fCropBottom));
1229 }
1230 }
1231
1232 basegfx::B2DPoint aPos;
1233
1234 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.0);
1235 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperLeft, fShearX, fRotate));
1236 aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0);
1237 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Upper, fShearX, fRotate));
1238 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0);
1239 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperRight, fShearX, fRotate));
1240 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5);
1241 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Left , fShearX, fRotate));
1242 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5);
1243 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Right, fShearX, fRotate));
1244 aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0);
1245 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerLeft, fShearX, fRotate));
1246 aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0);
1247 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Lower, fShearX, fRotate));
1248 aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0);
1249 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
1250}
1251
1252/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
8
Calling copy constructor for 'Reference<VirtualDevice>'
11
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
12
Calling 'Reference::clear'
19
Returning; memory was released
205 if (aTmp.get()) {
20
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
7
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
9
Assuming field 'm_pBody' is non-null
10
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
)
13
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
14
Calling 'VclReferenceBase::release'
18
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
21
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
15
Assuming the condition is true
16
Taking true branch
40 delete this;
17
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif