Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / svdraw / svdograf.cxx
blob6bf317f29c02984ec06804b9bef58cdf8ba86c89
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <unotools/streamwrap.hxx>
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>
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>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::io;
61 class SdrGraphicLink : public sfx2::SvBaseLink
63 SdrGrafObj& rGrafObj;
65 public:
66 explicit SdrGraphicLink(SdrGrafObj& rObj);
68 virtual void Closed() override;
70 virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
71 const OUString& rMimeType, const css::uno::Any & rValue ) override;
73 void Connect() { GetRealObject(); }
76 SdrGraphicLink::SdrGraphicLink(SdrGrafObj& rObj)
77 : ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB )
78 , rGrafObj( rObj )
80 SetSynchron( false );
83 ::sfx2::SvBaseLink::UpdateResult SdrGraphicLink::DataChanged(
84 const OUString& rMimeType, const css::uno::Any & rValue )
86 SdrModel& rModel(rGrafObj.getSdrModelFromSdrObject());
87 sfx2::LinkManager* pLinkManager(rModel.GetLinkManager());
89 if( pLinkManager && rValue.hasValue() )
91 sfx2::LinkManager::GetDisplayNames( this, nullptr, &rGrafObj.aFileName, nullptr, &rGrafObj.aFilterName );
93 Graphic aGraphic;
94 if (pLinkManager->GetGraphicFromAny(rMimeType, rValue, aGraphic, nullptr))
96 rGrafObj.ImpSetLinkedGraphic(aGraphic);
98 else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
100 // broadcasting, to update slide sorter
101 rGrafObj.BroadcastObjectChange();
104 return SUCCESS;
107 void SdrGraphicLink::Closed()
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();
116 std::unique_ptr<sdr::properties::BaseProperties> SdrGrafObj::CreateObjectSpecificProperties()
118 return std::make_unique<sdr::properties::GraphicProperties>(*this);
122 // DrawContact section
124 std::unique_ptr<sdr::contact::ViewContact> SdrGrafObj::CreateObjectSpecificViewContact()
126 return std::make_unique<sdr::contact::ViewContactOfGraphic>(*this);
130 // check if SVG and if try to get ObjectInfoPrimitive2D and extract info
132 void SdrGrafObj::onGraphicChanged()
134 if (!mpGraphicObject || !mpGraphicObject->GetGraphic().isAvailable())
135 return;
137 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
139 if (!rVectorGraphicDataPtr)
140 return;
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;
148 const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVectorGraphicDataPtr->getPrimitive2DSequence());
150 if (aSequence.empty())
151 return;
153 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
154 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
156 aProcessor.process(aSequence);
158 const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
160 if (!pResult)
161 return;
163 OUString aName = pResult->getName();
164 OUString aTitle = pResult->getTitle();
165 OUString aDesc = pResult->getDesc();
167 if(!aName.isEmpty())
169 SetName(aName);
172 if(!aTitle.isEmpty())
174 SetTitle(aTitle);
177 if(!aDesc.isEmpty())
179 SetDescription(aDesc);
183 SdrGrafObj::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)
193 onGraphicChanged();
195 // #i118485# Shear allowed and possible now
196 bNoShear = false;
198 mbGrafAnimationAllowed = true;
200 // #i25616#
201 mbLineIsOutsideGeometry = true;
203 // #i25616#
204 mbSupportTextIndentingOnLineWidthChange = false;
207 SdrGrafObj::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)
220 onGraphicChanged();
222 // #i118485# Shear allowed and possible now
223 bNoShear = false;
225 mbGrafAnimationAllowed = true;
227 // #i25616#
228 mbLineIsOutsideGeometry = true;
230 // #i25616#
231 mbSupportTextIndentingOnLineWidthChange = false;
234 SdrGrafObj::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)
246 onGraphicChanged();
248 // #i118485# Shear allowed and possible now
249 bNoShear = false;
251 mbGrafAnimationAllowed = true;
253 // #i25616#
254 mbLineIsOutsideGeometry = true;
256 // #i25616#
257 mbSupportTextIndentingOnLineWidthChange = false;
260 SdrGrafObj::~SdrGrafObj()
262 ImpDeregisterLink();
265 void SdrGrafObj::SetGraphicObject(const GraphicObject& rGraphicObject)
267 mpGraphicObject.reset(new GraphicObject(rGraphicObject));
268 mpReplacementGraphicObject.reset();
269 mpGraphicObject->SetUserData();
270 SetChanged();
271 BroadcastObjectChange();
272 onGraphicChanged();
275 const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const
277 if (bForceSwapIn)
278 ForceSwapIn();
279 return *mpGraphicObject;
282 const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const
284 if (!mpReplacementGraphicObject && mpGraphicObject)
286 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
288 if (rVectorGraphicDataPtr)
290 const_cast< SdrGrafObj* >(this)->mpReplacementGraphicObject.reset(new GraphicObject(rVectorGraphicDataPtr->getReplacement()));
292 else if (mpGraphicObject->GetGraphic().GetType() == GraphicType::GdiMetafile)
294 // Replacement graphic for PDF and metafiles is just the bitmap.
295 const_cast<SdrGrafObj*>(this)->mpReplacementGraphicObject.reset(new GraphicObject(mpGraphicObject->GetGraphic().GetBitmapEx()));
299 return mpReplacementGraphicObject.get();
302 void SdrGrafObj::NbcSetGraphic(const Graphic& rGraphic)
304 mpGraphicObject->SetGraphic(rGraphic);
305 mpReplacementGraphicObject.reset();
306 mpGraphicObject->SetUserData();
307 onGraphicChanged();
310 void SdrGrafObj::SetGraphic( const Graphic& rGraphic )
312 if (!rGraphic.getOriginURL().isEmpty())
314 ImpDeregisterLink();
315 aFileName = rGraphic.getOriginURL();
316 aFilterName = "";
318 NbcSetGraphic(rGraphic);
319 if (!rGraphic.getOriginURL().isEmpty())
321 ImpRegisterLink();
322 mpGraphicObject->SetUserData();
324 SetChanged();
325 BroadcastObjectChange();
326 ForceSwapIn();
329 const Graphic& SdrGrafObj::GetGraphic() const
331 return mpGraphicObject->GetGraphic();
334 Graphic SdrGrafObj::GetTransformedGraphic( SdrGrafObjTransformsAttrs nTransformFlags ) const
336 // Refactored most of the code to GraphicObject, where
337 // everybody can use e.g. the cropping functionality
338 MapMode aDestMap(
339 getSdrModelFromSdrObject().GetScaleUnit(),
340 Point(),
341 getSdrModelFromSdrObject().GetScaleFraction(),
342 getSdrModelFromSdrObject().GetScaleFraction());
343 const Size aDestSize( GetLogicRect().GetSize() );
344 GraphicAttr aActAttr = GetGraphicAttr(nTransformFlags);
346 // Delegate to moved code in GraphicObject
347 return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr );
350 GraphicType SdrGrafObj::GetGraphicType() const
352 return mpGraphicObject->GetType();
355 GraphicAttr SdrGrafObj::GetGraphicAttr( SdrGrafObjTransformsAttrs nTransformFlags ) const
357 GraphicAttr aActAttr;
359 GraphicType eType = GetGraphicType();
360 if( SdrGrafObjTransformsAttrs::NONE != nTransformFlags &&
361 GraphicType::NONE != eType )
363 const bool bMirror = bool( nTransformFlags & SdrGrafObjTransformsAttrs::MIRROR );
364 const bool bRotate = bool( nTransformFlags & SdrGrafObjTransformsAttrs::ROTATE ) &&
365 (aGeo.nRotationAngle && aGeo.nRotationAngle != 18000);
367 // Need cropping info earlier
368 const_cast<SdrGrafObj*>(this)->ImpSetAttrToGrafInfo();
370 // Actually transform the graphic only in this case.
371 // Cropping always happens, though.
372 aActAttr = aGrafInfo;
374 if( bMirror )
376 sal_uInt16 nMirrorCase = ( aGeo.nRotationAngle == 18000 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 );
377 bool bHMirr = nMirrorCase == 2 || nMirrorCase == 4;
378 bool bVMirr = nMirrorCase == 3 || nMirrorCase == 4;
380 aActAttr.SetMirrorFlags( ( bHMirr ? BmpMirrorFlags::Horizontal : BmpMirrorFlags::NONE ) | ( bVMirr ? BmpMirrorFlags::Vertical : BmpMirrorFlags::NONE ) );
383 if( bRotate )
384 aActAttr.SetRotation( Degree10(aGeo.nRotationAngle / 10) );
387 return aActAttr;
390 bool SdrGrafObj::IsAnimated() const
392 return mpGraphicObject->IsAnimated();
395 bool SdrGrafObj::IsEPS() const
397 return mpGraphicObject->IsEPS();
400 MapMode SdrGrafObj::GetGrafPrefMapMode() const
402 return mpGraphicObject->GetPrefMapMode();
405 Size SdrGrafObj::GetGrafPrefSize() const
407 return mpGraphicObject->GetPrefSize();
410 void SdrGrafObj::SetGrafStreamURL( const OUString& rGraphicStreamURL )
412 if( rGraphicStreamURL.isEmpty() )
414 mpGraphicObject->SetUserData();
416 else if(getSdrModelFromSdrObject().IsSwapGraphics() )
418 mpGraphicObject->SetUserData( rGraphicStreamURL );
422 OUString const & SdrGrafObj::GetGrafStreamURL() const
424 return mpGraphicObject->GetUserData();
427 Size SdrGrafObj::getOriginalSize() const
429 Size aSize = GetGrafPrefSize();
431 if (aGrafInfo.IsCropped())
433 const tools::Long aCroppedTop(OutputDevice::LogicToLogic(aGrafInfo.GetTopCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
434 const tools::Long aCroppedBottom(OutputDevice::LogicToLogic(aGrafInfo.GetBottomCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
435 const tools::Long aCroppedLeft(OutputDevice::LogicToLogic(aGrafInfo.GetLeftCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
436 const tools::Long aCroppedRight(OutputDevice::LogicToLogic(aGrafInfo.GetRightCrop(), getSdrModelFromSdrObject().GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit()));
437 const tools::Long aCroppedWidth(aSize.getWidth() - aCroppedLeft + aCroppedRight);
438 const tools::Long aCroppedHeight(aSize.getHeight() - aCroppedTop + aCroppedBottom);
440 aSize = Size ( aCroppedWidth, aCroppedHeight);
443 if ( GetGrafPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
444 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
445 else
446 aSize = OutputDevice::LogicToLogic(aSize, GetGrafPrefMapMode(), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
448 return aSize;
451 // TODO Remove
452 void SdrGrafObj::ForceSwapIn() const
454 if (pGraphicLink && (mpGraphicObject->GetType() == GraphicType::NONE ||
455 mpGraphicObject->GetType() == GraphicType::Default) )
457 pGraphicLink->Update();
461 void SdrGrafObj::ImpRegisterLink()
463 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
465 if( pLinkManager != nullptr && pGraphicLink == nullptr )
467 if (!aFileName.isEmpty())
469 pGraphicLink = new SdrGraphicLink( *this );
470 pLinkManager->InsertFileLink(
471 *pGraphicLink, sfx2::SvBaseLinkObjectType::ClientGraphic, aFileName, (aFilterName.isEmpty() ? nullptr : &aFilterName));
472 pGraphicLink->Connect();
477 void SdrGrafObj::ImpDeregisterLink()
479 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
481 if( pLinkManager != nullptr && pGraphicLink!=nullptr)
483 // When using Remove, the *pGraphicLink is implicitly deleted
484 pLinkManager->Remove( pGraphicLink );
485 pGraphicLink=nullptr;
489 void SdrGrafObj::SetGraphicLink(const OUString& rFileName)
491 Graphic aGraphic;
492 aGraphic.setOriginURL(rFileName);
493 SetGraphic(aGraphic);
496 void SdrGrafObj::ReleaseGraphicLink()
498 ImpDeregisterLink();
499 aFileName.clear();
500 aFilterName.clear();
502 auto aGraphic = mpGraphicObject->GetGraphic();
503 aGraphic.setOriginURL("");
504 SetGraphic(aGraphic);
507 bool SdrGrafObj::IsLinkedGraphic() const
509 return !mpGraphicObject->GetGraphic().getOriginURL().isEmpty();
512 void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
514 bool bNoPresGrf = ( mpGraphicObject->GetType() != GraphicType::NONE ) && !bEmptyPresObj;
516 rInfo.bResizeFreeAllowed = aGeo.nRotationAngle % 9000 == 0 ||
517 aGeo.nRotationAngle % 18000 == 0 ||
518 aGeo.nRotationAngle % 27000 == 0;
520 rInfo.bResizePropAllowed = true;
521 rInfo.bRotateFreeAllowed = bNoPresGrf;
522 rInfo.bRotate90Allowed = bNoPresGrf;
523 rInfo.bMirrorFreeAllowed = bNoPresGrf;
524 rInfo.bMirror45Allowed = bNoPresGrf;
525 rInfo.bMirror90Allowed = !bEmptyPresObj;
526 rInfo.bTransparenceAllowed = false;
528 // #i118485# Shear allowed and possible now
529 rInfo.bShearAllowed = true;
531 rInfo.bEdgeRadiusAllowed=false;
532 rInfo.bCanConvToPath = !IsEPS();
533 rInfo.bCanConvToPathLineToArea = false;
534 rInfo.bCanConvToPolyLineToArea = false;
535 rInfo.bCanConvToPoly = !IsEPS();
536 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
539 SdrObjKind SdrGrafObj::GetObjIdentifier() const
541 return OBJ_GRAF;
544 void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic )
546 const bool bIsChanged(getSdrModelFromSdrObject().IsChanged());
547 NbcSetGraphic( rGraphic );
548 ActionChanged();
549 BroadcastObjectChange();
550 getSdrModelFromSdrObject().SetChanged(bIsChanged);
553 OUString SdrGrafObj::TakeObjNameSingul() const
555 if (!mpGraphicObject)
556 return OUString();
558 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
560 OUStringBuffer sName;
562 if (rVectorGraphicDataPtr)
564 switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
566 case VectorGraphicDataType::Svg:
568 sName.append(SvxResId(STR_ObjNameSingulGRAFSVG));
569 break;
571 case VectorGraphicDataType::Wmf:
573 sName.append(SvxResId(STR_ObjNameSingulGRAFWMF));
574 break;
576 case VectorGraphicDataType::Emf:
578 sName.append(SvxResId(STR_ObjNameSingulGRAFEMF));
579 break;
581 case VectorGraphicDataType::Pdf:
583 sName.append(SvxResId(STR_ObjNameSingulGRAFPDF));
584 break;
586 } //no default, see tdf#137813
588 else
590 switch( mpGraphicObject->GetType() )
592 case GraphicType::Bitmap:
594 const char* pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
595 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) :
596 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) );
598 sName.append(SvxResId(pId));
600 break;
602 case GraphicType::GdiMetafile:
603 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF));
604 break;
606 case GraphicType::NONE:
607 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE));
608 break;
610 default:
611 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF));
612 break;
616 const OUString aName(GetName());
618 if (!aName.isEmpty())
620 sName.append(" '");
621 sName.append(aName);
622 sName.append('\'' );
625 return sName.makeStringAndClear();
628 OUString SdrGrafObj::TakeObjNamePlural() const
630 if (!mpGraphicObject)
631 return OUString();
633 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
635 OUStringBuffer sName;
637 if (rVectorGraphicDataPtr)
639 switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
641 case VectorGraphicDataType::Svg:
643 sName.append(SvxResId(STR_ObjNamePluralGRAFSVG));
644 break;
646 case VectorGraphicDataType::Wmf:
648 sName.append(SvxResId(STR_ObjNamePluralGRAFWMF));
649 break;
651 case VectorGraphicDataType::Emf:
653 sName.append(SvxResId(STR_ObjNamePluralGRAFEMF));
654 break;
656 case VectorGraphicDataType::Pdf:
658 sName.append(SvxResId(STR_ObjNamePluralGRAFPDF));
659 break;
661 } //no default, see tdf#137813
663 else
665 switch(mpGraphicObject->GetType())
667 case GraphicType::Bitmap:
669 const char* pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
670 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) :
671 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) );
673 sName.append(SvxResId(pId));
675 break;
677 case GraphicType::GdiMetafile:
678 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF));
679 break;
681 case GraphicType::NONE:
682 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE));
683 break;
685 default:
686 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF));
687 break;
691 const OUString aName(GetName());
693 if (!aName.isEmpty())
695 sName.append(" '");
696 sName.append(aName);
697 sName.append('\'');
700 return sName.makeStringAndClear();
703 SdrObjectUniquePtr SdrGrafObj::getFullDragClone() const
705 // call parent
706 SdrObjectUniquePtr pRetval = SdrRectObj::getFullDragClone();
708 // #i103116# the full drag clone leads to problems
709 // with linked graphics, so reset the link in this
710 // temporary interaction object and load graphic
711 if(pRetval && IsLinkedGraphic())
713 static_cast< SdrGrafObj* >(pRetval.get())->ReleaseGraphicLink();
716 return pRetval;
719 SdrGrafObj* SdrGrafObj::CloneSdrObject(SdrModel& rTargetModel) const
721 return CloneHelper< SdrGrafObj >(rTargetModel);
724 SdrGrafObj& SdrGrafObj::operator=( const SdrGrafObj& rObj )
726 if( this == &rObj )
727 return *this;
728 SdrRectObj::operator=( rObj );
730 aFileName = rObj.aFileName;
731 bMirrored = rObj.bMirrored;
733 mbIsSignatureLine = rObj.mbIsSignatureLine;
734 maSignatureLineId = rObj.maSignatureLineId;
735 maSignatureLineSuggestedSignerName = rObj.maSignatureLineSuggestedSignerName;
736 maSignatureLineSuggestedSignerTitle = rObj.maSignatureLineSuggestedSignerTitle;
737 maSignatureLineSuggestedSignerEmail = rObj.maSignatureLineSuggestedSignerEmail;
738 maSignatureLineSigningInstructions = rObj.maSignatureLineSigningInstructions;
739 mbIsSignatureLineShowSignDate = rObj.mbIsSignatureLineShowSignDate;
740 mbIsSignatureLineCanAddComment = rObj.mbIsSignatureLineCanAddComment;
741 mbSignatureLineIsSigned = false;
742 mpSignatureLineUnsignedGraphic = rObj.mpSignatureLineUnsignedGraphic;
744 if(rObj.mpQrCode)
746 mpQrCode = std::make_unique<css::drawing::QRCode>(*rObj.mpQrCode);
748 else
750 mpQrCode.reset();
753 if (mbIsSignatureLine && rObj.mpSignatureLineUnsignedGraphic)
754 mpGraphicObject->SetGraphic(rObj.mpSignatureLineUnsignedGraphic);
755 else
756 mpGraphicObject->SetGraphic( rObj.GetGraphic() );
758 if( rObj.IsLinkedGraphic() )
760 SetGraphicLink( aFileName );
763 ImpSetAttrToGrafInfo();
764 return *this;
767 sal_uInt32 SdrGrafObj::GetHdlCount() const
769 return 8;
772 void SdrGrafObj::AddToHdlList(SdrHdlList& rHdlList) const
774 SdrHdlList tempList(nullptr);
775 SdrRectObj::AddToHdlList( tempList );
776 tempList.RemoveHdl(0);
777 tempList.MoveTo(rHdlList);
780 void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
782 SdrRectObj::NbcResize( rRef, xFact, yFact );
784 bool bMirrX = xFact.GetNumerator() < 0;
785 bool bMirrY = yFact.GetNumerator() < 0;
787 if( bMirrX != bMirrY )
788 bMirrored = !bMirrored;
791 void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2)
793 SdrRectObj::NbcMirror(rRef1,rRef2);
794 bMirrored = !bMirrored;
797 SdrObjGeoData* SdrGrafObj::NewGeoData() const
799 return new SdrGrafObjGeoData;
802 void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const
804 SdrRectObj::SaveGeoData(rGeo);
805 SdrGrafObjGeoData& rGGeo=static_cast<SdrGrafObjGeoData&>(rGeo);
806 rGGeo.bMirrored=bMirrored;
809 void SdrGrafObj::RestGeoData(const SdrObjGeoData& rGeo)
811 SdrRectObj::RestGeoData(rGeo);
812 const SdrGrafObjGeoData& rGGeo=static_cast<const SdrGrafObjGeoData&>(rGeo);
813 bMirrored=rGGeo.bMirrored;
816 void SdrGrafObj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
818 const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
819 const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
821 if( bRemove )
823 // No SwapIn necessary here, because if something's not loaded, it can't be animated either.
824 if( mpGraphicObject->IsAnimated())
825 mpGraphicObject->StopAnimation();
827 if( pGraphicLink != nullptr )
828 ImpDeregisterLink();
831 // call parent
832 SdrRectObj::handlePageChange(pOldPage, pNewPage);
834 if (!aFileName.isEmpty() && bInsert)
836 ImpRegisterLink();
840 void SdrGrafObj::StartAnimation()
842 SetGrafAnimationAllowed(true);
845 bool SdrGrafObj::HasGDIMetaFile() const
847 return( mpGraphicObject->GetType() == GraphicType::GdiMetafile );
850 bool SdrGrafObj::isEmbeddedVectorGraphicData() const
852 return GraphicType::Bitmap == GetGraphicType() && GetGraphic().getVectorGraphicData();
855 GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedVectorGraphicData() const
857 GDIMetaFile aRetval;
859 if(isEmbeddedVectorGraphicData())
861 ScopedVclPtrInstance< VirtualDevice > pOut;
862 const tools::Rectangle aBoundRect(GetCurrentBoundRect());
863 const MapMode aMap(
864 getSdrModelFromSdrObject().GetScaleUnit(),
865 Point(),
866 getSdrModelFromSdrObject().GetScaleFraction(),
867 getSdrModelFromSdrObject().GetScaleFraction());
869 pOut->EnableOutput(false);
870 pOut->SetMapMode(aMap);
871 aRetval.Record(pOut);
872 SingleObjectPainter(*pOut);
873 aRetval.Stop();
874 aRetval.WindStart();
875 aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top());
876 aRetval.SetPrefMapMode(aMap);
877 aRetval.SetPrefSize(aBoundRect.GetSize());
880 return aRetval;
883 GDIMetaFile SdrGrafObj::GetMetaFile(GraphicType &rGraphicType) const
885 if (isEmbeddedVectorGraphicData())
887 // Embedded Vector Graphic Data
888 // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
889 // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
890 // use the old converter path over the MetaFile mechanism. Create Metafile from Svg
891 // primitives here pretty directly
892 rGraphicType = GraphicType::GdiMetafile;
893 return getMetafileFromEmbeddedVectorGraphicData();
895 else if (GraphicType::GdiMetafile == rGraphicType)
897 return GetTransformedGraphic(SdrGrafObjTransformsAttrs::MIRROR).GetGDIMetaFile();
899 return GDIMetaFile();
902 SdrObjectUniquePtr SdrGrafObj::DoConvertToPolyObj(bool bBezier, bool bAddText ) const
904 SdrObject* pRetval = nullptr;
905 GraphicType aGraphicType(GetGraphicType());
906 GDIMetaFile aMtf(GetMetaFile(aGraphicType));
907 switch(aGraphicType)
909 case GraphicType::GdiMetafile:
911 // Sort into group and return ONLY those objects that can be created from the MetaFile.
912 ImpSdrGDIMetaFileImport aFilter(
913 getSdrModelFromSdrObject(),
914 GetLayer(),
915 maRect);
916 SdrObjGroup* pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
918 if(aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0))
921 // copy transformation
922 GeoStat aGeoStat(GetGeoStat());
924 if(aGeoStat.nShearAngle)
926 aGeoStat.RecalcTan();
927 pGrp->NbcShear(maRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
930 if(aGeoStat.nRotationAngle)
932 aGeoStat.RecalcSinCos();
933 pGrp->NbcRotate(maRect.TopLeft(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
937 pRetval = pGrp;
938 pGrp->NbcSetLayer(GetLayer());
940 if(bAddText)
942 pRetval = ImpConvertAddText(SdrObjectUniquePtr(pRetval), bBezier).release();
945 // convert all children
946 if( pRetval )
948 SdrObject* pHalfDone = pRetval;
949 pRetval = pRetval->DoConvertToPolyObj(bBezier, bAddText).release();
950 SdrObject::Free( pHalfDone ); // resulting object is newly created
952 if( pRetval )
954 // flatten subgroups. As we call
955 // DoConvertToPolyObj() on the resulting group
956 // objects, subgroups can exist (e.g. text is
957 // a group object for every line).
958 SdrObjList* pList = pRetval->GetSubList();
959 if( pList )
960 pList->FlattenGroups();
964 else
966 // always use SdrObject::Free(...) for SdrObjects (!)
967 SdrObject* pTemp(pGrp);
968 SdrObject::Free(pTemp);
971 // #i118485# convert line and fill
972 SdrObjectUniquePtr pLineFill = SdrRectObj::DoConvertToPolyObj(bBezier, false);
974 if(pLineFill)
976 if(pRetval)
978 pGrp = dynamic_cast< SdrObjGroup* >(pRetval);
980 if(!pGrp)
982 pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
983 pGrp->NbcSetLayer(GetLayer());
984 pGrp->GetSubList()->NbcInsertObject(pRetval);
987 pGrp->GetSubList()->NbcInsertObject(pLineFill.release(), 0);
989 else
991 pRetval = pLineFill.release();
995 break;
997 case GraphicType::Bitmap:
999 // create basic object and add fill
1000 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText).release();
1002 // save bitmap as an attribute
1003 if(pRetval)
1005 // retrieve bitmap for the fill
1006 SfxItemSet aSet(GetObjectItemSet());
1008 aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
1009 const BitmapEx aBitmapEx(GetTransformedGraphic().GetBitmapEx());
1010 aSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
1011 aSet.Put(XFillBmpTileItem(false));
1013 pRetval->SetMergedItemSet(aSet);
1015 break;
1017 case GraphicType::NONE:
1018 case GraphicType::Default:
1020 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText).release();
1021 break;
1025 return SdrObjectUniquePtr(pRetval);
1028 void SdrGrafObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1030 SetXPolyDirty();
1031 SdrRectObj::Notify( rBC, rHint );
1032 ImpSetAttrToGrafInfo();
1036 void SdrGrafObj::SetMirrored( bool _bMirrored )
1038 bMirrored = _bMirrored;
1041 void SdrGrafObj::ImpSetAttrToGrafInfo()
1043 const SfxItemSet& rSet = GetObjectItemSet();
1044 const sal_uInt16 nTrans = rSet.Get( SDRATTR_GRAFTRANSPARENCE ).GetValue();
1045 const SdrGrafCropItem& rCrop = rSet.Get( SDRATTR_GRAFCROP );
1047 aGrafInfo.SetLuminance( rSet.Get( SDRATTR_GRAFLUMINANCE ).GetValue() );
1048 aGrafInfo.SetContrast( rSet.Get( SDRATTR_GRAFCONTRAST ).GetValue() );
1049 aGrafInfo.SetChannelR( rSet.Get( SDRATTR_GRAFRED ).GetValue() );
1050 aGrafInfo.SetChannelG( rSet.Get( SDRATTR_GRAFGREEN ).GetValue() );
1051 aGrafInfo.SetChannelB( rSet.Get( SDRATTR_GRAFBLUE ).GetValue() );
1052 aGrafInfo.SetGamma( rSet.Get( SDRATTR_GRAFGAMMA ).GetValue() * 0.01 );
1053 aGrafInfo.SetTransparency( static_cast<sal_uInt8>(FRound( std::min( nTrans, sal_uInt16(100) ) * 2.55 )) );
1054 aGrafInfo.SetInvert( rSet.Get( SDRATTR_GRAFINVERT ).GetValue() );
1055 aGrafInfo.SetDrawMode( rSet.Get( SDRATTR_GRAFMODE ).GetValue() );
1056 aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() );
1058 SetXPolyDirty();
1059 SetRectsDirty();
1062 void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly )
1064 Size aSize;
1065 Size aMaxSize( rMaxRect.GetSize() );
1066 if (mpGraphicObject->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
1067 aSize = Application::GetDefaultDevice()->PixelToLogic(mpGraphicObject->GetPrefSize(), MapMode(MapUnit::Map100thMM));
1068 else
1069 aSize = OutputDevice::LogicToLogic( mpGraphicObject->GetPrefSize(),
1070 mpGraphicObject->GetPrefMapMode(),
1071 MapMode( MapUnit::Map100thMM ) );
1073 if( aSize.IsEmpty() )
1074 return;
1076 Point aPos( rMaxRect.TopLeft() );
1078 // if the graphic is too large, fit it to page
1079 if ( (!bShrinkOnly ||
1080 ( aSize.Height() > aMaxSize.Height() ) ||
1081 ( aSize.Width() > aMaxSize.Width() ) )&&
1082 aSize.Height() && aMaxSize.Height() )
1084 float fGrfWH = static_cast<float>(aSize.Width()) /
1085 static_cast<float>(aSize.Height());
1086 float fWinWH = static_cast<float>(aMaxSize.Width()) /
1087 static_cast<float>(aMaxSize.Height());
1089 // Scale graphic to page size
1090 if ( fGrfWH < fWinWH )
1092 aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
1093 aSize.setHeight( aMaxSize.Height() );
1095 else if ( fGrfWH > 0.F )
1097 aSize.setWidth( aMaxSize.Width() );
1098 aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
1101 aPos = rMaxRect.Center();
1104 if( bShrinkOnly )
1105 aPos = maRect.TopLeft();
1107 aPos.AdjustX( -(aSize.Width() / 2) );
1108 aPos.AdjustY( -(aSize.Height() / 2) );
1109 SetLogicRect( tools::Rectangle( aPos, aSize ) );
1112 void SdrGrafObj::SetGrafAnimationAllowed(bool bNew)
1114 if(mbGrafAnimationAllowed != bNew)
1116 mbGrafAnimationAllowed = bNew;
1117 ActionChanged();
1121 Reference< XInputStream > SdrGrafObj::getInputStream() const
1123 Reference< XInputStream > xStream;
1125 if (mpGraphicObject && GetGraphic().IsGfxLink())
1127 Graphic aGraphic( GetGraphic() );
1128 GfxLink aLink( aGraphic.GetGfxLink() );
1129 sal_uInt32 nSize = aLink.GetDataSize();
1130 const void* pSourceData = static_cast<const void*>(aLink.GetData());
1131 if( nSize && pSourceData )
1133 sal_uInt8 * pBuffer = new sal_uInt8[ nSize ];
1134 memcpy( pBuffer, pSourceData, nSize );
1136 SvMemoryStream* pStream = new SvMemoryStream( static_cast<void*>(pBuffer), static_cast<std::size_t>(nSize), StreamMode::READ );
1137 pStream->ObjectOwnsMemory( true );
1138 xStream.set( new utl::OInputStreamWrapper( pStream, true ) );
1142 if (!xStream.is() && !aFileName.isEmpty())
1144 SvFileStream* pStream = new SvFileStream( aFileName, StreamMode::READ );
1145 xStream.set( new utl::OInputStreamWrapper( pStream ) );
1148 return xStream;
1151 // moved crop handle creation here; this is the object type using them
1152 void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
1154 basegfx::B2DHomMatrix aMatrix;
1155 basegfx::B2DPolyPolygon aPolyPolygon;
1157 // get object transformation
1158 TRGetBaseGeometry(aMatrix, aPolyPolygon);
1160 // part of object transformation correction, but used later, so defined outside next scope
1161 double fShearX(0.0), fRotate(0.0);
1163 { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
1164 basegfx::B2DTuple aScale;
1165 basegfx::B2DTuple aTranslate;
1167 aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1169 if(!basegfx::fTools::equalZero(fShearX))
1171 // shearX is used, correct it
1172 fShearX = -fShearX;
1175 aMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
1176 aScale,
1177 fShearX,
1178 fRotate,
1179 aTranslate);
1182 // get crop values
1183 const SdrGrafCropItem& rCrop = GetMergedItem(SDRATTR_GRAFCROP);
1185 if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom())
1187 // decompose object transformation to have current translate and scale
1188 basegfx::B2DVector aScale, aTranslate;
1189 double fLclRotate, fLclShearX;
1191 aMatrix.decompose(aScale, aTranslate, fLclRotate, fLclShearX);
1193 if(!aScale.equalZero())
1195 // get crop scale
1196 const basegfx::B2DVector aCropScaleFactor(
1197 GetGraphicObject().calculateCropScaling(
1198 aScale.getX(),
1199 aScale.getY(),
1200 rCrop.GetLeft(),
1201 rCrop.GetTop(),
1202 rCrop.GetRight(),
1203 rCrop.GetBottom()));
1205 // apply crop scale
1206 const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX());
1207 const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY());
1208 const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX());
1209 const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY());
1210 basegfx::B2DHomMatrix aMatrixForCropViewHdl(aMatrix);
1212 if(IsMirrored())
1214 // create corrected new matrix, TTTT can be removed with aw080
1215 // the old mirror only can mirror horizontally; the vertical mirror
1216 // is faked by using the horizontal and 180 degree rotation. Since
1217 // the object can be rotated differently from 180 degree, this is
1218 // not safe to detect. Just correct horizontal mirror (which is
1219 // in IsMirrored()) and keep the rotation angle
1220 // caution: Do not modify aMatrix, it is used below to calculate
1221 // the exact handle positions
1222 basegfx::B2DHomMatrix aPreMultiply;
1224 // mirrored X, apply
1225 aPreMultiply.translate(-0.5, 0.0);
1226 aPreMultiply.scale(-1.0, 1.0);
1227 aPreMultiply.translate(0.5, 0.0);
1229 aMatrixForCropViewHdl = aMatrixForCropViewHdl * aPreMultiply;
1232 rTarget.AddHdl(
1233 std::make_unique<SdrCropViewHdl>(
1234 aMatrixForCropViewHdl,
1235 GetGraphicObject().GetGraphic(),
1236 fCropLeft,
1237 fCropTop,
1238 fCropRight,
1239 fCropBottom));
1243 basegfx::B2DPoint aPos;
1245 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.0);
1246 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperLeft, fShearX, fRotate));
1247 aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0);
1248 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Upper, fShearX, fRotate));
1249 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0);
1250 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperRight, fShearX, fRotate));
1251 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5);
1252 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Left , fShearX, fRotate));
1253 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5);
1254 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Right, fShearX, fRotate));
1255 aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0);
1256 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerLeft, fShearX, fRotate));
1257 aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0);
1258 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Lower, fShearX, fRotate));
1259 aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0);
1260 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
1263 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */