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
;
58 using namespace ::com::sun::star::uno
;
59 using namespace ::com::sun::star::io
;
61 class SdrGraphicLink
: public sfx2::SvBaseLink
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
)
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
);
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();
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())
137 auto const & rVectorGraphicDataPtr
= mpGraphicObject
->GetGraphic().getVectorGraphicData();
139 if (!rVectorGraphicDataPtr
)
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
)
148 const drawinglayer::primitive2d::Primitive2DContainer
aSequence(rVectorGraphicDataPtr
->getPrimitive2DSequence());
150 if (aSequence
.empty())
153 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
154 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D
aProcessor(aViewInformation2D
);
156 aProcessor
.process(aSequence
);
158 const drawinglayer::primitive2d::ObjectInfoPrimitive2D
* pResult
= aProcessor
.getResult();
163 OUString aName
= pResult
->getName();
164 OUString aTitle
= pResult
->getTitle();
165 OUString aDesc
= pResult
->getDesc();
172 if(!aTitle
.isEmpty())
179 SetDescription(aDesc
);
183 SdrGrafObj::SdrGrafObj(SdrModel
& rSdrModel
)
184 : SdrRectObj(rSdrModel
)
185 ,mpGraphicObject(new GraphicObject
)
186 ,pGraphicLink(nullptr)
188 ,mbIsSignatureLine(false)
189 ,mbIsSignatureLineShowSignDate(true)
190 ,mbIsSignatureLineCanAddComment(false)
191 ,mbSignatureLineIsSigned(false)
195 // #i118485# Shear allowed and possible now
198 mbGrafAnimationAllowed
= true;
201 mbLineIsOutsideGeometry
= true;
204 mbSupportTextIndentingOnLineWidthChange
= false;
207 SdrGrafObj::SdrGrafObj(
209 const Graphic
& rGraphic
,
210 const tools::Rectangle
& rRect
)
211 : SdrRectObj(rSdrModel
, rRect
)
212 ,mpGraphicObject(new GraphicObject(rGraphic
))
213 ,pGraphicLink(nullptr)
215 ,mbIsSignatureLine(false)
216 ,mbIsSignatureLineShowSignDate(true)
217 ,mbIsSignatureLineCanAddComment(false)
218 ,mbSignatureLineIsSigned(false)
222 // #i118485# Shear allowed and possible now
225 mbGrafAnimationAllowed
= true;
228 mbLineIsOutsideGeometry
= true;
231 mbSupportTextIndentingOnLineWidthChange
= false;
234 SdrGrafObj::SdrGrafObj(
236 const Graphic
& rGraphic
)
237 : SdrRectObj(rSdrModel
)
238 ,mpGraphicObject(new GraphicObject(rGraphic
))
239 ,pGraphicLink(nullptr)
241 ,mbIsSignatureLine(false)
242 ,mbIsSignatureLineShowSignDate(true)
243 ,mbIsSignatureLineCanAddComment(false)
244 ,mbSignatureLineIsSigned(false)
248 // #i118485# Shear allowed and possible now
251 mbGrafAnimationAllowed
= true;
254 mbLineIsOutsideGeometry
= true;
257 mbSupportTextIndentingOnLineWidthChange
= false;
260 SdrGrafObj::~SdrGrafObj()
265 void SdrGrafObj::SetGraphicObject(const GraphicObject
& rGraphicObject
)
267 mpGraphicObject
.reset(new GraphicObject(rGraphicObject
));
268 mpReplacementGraphicObject
.reset();
269 mpGraphicObject
->SetUserData();
271 BroadcastObjectChange();
275 const GraphicObject
& SdrGrafObj::GetGraphicObject(bool bForceSwapIn
) const
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();
310 void SdrGrafObj::SetGraphic( const Graphic
& rGraphic
)
312 if (!rGraphic
.getOriginURL().isEmpty())
315 aFileName
= rGraphic
.getOriginURL();
318 NbcSetGraphic(rGraphic
);
319 if (!rGraphic
.getOriginURL().isEmpty())
322 mpGraphicObject
->SetUserData();
325 BroadcastObjectChange();
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
339 getSdrModelFromSdrObject().GetScaleUnit(),
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
;
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
) );
384 aActAttr
.SetRotation( Degree10(aGeo
.nRotationAngle
/ 10) );
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()));
446 aSize
= OutputDevice::LogicToLogic(aSize
, GetGrafPrefMapMode(), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
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
)
492 aGraphic
.setOriginURL(rFileName
);
493 SetGraphic(aGraphic
);
496 void SdrGrafObj::ReleaseGraphicLink()
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
544 void SdrGrafObj::ImpSetLinkedGraphic( const Graphic
& rGraphic
)
546 const bool bIsChanged(getSdrModelFromSdrObject().IsChanged());
547 NbcSetGraphic( rGraphic
);
549 BroadcastObjectChange();
550 getSdrModelFromSdrObject().SetChanged(bIsChanged
);
553 OUString
SdrGrafObj::TakeObjNameSingul() const
555 if (!mpGraphicObject
)
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
));
571 case VectorGraphicDataType::Wmf
:
573 sName
.append(SvxResId(STR_ObjNameSingulGRAFWMF
));
576 case VectorGraphicDataType::Emf
:
578 sName
.append(SvxResId(STR_ObjNameSingulGRAFEMF
));
581 case VectorGraphicDataType::Pdf
:
583 sName
.append(SvxResId(STR_ObjNameSingulGRAFPDF
));
586 } //no default, see tdf#137813
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
));
602 case GraphicType::GdiMetafile
:
603 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK
: STR_ObjNameSingulGRAFMTF
));
606 case GraphicType::NONE
:
607 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK
: STR_ObjNameSingulGRAFNONE
));
611 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK
: STR_ObjNameSingulGRAF
));
616 const OUString
aName(GetName());
618 if (!aName
.isEmpty())
625 return sName
.makeStringAndClear();
628 OUString
SdrGrafObj::TakeObjNamePlural() const
630 if (!mpGraphicObject
)
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
));
646 case VectorGraphicDataType::Wmf
:
648 sName
.append(SvxResId(STR_ObjNamePluralGRAFWMF
));
651 case VectorGraphicDataType::Emf
:
653 sName
.append(SvxResId(STR_ObjNamePluralGRAFEMF
));
656 case VectorGraphicDataType::Pdf
:
658 sName
.append(SvxResId(STR_ObjNamePluralGRAFPDF
));
661 } //no default, see tdf#137813
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
));
677 case GraphicType::GdiMetafile
:
678 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK
: STR_ObjNamePluralGRAFMTF
));
681 case GraphicType::NONE
:
682 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK
: STR_ObjNamePluralGRAFNONE
));
686 sName
.append(SvxResId(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK
: STR_ObjNamePluralGRAF
));
691 const OUString
aName(GetName());
693 if (!aName
.isEmpty())
700 return sName
.makeStringAndClear();
703 SdrObjectUniquePtr
SdrGrafObj::getFullDragClone() const
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();
719 SdrGrafObj
* SdrGrafObj::CloneSdrObject(SdrModel
& rTargetModel
) const
721 return CloneHelper
< SdrGrafObj
>(rTargetModel
);
724 SdrGrafObj
& SdrGrafObj::operator=( const SdrGrafObj
& rObj
)
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
;
746 mpQrCode
= std::make_unique
<css::drawing::QRCode
>(*rObj
.mpQrCode
);
753 if (mbIsSignatureLine
&& rObj
.mpSignatureLineUnsignedGraphic
)
754 mpGraphicObject
->SetGraphic(rObj
.mpSignatureLineUnsignedGraphic
);
756 mpGraphicObject
->SetGraphic( rObj
.GetGraphic() );
758 if( rObj
.IsLinkedGraphic() )
760 SetGraphicLink( aFileName
);
763 ImpSetAttrToGrafInfo();
767 sal_uInt32
SdrGrafObj::GetHdlCount() const
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);
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 )
832 SdrRectObj::handlePageChange(pOldPage
, pNewPage
);
834 if (!aFileName
.isEmpty() && bInsert
)
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
859 if(isEmbeddedVectorGraphicData())
861 ScopedVclPtrInstance
< VirtualDevice
> pOut
;
862 const tools::Rectangle
aBoundRect(GetCurrentBoundRect());
864 getSdrModelFromSdrObject().GetScaleUnit(),
866 getSdrModelFromSdrObject().GetScaleFraction(),
867 getSdrModelFromSdrObject().GetScaleFraction());
869 pOut
->EnableOutput(false);
870 pOut
->SetMapMode(aMap
);
871 aRetval
.Record(pOut
);
872 SingleObjectPainter(*pOut
);
875 aRetval
.Move(-aBoundRect
.Left(), -aBoundRect
.Top());
876 aRetval
.SetPrefMapMode(aMap
);
877 aRetval
.SetPrefSize(aBoundRect
.GetSize());
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
));
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(),
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
);
938 pGrp
->NbcSetLayer(GetLayer());
942 pRetval
= ImpConvertAddText(SdrObjectUniquePtr(pRetval
), bBezier
).release();
945 // convert all children
948 SdrObject
* pHalfDone
= pRetval
;
949 pRetval
= pRetval
->DoConvertToPolyObj(bBezier
, bAddText
).release();
950 SdrObject::Free( pHalfDone
); // resulting object is newly created
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();
960 pList
->FlattenGroups();
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);
978 pGrp
= dynamic_cast< SdrObjGroup
* >(pRetval
);
982 pGrp
= new SdrObjGroup(getSdrModelFromSdrObject());
983 pGrp
->NbcSetLayer(GetLayer());
984 pGrp
->GetSubList()->NbcInsertObject(pRetval
);
987 pGrp
->GetSubList()->NbcInsertObject(pLineFill
.release(), 0);
991 pRetval
= pLineFill
.release();
997 case GraphicType::Bitmap
:
999 // create basic object and add fill
1000 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
).release();
1002 // save bitmap as an attribute
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
);
1017 case GraphicType::NONE
:
1018 case GraphicType::Default
:
1020 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
).release();
1025 return SdrObjectUniquePtr(pRetval
);
1028 void SdrGrafObj::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
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() );
1062 void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool bShrinkOnly
)
1065 Size
aMaxSize( rMaxRect
.GetSize() );
1066 if (mpGraphicObject
->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
1067 aSize
= Application::GetDefaultDevice()->PixelToLogic(mpGraphicObject
->GetPrefSize(), MapMode(MapUnit::Map100thMM
));
1069 aSize
= OutputDevice::LogicToLogic( mpGraphicObject
->GetPrefSize(),
1070 mpGraphicObject
->GetPrefMapMode(),
1071 MapMode( MapUnit::Map100thMM
) );
1073 if( aSize
.IsEmpty() )
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();
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
;
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
) );
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
1175 aMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
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())
1196 const basegfx::B2DVector
aCropScaleFactor(
1197 GetGraphicObject().calculateCropScaling(
1203 rCrop
.GetBottom()));
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
);
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
;
1233 std::make_unique
<SdrCropViewHdl
>(
1234 aMatrixForCropViewHdl
,
1235 GetGraphicObject().GetGraphic(),
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: */