Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / graphic / ndgrf.cxx
blobe96c7557ba69eadaaca1e43c826da84fd048b031
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 <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>
36 #include <fmturl.hxx>
37 #include <frmfmt.hxx>
38 #include <doc.hxx>
39 #include <IDocumentLinksAdministration.hxx>
40 #include <IDocumentLayoutAccess.hxx>
41 #include <frmatr.hxx>
42 #include <grfatr.hxx>
43 #include <swtypes.hxx>
44 #include <ndgrf.hxx>
45 #include <fmtcol.hxx>
46 #include <hints.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;
60 SwGrfNode::SwGrfNode(
61 SwNode & rWhere,
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),
69 // #i73788#
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 ),
84 maGrfObj(rGrfObj),
85 mbInBaseLinkSwapIn(true),
86 // #i73788#
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),
107 // #i73788#
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 );
118 if( IsLinkedFile() )
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,
133 bool bNewGrf )
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" );
142 OUString sURLLink;
143 if (pGraphic)
145 Graphic aGraphic(*pGraphic);
147 sURLLink = aGraphic.getOriginURL();
148 if (sURLLink.isEmpty() && !rGrfName.isEmpty())
150 sURLLink = rGrfName;
151 aGraphic.setOriginURL(sURLLink);
154 else
156 sURLLink = rGrfName;
159 // with name
160 if( mxLink.is() )
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;
173 else
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() );
191 mxLink.clear();
194 if( pGraphic )
196 maGrfObj.SetGraphic( *pGraphic );
197 onGraphicChanged();
198 bReadGrf = true;
200 else
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 );
207 if( mxLink.is() )
209 if( getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) )
211 CallSwClientNotify(sw::GrfRereadAndInCacheHint());
213 else if ( bNewGrf )
215 //TODO refLink->setInputStream(getInputStream());
216 static_cast<SwBaseLink*>( mxLink.get() )->SwapIn();
219 onGraphicChanged();
220 bSetTwipSize = false;
223 else if( pGraphic && sURLLink.isEmpty() )
225 maGrfObj.SetGraphic( *pGraphic );
226 onGraphicChanged();
227 bReadGrf = true;
229 // Was the graphic already loaded?
230 else if( !bNewGrf && GraphicType::NONE != maGrfObj.GetType() )
231 return true;
232 else
234 // create new link for the graphic object
235 InsertLink( sURLLink, rFltName );
237 if( GetNodes().IsDocNodes() )
239 if( pGraphic )
241 maGrfObj.SetGraphic( *pGraphic );
242 onGraphicChanged();
243 bReadGrf = true;
244 // create connection without update, as we have the graphic
245 static_cast<SwBaseLink*>( mxLink.get() )->Connect();
247 else
249 Graphic aGrf;
250 aGrf.SetDefaultType();
251 maGrfObj.SetGraphic( aGrf );
252 onGraphicChanged();
253 if ( bNewGrf )
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
263 if( bSetTwipSize )
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));
273 return bReadGrf;
276 SwGrfNode::~SwGrfNode()
278 mpReplacementGraphic.reset();
280 // #i73788#
281 mpThreadConsumer.reset();
283 SwDoc& rDoc = GetDoc();
284 if( mxLink.is() )
286 OSL_ENSURE( !mbInSwapIn, "DTOR: I am still in SwapIn" );
287 rDoc.getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
288 mxLink->Disconnect();
290 else
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() )
304 DelFrames(nullptr);
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()
313 // when it is set.
314 SwFlyFrameFormat* pFlyFormat = dynamic_cast< SwFlyFrameFormat* >(GetFlyFormat());
316 if(!pFlyFormat)
317 return;
319 OUString aName;
320 OUString aTitle;
321 OUString aDesc;
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();
337 if(pResult)
339 aName = pResult->getName();
340 aTitle = pResult->getTitle();
341 aDesc = pResult->getDesc();
346 if(!aTitle.isEmpty())
348 SetTitle(aTitle);
350 else if (!aName.isEmpty())
352 SetTitle(aName);
355 if(!aDesc.isEmpty())
357 SetDescription(aDesc);
361 void SwGrfNode::SetGraphic(const Graphic& rGraphic)
363 maGrfObj.SetGraphic(rGraphic);
364 onGraphicChanged();
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);
382 return maGrfObj;
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." );
413 SwGrfNode *pNode;
414 // create object delayed, only from a SW/G-reader
415 if( !pGraphic )
416 pNode = new SwGrfNode( rWhere, rGrfName,
417 rFltName, pGrfColl, pAutoAttr );
418 else
419 pNode = new SwGrfNode( rWhere, rGrfName,
420 rFltName, pGraphic, pGrfColl, pAutoAttr );
421 return pNode;
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();
438 return mnGrfSize;
442 * @return true if ReRead or reading successful,
443 * false if not loaded
445 bool SwGrfNode::SwapIn(bool bWaitForData)
447 if(mbInSwapIn) // not recursively!
448 return true;
450 bool bRet = false;
451 mbInSwapIn = true;
452 SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
454 if( pLink )
456 if( (GraphicType::NONE == maGrfObj.GetType() ||
457 GraphicType::Default == maGrfObj.GetType()) &&
458 mbInBaseLinkSwapIn)
460 // link was not loaded yet
461 if( pLink->SwapIn( bWaitForData ) )
463 bRet = true;
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() );
472 onGraphicChanged();
473 CallSwClientNotify(sw::GraphicPieceArrivedHint());
476 else
478 bRet = true;
481 else
482 bRet = true;
484 if (bRet)
486 if( !mnGrfSize.Width() && !mnGrfSize.Height() )
487 SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
489 mbInSwapIn = false;
490 return bRet;
493 bool SwGrfNode::GetFileFilterNms( OUString* pFileNm, OUString* pFilterNm ) const
495 bool bRet = false;
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 )
504 OUString sApp;
505 OUString sTopic;
506 OUString sItem;
507 if( sfx2::LinkManager::GetDisplayNames(
508 mxLink.get(), &sApp, &sTopic, &sItem ) )
510 *pFileNm = sApp + OUStringChar(sfx2::cTokenSeparator)
511 + sTopic + OUStringChar(sfx2::cTokenSeparator)
512 + sItem;
513 *pFilterNm = "DDE";
514 bRet = true;
518 return bRet;
521 /** Make a graphic object ready for UNDO.
523 * If it is already in storage, it needs to be loaded.
525 bool SwGrfNode::SavePersistentData()
527 if( mxLink.is() )
529 OSL_ENSURE( !mbInSwapIn, "SavePersistentData: I am still in SwapIn" );
530 GetDoc().getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
531 return true;
534 // swap in first if in storage
535 if( HasEmbeddedStreamName() && !SwapIn() )
536 return false;
538 // #i44367#
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
550 return true;
553 bool SwGrfNode::RestorePersistentData()
555 if( mxLink.is() )
557 IDocumentLinksAdministration& rIDLA = getIDocumentLinksAdministration();
558 mxLink->SetVisible( rIDLA.IsVisibleLinks() );
559 rIDLA.GetLinkManager().InsertDDELink( mxLink.get() );
560 if( getIDocumentLayoutAccess().GetCurrentLayout() )
561 mxLink->Update();
563 return true;
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() )
572 return;
574 mxLink->SetVisible( rIDLA.IsVisibleLinks() );
575 if( rFltName == "DDE" )
577 sal_Int32 nTmp = 0;
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 );
583 else
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()
597 if( !mxLink.is() )
598 return;
600 Graphic aLocalGraphic(maGrfObj.GetGraphic());
601 const bool bHasOriginalData(aLocalGraphic.IsGfxLink());
604 mbInSwapIn = true;
605 SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
606 pLink->SwapIn( true, true );
607 mbInSwapIn = false;
610 getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
611 mxLink.clear();
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
622 if(bHasOriginalData)
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 )
633 mnGrfSize = rSz;
634 if( IsScaleImageMap() && mnGrfSize.Width() && mnGrfSize.Height() )
636 // resize Image-Map to size of the graphic
637 ScaleImageMap();
639 // do not re-scale Image-Map
640 SetScaleImageMap( false );
644 void SwGrfNode::ScaleImageMap()
646 if( !mnGrfSize.Width() || !mnGrfSize.Height() )
647 return;
649 // re-scale Image-Map
650 SwFrameFormat* pFormat = GetFlyFormat();
652 if( !pFormat )
653 return;
655 SwFormatURL aURL( pFormat->GetURL() );
656 if ( !aURL.GetMap() )
657 return;
659 bool bScale = false;
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 );
678 bScale = true;
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 );
693 bScale = true;
697 if( bScale )
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;
712 if( IsLinkedFile() )
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 );
719 sFilter = "DDE";
722 SwGrfNode* pGrfNd = SwNodes::MakeGrfNode( rIdx, sFile, sFilter,
723 &aTmpGrf, pColl,
724 GetpSwAttrSet() );
725 pGrfNd->SetTitle( GetTitle() );
726 pGrfNd->SetDescription( GetDescription() );
727 pGrfNd->SetContour( HasContour(), HasAutomaticContour() );
728 return pGrfNd;
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;
747 break;
748 case MirrorGraph::Vertical:
749 nMirror = BmpMirrorFlags::NONE;
750 break;
751 case MirrorGraph::Horizontal:
752 nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
753 break;
754 default:
755 nMirror = BmpMirrorFlags::Vertical;
756 break;
759 else
760 switch( rMirror.GetValue() )
762 case MirrorGraph::Both:
763 nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
764 break;
765 case MirrorGraph::Vertical:
766 nMirror = BmpMirrorFlags::Horizontal;
767 break;
768 case MirrorGraph::Horizontal:
769 nMirror = BmpMirrorFlags::Vertical;
770 break;
771 default: break;
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 )) );
818 return rGA;
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" );
832 return;
835 if (mpThreadConsumer != nullptr)
836 return;
838 mpThreadConsumer.reset(new SwAsyncRetrieveInputStreamThreadConsumer(*this), o3tl::default_delete<SwAsyncRetrieveInputStreamThreadConsumer>());
840 OUString sGrfNm;
841 sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
842 OUString sReferer;
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() )
872 return;
874 GetLink()->setStreamToLoadFrom( mxInputStream, mbIsStreamReadOnly );
875 GetLink()->Update();
876 TriggerGraphicArrived();
878 // #i88291#
879 mxInputStream.clear();
880 GetLink()->clearStreamToLoadFrom();
881 mbLinkedInputStreamReady = false;
882 mpThreadConsumer.reset();
885 // #i90395#
886 bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
888 bool bRet = false;
890 if ( IsLinkedFile() )
892 OUString sGrfNm;
893 sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
894 if ( !sGrfNm.startsWith( "vnd.sun.star.pkg:" ) )
896 bRet = true;
900 return bRet;
903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */