summaryrefslogtreecommitdiffstats
path: root/svx/source/svdraw/svdxcgv.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/svdraw/svdxcgv.cxx')
-rw-r--r--svx/source/svdraw/svdxcgv.cxx784
1 files changed, 784 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdxcgv.cxx b/svx/source/svdraw/svdxcgv.cxx
new file mode 100644
index 000000000..a9b720f30
--- /dev/null
+++ b/svx/source/svdraw/svdxcgv.cxx
@@ -0,0 +1,784 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vector>
+#include <unordered_set>
+#include <editeng/editdata.hxx>
+#include <rtl/strbuf.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/svdxcgv.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdorect.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <tools/bigint.hxx>
+#include <clonelist.hxx>
+#include <vcl/virdev.hxx>
+#include <svl/style.hxx>
+#include <fmobj.hxx>
+#include <vcl/vectorgraphicdata.hxx>
+#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/converters.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+#include <sdr/contact/objectcontactofobjlistpainter.hxx>
+#include <svx/sdr/contact/displayinfo.hxx>
+#include <svx/svdotable.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/lok.hxx>
+
+using namespace com::sun::star;
+
+SdrExchangeView::SdrExchangeView(
+ SdrModel& rSdrModel,
+ OutputDevice* pOut)
+: SdrObjEditView(rSdrModel, pOut)
+{
+}
+
+bool SdrExchangeView::ImpLimitToWorkArea(Point& rPt) const
+{
+ bool bRet(false);
+
+ if(!maMaxWorkArea.IsEmpty())
+ {
+ if(rPt.X()<maMaxWorkArea.Left())
+ {
+ rPt.setX( maMaxWorkArea.Left() );
+ bRet = true;
+ }
+
+ if(rPt.X()>maMaxWorkArea.Right())
+ {
+ rPt.setX( maMaxWorkArea.Right() );
+ bRet = true;
+ }
+
+ if(rPt.Y()<maMaxWorkArea.Top())
+ {
+ rPt.setY( maMaxWorkArea.Top() );
+ bRet = true;
+ }
+
+ if(rPt.Y()>maMaxWorkArea.Bottom())
+ {
+ rPt.setY( maMaxWorkArea.Bottom() );
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void SdrExchangeView::ImpGetPasteObjList(Point& /*rPos*/, SdrObjList*& rpLst)
+{
+ if (rpLst==nullptr)
+ {
+ SdrPageView* pPV = GetSdrPageView();
+
+ if (pPV!=nullptr) {
+ rpLst=pPV->GetObjList();
+ }
+ }
+}
+
+bool SdrExchangeView::ImpGetPasteLayer(const SdrObjList* pObjList, SdrLayerID& rLayer) const
+{
+ bool bRet=false;
+ rLayer=SdrLayerID(0);
+ if (pObjList!=nullptr) {
+ const SdrPage* pPg=pObjList->getSdrPageFromSdrObjList();
+ if (pPg!=nullptr) {
+ rLayer=pPg->GetLayerAdmin().GetLayerID(maActualLayer);
+ if (rLayer==SDRLAYER_NOTFOUND) rLayer=SdrLayerID(0);
+ SdrPageView* pPV = GetSdrPageView();
+ if (pPV!=nullptr) {
+ bRet=!pPV->GetLockedLayers().IsSet(rLayer) && pPV->GetVisibleLayers().IsSet(rLayer);
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SdrExchangeView::Paste(const OUString& rStr, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
+{
+ if (rStr.isEmpty())
+ return false;
+
+ Point aPos(rPos);
+ ImpGetPasteObjList(aPos,pLst);
+ ImpLimitToWorkArea( aPos );
+ if (pLst==nullptr) return false;
+ SdrLayerID nLayer;
+ if (!ImpGetPasteLayer(pLst,nLayer)) return false;
+ bool bUnmark = (nOptions & (SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
+ if (bUnmark) UnmarkAllObj();
+ tools::Rectangle aTextRect(0,0,500,500);
+ SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
+ if (pPage!=nullptr) {
+ aTextRect.SetSize(pPage->GetSize());
+ }
+ SdrRectObj* pObj = new SdrRectObj(
+ getSdrModelFromSdrView(),
+ SdrObjKind::Text,
+ aTextRect);
+
+ pObj->SetLayer(nLayer);
+ pObj->NbcSetText(rStr); // SetText before SetAttr, else SetAttr doesn't work!
+ if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
+
+ pObj->SetMergedItemSet(maDefaultAttr);
+
+ SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
+ aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
+ aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
+
+ pObj->SetMergedItemSet(aTempAttr);
+
+ pObj->FitFrameToTextSize();
+ Size aSiz(pObj->GetLogicRect().GetSize());
+ MapUnit eMap=mpModel->GetScaleUnit();
+ Fraction aMap=mpModel->GetScaleFraction();
+ ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
+ return true;
+}
+
+bool SdrExchangeView::Paste(SvStream& rInput, EETextFormat eFormat, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
+{
+ Point aPos(rPos);
+ ImpGetPasteObjList(aPos,pLst);
+ ImpLimitToWorkArea( aPos );
+ if (pLst==nullptr) return false;
+ SdrLayerID nLayer;
+ if (!ImpGetPasteLayer(pLst,nLayer)) return false;
+ bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
+ if (bUnmark) UnmarkAllObj();
+ tools::Rectangle aTextRect(0,0,500,500);
+ SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
+ if (pPage!=nullptr) {
+ aTextRect.SetSize(pPage->GetSize());
+ }
+ SdrRectObj* pObj = new SdrRectObj(
+ getSdrModelFromSdrView(),
+ SdrObjKind::Text,
+ aTextRect);
+
+ pObj->SetLayer(nLayer);
+ if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
+
+ pObj->SetMergedItemSet(maDefaultAttr);
+
+ SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
+ aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
+ aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
+
+ pObj->SetMergedItemSet(aTempAttr);
+
+ pObj->NbcSetText(rInput,OUString(),eFormat);
+ pObj->FitFrameToTextSize();
+ Size aSiz(pObj->GetLogicRect().GetSize());
+ MapUnit eMap=mpModel->GetScaleUnit();
+ Fraction aMap=mpModel->GetScaleFraction();
+ ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
+
+ // b4967543
+ if(pObj->GetOutlinerParaObject())
+ {
+ SdrOutliner& rOutliner = pObj->getSdrModelFromSdrObject().GetHitTestOutliner();
+ rOutliner.SetText(*pObj->GetOutlinerParaObject());
+
+ if(1 == rOutliner.GetParagraphCount())
+ {
+ SfxStyleSheet* pCandidate = rOutliner.GetStyleSheet(0);
+
+ if(pCandidate)
+ {
+ if(pObj->getSdrModelFromSdrObject().GetStyleSheetPool() == pCandidate->GetPool())
+ {
+ pObj->NbcSetStyleSheet(pCandidate, true);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool SdrExchangeView::Paste(
+ const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
+{
+ const SdrModel* pSrcMod=&rMod;
+ if (pSrcMod==mpModel)
+ return false; // this can't work, right?
+
+ const bool bUndo = IsUndoEnabled();
+
+ if( bUndo )
+ BegUndo(SvxResId(STR_ExchangePaste));
+
+ if( mxSelectionController.is() && mxSelectionController->PasteObjModel( rMod ) )
+ {
+ if( bUndo )
+ EndUndo();
+ return true;
+ }
+
+ Point aPos(rPos);
+ ImpGetPasteObjList(aPos,pLst);
+ SdrPageView* pMarkPV=nullptr;
+ SdrPageView* pPV = GetSdrPageView();
+
+ if(pPV && pPV->GetObjList() == pLst )
+ pMarkPV=pPV;
+
+ ImpLimitToWorkArea( aPos );
+ if (pLst==nullptr)
+ return false;
+
+ bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
+ if (bUnmark)
+ UnmarkAllObj();
+
+ // Rescale, if the Model uses a different MapUnit.
+ // Calculate the necessary factors first.
+ MapUnit eSrcUnit=pSrcMod->GetScaleUnit();
+ MapUnit eDstUnit=mpModel->GetScaleUnit();
+ bool bResize=eSrcUnit!=eDstUnit;
+ Fraction aXResize,aYResize;
+ Point aPt0;
+ if (bResize)
+ {
+ FrPair aResize(GetMapFactor(eSrcUnit,eDstUnit));
+ aXResize=aResize.X();
+ aYResize=aResize.Y();
+ }
+ SdrObjList* pDstLst=pLst;
+ sal_uInt16 nPg,nPgCount=pSrcMod->GetPageCount();
+ for (nPg=0; nPg<nPgCount; nPg++)
+ {
+ const SdrPage* pSrcPg=pSrcMod->GetPage(nPg);
+
+ // Use SnapRect, not BoundRect here
+ tools::Rectangle aR=pSrcPg->GetAllObjSnapRect();
+
+ if (bResize)
+ ResizeRect(aR,aPt0,aXResize,aYResize);
+ Point aDist(aPos-aR.Center());
+ Size aSiz(aDist.X(),aDist.Y());
+ size_t nCloneErrCnt = 0;
+ const size_t nObjCount = pSrcPg->GetObjCount();
+ bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
+
+ // #i13033#
+ // New mechanism to re-create the connections of cloned connectors
+ CloneList aCloneList;
+ std::unordered_set<rtl::OUString> aNameSet;
+ for (size_t nOb=0; nOb<nObjCount; ++nOb)
+ {
+ const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
+
+ SdrObject* pNewObj(pSrcOb->CloneSdrObject(*mpModel));
+
+ if (pNewObj!=nullptr)
+ {
+ if(bResize)
+ {
+ pNewObj->getSdrModelFromSdrObject().SetPasteResize(true);
+ pNewObj->NbcResize(aPt0,aXResize,aYResize);
+ pNewObj->getSdrModelFromSdrObject().SetPasteResize(false);
+ }
+
+ // #i39861#
+ pNewObj->NbcMove(aSiz);
+
+ const SdrPage* pPg = pDstLst->getSdrPageFromSdrObjList();
+
+ if(pPg)
+ {
+ // #i72535#
+ const SdrLayerAdmin& rAd = pPg->GetLayerAdmin();
+ SdrLayerID nLayer(0);
+
+ if(dynamic_cast<const FmFormObj*>( pNewObj) != nullptr)
+ {
+ // for FormControls, force to form layer
+ nLayer = rAd.GetLayerID(rAd.GetControlLayerName());
+ }
+ else
+ {
+ nLayer = rAd.GetLayerID(maActualLayer);
+ }
+
+ if(SDRLAYER_NOTFOUND == nLayer)
+ {
+ nLayer = SdrLayerID(0);
+ }
+
+ pNewObj->SetLayer(nLayer);
+ }
+
+ pDstLst->InsertObjectThenMakeNameUnique(pNewObj, aNameSet);
+
+ if( bUndo )
+ AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pNewObj));
+
+ if (bMark) {
+ // Don't already set Markhandles!
+ // That is instead being done by ModelHasChanged in MarkView.
+ MarkObj(pNewObj,pMarkPV,false,true);
+ }
+
+ // #i13033#
+ aCloneList.AddPair(pSrcOb, pNewObj);
+ }
+ else
+ {
+ nCloneErrCnt++;
+ }
+ }
+
+ // #i13033#
+ // New mechanism to re-create the connections of cloned connectors
+ aCloneList.CopyConnections();
+
+ if(0 != nCloneErrCnt)
+ {
+#ifdef DBG_UTIL
+ OStringBuffer aStr("SdrExchangeView::Paste(): Error when cloning ");
+
+ if(nCloneErrCnt == 1)
+ {
+ aStr.append("a drawing object.");
+ }
+ else
+ {
+ aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
+ aStr.append(" drawing objects.");
+ }
+
+ aStr.append(" Not copying object connectors.");
+
+ OSL_FAIL(aStr.getStr());
+#endif
+ }
+ }
+
+ if( bUndo )
+ EndUndo();
+
+ return true;
+}
+
+void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Point& rCenter, const Size& rSiz, const MapMode& rMap, SdrInsertFlags nOptions)
+{
+ BigInt nSizX(rSiz.Width());
+ BigInt nSizY(rSiz.Height());
+ MapUnit eSrcMU=rMap.GetMapUnit();
+ MapUnit eDstMU=mpModel->GetScaleUnit();
+ FrPair aMapFact(GetMapFactor(eSrcMU,eDstMU));
+ Fraction aDstFr(mpModel->GetScaleFraction());
+ nSizX *= double(aMapFact.X() * rMap.GetScaleX() * aDstFr);
+ nSizX *= aDstFr.GetDenominator();
+ nSizY *= double(aMapFact.Y() * rMap.GetScaleY());
+ nSizY /= aDstFr.GetNumerator();
+ tools::Long xs=nSizX;
+ tools::Long ys=nSizY;
+ // set the pos to 0, 0 for online case
+ bool isLOK = comphelper::LibreOfficeKit::isActive();
+ Point aPos(isLOK ? 0 : rCenter.X()-xs/2, isLOK ? 0 : rCenter.Y()-ys/2);
+ tools::Rectangle aR(aPos.X(),aPos.Y(),aPos.X()+xs,aPos.Y()+ys);
+ pObj->SetLogicRect(aR);
+ rLst.InsertObject(pObj, SAL_MAX_SIZE);
+
+ if( IsUndoEnabled() )
+ AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pObj));
+
+ SdrPageView* pMarkPV=nullptr;
+ SdrPageView* pPV = GetSdrPageView();
+
+ if(pPV && pPV->GetObjList()==&rLst)
+ pMarkPV=pPV;
+
+ bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
+ if (bMark)
+ { // select object the first PageView we found
+ MarkObj(pObj,pMarkPV);
+ }
+}
+
+BitmapEx SdrExchangeView::GetMarkedObjBitmapEx(bool bNoVDevIfOneBmpMarked, const sal_uInt32 nMaximumQuadraticPixels, const std::optional<Size>& rTargetDPI) const
+{
+ BitmapEx aBmp;
+
+ if( AreObjectsMarked() )
+ {
+ if(1 == GetMarkedObjectCount())
+ {
+ if(bNoVDevIfOneBmpMarked)
+ {
+ SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
+ SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>( pGrafObjTmp );
+
+ if( pGrafObj && ( pGrafObj->GetGraphicType() == GraphicType::Bitmap ) )
+ {
+ aBmp = pGrafObj->GetTransformedGraphic().GetBitmapEx();
+ }
+ }
+ else
+ {
+ const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(GetMarkedObjectByIndex(0));
+
+ if(pSdrGrafObj && pSdrGrafObj->isEmbeddedVectorGraphicData())
+ {
+ aBmp = pSdrGrafObj->GetGraphic().getVectorGraphicData()->getReplacement();
+ }
+ }
+ }
+
+ if( aBmp.IsEmpty() )
+ {
+ // choose conversion directly using primitives to bitmap to avoid
+ // rendering errors with tiled bitmap fills (these will be tiled in a
+ // in-between metafile, but tend to show 'gaps' since the target is *no*
+ // bitmap rendering)
+ ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
+ const sal_uInt32 nCount(aSdrObjects.size());
+
+ if(nCount)
+ {
+ // collect sub-primitives as group objects, thus no expensive append
+ // to existing sequence is needed
+ drawinglayer::primitive2d::Primitive2DContainer xPrimitives(nCount);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ SdrObject* pCandidate = aSdrObjects[a];
+ SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pCandidate);
+
+ if(pSdrGrafObj)
+ {
+ // #122753# To ensure existence of graphic content, force swap in
+ pSdrGrafObj->ForceSwapIn();
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer xRetval;
+ pCandidate->GetViewContact().getViewIndependentPrimitive2DContainer(xRetval);
+ xPrimitives[a] = new drawinglayer::primitive2d::GroupPrimitive2D(
+ std::move(xRetval));
+ }
+
+ // get logic range
+ const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+ const basegfx::B2DRange aRange(xPrimitives.getB2DRange(aViewInformation2D));
+
+ if(!aRange.isEmpty())
+ {
+ o3tl::Length eRangeUnit = o3tl::Length::mm100;
+
+ if (GetModel()->IsWriter())
+ {
+ eRangeUnit = o3tl::Length::twip;
+ }
+
+ // if we have geometry and it has a range, convert to BitmapEx using
+ // common tooling
+ aBmp = drawinglayer::convertPrimitive2DContainerToBitmapEx(
+ std::move(xPrimitives),
+ aRange,
+ nMaximumQuadraticPixels,
+ eRangeUnit,
+ rTargetDPI);
+ }
+ }
+ }
+ }
+
+ return aBmp;
+}
+
+
+GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) const
+{
+ GDIMetaFile aMtf;
+
+ if( AreObjectsMarked() )
+ {
+ tools::Rectangle aBound( GetMarkedObjBoundRect() );
+ Size aBoundSize( aBound.GetWidth(), aBound.GetHeight() );
+ MapMode aMap( mpModel->GetScaleUnit(), Point(), mpModel->GetScaleFraction(), mpModel->GetScaleFraction() );
+
+ if( bNoVDevIfOneMtfMarked )
+ {
+ SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
+ SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() ==1 ) ? dynamic_cast<SdrGrafObj*>( pGrafObjTmp ) : nullptr;
+
+ if( pGrafObj )
+ {
+ Graphic aGraphic( pGrafObj->GetTransformedGraphic() );
+
+ // #119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
+ aMtf = aGraphic.GetGDIMetaFile();
+ }
+ }
+
+ if( !aMtf.GetActionSize() )
+ {
+ ScopedVclPtrInstance< VirtualDevice > pOut;
+ const Size aDummySize(2, 2);
+
+ pOut->SetOutputSizePixel(aDummySize);
+ pOut->EnableOutput(false);
+ pOut->SetMapMode(aMap);
+ aMtf.Clear();
+ aMtf.Record(pOut);
+
+ DrawMarkedObj(*pOut);
+
+ aMtf.Stop();
+ aMtf.WindStart();
+
+ // moving the result is more reliable then setting a relative MapMode at the VDev (used
+ // before), also see #i99268# in GetObjGraphic() below. Some draw actions at
+ // the OutDev are simply not handled correctly when a MapMode is set at the
+ // target device, e.g. MetaFloatTransparentAction. Even the Move for this action
+ // was missing the manipulation of the embedded Metafile
+ aMtf.Move(-aBound.Left(), -aBound.Top());
+
+ aMtf.SetPrefMapMode( aMap );
+
+ // removed PrefSize extension. It is principally wrong to set a reduced size at
+ // the created MetaFile. The mentioned errors occur at output time since the integer
+ // MapModes from VCL lead to errors. It is now corrected in the VCLRenderer for
+ // primitives (and may later be done in breaking up a MetaFile to primitives)
+ aMtf.SetPrefSize(aBoundSize);
+ }
+ }
+
+ return aMtf;
+}
+
+
+Graphic SdrExchangeView::GetAllMarkedGraphic() const
+{
+ Graphic aRet;
+
+ if( AreObjectsMarked() )
+ {
+ if( ( 1 == GetMarkedObjectCount() ) && GetSdrMarkByIndex( 0 ) )
+ aRet = SdrExchangeView::GetObjGraphic(*GetMarkedObjectByIndex(0));
+ else
+ aRet = GetMarkedObjMetaFile();
+ }
+
+ return aRet;
+}
+
+
+Graphic SdrExchangeView::GetObjGraphic(const SdrObject& rSdrObject)
+{
+ Graphic aRet;
+
+ // try to get a graphic from the object first
+ const SdrGrafObj* pSdrGrafObj(dynamic_cast< const SdrGrafObj* >(&rSdrObject));
+ const SdrOle2Obj* pSdrOle2Obj(dynamic_cast< const SdrOle2Obj* >(&rSdrObject));
+
+ if(pSdrGrafObj)
+ {
+ if(pSdrGrafObj->isEmbeddedVectorGraphicData())
+ {
+ // get Metafile for Svg content
+ aRet = pSdrGrafObj->getMetafileFromEmbeddedVectorGraphicData();
+ }
+ else
+ {
+ // Make behaviour coherent with metafile
+ // recording below (which of course also takes
+ // view-transformed objects)
+ aRet = pSdrGrafObj->GetTransformedGraphic();
+ }
+ }
+ else if(pSdrOle2Obj)
+ {
+ if(pSdrOle2Obj->GetGraphic())
+ {
+ aRet = *pSdrOle2Obj->GetGraphic();
+ }
+ }
+
+ // if graphic could not be retrieved => go the hard way and create a MetaFile
+ if((GraphicType::NONE == aRet.GetType()) || (GraphicType::Default == aRet.GetType()))
+ {
+ ScopedVclPtrInstance< VirtualDevice > pOut;
+ GDIMetaFile aMtf;
+ const tools::Rectangle aBoundRect(rSdrObject.GetCurrentBoundRect());
+ const MapMode aMap(rSdrObject.getSdrModelFromSdrObject().GetScaleUnit(),
+ Point(),
+ rSdrObject.getSdrModelFromSdrObject().GetScaleFraction(),
+ rSdrObject.getSdrModelFromSdrObject().GetScaleFraction());
+
+ pOut->EnableOutput(false);
+ pOut->SetMapMode(aMap);
+ aMtf.Record(pOut);
+ rSdrObject.SingleObjectPainter(*pOut);
+ aMtf.Stop();
+ aMtf.WindStart();
+
+ // #i99268# replace the original offset from using XOutDev's SetOffset
+ // NOT (as tried with #i92760#) with another MapMode which gets recorded
+ // by the Metafile itself (what always leads to problems), but by
+ // moving the result directly
+ aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
+ aMtf.SetPrefMapMode(aMap);
+ aMtf.SetPrefSize(aBoundRect.GetSize());
+
+ if(aMtf.GetActionSize())
+ {
+ aRet = aMtf;
+ }
+ }
+
+ return aRet;
+}
+
+
+::std::vector< SdrObject* > SdrExchangeView::GetMarkedObjects() const
+{
+ SortMarkedObjects();
+ ::std::vector< SdrObject* > aRetval;
+
+ ::std::vector< ::std::vector< SdrMark* > > aObjVectors( 2 );
+ ::std::vector< SdrMark* >& rObjVector1 = aObjVectors[ 0 ];
+ ::std::vector< SdrMark* >& rObjVector2 = aObjVectors[ 1 ];
+ const SdrLayerAdmin& rLayerAdmin = mpModel->GetLayerAdmin();
+ const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() );
+
+ for( size_t n = 0, nCount = GetMarkedObjectCount(); n < nCount; ++n )
+ {
+ SdrMark* pMark = GetSdrMarkByIndex( n );
+
+ // paint objects on control layer on top of all other objects
+ if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() )
+ rObjVector2.push_back( pMark );
+ else
+ rObjVector1.push_back( pMark );
+ }
+
+ for(const std::vector<SdrMark*> & rObjVector : aObjVectors)
+ {
+ for(SdrMark* pMark : rObjVector)
+ {
+ aRetval.push_back(pMark->GetMarkedSdrObj());
+ }
+ }
+
+ return aRetval;
+}
+
+
+void SdrExchangeView::DrawMarkedObj(OutputDevice& rOut) const
+{
+ ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
+
+ if(!aSdrObjects.empty())
+ {
+ sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, std::move(aSdrObjects), aSdrObjects[0]->getSdrPageFromSdrObject());
+ sdr::contact::DisplayInfo aDisplayInfo;
+
+ // do processing
+ aPainter.ProcessDisplay(aDisplayInfo);
+ }
+}
+
+std::unique_ptr<SdrModel> SdrExchangeView::CreateMarkedObjModel() const
+{
+ // Sorting the MarkList here might be problematic in the future, so
+ // use a copy.
+ SortMarkedObjects();
+ std::unique_ptr<SdrModel> pNewModel(mpModel->AllocModel());
+ rtl::Reference<SdrPage> pNewPage = pNewModel->AllocPage(false);
+ pNewModel->InsertPage(pNewPage.get());
+ ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
+
+ // #i13033#
+ // New mechanism to re-create the connections of cloned connectors
+ CloneList aCloneList;
+
+ for(SdrObject* pObj : aSdrObjects)
+ {
+ SdrObject* pNewObj(nullptr);
+
+ if(nullptr != dynamic_cast< const SdrPageObj* >(pObj))
+ {
+ // convert SdrPageObj's to a graphic representation, because
+ // virtual connection to referenced page gets lost in new model
+ pNewObj = new SdrGrafObj(
+ *pNewModel,
+ GetObjGraphic(*pObj),
+ pObj->GetLogicRect());
+ }
+ else if(nullptr != dynamic_cast< const sdr::table::SdrTableObj* >(pObj))
+ {
+ // check if we have a valid selection *different* from whole table
+ // being selected
+ if(mxSelectionController.is())
+ {
+ pNewObj = mxSelectionController->GetMarkedSdrObjClone(*pNewModel);
+ }
+ }
+
+ if(nullptr == pNewObj)
+ {
+ // not cloned yet
+ if(pObj->GetObjIdentifier() == SdrObjKind::OLE2 && nullptr == mpModel->GetPersist())
+ {
+ // tdf#125520 - former fix was wrong, the SdrModel
+ // has to have a GetPersist() already, see task.
+ // We can still warn here when this is not the case
+ SAL_WARN( "svx", "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied" );
+ }
+
+ // use default way
+ pNewObj = pObj->CloneSdrObject(*pNewModel);
+ }
+
+ if(pNewObj)
+ {
+ pNewPage->InsertObject(pNewObj, SAL_MAX_SIZE);
+
+ // #i13033#
+ aCloneList.AddPair(pObj, pNewObj);
+ }
+ }
+
+ // #i13033#
+ // New mechanism to re-create the connections of cloned connectors
+ aCloneList.CopyConnections();
+
+ return pNewModel;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */