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 <sal/config.h>
22 #include <string_view>
24 #include <hintids.hxx>
25 #include <tools/helpers.hxx>
26 #include <tools/urlobj.hxx>
27 #include <tools/fract.hxx>
28 #include <tools/UnitConversion.hxx>
29 #include <svl/fstathelper.hxx>
30 #include <vcl/imap.hxx>
31 #include <sfx2/docfile.hxx>
32 #include <sfx2/linkmgr.hxx>
33 #include <editeng/boxitem.hxx>
34 #include <sot/formats.hxx>
35 #include <fmtfsize.hxx>
39 #include <IDocumentLinksAdministration.hxx>
40 #include <IDocumentLayoutAccess.hxx>
43 #include <swtypes.hxx>
47 #include <swbaslnk.hxx>
48 #include <pagefrm.hxx>
50 #include <rtl/ustring.hxx>
51 #include <o3tl/deleter.hxx>
52 #include <o3tl/string_view.hxx>
53 #include <osl/diagnose.h>
54 #include <retrieveinputstreamconsumer.hxx>
55 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
56 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
58 using namespace com::sun::star
;
62 const OUString
& rGrfName
,
63 const OUString
& rFltName
,
64 const Graphic
* pGraphic
,
65 SwGrfFormatColl
*pGrfColl
,
66 SwAttrSet
const * pAutoAttr
) :
67 SwNoTextNode( rWhere
, SwNodeType::Grf
, pGrfColl
, pAutoAttr
),
68 mbInBaseLinkSwapIn(true),
70 mbLinkedInputStreamReady( false ),
71 mbIsStreamReadOnly( false )
73 mbInSwapIn
= mbChangeTwipSize
=
74 mbFrameInPaint
= mbScaleImageMap
= false;
76 ReRead(rGrfName
, rFltName
, pGraphic
, false);
79 SwGrfNode::SwGrfNode( SwNode
& rWhere
,
80 const GraphicObject
& rGrfObj
,
81 SwGrfFormatColl
*pGrfColl
,
82 SwAttrSet
const * pAutoAttr
) :
83 SwNoTextNode( rWhere
, SwNodeType::Grf
, pGrfColl
, pAutoAttr
),
85 mbInBaseLinkSwapIn(true),
87 mbLinkedInputStreamReady( false ),
88 mbIsStreamReadOnly( false )
90 mbInSwapIn
= mbChangeTwipSize
=
91 mbFrameInPaint
= mbScaleImageMap
= false;
94 /** Create new SW/G reader.
96 * Use this ctor if you want to read a linked graphic.
98 * @note Does not read/open the image itself!
100 SwGrfNode::SwGrfNode( SwNode
& rWhere
,
101 std::u16string_view rGrfName
,
102 const OUString
& rFltName
,
103 SwGrfFormatColl
*pGrfColl
,
104 SwAttrSet
const * pAutoAttr
) :
105 SwNoTextNode( rWhere
, SwNodeType::Grf
, pGrfColl
, pAutoAttr
),
106 mbInBaseLinkSwapIn(true),
108 mbLinkedInputStreamReady( false ),
109 mbIsStreamReadOnly( false )
111 Graphic aGrf
; aGrf
.SetDefaultType();
112 maGrfObj
.SetGraphic( aGrf
);
114 mbInSwapIn
= mbChangeTwipSize
=
115 mbFrameInPaint
= mbScaleImageMap
= false;
117 InsertLink( rGrfName
, rFltName
);
120 INetURLObject
aUrl( rGrfName
);
121 if( INetProtocol::File
== aUrl
.GetProtocol() &&
122 FStatHelper::IsDocument( aUrl
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) ))
124 // file exists, so create connection without an update
125 static_cast<SwBaseLink
*>( mxLink
.get() )->Connect();
130 bool SwGrfNode::ReRead(
131 const OUString
& rGrfName
, const OUString
& rFltName
,
132 const Graphic
* pGraphic
,
135 bool bReadGrf
= false;
136 bool bSetTwipSize
= true;
137 mpReplacementGraphic
.reset();
139 OSL_ENSURE( pGraphic
|| !rGrfName
.isEmpty(),
140 "GraphicNode without a name, Graphic or GraphicObject" );
145 Graphic
aGraphic(*pGraphic
);
147 sURLLink
= aGraphic
.getOriginURL();
148 if (sURLLink
.isEmpty() && !rGrfName
.isEmpty())
151 aGraphic
.setOriginURL(sURLLink
);
162 OSL_ENSURE( !mbInSwapIn
, "ReRead: I am still in SwapIn" );
164 if( !sURLLink
.isEmpty() )
166 // Note: if there is DDE in the FltName, then it is a DDE-linked graphic
167 OUString
sCmd( sURLLink
);
168 if( !rFltName
.isEmpty() )
170 sfx2::SvBaseLinkObjectType nNewType
;
171 if( rFltName
== "DDE" )
172 nNewType
= sfx2::SvBaseLinkObjectType::ClientDde
;
175 sfx2::MakeLnkName( sCmd
, nullptr, sURLLink
, std::u16string_view(), &rFltName
);
176 nNewType
= sfx2::SvBaseLinkObjectType::ClientGraphic
;
179 if( nNewType
!= mxLink
->GetObjType() )
181 mxLink
->Disconnect();
182 static_cast<SwBaseLink
*>( mxLink
.get() )->SetObjType( nNewType
);
186 mxLink
->SetLinkSourceName( sCmd
);
188 else // no name anymore, so remove link
190 GetDoc().getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink
.get() );
196 maGrfObj
.SetGraphic( *pGraphic
);
202 // reset data of the old graphic so that the correct placeholder is
203 // shown in case the new link could not be loaded
204 Graphic aGrf
; aGrf
.SetDefaultType();
205 maGrfObj
.SetGraphic( aGrf
);
209 if( getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) )
211 CallSwClientNotify(sw::GrfRereadAndInCacheHint());
215 //TODO refLink->setInputStream(getInputStream());
216 static_cast<SwBaseLink
*>( mxLink
.get() )->SwapIn();
220 bSetTwipSize
= false;
223 else if( pGraphic
&& sURLLink
.isEmpty() )
225 maGrfObj
.SetGraphic( *pGraphic
);
229 // Was the graphic already loaded?
230 else if( !bNewGrf
&& GraphicType::NONE
!= maGrfObj
.GetType() )
234 // create new link for the graphic object
235 InsertLink( sURLLink
, rFltName
);
237 if( GetNodes().IsDocNodes() )
241 maGrfObj
.SetGraphic( *pGraphic
);
244 // create connection without update, as we have the graphic
245 static_cast<SwBaseLink
*>( mxLink
.get() )->Connect();
250 aGrf
.SetDefaultType();
251 maGrfObj
.SetGraphic( aGrf
);
255 static_cast<SwBaseLink
*>( mxLink
.get() )->SwapIn();
261 // Bug 39281: Do not delete Size immediately - Events on ImageMaps should have
262 // something to work with when swapping
264 SetTwipSize( ::GetGraphicSizeTwip( maGrfObj
.GetGraphic(), nullptr ) );
266 // create an updates for the frames
267 if( bReadGrf
&& bNewGrf
)
269 const SwUpdateAttr
aHint(0,0,0);
270 CallSwClientNotify(sw::LegacyModifyHint(&aHint
, &aHint
));
276 SwGrfNode::~SwGrfNode()
278 mpReplacementGraphic
.reset();
281 mpThreadConsumer
.reset();
283 SwDoc
& rDoc
= GetDoc();
286 OSL_ENSURE( !mbInSwapIn
, "DTOR: I am still in SwapIn" );
287 rDoc
.getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink
.get() );
288 mxLink
->Disconnect();
292 // #i40014# - A graphic node, which is in a linked
293 // section, whose link is another section in the document, doesn't
294 // have to remove the stream from the storage.
295 // Because it's hard to detect this case here and it would only fix
296 // one problem with shared graphic files - there are also problems,
297 // a certain graphic file is referenced by two independent graphic nodes,
298 // brush item or drawing objects, the stream isn't no longer removed here.
299 // To do this stuff correctly, a reference counting on shared streams
300 // inside one document has to be implemented.
302 //#39289# delete frames already here since the Frames' dtor needs the graphic for its StopAnimation
303 if( HasWriterListeners() )
305 ResetAttr(RES_PAGEDESC
);
308 /// allow reaction on change of content of GraphicObject
309 void SwGrfNode::onGraphicChanged()
311 // try to access SwFlyFrameFormat; since title/desc/name are set there, there is no
312 // use to continue if it is not yet set. If not yet set, call onGraphicChanged()
314 SwFlyFrameFormat
* pFlyFormat
= dynamic_cast< SwFlyFrameFormat
* >(GetFlyFormat());
322 auto const & rVectorGraphicDataPtr
= GetGrf().getVectorGraphicData();
324 if (rVectorGraphicDataPtr
)
326 const drawinglayer::primitive2d::Primitive2DContainer
aSequence(rVectorGraphicDataPtr
->getPrimitive2DSequence());
328 if(!aSequence
.empty())
330 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
331 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D
aProcessor(aViewInformation2D
);
333 aProcessor
.process(aSequence
);
335 const drawinglayer::primitive2d::ObjectInfoPrimitive2D
* pResult
= aProcessor
.getResult();
339 aName
= pResult
->getName();
340 aTitle
= pResult
->getTitle();
341 aDesc
= pResult
->getDesc();
346 if(!aTitle
.isEmpty())
350 else if (!aName
.isEmpty())
357 SetDescription(aDesc
);
361 void SwGrfNode::SetGraphic(const Graphic
& rGraphic
)
363 maGrfObj
.SetGraphic(rGraphic
);
367 void SwGrfNode::TriggerGraphicArrived()
369 CallSwClientNotify(sw::PreGraphicArrivedHint());
370 CallSwClientNotify(sw::PostGraphicArrivedHint());
373 const Graphic
& SwGrfNode::GetGrf(bool bWait
) const
375 const_cast<SwGrfNode
*>(this)->SwapIn(bWait
);
376 return maGrfObj
.GetGraphic();
379 const GraphicObject
& SwGrfNode::GetGrfObj(bool bWait
) const
381 const_cast<SwGrfNode
*>(this)->SwapIn(bWait
);
385 const GraphicObject
* SwGrfNode::GetReplacementGrfObj() const
387 if(!mpReplacementGraphic
)
389 auto const & rVectorGraphicDataPtr
= GetGrfObj().GetGraphic().getVectorGraphicData();
391 if (rVectorGraphicDataPtr
)
393 const_cast< SwGrfNode
* >(this)->mpReplacementGraphic
.reset( new GraphicObject(rVectorGraphicDataPtr
->getReplacement()) );
395 else if (GetGrfObj().GetGraphic().GetType() == GraphicType::GdiMetafile
)
397 // Replacement graphic for PDF and metafiles is just the bitmap.
398 const_cast<SwGrfNode
*>(this)->mpReplacementGraphic
.reset( new GraphicObject(GetGrfObj().GetGraphic().GetBitmapEx()) );
402 return mpReplacementGraphic
.get();
405 SwGrfNode
* SwNodes::MakeGrfNode( SwNode
& rWhere
,
406 const OUString
& rGrfName
,
407 const OUString
& rFltName
,
408 const Graphic
* pGraphic
,
409 SwGrfFormatColl
* pGrfColl
,
410 SwAttrSet
const * pAutoAttr
)
412 OSL_ENSURE( pGrfColl
, "MakeGrfNode: Formatpointer is 0." );
414 // create object delayed, only from a SW/G-reader
416 pNode
= new SwGrfNode( rWhere
, rGrfName
,
417 rFltName
, pGrfColl
, pAutoAttr
);
419 pNode
= new SwGrfNode( rWhere
, rGrfName
,
420 rFltName
, pGraphic
, pGrfColl
, pAutoAttr
);
424 SwGrfNode
* SwNodes::MakeGrfNode( SwNode
& rWhere
,
425 const GraphicObject
& rGrfObj
,
426 SwGrfFormatColl
* pGrfColl
)
428 OSL_ENSURE( pGrfColl
, "MakeGrfNode: Formatpointer is 0." );
429 return new SwGrfNode( rWhere
, rGrfObj
, pGrfColl
, nullptr );
432 Size
SwGrfNode::GetTwipSize() const
434 if( !mnGrfSize
.Width() && !mnGrfSize
.Height() )
436 const_cast<SwGrfNode
*>(this)->SwapIn();
442 * @return true if ReRead or reading successful,
443 * false if not loaded
445 bool SwGrfNode::SwapIn(bool bWaitForData
)
447 if(mbInSwapIn
) // not recursively!
452 SwBaseLink
* pLink
= static_cast<SwBaseLink
*>( mxLink
.get() );
456 if( (GraphicType::NONE
== maGrfObj
.GetType() ||
457 GraphicType::Default
== maGrfObj
.GetType()) &&
460 // link was not loaded yet
461 if( pLink
->SwapIn( bWaitForData
) )
464 mbInBaseLinkSwapIn
= false;
466 else if( GraphicType::Default
== maGrfObj
.GetType() )
468 // no default bitmap anymore, thus re-paint
469 mpReplacementGraphic
.reset();
471 maGrfObj
.SetGraphic( Graphic() );
473 CallSwClientNotify(sw::GraphicPieceArrivedHint());
486 if( !mnGrfSize
.Width() && !mnGrfSize
.Height() )
487 SetTwipSize( ::GetGraphicSizeTwip( maGrfObj
.GetGraphic(), nullptr ) );
493 bool SwGrfNode::GetFileFilterNms( OUString
* pFileNm
, OUString
* pFilterNm
) const
496 if( mxLink
.is() && mxLink
->GetLinkManager() )
498 sfx2::SvBaseLinkObjectType nType
= mxLink
->GetObjType();
499 if( sfx2::SvBaseLinkObjectType::ClientGraphic
== nType
)
500 bRet
= sfx2::LinkManager::GetDisplayNames(
501 mxLink
.get(), nullptr, pFileNm
, nullptr, pFilterNm
);
502 else if( sfx2::SvBaseLinkObjectType::ClientDde
== nType
&& pFileNm
&& pFilterNm
)
507 if( sfx2::LinkManager::GetDisplayNames(
508 mxLink
.get(), &sApp
, &sTopic
, &sItem
) )
510 *pFileNm
= sApp
+ OUStringChar(sfx2::cTokenSeparator
)
511 + sTopic
+ OUStringChar(sfx2::cTokenSeparator
)
521 /** Make a graphic object ready for UNDO.
523 * If it is already in storage, it needs to be loaded.
525 bool SwGrfNode::SavePersistentData()
529 OSL_ENSURE( !mbInSwapIn
, "SavePersistentData: I am still in SwapIn" );
530 GetDoc().getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink
.get() );
534 // swap in first if in storage
535 if( HasEmbeddedStreamName() && !SwapIn() )
539 // Do not delete graphic file in storage, because the graphic file could
540 // be referenced by other graphic nodes.
541 // Because it's hard to detect this case here and it would only fix
542 // one problem with shared graphic files - there are also problems, if
543 // a certain graphic file is referenced by two independent graphic nodes,
544 // brush item or drawing objects, the stream isn't no longer removed here.
545 // To do this stuff correct, a reference counting on shared streams
546 // inside one document has to be implemented.
547 // Important note: see also fix for #i40014#
549 // swap out into temp file
553 bool SwGrfNode::RestorePersistentData()
557 IDocumentLinksAdministration
& rIDLA
= getIDocumentLinksAdministration();
558 mxLink
->SetVisible( rIDLA
.IsVisibleLinks() );
559 rIDLA
.GetLinkManager().InsertDDELink( mxLink
.get() );
560 if( getIDocumentLayoutAccess().GetCurrentLayout() )
566 void SwGrfNode::InsertLink( std::u16string_view rGrfName
, const OUString
& rFltName
)
568 mxLink
= new SwBaseLink( SfxLinkUpdateMode::ONCALL
, SotClipboardFormatId::GDIMETAFILE
, this );
570 IDocumentLinksAdministration
& rIDLA
= getIDocumentLinksAdministration();
571 if( !GetNodes().IsDocNodes() )
574 mxLink
->SetVisible( rIDLA
.IsVisibleLinks() );
575 if( rFltName
== "DDE" )
578 const OUString sApp
{ o3tl::getToken(rGrfName
, 0, sfx2::cTokenSeparator
, nTmp
) };
579 const std::u16string_view sTopic
{ o3tl::getToken(rGrfName
, 0, sfx2::cTokenSeparator
, nTmp
) };
580 const std::u16string_view sItem
{ rGrfName
.substr( nTmp
) };
581 rIDLA
.GetLinkManager().InsertDDELink( mxLink
.get(), sApp
, sTopic
, sItem
);
585 const bool bSync
= rFltName
== "SYNCHRON";
586 mxLink
->SetSynchron( bSync
);
587 mxLink
->SetContentType( SotClipboardFormatId::SVXB
);
589 rIDLA
.GetLinkManager().InsertFileLink( *mxLink
,
590 sfx2::SvBaseLinkObjectType::ClientGraphic
, rGrfName
,
591 (!bSync
&& !rFltName
.isEmpty() ? &rFltName
: nullptr) );
595 void SwGrfNode::ReleaseLink()
600 Graphic
aLocalGraphic(maGrfObj
.GetGraphic());
601 const bool bHasOriginalData(aLocalGraphic
.IsGfxLink());
605 SwBaseLink
* pLink
= static_cast<SwBaseLink
*>( mxLink
.get() );
606 pLink
->SwapIn( true, true );
610 getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink
.get() );
612 aLocalGraphic
.setOriginURL("");
614 // #i15508# added extra processing after getting rid of the link. Use whatever is
615 // known from the formerly linked graphic to get to a state as close to a directly
616 // unlinked inserted graphic as possible. Goal is to have a valid GfxLink at the
617 // ImplGraphic (see there) that holds temporary data to the original data and type
618 // information about the original data. Only when this is given will
619 // SvXMLGraphicHelper::ImplInsertGraphicURL which is used at export use that type
620 // and use the original graphic at export for the ODF, without evtl. recoding
621 // of the bitmap graphic data to something without loss (e.g. PNG) but bigger
624 // #i15508# if we have the original data at the Graphic, let it survive
625 // by using that Graphic again, this time at a GraphicObject without link.
626 // This happens e.g. when inserting a linked graphic and breaking the link
627 maGrfObj
.SetGraphic(aLocalGraphic
);
631 void SwGrfNode::SetTwipSize( const Size
& rSz
)
634 if( IsScaleImageMap() && mnGrfSize
.Width() && mnGrfSize
.Height() )
636 // resize Image-Map to size of the graphic
639 // do not re-scale Image-Map
640 SetScaleImageMap( false );
644 void SwGrfNode::ScaleImageMap()
646 if( !mnGrfSize
.Width() || !mnGrfSize
.Height() )
649 // re-scale Image-Map
650 SwFrameFormat
* pFormat
= GetFlyFormat();
655 SwFormatURL
aURL( pFormat
->GetURL() );
656 if ( !aURL
.GetMap() )
660 Fraction
aScaleX( 1, 1 );
661 Fraction
aScaleY( 1, 1 );
663 const SwFormatFrameSize
& rFrameSize
= pFormat
->GetFrameSize();
664 const SvxBoxItem
& rBox
= pFormat
->GetBox();
666 if( !rFrameSize
.GetWidthPercent() )
668 SwTwips nWidth
= rFrameSize
.GetWidth();
670 nWidth
-= rBox
.CalcLineSpace(SvxBoxItemLine::LEFT
) +
671 rBox
.CalcLineSpace(SvxBoxItemLine::RIGHT
);
673 OSL_ENSURE( nWidth
>0, "Do any 0 twip wide graphics exist!?" );
675 if( mnGrfSize
.Width() != nWidth
)
677 aScaleX
= Fraction( mnGrfSize
.Width(), nWidth
);
681 if( !rFrameSize
.GetHeightPercent() )
683 SwTwips nHeight
= rFrameSize
.GetHeight();
685 nHeight
-= rBox
.CalcLineSpace(SvxBoxItemLine::TOP
) +
686 rBox
.CalcLineSpace(SvxBoxItemLine::BOTTOM
);
688 OSL_ENSURE( nHeight
>0, "Do any 0 twip high graphics exist!?" );
690 if( mnGrfSize
.Height() != nHeight
)
692 aScaleY
= Fraction( mnGrfSize
.Height(), nHeight
);
699 aURL
.GetMap()->Scale( aScaleX
, aScaleY
);
700 pFormat
->SetFormatAttr( aURL
);
704 SwContentNode
* SwGrfNode::MakeCopy(SwDoc
& rDoc
, SwNode
& rIdx
, bool) const
706 // copy formats into the other document
707 SwGrfFormatColl
* pColl
= rDoc
.CopyGrfColl( *GetGrfColl() );
709 Graphic aTmpGrf
= GetGrf();
711 OUString sFile
, sFilter
;
713 sfx2::LinkManager::GetDisplayNames( mxLink
.get(), nullptr, &sFile
, nullptr, &sFilter
);
714 else if( IsLinkedDDE() )
716 OUString sTmp1
, sTmp2
;
717 sfx2::LinkManager::GetDisplayNames( mxLink
.get(), &sTmp1
, &sTmp2
, &sFilter
);
718 sfx2::MakeLnkName( sFile
, &sTmp1
, sTmp2
, sFilter
);
722 SwGrfNode
* pGrfNd
= SwNodes::MakeGrfNode( rIdx
, sFile
, sFilter
,
725 pGrfNd
->SetTitle( GetTitle() );
726 pGrfNd
->SetDescription( GetDescription() );
727 pGrfNd
->SetContour( HasContour(), HasAutomaticContour() );
731 /// returns the Graphic-Attr-Structure filled with our graphic attributes
732 GraphicAttr
& SwGrfNode::GetGraphicAttr( GraphicAttr
& rGA
,
733 const SwFrame
* pFrame
) const
735 const SwAttrSet
& rSet
= GetSwAttrSet();
737 rGA
.SetDrawMode( rSet
.GetDrawModeGrf().GetValue() );
739 const SwMirrorGrf
& rMirror
= rSet
.GetMirrorGrf();
740 BmpMirrorFlags nMirror
= BmpMirrorFlags::NONE
;
741 if( rMirror
.IsGrfToggle() && pFrame
&& !pFrame
->FindPageFrame()->OnRightPage() )
743 switch( rMirror
.GetValue() )
745 case MirrorGraph::Dont
:
746 nMirror
= BmpMirrorFlags::Horizontal
;
748 case MirrorGraph::Vertical
:
749 nMirror
= BmpMirrorFlags::NONE
;
751 case MirrorGraph::Horizontal
:
752 nMirror
= BmpMirrorFlags::Horizontal
|BmpMirrorFlags::Vertical
;
755 nMirror
= BmpMirrorFlags::Vertical
;
760 switch( rMirror
.GetValue() )
762 case MirrorGraph::Both
:
763 nMirror
= BmpMirrorFlags::Horizontal
|BmpMirrorFlags::Vertical
;
765 case MirrorGraph::Vertical
:
766 nMirror
= BmpMirrorFlags::Horizontal
;
768 case MirrorGraph::Horizontal
:
769 nMirror
= BmpMirrorFlags::Vertical
;
774 rGA
.SetMirrorFlags( nMirror
);
776 const SwCropGrf
& rCrop
= rSet
.GetCropGrf();
778 tools::Long nCropLeft
= rCrop
.GetLeft();
779 tools::Long nCropTop
= rCrop
.GetTop();
780 tools::Long nCropRight
= rCrop
.GetRight();
781 tools::Long nCropBottom
= rCrop
.GetBottom();
783 // take mirroring of crop values into consideration
784 // while cropping a flipped image. otherwise,
785 // cropping will crop the opposite side of the image.
786 if (rGA
.GetMirrorFlags() & BmpMirrorFlags::Vertical
)
788 nCropTop
= rCrop
.GetBottom();
789 nCropBottom
= rCrop
.GetTop();
792 if (rGA
.GetMirrorFlags() & BmpMirrorFlags::Horizontal
)
794 nCropLeft
= rCrop
.GetRight();
795 nCropRight
= rCrop
.GetLeft();
798 rGA
.SetCrop( convertTwipToMm100( nCropLeft
),
799 convertTwipToMm100( nCropTop
),
800 convertTwipToMm100( nCropRight
),
801 convertTwipToMm100( nCropBottom
));
803 const SwRotationGrf
& rRotation
= rSet
.GetRotationGrf();
804 rGA
.SetRotation( rRotation
.GetValue() );
806 rGA
.SetLuminance( rSet
.GetLuminanceGrf().GetValue() );
807 rGA
.SetContrast( rSet
.GetContrastGrf().GetValue() );
808 rGA
.SetChannelR( rSet
.GetChannelRGrf().GetValue() );
809 rGA
.SetChannelG( rSet
.GetChannelGGrf().GetValue() );
810 rGA
.SetChannelB( rSet
.GetChannelBGrf().GetValue() );
811 rGA
.SetGamma( rSet
.GetGammaGrf().GetValue() );
812 rGA
.SetInvert( rSet
.GetInvertGrf().GetValue() );
814 const sal_uInt16 nTrans
= rSet
.GetTransparencyGrf().GetValue();
815 rGA
.SetAlpha( 255 - static_cast<sal_uInt8
>(FRound(
816 std::min( nTrans
, sal_uInt16(100) ) * 2.55 )) );
821 bool SwGrfNode::IsTransparent() const
823 return maGrfObj
.IsTransparent() ||
824 GetSwAttrSet().GetTransparencyGrf().GetValue() != 0;
827 void SwGrfNode::TriggerAsyncRetrieveInputStream()
829 if ( !IsLinkedFile() )
831 OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
835 if (mpThreadConsumer
!= nullptr)
838 mpThreadConsumer
.reset(new SwAsyncRetrieveInputStreamThreadConsumer(*this), o3tl::default_delete
<SwAsyncRetrieveInputStreamThreadConsumer
>());
841 sfx2::LinkManager::GetDisplayNames( mxLink
.get(), nullptr, &sGrfNm
);
843 SfxObjectShell
* sh
= GetDoc().GetPersist();
844 if (sh
!= nullptr && sh
->HasName())
846 sReferer
= sh
->GetMedium()->GetName();
848 mpThreadConsumer
->CreateThread( sGrfNm
, sReferer
);
852 void SwGrfNode::ApplyInputStream(
853 const css::uno::Reference
<css::io::XInputStream
>& xInputStream
,
854 const bool bIsStreamReadOnly
)
856 if ( IsLinkedFile() )
858 if ( xInputStream
.is() )
860 mxInputStream
= xInputStream
;
861 mbIsStreamReadOnly
= bIsStreamReadOnly
;
862 mbLinkedInputStreamReady
= true;
863 CallSwClientNotify(sw::LinkedGraphicStreamArrivedHint());
868 void SwGrfNode::UpdateLinkWithInputStream()
870 // do not work on link, if a <SwapIn> has been triggered.
871 if ( mbInSwapIn
|| !IsLinkedFile() )
874 GetLink()->setStreamToLoadFrom( mxInputStream
, mbIsStreamReadOnly
);
876 TriggerGraphicArrived();
879 mxInputStream
.clear();
880 GetLink()->clearStreamToLoadFrom();
881 mbLinkedInputStreamReady
= false;
882 mpThreadConsumer
.reset();
886 bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
890 if ( IsLinkedFile() )
893 sfx2::LinkManager::GetDisplayNames( mxLink
.get(), nullptr, &sGrfNm
);
894 if ( !sGrfNm
.startsWith( "vnd.sun.star.pkg:" ) )
903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */