File: | home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx |
Warning: | line 739, column 16 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
52 | using namespace com::sun::star; | |||
53 | ||||
54 | SdrExchangeView::SdrExchangeView( | |||
55 | SdrModel& rSdrModel, | |||
56 | OutputDevice* pOut) | |||
57 | : SdrObjEditView(rSdrModel, pOut) | |||
58 | { | |||
59 | } | |||
60 | ||||
61 | bool 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 | ||||
94 | void 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 | ||||
106 | bool 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 | ||||
124 | bool 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 | ||||
167 | bool 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 | ||||
228 | bool 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 | ||||
393 | void 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 | ||||
428 | BitmapEx 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 | ||||
507 | GDIMetaFile 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 | ||||
568 | Graphic 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 | ||||
584 | Graphic 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 | ||||
685 | void 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 | ||||
699 | std::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) | |||
| ||||
714 | { | |||
715 | SdrObject* pNewObj(nullptr); | |||
716 | ||||
717 | if(nullptr != dynamic_cast< const SdrPageObj* >(pObj)) | |||
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)) | |||
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) | |||
737 | { | |||
738 | // not cloned yet | |||
739 | if(pObj->GetObjIdentifier() == OBJ_OLE2 && nullptr == mpModel->GetPersist()) | |||
| ||||
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: */ |