Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / svdraw / svdograf.cxx
blobb36daff54745b96b95f61f7a0be553ecd7f79626
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;
59 class SdrGraphicLink : public sfx2::SvBaseLink
61 SdrGrafObj& rGrafObj;
63 public:
64 explicit SdrGraphicLink(SdrGrafObj& rObj);
66 virtual void Closed() override;
68 virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
69 const OUString& rMimeType, const uno::Any & rValue ) override;
71 void Connect() { GetRealObject(); }
74 SdrGraphicLink::SdrGraphicLink(SdrGrafObj& rObj)
75 : ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB )
76 , rGrafObj( rObj )
78 SetSynchron( false );
81 ::sfx2::SvBaseLink::UpdateResult SdrGraphicLink::DataChanged(
82 const OUString& rMimeType, const uno::Any & rValue )
84 SdrModel& rModel(rGrafObj.getSdrModelFromSdrObject());
85 sfx2::LinkManager* pLinkManager(rModel.GetLinkManager());
87 if( pLinkManager && rValue.hasValue() )
89 sfx2::LinkManager::GetDisplayNames( this, nullptr, &rGrafObj.aFileName, nullptr, &rGrafObj.aFilterName );
91 Graphic aGraphic;
92 if (pLinkManager->GetGraphicFromAny(rMimeType, rValue, aGraphic, nullptr))
94 rGrafObj.ImpSetLinkedGraphic(aGraphic);
96 else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
98 // broadcasting, to update slide sorter
99 rGrafObj.BroadcastObjectChange();
102 return SUCCESS;
105 void SdrGraphicLink::Closed()
107 // close connection; set pLink of the object to NULL, as link instance is just about getting destructed.
108 rGrafObj.ForceSwapIn();
109 rGrafObj.pGraphicLink=nullptr;
110 rGrafObj.ReleaseGraphicLink();
111 SvBaseLink::Closed();
114 std::unique_ptr<sdr::properties::BaseProperties> SdrGrafObj::CreateObjectSpecificProperties()
116 return std::make_unique<sdr::properties::GraphicProperties>(*this);
120 // DrawContact section
122 std::unique_ptr<sdr::contact::ViewContact> SdrGrafObj::CreateObjectSpecificViewContact()
124 return std::make_unique<sdr::contact::ViewContactOfGraphic>(*this);
128 // check if SVG and if try to get ObjectInfoPrimitive2D and extract info
130 void SdrGrafObj::onGraphicChanged()
132 if (!mpGraphicObject || !mpGraphicObject->GetGraphic().isAvailable())
133 return;
135 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
137 if (!rVectorGraphicDataPtr)
138 return;
140 // Skip for PDF as it is only a bitmap primitive in a sequence and
141 // doesn't contain metadata. However getting the primitive sequence
142 // will also trigger a premature rendering of the PDF.
143 if (rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Pdf)
144 return;
146 const std::deque<uno::Reference<graphic::XPrimitive2D>>& rContainer(rVectorGraphicDataPtr->getPrimitive2DSequence());
148 if (rContainer.empty())
149 return;
151 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
152 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
154 aProcessor.process(rContainer);
156 const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
158 if (!pResult)
159 return;
161 OUString aName = pResult->getName();
162 OUString aTitle = pResult->getTitle();
163 OUString aDesc = pResult->getDesc();
165 if(!aName.isEmpty())
167 SetName(aName);
170 if(!aTitle.isEmpty())
172 SetTitle(aTitle);
175 if(!aDesc.isEmpty())
177 SetDescription(aDesc);
181 SdrGrafObj::SdrGrafObj(SdrModel& rSdrModel)
182 : SdrRectObj(rSdrModel)
183 ,mpGraphicObject(new GraphicObject)
184 ,pGraphicLink(nullptr)
185 ,bMirrored(false)
186 ,mbIsSignatureLine(false)
187 ,mbIsSignatureLineShowSignDate(true)
188 ,mbIsSignatureLineCanAddComment(false)
189 ,mbSignatureLineIsSigned(false)
191 onGraphicChanged();
193 // #i118485# Shear allowed and possible now
194 mbNoShear = false;
196 mbGrafAnimationAllowed = true;
198 // #i25616#
199 mbLineIsOutsideGeometry = true;
201 // #i25616#
202 mbSupportTextIndentingOnLineWidthChange = false;
205 SdrGrafObj::SdrGrafObj(SdrModel& rSdrModel, SdrGrafObj const & rSource)
206 : SdrRectObj(rSdrModel, rSource)
207 ,mpGraphicObject(new GraphicObject)
208 ,pGraphicLink(nullptr)
210 onGraphicChanged();
212 // #i118485# Shear allowed and possible now
213 mbNoShear = false;
215 mbGrafAnimationAllowed = true;
217 // #i25616#
218 mbLineIsOutsideGeometry = true;
220 // #i25616#
221 mbSupportTextIndentingOnLineWidthChange = false;
223 aFileName = rSource.aFileName;
224 bMirrored = rSource.bMirrored;
226 mbIsSignatureLine = rSource.mbIsSignatureLine;
227 maSignatureLineId = rSource.maSignatureLineId;
228 maSignatureLineSuggestedSignerName = rSource.maSignatureLineSuggestedSignerName;
229 maSignatureLineSuggestedSignerTitle = rSource.maSignatureLineSuggestedSignerTitle;
230 maSignatureLineSuggestedSignerEmail = rSource.maSignatureLineSuggestedSignerEmail;
231 maSignatureLineSigningInstructions = rSource.maSignatureLineSigningInstructions;
232 mbIsSignatureLineShowSignDate = rSource.mbIsSignatureLineShowSignDate;
233 mbIsSignatureLineCanAddComment = rSource.mbIsSignatureLineCanAddComment;
234 mbSignatureLineIsSigned = false;
235 mpSignatureLineUnsignedGraphic = rSource.mpSignatureLineUnsignedGraphic;
237 if(rSource.mpBarCode)
239 mpBarCode = std::make_unique<drawing::BarCode>(*rSource.mpBarCode);
241 else
243 mpBarCode.reset();
246 if (mbIsSignatureLine && rSource.mpSignatureLineUnsignedGraphic)
247 mpGraphicObject->SetGraphic(rSource.mpSignatureLineUnsignedGraphic);
248 else
249 mpGraphicObject->SetGraphic( rSource.GetGraphic() );
251 if( rSource.IsLinkedGraphic() )
253 SetGraphicLink( aFileName );
256 ImpSetAttrToGrafInfo();
259 SdrGrafObj::SdrGrafObj(
260 SdrModel& rSdrModel,
261 const Graphic& rGraphic,
262 const tools::Rectangle& rRect)
263 : SdrRectObj(rSdrModel, rRect)
264 ,mpGraphicObject(new GraphicObject(rGraphic))
265 ,pGraphicLink(nullptr)
266 ,bMirrored(false)
267 ,mbIsSignatureLine(false)
268 ,mbIsSignatureLineShowSignDate(true)
269 ,mbIsSignatureLineCanAddComment(false)
270 ,mbSignatureLineIsSigned(false)
272 onGraphicChanged();
274 // #i118485# Shear allowed and possible now
275 mbNoShear = false;
277 mbGrafAnimationAllowed = true;
279 // #i25616#
280 mbLineIsOutsideGeometry = true;
282 // #i25616#
283 mbSupportTextIndentingOnLineWidthChange = false;
286 SdrGrafObj::SdrGrafObj(
287 SdrModel& rSdrModel,
288 const Graphic& rGraphic)
289 : SdrRectObj(rSdrModel)
290 ,mpGraphicObject(new GraphicObject(rGraphic))
291 ,pGraphicLink(nullptr)
292 ,bMirrored(false)
293 ,mbIsSignatureLine(false)
294 ,mbIsSignatureLineShowSignDate(true)
295 ,mbIsSignatureLineCanAddComment(false)
296 ,mbSignatureLineIsSigned(false)
298 onGraphicChanged();
300 // #i118485# Shear allowed and possible now
301 mbNoShear = false;
303 mbGrafAnimationAllowed = true;
305 // #i25616#
306 mbLineIsOutsideGeometry = true;
308 // #i25616#
309 mbSupportTextIndentingOnLineWidthChange = false;
312 SdrGrafObj::~SdrGrafObj()
314 ImpDeregisterLink();
317 void SdrGrafObj::SetGraphicObject(const GraphicObject& rGraphicObject)
319 mpGraphicObject.reset(new GraphicObject(rGraphicObject));
320 mpReplacementGraphicObject.reset();
321 mpGraphicObject->SetUserData();
322 SetChanged();
323 BroadcastObjectChange();
324 onGraphicChanged();
327 const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const
329 if (bForceSwapIn)
330 ForceSwapIn();
331 return *mpGraphicObject;
334 const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const
336 if (!mpReplacementGraphicObject && mpGraphicObject)
338 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
340 if (rVectorGraphicDataPtr)
342 const_cast< SdrGrafObj* >(this)->mpReplacementGraphicObject.reset(new GraphicObject(rVectorGraphicDataPtr->getReplacement()));
344 else if (mpGraphicObject->GetGraphic().GetType() == GraphicType::GdiMetafile)
346 // Replacement graphic for PDF and metafiles is just the bitmap.
347 const_cast<SdrGrafObj*>(this)->mpReplacementGraphicObject.reset(new GraphicObject(mpGraphicObject->GetGraphic().GetBitmapEx()));
351 return mpReplacementGraphicObject.get();
354 void SdrGrafObj::NbcSetGraphic(const Graphic& rGraphic)
356 mpGraphicObject->SetGraphic(rGraphic);
357 mpReplacementGraphicObject.reset();
358 mpGraphicObject->SetUserData();
359 onGraphicChanged();
362 void SdrGrafObj::SetGraphic( const Graphic& rGraphic )
364 if (!rGraphic.getOriginURL().isEmpty())
366 ImpDeregisterLink();
367 aFileName = rGraphic.getOriginURL();
368 aFilterName = "";
370 NbcSetGraphic(rGraphic);
371 if (!rGraphic.getOriginURL().isEmpty())
373 ImpRegisterLink();
374 mpGraphicObject->SetUserData();
376 SetChanged();
377 BroadcastObjectChange();
378 ForceSwapIn();
381 const Graphic& SdrGrafObj::GetGraphic() const
383 return mpGraphicObject->GetGraphic();
386 Graphic SdrGrafObj::GetTransformedGraphic( SdrGrafObjTransformsAttrs nTransformFlags ) const
388 // Refactored most of the code to GraphicObject, where
389 // everybody can use e.g. the cropping functionality
390 MapMode aDestMap(getSdrModelFromSdrObject().GetScaleUnit());
391 const Size aDestSize( GetLogicRect().GetSize() );
392 GraphicAttr aActAttr = GetGraphicAttr(nTransformFlags);
394 // Delegate to moved code in GraphicObject
395 return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr );
398 GraphicType SdrGrafObj::GetGraphicType() const
400 return mpGraphicObject->GetType();
403 GraphicAttr SdrGrafObj::GetGraphicAttr( SdrGrafObjTransformsAttrs nTransformFlags ) const
405 GraphicAttr aActAttr;
407 GraphicType eType = GetGraphicType();
408 if( SdrGrafObjTransformsAttrs::NONE != nTransformFlags &&
409 GraphicType::NONE != eType )
411 const bool bMirror = bool( nTransformFlags & SdrGrafObjTransformsAttrs::MIRROR );
412 const bool bRotate = bool( nTransformFlags & SdrGrafObjTransformsAttrs::ROTATE ) &&
413 (maGeo.nRotationAngle && maGeo.nRotationAngle != 18000_deg100);
415 // Need cropping info earlier
416 const_cast<SdrGrafObj*>(this)->ImpSetAttrToGrafInfo();
418 // Actually transform the graphic only in this case.
419 // Cropping always happens, though.
420 aActAttr = aGrafInfo;
422 if( bMirror )
424 sal_uInt16 nMirrorCase = ( maGeo.nRotationAngle == 18000_deg100 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 );
425 bool bHMirr = nMirrorCase == 2 || nMirrorCase == 4;
426 bool bVMirr = nMirrorCase == 3 || nMirrorCase == 4;
428 aActAttr.SetMirrorFlags( ( bHMirr ? BmpMirrorFlags::Horizontal : BmpMirrorFlags::NONE ) | ( bVMirr ? BmpMirrorFlags::Vertical : BmpMirrorFlags::NONE ) );
431 if( bRotate )
432 aActAttr.SetRotation( to<Degree10>(maGeo.nRotationAngle ) );
435 return aActAttr;
438 bool SdrGrafObj::IsAnimated() const
440 return mpGraphicObject->IsAnimated();
443 bool SdrGrafObj::IsEPS() const
445 return mpGraphicObject->IsEPS();
448 MapMode SdrGrafObj::GetGrafPrefMapMode() const
450 return mpGraphicObject->GetPrefMapMode();
453 Size SdrGrafObj::GetGrafPrefSize() const
455 return mpGraphicObject->GetPrefSize();
458 void SdrGrafObj::SetGrafStreamURL( const OUString& rGraphicStreamURL )
460 if( rGraphicStreamURL.isEmpty() )
462 mpGraphicObject->SetUserData();
464 else if(getSdrModelFromSdrObject().IsSwapGraphics() )
466 mpGraphicObject->SetUserData( rGraphicStreamURL );
470 OUString const & SdrGrafObj::GetGrafStreamURL() const
472 return mpGraphicObject->GetUserData();
475 Size SdrGrafObj::getOriginalSize() const
477 Size aSize = GetGrafPrefSize();
479 if (GetGrafPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
480 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
481 else
482 aSize = OutputDevice::LogicToLogic(aSize, GetGrafPrefMapMode(), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
484 if (aGrafInfo.IsCropped())
486 const tools::Long aCroppedWidth(aSize.getWidth() - aGrafInfo.GetLeftCrop()
487 - aGrafInfo.GetRightCrop());
488 const tools::Long aCroppedHeight(aSize.getHeight() - aGrafInfo.GetTopCrop()
489 - aGrafInfo.GetBottomCrop());
491 aSize = Size(aCroppedWidth, aCroppedHeight);
494 return aSize;
497 // TODO Remove
498 void SdrGrafObj::ForceSwapIn() const
500 if (pGraphicLink && (mpGraphicObject->GetType() == GraphicType::NONE ||
501 mpGraphicObject->GetType() == GraphicType::Default) )
503 pGraphicLink->Update();
507 void SdrGrafObj::ImpRegisterLink()
509 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
511 if( pLinkManager != nullptr && pGraphicLink == nullptr )
513 if (!aFileName.isEmpty())
515 pGraphicLink = new SdrGraphicLink( *this );
516 pLinkManager->InsertFileLink(
517 *pGraphicLink, sfx2::SvBaseLinkObjectType::ClientGraphic, aFileName, (aFilterName.isEmpty() ? nullptr : &aFilterName));
518 pGraphicLink->Connect();
523 void SdrGrafObj::ImpDeregisterLink()
525 sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
527 if( pLinkManager != nullptr && pGraphicLink!=nullptr)
529 // When using Remove, the *pGraphicLink is implicitly deleted
530 pLinkManager->Remove( pGraphicLink );
531 pGraphicLink=nullptr;
535 void SdrGrafObj::SetGraphicLink(const OUString& rFileName)
537 Graphic aGraphic;
538 aGraphic.setOriginURL(rFileName);
539 SetGraphic(aGraphic);
542 void SdrGrafObj::ReleaseGraphicLink()
544 ImpDeregisterLink();
545 aFileName.clear();
546 aFilterName.clear();
548 auto aGraphic = mpGraphicObject->GetGraphic();
549 aGraphic.setOriginURL("");
550 SetGraphic(aGraphic);
553 bool SdrGrafObj::IsLinkedGraphic() const
555 return !mpGraphicObject->GetGraphic().getOriginURL().isEmpty();
558 void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
560 bool bNoPresGrf = ( mpGraphicObject->GetType() != GraphicType::NONE ) && !m_bEmptyPresObj;
562 rInfo.bResizeFreeAllowed = maGeo.nRotationAngle.get() % 9000 == 0 ||
563 maGeo.nRotationAngle.get() % 18000 == 0 ||
564 maGeo.nRotationAngle.get() % 27000 == 0;
566 rInfo.bResizePropAllowed = true;
567 rInfo.bRotateFreeAllowed = bNoPresGrf;
568 rInfo.bRotate90Allowed = bNoPresGrf;
569 rInfo.bMirrorFreeAllowed = bNoPresGrf;
570 rInfo.bMirror45Allowed = bNoPresGrf;
571 rInfo.bMirror90Allowed = !m_bEmptyPresObj;
572 rInfo.bTransparenceAllowed = false;
574 // #i118485# Shear allowed and possible now
575 rInfo.bShearAllowed = true;
577 rInfo.bEdgeRadiusAllowed=false;
578 rInfo.bCanConvToPath = !IsEPS();
579 rInfo.bCanConvToPathLineToArea = false;
580 rInfo.bCanConvToPolyLineToArea = false;
581 rInfo.bCanConvToPoly = !IsEPS();
582 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
585 SdrObjKind SdrGrafObj::GetObjIdentifier() const
587 return SdrObjKind::Graphic;
590 void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic )
592 const bool bIsChanged(getSdrModelFromSdrObject().IsChanged());
593 NbcSetGraphic( rGraphic );
594 ActionChanged();
595 BroadcastObjectChange();
596 getSdrModelFromSdrObject().SetChanged(bIsChanged);
599 OUString SdrGrafObj::TakeObjNameSingul() const
601 if (!mpGraphicObject)
602 return OUString();
604 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
606 OUStringBuffer sName;
608 if (rVectorGraphicDataPtr)
610 switch (rVectorGraphicDataPtr->getType())
612 case VectorGraphicDataType::Svg:
614 sName.append(SvxResId(STR_ObjNameSingulGRAFSVG));
615 break;
617 case VectorGraphicDataType::Wmf:
619 sName.append(SvxResId(STR_ObjNameSingulGRAFWMF));
620 break;
622 case VectorGraphicDataType::Emf:
624 sName.append(SvxResId(STR_ObjNameSingulGRAFEMF));
625 break;
627 case VectorGraphicDataType::Pdf:
629 sName.append(SvxResId(STR_ObjNameSingulGRAFPDF));
630 break;
632 } //no default, see tdf#137813
634 else
636 switch( mpGraphicObject->GetType() )
638 case GraphicType::Bitmap:
640 TranslateId pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
641 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) :
642 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) );
644 sName.append(SvxResId(pId));
646 break;
648 case GraphicType::GdiMetafile:
649 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF));
650 break;
652 case GraphicType::NONE:
653 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE));
654 break;
656 default:
657 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF));
658 break;
662 const OUString aName(GetName());
664 if (!aName.isEmpty())
666 sName.append(" '" + aName + "\'" );
669 return sName.makeStringAndClear();
672 OUString SdrGrafObj::TakeObjNamePlural() const
674 if (!mpGraphicObject)
675 return OUString();
677 auto const & rVectorGraphicDataPtr = mpGraphicObject->GetGraphic().getVectorGraphicData();
679 OUStringBuffer sName;
681 if (rVectorGraphicDataPtr)
683 switch (rVectorGraphicDataPtr->getType())
685 case VectorGraphicDataType::Svg:
687 sName.append(SvxResId(STR_ObjNamePluralGRAFSVG));
688 break;
690 case VectorGraphicDataType::Wmf:
692 sName.append(SvxResId(STR_ObjNamePluralGRAFWMF));
693 break;
695 case VectorGraphicDataType::Emf:
697 sName.append(SvxResId(STR_ObjNamePluralGRAFEMF));
698 break;
700 case VectorGraphicDataType::Pdf:
702 sName.append(SvxResId(STR_ObjNamePluralGRAFPDF));
703 break;
705 } //no default, see tdf#137813
707 else
709 switch(mpGraphicObject->GetType())
711 case GraphicType::Bitmap:
713 TranslateId pId = ( ( mpGraphicObject->IsTransparent() || GetObjectItem( SDRATTR_GRAFTRANSPARENCE ).GetValue() ) ?
714 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) :
715 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) );
717 sName.append(SvxResId(pId));
719 break;
721 case GraphicType::GdiMetafile:
722 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF));
723 break;
725 case GraphicType::NONE:
726 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE));
727 break;
729 default:
730 sName.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF));
731 break;
735 const OUString aName(GetName());
737 if (!aName.isEmpty())
739 sName.append(" '" + aName + "\'");
742 return sName.makeStringAndClear();
745 rtl::Reference<SdrObject> SdrGrafObj::getFullDragClone() const
747 // call parent
748 rtl::Reference<SdrObject> pRetval = SdrRectObj::getFullDragClone();
750 // #i103116# the full drag clone leads to problems
751 // with linked graphics, so reset the link in this
752 // temporary interaction object and load graphic
753 if(pRetval && IsLinkedGraphic())
755 static_cast< SdrGrafObj* >(pRetval.get())->ReleaseGraphicLink();
758 return pRetval;
761 rtl::Reference<SdrObject> SdrGrafObj::CloneSdrObject(SdrModel& rTargetModel) const
763 return new SdrGrafObj(rTargetModel, *this);
766 sal_uInt32 SdrGrafObj::GetHdlCount() const
768 return 8;
771 void SdrGrafObj::AddToHdlList(SdrHdlList& rHdlList) const
773 SdrHdlList tempList(nullptr);
774 SdrRectObj::AddToHdlList( tempList );
775 tempList.RemoveHdl(0);
776 tempList.MoveTo(rHdlList);
779 void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
781 SdrRectObj::NbcResize( rRef, xFact, yFact );
783 bool bMirrX = xFact.GetNumerator() < 0;
784 bool bMirrY = yFact.GetNumerator() < 0;
786 if( bMirrX != bMirrY )
787 bMirrored = !bMirrored;
790 void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2)
792 SdrRectObj::NbcMirror(rRef1,rRef2);
793 bMirrored = !bMirrored;
796 std::unique_ptr<SdrObjGeoData> SdrGrafObj::NewGeoData() const
798 return std::make_unique<SdrGrafObjGeoData>();
801 void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const
803 SdrRectObj::SaveGeoData(rGeo);
804 SdrGrafObjGeoData& rGGeo=static_cast<SdrGrafObjGeoData&>(rGeo);
805 rGGeo.bMirrored=bMirrored;
808 void SdrGrafObj::RestoreGeoData(const SdrObjGeoData& rGeo)
810 SdrRectObj::RestoreGeoData(rGeo);
811 const SdrGrafObjGeoData& rGGeo=static_cast<const SdrGrafObjGeoData&>(rGeo);
812 bMirrored=rGGeo.bMirrored;
815 void SdrGrafObj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
817 const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
818 const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
820 if( bRemove )
822 // No SwapIn necessary here, because if something's not loaded, it can't be animated either.
823 if( mpGraphicObject->IsAnimated())
824 mpGraphicObject->StopAnimation();
826 if( pGraphicLink != nullptr )
827 ImpDeregisterLink();
830 // call parent
831 SdrRectObj::handlePageChange(pOldPage, pNewPage);
833 if (!aFileName.isEmpty() && bInsert)
835 ImpRegisterLink();
839 void SdrGrafObj::StartAnimation()
841 SetGrafAnimationAllowed(true);
844 bool SdrGrafObj::HasGDIMetaFile() const
846 return( mpGraphicObject->GetType() == GraphicType::GdiMetafile );
849 bool SdrGrafObj::isEmbeddedVectorGraphicData() const
851 return GraphicType::Bitmap == GetGraphicType() && GetGraphic().getVectorGraphicData();
854 GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedVectorGraphicData() const
856 GDIMetaFile aRetval;
858 if(isEmbeddedVectorGraphicData())
860 ScopedVclPtrInstance< VirtualDevice > pOut;
861 const tools::Rectangle aBoundRect(GetCurrentBoundRect());
862 const MapMode aMap(getSdrModelFromSdrObject().GetScaleUnit());
864 pOut->EnableOutput(false);
865 pOut->SetMapMode(aMap);
866 aRetval.Record(pOut);
867 SingleObjectPainter(*pOut);
868 aRetval.Stop();
869 aRetval.WindStart();
870 aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top());
871 aRetval.SetPrefMapMode(aMap);
872 aRetval.SetPrefSize(aBoundRect.GetSize());
875 return aRetval;
878 GDIMetaFile SdrGrafObj::GetMetaFile(GraphicType &rGraphicType) const
880 if (isEmbeddedVectorGraphicData())
882 // Embedded Vector Graphic Data
883 // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
884 // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
885 // use the old converter path over the MetaFile mechanism. Create Metafile from Svg
886 // primitives here pretty directly
887 rGraphicType = GraphicType::GdiMetafile;
888 return getMetafileFromEmbeddedVectorGraphicData();
890 else if (GraphicType::GdiMetafile == rGraphicType)
892 return GetTransformedGraphic(SdrGrafObjTransformsAttrs::MIRROR).GetGDIMetaFile();
894 return GDIMetaFile();
897 rtl::Reference<SdrObject> SdrGrafObj::DoConvertToPolyObj(bool bBezier, bool bAddText ) const
899 rtl::Reference<SdrObject> pRetval;
900 GraphicType aGraphicType(GetGraphicType());
901 GDIMetaFile aMtf(GetMetaFile(aGraphicType));
902 switch(aGraphicType)
904 case GraphicType::GdiMetafile:
906 // Sort into group and return ONLY those objects that can be created from the MetaFile.
907 ImpSdrGDIMetaFileImport aFilter(
908 getSdrModelFromSdrObject(),
909 GetLayer(),
910 getRectangle());
911 rtl::Reference<SdrObjGroup> pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
913 if(aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0))
916 // copy transformation
917 GeoStat aGeoStat(GetGeoStat());
919 if(aGeoStat.nShearAngle)
921 aGeoStat.RecalcTan();
922 pGrp->NbcShear(getRectangle().TopLeft(), aGeoStat.nShearAngle, aGeoStat.mfTanShearAngle, false);
925 if(aGeoStat.nRotationAngle)
927 aGeoStat.RecalcSinCos();
928 pGrp->NbcRotate(getRectangle().TopLeft(), aGeoStat.nRotationAngle, aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle);
932 pRetval = pGrp;
933 pGrp->NbcSetLayer(GetLayer());
935 if(bAddText)
937 pRetval = ImpConvertAddText(pRetval, bBezier);
940 // convert all children
941 if( pRetval )
943 pRetval = pRetval->DoConvertToPolyObj(bBezier, bAddText);
945 if( pRetval )
947 // flatten subgroups. As we call
948 // DoConvertToPolyObj() on the resulting group
949 // objects, subgroups can exist (e.g. text is
950 // a group object for every line).
951 SdrObjList* pList = pRetval->GetSubList();
952 if( pList )
953 pList->FlattenGroups();
957 else
958 pGrp.clear();
960 // #i118485# convert line and fill
961 rtl::Reference<SdrObject> pLineFill = SdrRectObj::DoConvertToPolyObj(bBezier, false);
963 if(pLineFill)
965 if(pRetval)
967 pGrp = dynamic_cast< SdrObjGroup* >(pRetval.get());
969 if(!pGrp)
971 pGrp = new SdrObjGroup(getSdrModelFromSdrObject());
972 pGrp->NbcSetLayer(GetLayer());
973 pGrp->GetSubList()->NbcInsertObject(pRetval.get());
976 pGrp->GetSubList()->NbcInsertObject(pLineFill.get(), 0);
978 else
980 pRetval = pLineFill;
984 break;
986 case GraphicType::Bitmap:
988 // create basic object and add fill
989 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
991 // save bitmap as an attribute
992 if(pRetval)
994 // retrieve bitmap for the fill
995 SfxItemSet aSet(GetObjectItemSet());
997 aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
998 const BitmapEx aBitmapEx(GetTransformedGraphic().GetBitmapEx());
999 aSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
1000 aSet.Put(XFillBmpTileItem(false));
1002 pRetval->SetMergedItemSet(aSet);
1004 break;
1006 case GraphicType::NONE:
1007 case GraphicType::Default:
1009 pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
1010 break;
1014 return pRetval;
1017 void SdrGrafObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1019 SetXPolyDirty();
1020 SdrRectObj::Notify( rBC, rHint );
1021 ImpSetAttrToGrafInfo();
1025 void SdrGrafObj::SetMirrored( bool _bMirrored )
1027 bMirrored = _bMirrored;
1030 void SdrGrafObj::ImpSetAttrToGrafInfo()
1032 const SfxItemSet& rSet = GetObjectItemSet();
1033 const sal_uInt16 nTrans = rSet.Get( SDRATTR_GRAFTRANSPARENCE ).GetValue();
1034 const SdrGrafCropItem& rCrop = rSet.Get( SDRATTR_GRAFCROP );
1036 aGrafInfo.SetLuminance( rSet.Get( SDRATTR_GRAFLUMINANCE ).GetValue() );
1037 aGrafInfo.SetContrast( rSet.Get( SDRATTR_GRAFCONTRAST ).GetValue() );
1038 aGrafInfo.SetChannelR( rSet.Get( SDRATTR_GRAFRED ).GetValue() );
1039 aGrafInfo.SetChannelG( rSet.Get( SDRATTR_GRAFGREEN ).GetValue() );
1040 aGrafInfo.SetChannelB( rSet.Get( SDRATTR_GRAFBLUE ).GetValue() );
1041 aGrafInfo.SetGamma( rSet.Get( SDRATTR_GRAFGAMMA ).GetValue() * 0.01 );
1042 aGrafInfo.SetAlpha( 255 - static_cast<sal_uInt8>(FRound( std::min( nTrans, sal_uInt16(100) ) * 2.55 )) );
1043 aGrafInfo.SetInvert( rSet.Get( SDRATTR_GRAFINVERT ).GetValue() );
1044 aGrafInfo.SetDrawMode( rSet.Get( SDRATTR_GRAFMODE ).GetValue() );
1045 aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() );
1047 SetXPolyDirty();
1048 SetBoundAndSnapRectsDirty();
1051 void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly )
1053 Size aSize;
1054 Size aMaxSize( rMaxRect.GetSize() );
1055 if (mpGraphicObject->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
1056 aSize = Application::GetDefaultDevice()->PixelToLogic(mpGraphicObject->GetPrefSize(), MapMode(MapUnit::Map100thMM));
1057 else
1058 aSize = OutputDevice::LogicToLogic( mpGraphicObject->GetPrefSize(),
1059 mpGraphicObject->GetPrefMapMode(),
1060 MapMode( MapUnit::Map100thMM ) );
1062 if( aSize.IsEmpty() )
1063 return;
1065 Point aPos( rMaxRect.TopLeft() );
1067 // if the graphic is too large, fit it to page
1068 if ( (!bShrinkOnly ||
1069 ( aSize.Height() > aMaxSize.Height() ) ||
1070 ( aSize.Width() > aMaxSize.Width() ) )&&
1071 aSize.Height() && aMaxSize.Height() )
1073 float fGrfWH = static_cast<float>(aSize.Width()) /
1074 static_cast<float>(aSize.Height());
1075 float fWinWH = static_cast<float>(aMaxSize.Width()) /
1076 static_cast<float>(aMaxSize.Height());
1078 // Scale graphic to page size
1079 if ( fGrfWH < fWinWH )
1081 aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
1082 aSize.setHeight( aMaxSize.Height() );
1084 else if ( fGrfWH > 0.F )
1086 aSize.setWidth( aMaxSize.Width() );
1087 aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
1090 aPos = rMaxRect.Center();
1093 if( bShrinkOnly )
1094 aPos = getRectangle().TopLeft();
1096 aPos.AdjustX( -(aSize.Width() / 2) );
1097 aPos.AdjustY( -(aSize.Height() / 2) );
1098 SetLogicRect( tools::Rectangle( aPos, aSize ) );
1101 void SdrGrafObj::SetGrafAnimationAllowed(bool bNew)
1103 if(mbGrafAnimationAllowed != bNew)
1105 mbGrafAnimationAllowed = bNew;
1106 ActionChanged();
1110 uno::Reference<io::XInputStream> SdrGrafObj::getInputStream() const
1112 uno::Reference<io::XInputStream> xStream;
1114 if (mpGraphicObject && GetGraphic().IsGfxLink())
1116 Graphic aGraphic( GetGraphic() );
1117 GfxLink aLink( aGraphic.GetGfxLink() );
1118 sal_uInt32 nSize = aLink.GetDataSize();
1119 const void* pSourceData = static_cast<const void*>(aLink.GetData());
1120 if( nSize && pSourceData )
1122 sal_uInt8 * pBuffer = new sal_uInt8[ nSize ];
1123 memcpy( pBuffer, pSourceData, nSize );
1125 SvMemoryStream* pStream = new SvMemoryStream( static_cast<void*>(pBuffer), static_cast<std::size_t>(nSize), StreamMode::READ );
1126 pStream->ObjectOwnsMemory( true );
1127 xStream.set( new utl::OInputStreamWrapper( pStream, true ) );
1131 if (!xStream.is() && !aFileName.isEmpty())
1133 SvFileStream* pStream = new SvFileStream( aFileName, StreamMode::READ );
1134 xStream.set( new utl::OInputStreamWrapper( pStream ) );
1137 return xStream;
1140 // moved crop handle creation here; this is the object type using them
1141 void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
1143 basegfx::B2DHomMatrix aMatrix;
1144 basegfx::B2DPolyPolygon aPolyPolygon;
1146 // get object transformation
1147 TRGetBaseGeometry(aMatrix, aPolyPolygon);
1149 // part of object transformation correction, but used later, so defined outside next scope
1150 double fShearX(0.0), fRotate(0.0);
1152 { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
1153 basegfx::B2DTuple aScale;
1154 basegfx::B2DTuple aTranslate;
1156 aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1158 if(!basegfx::fTools::equalZero(fShearX))
1160 // shearX is used, correct it
1161 fShearX = -fShearX;
1164 aMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
1165 aScale,
1166 fShearX,
1167 fRotate,
1168 aTranslate);
1171 // get crop values
1172 const SdrGrafCropItem& rCrop = GetMergedItem(SDRATTR_GRAFCROP);
1174 if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom())
1176 // decompose object transformation to have current translate and scale
1177 basegfx::B2DVector aScale, aTranslate;
1178 double fLclRotate, fLclShearX;
1180 aMatrix.decompose(aScale, aTranslate, fLclRotate, fLclShearX);
1182 if(!aScale.equalZero())
1184 // get crop scale
1185 const basegfx::B2DVector aCropScaleFactor(
1186 GetGraphicObject().calculateCropScaling(
1187 aScale.getX(),
1188 aScale.getY(),
1189 rCrop.GetLeft(),
1190 rCrop.GetTop(),
1191 rCrop.GetRight(),
1192 rCrop.GetBottom()));
1194 // apply crop scale
1195 const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX());
1196 const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY());
1197 const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX());
1198 const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY());
1199 basegfx::B2DHomMatrix aMatrixForCropViewHdl(aMatrix);
1201 if(IsMirrored())
1203 // create corrected new matrix, TTTT can be removed with aw080
1204 // the old mirror only can mirror horizontally; the vertical mirror
1205 // is faked by using the horizontal and 180 degree rotation. Since
1206 // the object can be rotated differently from 180 degree, this is
1207 // not safe to detect. Just correct horizontal mirror (which is
1208 // in IsMirrored()) and keep the rotation angle
1209 // caution: Do not modify aMatrix, it is used below to calculate
1210 // the exact handle positions
1211 basegfx::B2DHomMatrix aPreMultiply;
1213 // mirrored X, apply
1214 aPreMultiply.translate(-0.5, 0.0);
1215 aPreMultiply.scale(-1.0, 1.0);
1216 aPreMultiply.translate(0.5, 0.0);
1218 aMatrixForCropViewHdl = aMatrixForCropViewHdl * aPreMultiply;
1221 rTarget.AddHdl(
1222 std::make_unique<SdrCropViewHdl>(
1223 aMatrixForCropViewHdl,
1224 GetGraphicObject().GetGraphic(),
1225 fCropLeft,
1226 fCropTop,
1227 fCropRight,
1228 fCropBottom));
1232 basegfx::B2DPoint aPos;
1234 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.0);
1235 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperLeft, fShearX, fRotate));
1236 aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0);
1237 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Upper, fShearX, fRotate));
1238 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0);
1239 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperRight, fShearX, fRotate));
1240 aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5);
1241 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Left , fShearX, fRotate));
1242 aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5);
1243 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Right, fShearX, fRotate));
1244 aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0);
1245 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerLeft, fShearX, fRotate));
1246 aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0);
1247 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Lower, fShearX, fRotate));
1248 aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0);
1249 rTarget.AddHdl(std::make_unique<SdrCropHdl>(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
1252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */