Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx
Warning:line 739, 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 svdxcgv.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/svdxcgv.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 <vector>
21#include <unordered_set>
22#include <editeng/editdata.hxx>
23#include <rtl/strbuf.hxx>
24#include <svx/xfillit0.hxx>
25#include <svx/xlineit0.hxx>
26#include <svx/svdxcgv.hxx>
27#include <svx/svdoutl.hxx>
28#include <svx/svdundo.hxx>
29#include <svx/svdograf.hxx>
30#include <svx/svdoole2.hxx>
31#include <svx/svdorect.hxx>
32#include <svx/svdopage.hxx>
33#include <svx/svdpage.hxx>
34#include <svx/svdpagv.hxx>
35#include <svx/svdtrans.hxx>
36#include <svx/strings.hrc>
37#include <svx/dialmgr.hxx>
38#include <tools/bigint.hxx>
39#include <clonelist.hxx>
40#include <vcl/virdev.hxx>
41#include <svl/style.hxx>
42#include <fmobj.hxx>
43#include <vcl/vectorgraphicdata.hxx>
44#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
45#include <drawinglayer/geometry/viewinformation2d.hxx>
46#include <svx/sdr/contact/viewcontact.hxx>
47#include <sdr/contact/objectcontactofobjlistpainter.hxx>
48#include <svx/sdr/contact/displayinfo.hxx>
49#include <svx/svdotable.hxx>
50#include <sal/log.hxx>
51
52using namespace com::sun::star;
53
54SdrExchangeView::SdrExchangeView(
55 SdrModel& rSdrModel,
56 OutputDevice* pOut)
57: SdrObjEditView(rSdrModel, pOut)
58{
59}
60
61bool SdrExchangeView::ImpLimitToWorkArea(Point& rPt) const
62{
63 bool bRet(false);
64
65 if(!maMaxWorkArea.IsEmpty())
66 {
67 if(rPt.X()<maMaxWorkArea.Left())
68 {
69 rPt.setX( maMaxWorkArea.Left() );
70 bRet = true;
71 }
72
73 if(rPt.X()>maMaxWorkArea.Right())
74 {
75 rPt.setX( maMaxWorkArea.Right() );
76 bRet = true;
77 }
78
79 if(rPt.Y()<maMaxWorkArea.Top())
80 {
81 rPt.setY( maMaxWorkArea.Top() );
82 bRet = true;
83 }
84
85 if(rPt.Y()>maMaxWorkArea.Bottom())
86 {
87 rPt.setY( maMaxWorkArea.Bottom() );
88 bRet = true;
89 }
90 }
91 return bRet;
92}
93
94void SdrExchangeView::ImpGetPasteObjList(Point& /*rPos*/, SdrObjList*& rpLst)
95{
96 if (rpLst==nullptr)
97 {
98 SdrPageView* pPV = GetSdrPageView();
99
100 if (pPV!=nullptr) {
101 rpLst=pPV->GetObjList();
102 }
103 }
104}
105
106bool SdrExchangeView::ImpGetPasteLayer(const SdrObjList* pObjList, SdrLayerID& rLayer) const
107{
108 bool bRet=false;
109 rLayer=SdrLayerID(0);
110 if (pObjList!=nullptr) {
111 const SdrPage* pPg=pObjList->getSdrPageFromSdrObjList();
112 if (pPg!=nullptr) {
113 rLayer=pPg->GetLayerAdmin().GetLayerID(maActualLayer);
114 if (rLayer==SDRLAYER_NOTFOUND) rLayer=SdrLayerID(0);
115 SdrPageView* pPV = GetSdrPageView();
116 if (pPV!=nullptr) {
117 bRet=!pPV->GetLockedLayers().IsSet(rLayer) && pPV->GetVisibleLayers().IsSet(rLayer);
118 }
119 }
120 }
121 return bRet;
122}
123
124bool SdrExchangeView::Paste(const OUString& rStr, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
125{
126 if (rStr.isEmpty())
127 return false;
128
129 Point aPos(rPos);
130 ImpGetPasteObjList(aPos,pLst);
131 ImpLimitToWorkArea( aPos );
132 if (pLst==nullptr) return false;
133 SdrLayerID nLayer;
134 if (!ImpGetPasteLayer(pLst,nLayer)) return false;
135 bool bUnmark = (nOptions & (SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
136 if (bUnmark) UnmarkAllObj();
137 tools::Rectangle aTextRect(0,0,500,500);
138 SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
139 if (pPage!=nullptr) {
140 aTextRect.SetSize(pPage->GetSize());
141 }
142 SdrRectObj* pObj = new SdrRectObj(
143 getSdrModelFromSdrView(),
144 OBJ_TEXT,
145 aTextRect);
146
147 pObj->SetLayer(nLayer);
148 pObj->NbcSetText(rStr); // SetText before SetAttr, else SetAttr doesn't work!
149 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
150
151 pObj->SetMergedItemSet(maDefaultAttr);
152
153 SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
154 aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
155 aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
156
157 pObj->SetMergedItemSet(aTempAttr);
158
159 pObj->FitFrameToTextSize();
160 Size aSiz(pObj->GetLogicRect().GetSize());
161 MapUnit eMap=mpModel->GetScaleUnit();
162 Fraction aMap=mpModel->GetScaleFraction();
163 ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
164 return true;
165}
166
167bool SdrExchangeView::Paste(SvStream& rInput, EETextFormat eFormat, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
168{
169 Point aPos(rPos);
170 ImpGetPasteObjList(aPos,pLst);
171 ImpLimitToWorkArea( aPos );
172 if (pLst==nullptr) return false;
173 SdrLayerID nLayer;
174 if (!ImpGetPasteLayer(pLst,nLayer)) return false;
175 bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
176 if (bUnmark) UnmarkAllObj();
177 tools::Rectangle aTextRect(0,0,500,500);
178 SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
179 if (pPage!=nullptr) {
180 aTextRect.SetSize(pPage->GetSize());
181 }
182 SdrRectObj* pObj = new SdrRectObj(
183 getSdrModelFromSdrView(),
184 OBJ_TEXT,
185 aTextRect);
186
187 pObj->SetLayer(nLayer);
188 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
189
190 pObj->SetMergedItemSet(maDefaultAttr);
191
192 SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
193 aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
194 aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
195
196 pObj->SetMergedItemSet(aTempAttr);
197
198 pObj->NbcSetText(rInput,OUString(),eFormat);
199 pObj->FitFrameToTextSize();
200 Size aSiz(pObj->GetLogicRect().GetSize());
201 MapUnit eMap=mpModel->GetScaleUnit();
202 Fraction aMap=mpModel->GetScaleFraction();
203 ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
204
205 // b4967543
206 if(pObj->GetOutlinerParaObject())
207 {
208 SdrOutliner& rOutliner = pObj->getSdrModelFromSdrObject().GetHitTestOutliner();
209 rOutliner.SetText(*pObj->GetOutlinerParaObject());
210
211 if(1 == rOutliner.GetParagraphCount())
212 {
213 SfxStyleSheet* pCandidate = rOutliner.GetStyleSheet(0);
214
215 if(pCandidate)
216 {
217 if(pObj->getSdrModelFromSdrObject().GetStyleSheetPool() == pCandidate->GetPool())
218 {
219 pObj->NbcSetStyleSheet(pCandidate, true);
220 }
221 }
222 }
223 }
224
225 return true;
226}
227
228bool SdrExchangeView::Paste(
229 const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
230{
231 const SdrModel* pSrcMod=&rMod;
232 if (pSrcMod==mpModel)
233 return false; // this can't work, right?
234
235 const bool bUndo = IsUndoEnabled();
236
237 if( bUndo )
238 BegUndo(SvxResId(STR_ExchangePastereinterpret_cast<char const *>("STR_ExchangePaste" "\004"
u8"Insert object(s)")
));
239
240 if( mxSelectionController.is() && mxSelectionController->PasteObjModel( rMod ) )
241 {
242 if( bUndo )
243 EndUndo();
244 return true;
245 }
246
247 Point aPos(rPos);
248 ImpGetPasteObjList(aPos,pLst);
249 SdrPageView* pMarkPV=nullptr;
250 SdrPageView* pPV = GetSdrPageView();
251
252 if(pPV && pPV->GetObjList() == pLst )
253 pMarkPV=pPV;
254
255 ImpLimitToWorkArea( aPos );
256 if (pLst==nullptr)
257 return false;
258
259 bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
260 if (bUnmark)
261 UnmarkAllObj();
262
263 // Rescale, if the Model uses a different MapUnit.
264 // Calculate the necessary factors first.
265 MapUnit eSrcUnit=pSrcMod->GetScaleUnit();
266 MapUnit eDstUnit=mpModel->GetScaleUnit();
267 bool bResize=eSrcUnit!=eDstUnit;
268 Fraction aXResize,aYResize;
269 Point aPt0;
270 if (bResize)
271 {
272 FrPair aResize(GetMapFactor(eSrcUnit,eDstUnit));
273 aXResize=aResize.X();
274 aYResize=aResize.Y();
275 }
276 SdrObjList* pDstLst=pLst;
277 sal_uInt16 nPg,nPgCount=pSrcMod->GetPageCount();
278 for (nPg=0; nPg<nPgCount; nPg++)
279 {
280 const SdrPage* pSrcPg=pSrcMod->GetPage(nPg);
281
282 // Use SnapRect, not BoundRect here
283 tools::Rectangle aR=pSrcPg->GetAllObjSnapRect();
284
285 if (bResize)
286 ResizeRect(aR,aPt0,aXResize,aYResize);
287 Point aDist(aPos-aR.Center());
288 Size aSiz(aDist.X(),aDist.Y());
289 size_t nCloneErrCnt = 0;
290 const size_t nObjCount = pSrcPg->GetObjCount();
291 bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
292
293 // #i13033#
294 // New mechanism to re-create the connections of cloned connectors
295 CloneList aCloneList;
296 std::unordered_set<rtl::OUString> aNameSet;
297 for (size_t nOb=0; nOb<nObjCount; ++nOb)
298 {
299 const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
300
301 SdrObject* pNewObj(pSrcOb->CloneSdrObject(*mpModel));
302
303 if (pNewObj!=nullptr)
304 {
305 if(bResize)
306 {
307 pNewObj->getSdrModelFromSdrObject().SetPasteResize(true);
308 pNewObj->NbcResize(aPt0,aXResize,aYResize);
309 pNewObj->getSdrModelFromSdrObject().SetPasteResize(false);
310 }
311
312 // #i39861#
313 pNewObj->NbcMove(aSiz);
314
315 const SdrPage* pPg = pDstLst->getSdrPageFromSdrObjList();
316
317 if(pPg)
318 {
319 // #i72535#
320 const SdrLayerAdmin& rAd = pPg->GetLayerAdmin();
321 SdrLayerID nLayer(0);
322
323 if(dynamic_cast<const FmFormObj*>( pNewObj) != nullptr)
324 {
325 // for FormControls, force to form layer
326 nLayer = rAd.GetLayerID(rAd.GetControlLayerName());
327 }
328 else
329 {
330 nLayer = rAd.GetLayerID(maActualLayer);
331 }
332
333 if(SDRLAYER_NOTFOUND == nLayer)
334 {
335 nLayer = SdrLayerID(0);
336 }
337
338 pNewObj->SetLayer(nLayer);
339 }
340
341 pDstLst->InsertObjectThenMakeNameUnique(pNewObj, aNameSet);
342
343 if( bUndo )
344 AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pNewObj));
345
346 if (bMark) {
347 // Don't already set Markhandles!
348 // That is instead being done by ModelHasChanged in MarkView.
349 MarkObj(pNewObj,pMarkPV,false,true);
350 }
351
352 // #i13033#
353 aCloneList.AddPair(pSrcOb, pNewObj);
354 }
355 else
356 {
357 nCloneErrCnt++;
358 }
359 }
360
361 // #i13033#
362 // New mechanism to re-create the connections of cloned connectors
363 aCloneList.CopyConnections();
364
365 if(0 != nCloneErrCnt)
366 {
367#ifdef DBG_UTIL
368 OStringBuffer aStr("SdrExchangeView::Paste(): Error when cloning ");
369
370 if(nCloneErrCnt == 1)
371 {
372 aStr.append("a drawing object.");
373 }
374 else
375 {
376 aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
377 aStr.append(" drawing objects.");
378 }
379
380 aStr.append(" Not copying object connectors.");
381
382 OSL_FAIL(aStr.getStr())do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "382" ": "), "%s", aStr.getStr()); } } while (false)
;
383#endif
384 }
385 }
386
387 if( bUndo )
388 EndUndo();
389
390 return true;
391}
392
393void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Point& rCenter, const Size& rSiz, const MapMode& rMap, SdrInsertFlags nOptions)
394{
395 BigInt nSizX(rSiz.Width());
396 BigInt nSizY(rSiz.Height());
397 MapUnit eSrcMU=rMap.GetMapUnit();
398 MapUnit eDstMU=mpModel->GetScaleUnit();
399 FrPair aMapFact(GetMapFactor(eSrcMU,eDstMU));
400 Fraction aDstFr(mpModel->GetScaleFraction());
401 nSizX *= double(aMapFact.X() * rMap.GetScaleX() * aDstFr);
402 nSizX *= aDstFr.GetDenominator();
403 nSizY *= double(aMapFact.Y() * rMap.GetScaleY());
404 nSizY /= aDstFr.GetNumerator();
405 long xs=nSizX;
406 long ys=nSizY;
407 Point aPos(rCenter.X()-xs/2,rCenter.Y()-ys/2);
408 tools::Rectangle aR(aPos.X(),aPos.Y(),aPos.X()+xs,aPos.Y()+ys);
409 pObj->SetLogicRect(aR);
410 rLst.InsertObject(pObj, SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
411
412 if( IsUndoEnabled() )
413 AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pObj));
414
415 SdrPageView* pMarkPV=nullptr;
416 SdrPageView* pPV = GetSdrPageView();
417
418 if(pPV && pPV->GetObjList()==&rLst)
419 pMarkPV=pPV;
420
421 bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
422 if (bMark)
423 { // select object the first PageView we found
424 MarkObj(pObj,pMarkPV);
425 }
426}
427
428BitmapEx SdrExchangeView::GetMarkedObjBitmapEx(bool bNoVDevIfOneBmpMarked) const
429{
430 BitmapEx aBmp;
431
432 if( AreObjectsMarked() )
433 {
434 if(1 == GetMarkedObjectCount())
435 {
436 if(bNoVDevIfOneBmpMarked)
437 {
438 SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
439 SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>( pGrafObjTmp );
440
441 if( pGrafObj && ( pGrafObj->GetGraphicType() == GraphicType::Bitmap ) )
442 {
443 aBmp = pGrafObj->GetTransformedGraphic().GetBitmapEx();
444 }
445 }
446 else
447 {
448 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(GetMarkedObjectByIndex(0));
449
450 if(pSdrGrafObj && pSdrGrafObj->isEmbeddedVectorGraphicData())
451 {
452 aBmp = pSdrGrafObj->GetGraphic().getVectorGraphicData()->getReplacement();
453 }
454 }
455 }
456
457 if( !aBmp )
458 {
459 // choose conversion directly using primitives to bitmap to avoid
460 // rendering errors with tiled bitmap fills (these will be tiled in a
461 // in-between metafile, but tend to show 'gaps' since the target is *no*
462 // bitmap rendering)
463 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
464 const sal_uInt32 nCount(aSdrObjects.size());
465
466 if(nCount)
467 {
468 // collect sub-primitives as group objects, thus no expensive append
469 // to existing sequence is needed
470 drawinglayer::primitive2d::Primitive2DContainer xPrimitives(nCount);
471
472 for(sal_uInt32 a(0); a < nCount; a++)
473 {
474 SdrObject* pCandidate = aSdrObjects[a];
475 SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pCandidate);
476
477 if(pSdrGrafObj)
478 {
479 // #122753# To ensure existence of graphic content, force swap in
480 pSdrGrafObj->ForceSwapIn();
481 }
482
483 xPrimitives[a] = new drawinglayer::primitive2d::GroupPrimitive2D(
484 pCandidate->GetViewContact().getViewIndependentPrimitive2DContainer());
485 }
486
487 // get logic range
488 const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
489 const basegfx::B2DRange aRange(xPrimitives.getB2DRange(aViewInformation2D));
490
491 if(!aRange.isEmpty())
492 {
493 // if we have geometry and it has a range, convert to BitmapEx using
494 // common tooling
495 aBmp = convertPrimitive2DSequenceToBitmapEx(
496 xPrimitives,
497 aRange);
498 }
499 }
500 }
501 }
502
503 return aBmp;
504}
505
506
507GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) const
508{
509 GDIMetaFile aMtf;
510
511 if( AreObjectsMarked() )
512 {
513 tools::Rectangle aBound( GetMarkedObjBoundRect() );
514 Size aBoundSize( aBound.GetWidth(), aBound.GetHeight() );
515 MapMode aMap( mpModel->GetScaleUnit(), Point(), mpModel->GetScaleFraction(), mpModel->GetScaleFraction() );
516
517 if( bNoVDevIfOneMtfMarked )
518 {
519 SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
520 SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() ==1 ) ? dynamic_cast<SdrGrafObj*>( pGrafObjTmp ) : nullptr;
521
522 if( pGrafObj )
523 {
524 Graphic aGraphic( pGrafObj->GetTransformedGraphic() );
525
526 // #119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
527 aMtf = aGraphic.GetGDIMetaFile();
528 }
529 }
530
531 if( !aMtf.GetActionSize() )
532 {
533 ScopedVclPtrInstance< VirtualDevice > pOut;
534 const Size aDummySize(2, 2);
535
536 pOut->SetOutputSizePixel(aDummySize);
537 pOut->EnableOutput(false);
538 pOut->SetMapMode(aMap);
539 aMtf.Clear();
540 aMtf.Record(pOut);
541
542 DrawMarkedObj(*pOut);
543
544 aMtf.Stop();
545 aMtf.WindStart();
546
547 // moving the result is more reliable then setting a relative MapMode at the VDev (used
548 // before), also see #i99268# in GetObjGraphic() below. Some draw actions at
549 // the OutDev are simply not handled correctly when a MapMode is set at the
550 // target device, e.g. MetaFloatTransparentAction. Even the Move for this action
551 // was missing the manipulation of the embedded Metafile
552 aMtf.Move(-aBound.Left(), -aBound.Top());
553
554 aMtf.SetPrefMapMode( aMap );
555
556 // removed PrefSize extension. It is principally wrong to set a reduced size at
557 // the created MetaFile. The mentioned errors occur at output time since the integer
558 // MapModes from VCL lead to errors. It is now corrected in the VCLRenderer for
559 // primitives (and may later be done in breaking up a MetaFile to primitives)
560 aMtf.SetPrefSize(aBoundSize);
561 }
562 }
563
564 return aMtf;
565}
566
567
568Graphic SdrExchangeView::GetAllMarkedGraphic() const
569{
570 Graphic aRet;
571
572 if( AreObjectsMarked() )
573 {
574 if( ( 1 == GetMarkedObjectCount() ) && GetSdrMarkByIndex( 0 ) )
575 aRet = SdrExchangeView::GetObjGraphic(*GetMarkedObjectByIndex(0));
576 else
577 aRet = GetMarkedObjMetaFile();
578 }
579
580 return aRet;
581}
582
583
584Graphic SdrExchangeView::GetObjGraphic(const SdrObject& rSdrObject)
585{
586 Graphic aRet;
587
588 // try to get a graphic from the object first
589 const SdrGrafObj* pSdrGrafObj(dynamic_cast< const SdrGrafObj* >(&rSdrObject));
590 const SdrOle2Obj* pSdrOle2Obj(dynamic_cast< const SdrOle2Obj* >(&rSdrObject));
591
592 if(pSdrGrafObj)
593 {
594 if(pSdrGrafObj->isEmbeddedVectorGraphicData())
595 {
596 // get Metafile for Svg content
597 aRet = pSdrGrafObj->getMetafileFromEmbeddedVectorGraphicData();
598 }
599 else
600 {
601 // Make behaviour coherent with metafile
602 // recording below (which of course also takes
603 // view-transformed objects)
604 aRet = pSdrGrafObj->GetTransformedGraphic();
605 }
606 }
607 else if(pSdrOle2Obj)
608 {
609 if(pSdrOle2Obj->GetGraphic())
610 {
611 aRet = *pSdrOle2Obj->GetGraphic();
612 }
613 }
614
615 // if graphic could not be retrieved => go the hard way and create a MetaFile
616 if((GraphicType::NONE == aRet.GetType()) || (GraphicType::Default == aRet.GetType()))
617 {
618 ScopedVclPtrInstance< VirtualDevice > pOut;
619 GDIMetaFile aMtf;
620 const tools::Rectangle aBoundRect(rSdrObject.GetCurrentBoundRect());
621 const MapMode aMap(rSdrObject.getSdrModelFromSdrObject().GetScaleUnit(),
622 Point(),
623 rSdrObject.getSdrModelFromSdrObject().GetScaleFraction(),
624 rSdrObject.getSdrModelFromSdrObject().GetScaleFraction());
625
626 pOut->EnableOutput(false);
627 pOut->SetMapMode(aMap);
628 aMtf.Record(pOut);
629 rSdrObject.SingleObjectPainter(*pOut);
630 aMtf.Stop();
631 aMtf.WindStart();
632
633 // #i99268# replace the original offset from using XOutDev's SetOffset
634 // NOT (as tried with #i92760#) with another MapMode which gets recorded
635 // by the Metafile itself (what always leads to problems), but by
636 // moving the result directly
637 aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
638 aMtf.SetPrefMapMode(aMap);
639 aMtf.SetPrefSize(aBoundRect.GetSize());
640
641 if(aMtf.GetActionSize())
642 {
643 aRet = aMtf;
644 }
645 }
646
647 return aRet;
648}
649
650
651::std::vector< SdrObject* > SdrExchangeView::GetMarkedObjects() const
652{
653 SortMarkedObjects();
654 ::std::vector< SdrObject* > aRetval;
655
656 ::std::vector< ::std::vector< SdrMark* > > aObjVectors( 2 );
657 ::std::vector< SdrMark* >& rObjVector1 = aObjVectors[ 0 ];
658 ::std::vector< SdrMark* >& rObjVector2 = aObjVectors[ 1 ];
659 const SdrLayerAdmin& rLayerAdmin = mpModel->GetLayerAdmin();
660 const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() );
661
662 for( size_t n = 0, nCount = GetMarkedObjectCount(); n < nCount; ++n )
663 {
664 SdrMark* pMark = GetSdrMarkByIndex( n );
665
666 // paint objects on control layer on top of all other objects
667 if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() )
668 rObjVector2.push_back( pMark );
669 else
670 rObjVector1.push_back( pMark );
671 }
672
673 for(const std::vector<SdrMark*> & rObjVector : aObjVectors)
674 {
675 for(SdrMark* pMark : rObjVector)
676 {
677 aRetval.push_back(pMark->GetMarkedSdrObj());
678 }
679 }
680
681 return aRetval;
682}
683
684
685void SdrExchangeView::DrawMarkedObj(OutputDevice& rOut) const
686{
687 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
688
689 if(!aSdrObjects.empty())
690 {
691 sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, aSdrObjects, aSdrObjects[0]->getSdrPageFromSdrObject());
692 sdr::contact::DisplayInfo aDisplayInfo;
693
694 // do processing
695 aPainter.ProcessDisplay(aDisplayInfo);
696 }
697}
698
699std::unique_ptr<SdrModel> SdrExchangeView::CreateMarkedObjModel() const
700{
701 // Sorting the MarkList here might be problematic in the future, so
702 // use a copy.
703 SortMarkedObjects();
704 std::unique_ptr<SdrModel> pNewModel(mpModel->AllocModel());
705 SdrPage* pNewPage(pNewModel->AllocPage(false));
706 pNewModel->InsertPage(pNewPage);
707 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
708
709 // #i13033#
710 // New mechanism to re-create the connections of cloned connectors
711 CloneList aCloneList;
712
713 for(SdrObject* pObj : aSdrObjects)
1
'pObj' initialized here
714 {
715 SdrObject* pNewObj(nullptr);
716
717 if(nullptr != dynamic_cast< const SdrPageObj* >(pObj))
2
Assuming pointer value is null
3
Taking false branch
718 {
719 // convert SdrPageObj's to a graphic representation, because
720 // virtual connection to referenced page gets lost in new model
721 pNewObj = new SdrGrafObj(
722 *pNewModel,
723 GetObjGraphic(*pObj),
724 pObj->GetLogicRect());
725 }
726 else if(nullptr != dynamic_cast< const sdr::table::SdrTableObj* >(pObj))
4
Taking false branch
727 {
728 // check if we have a valid selection *different* from whole table
729 // being selected
730 if(mxSelectionController.is())
731 {
732 pNewObj = mxSelectionController->GetMarkedSdrObjClone(*pNewModel);
733 }
734 }
735
736 if(nullptr == pNewObj)
5
Taking true branch
737 {
738 // not cloned yet
739 if(pObj->GetObjIdentifier() == OBJ_OLE2 && nullptr == mpModel->GetPersist())
6
Called C++ object pointer is null
740 {
741 // tdf#125520 - former fix was wrong, the SdrModel
742 // has to have a GetPersist() already, see task.
743 // We can still warn here when this is not the case
744 SAL_WARN( "svx", "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied" )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
() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"
), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"),
("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"
), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"),
("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
745 }
746
747 // use default way
748 pNewObj = pObj->CloneSdrObject(*pNewModel);
749 }
750
751 if(pNewObj)
752 {
753 pNewPage->InsertObject(pNewObj, SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
754
755 // #i13033#
756 aCloneList.AddPair(pObj, pNewObj);
757 }
758 }
759
760 // #i13033#
761 // New mechanism to re-create the connections of cloned connectors
762 aCloneList.CopyConnections();
763
764 return pNewModel;
765}
766
767/* vim:set shiftwidth=4 softtabstop=4 expandtab: */