1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
57 using namespace ::com::sun::star
;
59 class SdrGraphicLink
: public sfx2::SvBaseLink
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
)
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
);
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();
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())
135 auto const & rVectorGraphicDataPtr
= mpGraphicObject
->GetGraphic().getVectorGraphicData();
137 if (!rVectorGraphicDataPtr
)
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
)
146 const std::deque
<uno::Reference
<graphic::XPrimitive2D
>>& rContainer(rVectorGraphicDataPtr
->getPrimitive2DSequence());
148 if (rContainer
.empty())
151 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
152 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D
aProcessor(aViewInformation2D
);
154 aProcessor
.process(rContainer
);
156 const drawinglayer::primitive2d::ObjectInfoPrimitive2D
* pResult
= aProcessor
.getResult();
161 OUString aName
= pResult
->getName();
162 OUString aTitle
= pResult
->getTitle();
163 OUString aDesc
= pResult
->getDesc();
170 if(!aTitle
.isEmpty())
177 SetDescription(aDesc
);
181 SdrGrafObj::SdrGrafObj(SdrModel
& rSdrModel
)
182 : SdrRectObj(rSdrModel
)
183 ,mpGraphicObject(new GraphicObject
)
184 ,pGraphicLink(nullptr)
186 ,mbIsSignatureLine(false)
187 ,mbIsSignatureLineShowSignDate(true)
188 ,mbIsSignatureLineCanAddComment(false)
189 ,mbSignatureLineIsSigned(false)
193 // #i118485# Shear allowed and possible now
196 mbGrafAnimationAllowed
= true;
199 mbLineIsOutsideGeometry
= true;
202 mbSupportTextIndentingOnLineWidthChange
= false;
205 SdrGrafObj::SdrGrafObj(SdrModel
& rSdrModel
, SdrGrafObj
const & rSource
)
206 : SdrRectObj(rSdrModel
, rSource
)
207 ,mpGraphicObject(new GraphicObject
)
208 ,pGraphicLink(nullptr)
212 // #i118485# Shear allowed and possible now
215 mbGrafAnimationAllowed
= true;
218 mbLineIsOutsideGeometry
= true;
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
);
246 if (mbIsSignatureLine
&& rSource
.mpSignatureLineUnsignedGraphic
)
247 mpGraphicObject
->SetGraphic(rSource
.mpSignatureLineUnsignedGraphic
);
249 mpGraphicObject
->SetGraphic( rSource
.GetGraphic() );
251 if( rSource
.IsLinkedGraphic() )
253 SetGraphicLink( aFileName
);
256 ImpSetAttrToGrafInfo();
259 SdrGrafObj::SdrGrafObj(
261 const Graphic
& rGraphic
,
262 const tools::Rectangle
& rRect
)
263 : SdrRectObj(rSdrModel
, rRect
)
264 ,mpGraphicObject(new GraphicObject(rGraphic
))
265 ,pGraphicLink(nullptr)
267 ,mbIsSignatureLine(false)
268 ,mbIsSignatureLineShowSignDate(true)
269 ,mbIsSignatureLineCanAddComment(false)
270 ,mbSignatureLineIsSigned(false)
274 // #i118485# Shear allowed and possible now
277 mbGrafAnimationAllowed
= true;
280 mbLineIsOutsideGeometry
= true;
283 mbSupportTextIndentingOnLineWidthChange
= false;
286 SdrGrafObj::SdrGrafObj(
288 const Graphic
& rGraphic
)
289 : SdrRectObj(rSdrModel
)
290 ,mpGraphicObject(new GraphicObject(rGraphic
))
291 ,pGraphicLink(nullptr)
293 ,mbIsSignatureLine(false)
294 ,mbIsSignatureLineShowSignDate(true)
295 ,mbIsSignatureLineCanAddComment(false)
296 ,mbSignatureLineIsSigned(false)
300 // #i118485# Shear allowed and possible now
303 mbGrafAnimationAllowed
= true;
306 mbLineIsOutsideGeometry
= true;
309 mbSupportTextIndentingOnLineWidthChange
= false;
312 SdrGrafObj::~SdrGrafObj()
317 void SdrGrafObj::SetGraphicObject(const GraphicObject
& rGraphicObject
)
319 mpGraphicObject
.reset(new GraphicObject(rGraphicObject
));
320 mpReplacementGraphicObject
.reset();
321 mpGraphicObject
->SetUserData();
323 BroadcastObjectChange();
327 const GraphicObject
& SdrGrafObj::GetGraphicObject(bool bForceSwapIn
) const
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();
362 void SdrGrafObj::SetGraphic( const Graphic
& rGraphic
)
364 if (!rGraphic
.getOriginURL().isEmpty())
367 aFileName
= rGraphic
.getOriginURL();
370 NbcSetGraphic(rGraphic
);
371 if (!rGraphic
.getOriginURL().isEmpty())
374 mpGraphicObject
->SetUserData();
377 BroadcastObjectChange();
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
;
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
) );
432 aActAttr
.SetRotation( to
<Degree10
>(maGeo
.nRotationAngle
) );
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()));
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
);
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
)
538 aGraphic
.setOriginURL(rFileName
);
539 SetGraphic(aGraphic
);
542 void SdrGrafObj::ReleaseGraphicLink()
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
);
595 BroadcastObjectChange();
596 getSdrModelFromSdrObject().SetChanged(bIsChanged
);
599 OUString
SdrGrafObj::TakeObjNameSingul() const
601 if (!mpGraphicObject
)
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
));
617 case VectorGraphicDataType::Wmf
:
619 sName
.append(SvxResId(STR_ObjNameSingulGRAFWMF
));
622 case VectorGraphicDataType::Emf
:
624 sName
.append(SvxResId(STR_ObjNameSingulGRAFEMF
));
627 case VectorGraphicDataType::Pdf
:
629 sName
.append(SvxResId(STR_ObjNameSingulGRAFPDF
));
632 } //no default, see tdf#137813
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
));
648 case GraphicType::GdiMetafile
:
649 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK
: STR_ObjNameSingulGRAFMTF
));
652 case GraphicType::NONE
:
653 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK
: STR_ObjNameSingulGRAFNONE
));
657 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK
: STR_ObjNameSingulGRAF
));
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
)
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
));
690 case VectorGraphicDataType::Wmf
:
692 sName
.append(SvxResId(STR_ObjNamePluralGRAFWMF
));
695 case VectorGraphicDataType::Emf
:
697 sName
.append(SvxResId(STR_ObjNamePluralGRAFEMF
));
700 case VectorGraphicDataType::Pdf
:
702 sName
.append(SvxResId(STR_ObjNamePluralGRAFPDF
));
705 } //no default, see tdf#137813
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
));
721 case GraphicType::GdiMetafile
:
722 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK
: STR_ObjNamePluralGRAFMTF
));
725 case GraphicType::NONE
:
726 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK
: STR_ObjNamePluralGRAFNONE
));
730 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK
: STR_ObjNamePluralGRAF
));
735 const OUString
aName(GetName());
737 if (!aName
.isEmpty())
739 sName
.append(" '" + aName
+ "\'");
742 return sName
.makeStringAndClear();
745 rtl::Reference
<SdrObject
> SdrGrafObj::getFullDragClone() const
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();
761 rtl::Reference
<SdrObject
> SdrGrafObj::CloneSdrObject(SdrModel
& rTargetModel
) const
763 return new SdrGrafObj(rTargetModel
, *this);
766 sal_uInt32
SdrGrafObj::GetHdlCount() const
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);
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 )
831 SdrRectObj::handlePageChange(pOldPage
, pNewPage
);
833 if (!aFileName
.isEmpty() && bInsert
)
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
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
);
870 aRetval
.Move(-aBoundRect
.Left(), -aBoundRect
.Top());
871 aRetval
.SetPrefMapMode(aMap
);
872 aRetval
.SetPrefSize(aBoundRect
.GetSize());
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
));
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(),
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
);
933 pGrp
->NbcSetLayer(GetLayer());
937 pRetval
= ImpConvertAddText(pRetval
, bBezier
);
940 // convert all children
943 pRetval
= pRetval
->DoConvertToPolyObj(bBezier
, bAddText
);
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();
953 pList
->FlattenGroups();
960 // #i118485# convert line and fill
961 rtl::Reference
<SdrObject
> pLineFill
= SdrRectObj::DoConvertToPolyObj(bBezier
, false);
967 pGrp
= dynamic_cast< SdrObjGroup
* >(pRetval
.get());
971 pGrp
= new SdrObjGroup(getSdrModelFromSdrObject());
972 pGrp
->NbcSetLayer(GetLayer());
973 pGrp
->GetSubList()->NbcInsertObject(pRetval
.get());
976 pGrp
->GetSubList()->NbcInsertObject(pLineFill
.get(), 0);
986 case GraphicType::Bitmap
:
988 // create basic object and add fill
989 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
991 // save bitmap as an attribute
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
);
1006 case GraphicType::NONE
:
1007 case GraphicType::Default
:
1009 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
1017 void SdrGrafObj::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
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() );
1048 SetBoundAndSnapRectsDirty();
1051 void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool bShrinkOnly
)
1054 Size
aMaxSize( rMaxRect
.GetSize() );
1055 if (mpGraphicObject
->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
1056 aSize
= Application::GetDefaultDevice()->PixelToLogic(mpGraphicObject
->GetPrefSize(), MapMode(MapUnit::Map100thMM
));
1058 aSize
= OutputDevice::LogicToLogic( mpGraphicObject
->GetPrefSize(),
1059 mpGraphicObject
->GetPrefMapMode(),
1060 MapMode( MapUnit::Map100thMM
) );
1062 if( aSize
.IsEmpty() )
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();
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
;
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
) );
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
1164 aMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
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())
1185 const basegfx::B2DVector
aCropScaleFactor(
1186 GetGraphicObject().calculateCropScaling(
1192 rCrop
.GetBottom()));
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
);
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
;
1222 std::make_unique
<SdrCropViewHdl
>(
1223 aMatrixForCropViewHdl
,
1224 GetGraphicObject().GetGraphic(),
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: */