nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / graphic / ndgrf.cxx
blobdf244ccf18653f0b6fda64a9a86ae61ba4af9d40
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 <hintids.hxx>
21 #include <tools/helpers.hxx>
22 #include <tools/urlobj.hxx>
23 #include <tools/fract.hxx>
24 #include <tools/UnitConversion.hxx>
25 #include <svl/fstathelper.hxx>
26 #include <vcl/imap.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/linkmgr.hxx>
29 #include <editeng/boxitem.hxx>
30 #include <sot/formats.hxx>
31 #include <fmtfsize.hxx>
32 #include <fmturl.hxx>
33 #include <frmfmt.hxx>
34 #include <doc.hxx>
35 #include <IDocumentLinksAdministration.hxx>
36 #include <IDocumentLayoutAccess.hxx>
37 #include <frmatr.hxx>
38 #include <grfatr.hxx>
39 #include <swtypes.hxx>
40 #include <ndgrf.hxx>
41 #include <fmtcol.hxx>
42 #include <hints.hxx>
43 #include <swbaslnk.hxx>
44 #include <pagefrm.hxx>
45 #include <cntfrm.hxx>
47 #include <rtl/ustring.hxx>
48 #include <o3tl/deleter.hxx>
49 #include <retrieveinputstreamconsumer.hxx>
50 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
51 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
53 using namespace com::sun::star;
55 SwGrfNode::SwGrfNode(
56 const SwNodeIndex & rWhere,
57 const OUString& rGrfName,
58 const OUString& rFltName,
59 const Graphic* pGraphic,
60 SwGrfFormatColl *pGrfColl,
61 SwAttrSet const * pAutoAttr ) :
62 SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
63 maGrfObj(),
64 mbInBaseLinkSwapIn(true),
65 // #i73788#
66 mbLinkedInputStreamReady( false ),
67 mbIsStreamReadOnly( false )
69 mbInSwapIn = mbChangeTwipSize =
70 mbFrameInPaint = mbScaleImageMap = false;
72 ReRead(rGrfName, rFltName, pGraphic, false);
75 SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
76 const GraphicObject& rGrfObj,
77 SwGrfFormatColl *pGrfColl,
78 SwAttrSet const * pAutoAttr ) :
79 SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
80 maGrfObj(rGrfObj),
81 mbInBaseLinkSwapIn(true),
82 // #i73788#
83 mbLinkedInputStreamReady( false ),
84 mbIsStreamReadOnly( false )
86 mbInSwapIn = mbChangeTwipSize =
87 mbFrameInPaint = mbScaleImageMap = false;
90 /** Create new SW/G reader.
92 * Use this ctor if you want to read a linked graphic.
94 * @note Does not read/open the image itself!
96 SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
97 const OUString& rGrfName,
98 const OUString& rFltName,
99 SwGrfFormatColl *pGrfColl,
100 SwAttrSet const * pAutoAttr ) :
101 SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
102 maGrfObj(),
103 mbInBaseLinkSwapIn(true),
104 // #i73788#
105 mbLinkedInputStreamReady( false ),
106 mbIsStreamReadOnly( false )
108 Graphic aGrf; aGrf.SetDefaultType();
109 maGrfObj.SetGraphic( aGrf );
111 mbInSwapIn = mbChangeTwipSize =
112 mbFrameInPaint = mbScaleImageMap = false;
114 InsertLink( rGrfName, rFltName );
115 if( IsLinkedFile() )
117 INetURLObject aUrl( rGrfName );
118 if( INetProtocol::File == aUrl.GetProtocol() &&
119 FStatHelper::IsDocument( aUrl.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ))
121 // file exists, so create connection without an update
122 static_cast<SwBaseLink*>( mxLink.get() )->Connect();
127 bool SwGrfNode::ReRead(
128 const OUString& rGrfName, const OUString& rFltName,
129 const Graphic* pGraphic,
130 bool bNewGrf )
132 bool bReadGrf = false;
133 bool bSetTwipSize = true;
134 mpReplacementGraphic.reset();
136 OSL_ENSURE( pGraphic || !rGrfName.isEmpty(),
137 "GraphicNode without a name, Graphic or GraphicObject" );
139 OUString sURLLink;
140 if (pGraphic)
142 Graphic aGraphic(*pGraphic);
144 sURLLink = aGraphic.getOriginURL();
145 if (sURLLink.isEmpty() && !rGrfName.isEmpty())
147 sURLLink = rGrfName;
148 aGraphic.setOriginURL(sURLLink);
151 else
153 sURLLink = rGrfName;
156 // with name
157 if( mxLink.is() )
159 OSL_ENSURE( !mbInSwapIn, "ReRead: I am still in SwapIn" );
161 if( !sURLLink.isEmpty() )
163 // Note: if there is DDE in the FltName, then it is a DDE-linked graphic
164 OUString sCmd( sURLLink );
165 if( !rFltName.isEmpty() )
167 sfx2::SvBaseLinkObjectType nNewType;
168 if( rFltName == "DDE" )
169 nNewType = sfx2::SvBaseLinkObjectType::ClientDde;
170 else
172 sfx2::MakeLnkName( sCmd, nullptr, sURLLink, OUString(), &rFltName );
173 nNewType = sfx2::SvBaseLinkObjectType::ClientGraphic;
176 if( nNewType != mxLink->GetObjType() )
178 mxLink->Disconnect();
179 static_cast<SwBaseLink*>( mxLink.get() )->SetObjType( nNewType );
183 mxLink->SetLinkSourceName( sCmd );
185 else // no name anymore, so remove link
187 GetDoc().getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
188 mxLink.clear();
191 if( pGraphic )
193 maGrfObj.SetGraphic( *pGraphic );
194 onGraphicChanged();
195 bReadGrf = true;
197 else
199 // reset data of the old graphic so that the correct placeholder is
200 // shown in case the new link could not be loaded
201 Graphic aGrf; aGrf.SetDefaultType();
202 maGrfObj.SetGraphic( aGrf );
204 if( mxLink.is() )
206 if( getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) )
208 CallSwClientNotify(sw::GrfRereadAndInCacheHint());
210 else if ( bNewGrf )
212 //TODO refLink->setInputStream(getInputStream());
213 static_cast<SwBaseLink*>( mxLink.get() )->SwapIn();
216 onGraphicChanged();
217 bSetTwipSize = false;
220 else if( pGraphic && sURLLink.isEmpty() )
222 maGrfObj.SetGraphic( *pGraphic );
223 onGraphicChanged();
224 bReadGrf = true;
226 // Was the graphic already loaded?
227 else if( !bNewGrf && GraphicType::NONE != maGrfObj.GetType() )
228 return true;
229 else
231 // create new link for the graphic object
232 InsertLink( sURLLink, rFltName );
234 if( GetNodes().IsDocNodes() )
236 if( pGraphic )
238 maGrfObj.SetGraphic( *pGraphic );
239 onGraphicChanged();
240 bReadGrf = true;
241 // create connection without update, as we have the graphic
242 static_cast<SwBaseLink*>( mxLink.get() )->Connect();
244 else
246 Graphic aGrf;
247 aGrf.SetDefaultType();
248 maGrfObj.SetGraphic( aGrf );
249 onGraphicChanged();
250 if ( bNewGrf )
252 static_cast<SwBaseLink*>( mxLink.get() )->SwapIn();
258 // Bug 39281: Do not delete Size immediately - Events on ImageMaps should have
259 // something to work with when swapping
260 if( bSetTwipSize )
261 SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
263 // create an updates for the frames
264 if( bReadGrf && bNewGrf )
266 const SwUpdateAttr aHint(0,0,0);
267 CallSwClientNotify(sw::LegacyModifyHint(&aHint, &aHint));
270 return bReadGrf;
273 SwGrfNode::~SwGrfNode()
275 mpReplacementGraphic.reset();
277 // #i73788#
278 mpThreadConsumer.reset();
280 SwDoc& rDoc = GetDoc();
281 if( mxLink.is() )
283 OSL_ENSURE( !mbInSwapIn, "DTOR: I am still in SwapIn" );
284 rDoc.getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
285 mxLink->Disconnect();
287 else
289 // #i40014# - A graphic node, which is in a linked
290 // section, whose link is another section in the document, doesn't
291 // have to remove the stream from the storage.
292 // Because it's hard to detect this case here and it would only fix
293 // one problem with shared graphic files - there are also problems,
294 // a certain graphic file is referenced by two independent graphic nodes,
295 // brush item or drawing objects, the stream isn't no longer removed here.
296 // To do this stuff correctly, a reference counting on shared streams
297 // inside one document has to be implemented.
299 //#39289# delete frames already here since the Frames' dtor needs the graphic for its StopAnimation
300 if( HasWriterListeners() )
301 DelFrames(nullptr);
304 /// allow reaction on change of content of GraphicObject
305 void SwGrfNode::onGraphicChanged()
307 // try to access SwFlyFrameFormat; since title/desc/name are set there, there is no
308 // use to continue if it is not yet set. If not yet set, call onGraphicChanged()
309 // when it is set.
310 SwFlyFrameFormat* pFlyFormat = dynamic_cast< SwFlyFrameFormat* >(GetFlyFormat());
312 if(!pFlyFormat)
313 return;
315 OUString aName;
316 OUString aTitle;
317 OUString aDesc;
318 auto const & rVectorGraphicDataPtr = GetGrf().getVectorGraphicData();
320 if (rVectorGraphicDataPtr)
322 const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVectorGraphicDataPtr->getPrimitive2DSequence());
324 if(!aSequence.empty())
326 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
327 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
329 aProcessor.process(aSequence);
331 const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
333 if(pResult)
335 aName = pResult->getName();
336 aTitle = pResult->getTitle();
337 aDesc = pResult->getDesc();
342 if(!aTitle.isEmpty())
344 SetTitle(aTitle);
346 else if (!aName.isEmpty())
348 SetTitle(aName);
351 if(!aDesc.isEmpty())
353 SetDescription(aDesc);
357 void SwGrfNode::SetGraphic(const Graphic& rGraphic)
359 maGrfObj.SetGraphic(rGraphic);
360 onGraphicChanged();
363 void SwGrfNode::TriggerGraphicArrived()
365 CallSwClientNotify(sw::PreGraphicArrivedHint());
366 CallSwClientNotify(sw::PostGraphicArrivedHint());
369 const Graphic& SwGrfNode::GetGrf(bool bWait) const
371 const_cast<SwGrfNode*>(this)->SwapIn(bWait);
372 return maGrfObj.GetGraphic();
375 const GraphicObject& SwGrfNode::GetGrfObj(bool bWait) const
377 const_cast<SwGrfNode*>(this)->SwapIn(bWait);
378 return maGrfObj;
381 const GraphicObject* SwGrfNode::GetReplacementGrfObj() const
383 if(!mpReplacementGraphic)
385 auto const & rVectorGraphicDataPtr = GetGrfObj().GetGraphic().getVectorGraphicData();
387 if (rVectorGraphicDataPtr)
389 const_cast< SwGrfNode* >(this)->mpReplacementGraphic.reset( new GraphicObject(rVectorGraphicDataPtr->getReplacement()) );
391 else if (GetGrfObj().GetGraphic().GetType() == GraphicType::GdiMetafile)
393 // Replacement graphic for PDF and metafiles is just the bitmap.
394 const_cast<SwGrfNode*>(this)->mpReplacementGraphic.reset( new GraphicObject(GetGrfObj().GetGraphic().GetBitmapEx()) );
398 return mpReplacementGraphic.get();
401 SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
402 const OUString& rGrfName,
403 const OUString& rFltName,
404 const Graphic* pGraphic,
405 SwGrfFormatColl* pGrfColl,
406 SwAttrSet const * pAutoAttr )
408 OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer is 0." );
409 SwGrfNode *pNode;
410 // create object delayed, only from a SW/G-reader
411 if( !pGraphic )
412 pNode = new SwGrfNode( rWhere, rGrfName,
413 rFltName, pGrfColl, pAutoAttr );
414 else
415 pNode = new SwGrfNode( rWhere, rGrfName,
416 rFltName, pGraphic, pGrfColl, pAutoAttr );
417 return pNode;
420 SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
421 const GraphicObject& rGrfObj,
422 SwGrfFormatColl* pGrfColl )
424 OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer is 0." );
425 return new SwGrfNode( rWhere, rGrfObj, pGrfColl, nullptr );
428 Size SwGrfNode::GetTwipSize() const
430 if( !mnGrfSize.Width() && !mnGrfSize.Height() )
432 const_cast<SwGrfNode*>(this)->SwapIn();
434 return mnGrfSize;
438 * @return true if ReRead or reading successful,
439 * false if not loaded
441 bool SwGrfNode::SwapIn(bool bWaitForData)
443 if(mbInSwapIn) // not recursively!
444 return true;
446 bool bRet = false;
447 mbInSwapIn = true;
448 SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
450 if( pLink )
452 if( (GraphicType::NONE == maGrfObj.GetType() ||
453 GraphicType::Default == maGrfObj.GetType()) &&
454 mbInBaseLinkSwapIn)
456 // link was not loaded yet
457 if( pLink->SwapIn( bWaitForData ) )
459 bRet = true;
460 mbInBaseLinkSwapIn = false;
462 else if( GraphicType::Default == maGrfObj.GetType() )
464 // no default bitmap anymore, thus re-paint
465 mpReplacementGraphic.reset();
467 maGrfObj.SetGraphic( Graphic() );
468 onGraphicChanged();
469 SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
470 CallSwClientNotify(sw::LegacyModifyHint(&aMsgHint, &aMsgHint));
473 else
475 bRet = true;
478 else
479 bRet = true;
481 if (bRet)
483 if( !mnGrfSize.Width() && !mnGrfSize.Height() )
484 SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
486 mbInSwapIn = false;
487 return bRet;
490 bool SwGrfNode::GetFileFilterNms( OUString* pFileNm, OUString* pFilterNm ) const
492 bool bRet = false;
493 if( mxLink.is() && mxLink->GetLinkManager() )
495 sfx2::SvBaseLinkObjectType nType = mxLink->GetObjType();
496 if( sfx2::SvBaseLinkObjectType::ClientGraphic == nType )
497 bRet = sfx2::LinkManager::GetDisplayNames(
498 mxLink.get(), nullptr, pFileNm, nullptr, pFilterNm );
499 else if( sfx2::SvBaseLinkObjectType::ClientDde == nType && pFileNm && pFilterNm )
501 OUString sApp;
502 OUString sTopic;
503 OUString sItem;
504 if( sfx2::LinkManager::GetDisplayNames(
505 mxLink.get(), &sApp, &sTopic, &sItem ) )
507 *pFileNm = sApp + OUStringChar(sfx2::cTokenSeparator)
508 + sTopic + OUStringChar(sfx2::cTokenSeparator)
509 + sItem;
510 *pFilterNm = "DDE";
511 bRet = true;
515 return bRet;
518 /** Make a graphic object ready for UNDO.
520 * If it is already in storage, it needs to be loaded.
522 bool SwGrfNode::SavePersistentData()
524 if( mxLink.is() )
526 OSL_ENSURE( !mbInSwapIn, "SavePersistentData: I am still in SwapIn" );
527 GetDoc().getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
528 return true;
531 // swap in first if in storage
532 if( HasEmbeddedStreamName() && !SwapIn() )
533 return false;
535 // #i44367#
536 // Do not delete graphic file in storage, because the graphic file could
537 // be referenced by other graphic nodes.
538 // Because it's hard to detect this case here and it would only fix
539 // one problem with shared graphic files - there are also problems, if
540 // a certain graphic file is referenced by two independent graphic nodes,
541 // brush item or drawing objects, the stream isn't no longer removed here.
542 // To do this stuff correct, a reference counting on shared streams
543 // inside one document has to be implemented.
544 // Important note: see also fix for #i40014#
546 // swap out into temp file
547 return true;
550 bool SwGrfNode::RestorePersistentData()
552 if( mxLink.is() )
554 IDocumentLinksAdministration& rIDLA = getIDocumentLinksAdministration();
555 mxLink->SetVisible( rIDLA.IsVisibleLinks() );
556 rIDLA.GetLinkManager().InsertDDELink( mxLink.get() );
557 if( getIDocumentLayoutAccess().GetCurrentLayout() )
558 mxLink->Update();
560 return true;
563 void SwGrfNode::InsertLink( const OUString& rGrfName, const OUString& rFltName )
565 mxLink = new SwBaseLink( SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::GDIMETAFILE, this );
567 IDocumentLinksAdministration& rIDLA = getIDocumentLinksAdministration();
568 if( !GetNodes().IsDocNodes() )
569 return;
571 mxLink->SetVisible( rIDLA.IsVisibleLinks() );
572 if( rFltName == "DDE" )
574 sal_Int32 nTmp = 0;
575 const OUString sApp{ rGrfName.getToken( 0, sfx2::cTokenSeparator, nTmp ) };
576 const OUString sTopic{ rGrfName.getToken( 0, sfx2::cTokenSeparator, nTmp ) };
577 const OUString sItem{ rGrfName.copy( nTmp ) };
578 rIDLA.GetLinkManager().InsertDDELink( mxLink.get(), sApp, sTopic, sItem );
580 else
582 const bool bSync = rFltName == "SYNCHRON";
583 mxLink->SetSynchron( bSync );
584 mxLink->SetContentType( SotClipboardFormatId::SVXB );
586 rIDLA.GetLinkManager().InsertFileLink( *mxLink,
587 sfx2::SvBaseLinkObjectType::ClientGraphic, rGrfName,
588 (!bSync && !rFltName.isEmpty() ? &rFltName : nullptr) );
592 void SwGrfNode::ReleaseLink()
594 if( !mxLink.is() )
595 return;
597 Graphic aLocalGraphic(maGrfObj.GetGraphic());
598 const bool bHasOriginalData(aLocalGraphic.IsGfxLink());
601 mbInSwapIn = true;
602 SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
603 pLink->SwapIn( true, true );
604 mbInSwapIn = false;
607 getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
608 mxLink.clear();
609 aLocalGraphic.setOriginURL("");
611 // #i15508# added extra processing after getting rid of the link. Use whatever is
612 // known from the formerly linked graphic to get to a state as close to a directly
613 // unlinked inserted graphic as possible. Goal is to have a valid GfxLink at the
614 // ImplGraphic (see there) that holds temporary data to the original data and type
615 // information about the original data. Only when this is given will
616 // SvXMLGraphicHelper::ImplInsertGraphicURL which is used at export use that type
617 // and use the original graphic at export for the ODF, without evtl. recoding
618 // of the bitmap graphic data to something without loss (e.g. PNG) but bigger
619 if(bHasOriginalData)
621 // #i15508# if we have the original data at the Graphic, let it survive
622 // by using that Graphic again, this time at a GraphicObject without link.
623 // This happens e.g. when inserting a linked graphic and breaking the link
624 maGrfObj.SetGraphic(aLocalGraphic);
628 void SwGrfNode::SetTwipSize( const Size& rSz )
630 mnGrfSize = rSz;
631 if( IsScaleImageMap() && mnGrfSize.Width() && mnGrfSize.Height() )
633 // resize Image-Map to size of the graphic
634 ScaleImageMap();
636 // do not re-scale Image-Map
637 SetScaleImageMap( false );
641 void SwGrfNode::ScaleImageMap()
643 if( !mnGrfSize.Width() || !mnGrfSize.Height() )
644 return;
646 // re-scale Image-Map
647 SwFrameFormat* pFormat = GetFlyFormat();
649 if( !pFormat )
650 return;
652 SwFormatURL aURL( pFormat->GetURL() );
653 if ( !aURL.GetMap() )
654 return;
656 bool bScale = false;
657 Fraction aScaleX( 1, 1 );
658 Fraction aScaleY( 1, 1 );
660 const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize();
661 const SvxBoxItem& rBox = pFormat->GetBox();
663 if( !rFrameSize.GetWidthPercent() )
665 SwTwips nWidth = rFrameSize.GetWidth();
667 nWidth -= rBox.CalcLineSpace(SvxBoxItemLine::LEFT) +
668 rBox.CalcLineSpace(SvxBoxItemLine::RIGHT);
670 OSL_ENSURE( nWidth>0, "Do any 0 twip wide graphics exist!?" );
672 if( mnGrfSize.Width() != nWidth )
674 aScaleX = Fraction( mnGrfSize.Width(), nWidth );
675 bScale = true;
678 if( !rFrameSize.GetHeightPercent() )
680 SwTwips nHeight = rFrameSize.GetHeight();
682 nHeight -= rBox.CalcLineSpace(SvxBoxItemLine::TOP) +
683 rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM);
685 OSL_ENSURE( nHeight>0, "Do any 0 twip high graphics exist!?" );
687 if( mnGrfSize.Height() != nHeight )
689 aScaleY = Fraction( mnGrfSize.Height(), nHeight );
690 bScale = true;
694 if( bScale )
696 aURL.GetMap()->Scale( aScaleX, aScaleY );
697 pFormat->SetFormatAttr( aURL );
701 SwContentNode* SwGrfNode::MakeCopy(SwDoc& rDoc, const SwNodeIndex& rIdx, bool) const
703 // copy formats into the other document
704 SwGrfFormatColl* pColl = rDoc.CopyGrfColl( *GetGrfColl() );
706 Graphic aTmpGrf = GetGrf();
708 OUString sFile, sFilter;
709 if( IsLinkedFile() )
710 sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sFile, nullptr, &sFilter );
711 else if( IsLinkedDDE() )
713 OUString sTmp1, sTmp2;
714 sfx2::LinkManager::GetDisplayNames( mxLink.get(), &sTmp1, &sTmp2, &sFilter );
715 sfx2::MakeLnkName( sFile, &sTmp1, sTmp2, sFilter );
716 sFilter = "DDE";
719 SwGrfNode* pGrfNd = SwNodes::MakeGrfNode( rIdx, sFile, sFilter,
720 &aTmpGrf, pColl,
721 GetpSwAttrSet() );
722 pGrfNd->SetTitle( GetTitle() );
723 pGrfNd->SetDescription( GetDescription() );
724 pGrfNd->SetContour( HasContour(), HasAutomaticContour() );
725 return pGrfNd;
728 /// returns the Graphic-Attr-Structure filled with our graphic attributes
729 GraphicAttr& SwGrfNode::GetGraphicAttr( GraphicAttr& rGA,
730 const SwFrame* pFrame ) const
732 const SwAttrSet& rSet = GetSwAttrSet();
734 rGA.SetDrawMode( rSet.GetDrawModeGrf().GetValue() );
736 const SwMirrorGrf & rMirror = rSet.GetMirrorGrf();
737 BmpMirrorFlags nMirror = BmpMirrorFlags::NONE;
738 if( rMirror.IsGrfToggle() && pFrame && !pFrame->FindPageFrame()->OnRightPage() )
740 switch( rMirror.GetValue() )
742 case MirrorGraph::Dont:
743 nMirror = BmpMirrorFlags::Horizontal;
744 break;
745 case MirrorGraph::Vertical:
746 nMirror = BmpMirrorFlags::NONE;
747 break;
748 case MirrorGraph::Horizontal:
749 nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
750 break;
751 default:
752 nMirror = BmpMirrorFlags::Vertical;
753 break;
756 else
757 switch( rMirror.GetValue() )
759 case MirrorGraph::Both:
760 nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
761 break;
762 case MirrorGraph::Vertical:
763 nMirror = BmpMirrorFlags::Horizontal;
764 break;
765 case MirrorGraph::Horizontal:
766 nMirror = BmpMirrorFlags::Vertical;
767 break;
768 default: break;
771 rGA.SetMirrorFlags( nMirror );
773 const SwCropGrf& rCrop = rSet.GetCropGrf();
774 rGA.SetCrop( convertTwipToMm100( rCrop.GetLeft() ),
775 convertTwipToMm100( rCrop.GetTop() ),
776 convertTwipToMm100( rCrop.GetRight() ),
777 convertTwipToMm100( rCrop.GetBottom() ));
779 const SwRotationGrf& rRotation = rSet.GetRotationGrf();
780 rGA.SetRotation( Degree10(rRotation.GetValue()) );
782 rGA.SetLuminance( rSet.GetLuminanceGrf().GetValue() );
783 rGA.SetContrast( rSet.GetContrastGrf().GetValue() );
784 rGA.SetChannelR( rSet.GetChannelRGrf().GetValue() );
785 rGA.SetChannelG( rSet.GetChannelGGrf().GetValue() );
786 rGA.SetChannelB( rSet.GetChannelBGrf().GetValue() );
787 rGA.SetGamma( rSet.GetGammaGrf().GetValue() );
788 rGA.SetInvert( rSet.GetInvertGrf().GetValue() );
790 const sal_uInt16 nTrans = rSet.GetTransparencyGrf().GetValue();
791 rGA.SetTransparency( static_cast<sal_uInt8>(FRound(
792 std::min( nTrans, sal_uInt16(100) ) * 2.55 )) );
794 return rGA;
797 bool SwGrfNode::IsTransparent() const
799 return maGrfObj.IsTransparent() ||
800 GetSwAttrSet().GetTransparencyGrf().GetValue() != 0;
803 void SwGrfNode::TriggerAsyncRetrieveInputStream()
805 if ( !IsLinkedFile() )
807 OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
808 return;
811 if (mpThreadConsumer != nullptr)
812 return;
814 mpThreadConsumer.reset(new SwAsyncRetrieveInputStreamThreadConsumer(*this), o3tl::default_delete<SwAsyncRetrieveInputStreamThreadConsumer>());
816 OUString sGrfNm;
817 sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
818 OUString sReferer;
819 SfxObjectShell * sh = GetDoc().GetPersist();
820 if (sh != nullptr && sh->HasName())
822 sReferer = sh->GetMedium()->GetName();
824 mpThreadConsumer->CreateThread( sGrfNm, sReferer );
828 void SwGrfNode::ApplyInputStream(
829 const css::uno::Reference<css::io::XInputStream>& xInputStream,
830 const bool bIsStreamReadOnly )
832 if ( IsLinkedFile() )
834 if ( xInputStream.is() )
836 mxInputStream = xInputStream;
837 mbIsStreamReadOnly = bIsStreamReadOnly;
838 mbLinkedInputStreamReady = true;
839 SwMsgPoolItem aMsgHint( RES_LINKED_GRAPHIC_STREAM_ARRIVED );
840 CallSwClientNotify(sw::LegacyModifyHint(&aMsgHint, &aMsgHint));
845 void SwGrfNode::UpdateLinkWithInputStream()
847 // do not work on link, if a <SwapIn> has been triggered.
848 if ( mbInSwapIn || !IsLinkedFile() )
849 return;
851 GetLink()->setStreamToLoadFrom( mxInputStream, mbIsStreamReadOnly );
852 GetLink()->Update();
853 TriggerGraphicArrived();
855 // #i88291#
856 mxInputStream.clear();
857 GetLink()->clearStreamToLoadFrom();
858 mbLinkedInputStreamReady = false;
859 mpThreadConsumer.reset();
862 // #i90395#
863 bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
865 bool bRet = false;
867 if ( IsLinkedFile() )
869 OUString sGrfNm;
870 sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
871 if ( !sGrfNm.startsWith( "vnd.sun.star.pkg:" ) )
873 bRet = true;
877 return bRet;
880 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */