summaryrefslogtreecommitdiffstats
path: root/sw/source/core/graphic
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/graphic')
-rw-r--r--sw/source/core/graphic/grfatr.cxx338
-rw-r--r--sw/source/core/graphic/ndgrf.cxx874
2 files changed, 1212 insertions, 0 deletions
diff --git a/sw/source/core/graphic/grfatr.cxx b/sw/source/core/graphic/grfatr.cxx
new file mode 100644
index 000000000..a8e2e63c7
--- /dev/null
+++ b/sw/source/core/graphic/grfatr.cxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <o3tl/any.hxx>
+#include <vcl/GraphicObject.hxx>
+#include <grfatr.hxx>
+#include <swunohelper.hxx>
+#include <osl/diagnose.h>
+
+#include <unomid.h>
+
+using namespace ::com::sun::star;
+
+SwMirrorGrf* SwMirrorGrf::Clone( SfxItemPool* ) const
+{
+ return new SwMirrorGrf( *this );
+}
+
+sal_uInt16 SwMirrorGrf::GetValueCount() const
+{
+ return 4;
+}
+
+bool SwMirrorGrf::operator==( const SfxPoolItem& rItem) const
+{
+ return SfxEnumItem::operator==(static_cast<const SfxEnumItem<MirrorGraph>&>(rItem)) &&
+ static_cast<const SwMirrorGrf&>(rItem).IsGrfToggle() == IsGrfToggle();
+}
+
+static bool lcl_IsHoriOnEvenPages(MirrorGraph nEnum, bool bToggle)
+{
+ bool bEnum = nEnum == MirrorGraph::Vertical ||
+ nEnum == MirrorGraph::Both;
+ return bEnum != bToggle;
+}
+
+static bool lcl_IsHoriOnOddPages(MirrorGraph nEnum)
+{
+ bool bEnum = nEnum == MirrorGraph::Vertical ||
+ nEnum == MirrorGraph::Both;
+ return bEnum;
+}
+
+bool SwMirrorGrf::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+ // vertical and horizontal were swapped at some point
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_MIRROR_HORZ_EVEN_PAGES:
+ bVal = lcl_IsHoriOnEvenPages(GetValue(), IsGrfToggle());
+ break;
+ case MID_MIRROR_HORZ_ODD_PAGES:
+ bVal = lcl_IsHoriOnOddPages(GetValue());
+ break;
+ case MID_MIRROR_VERT:
+ bVal = GetValue() == MirrorGraph::Horizontal ||
+ GetValue() == MirrorGraph::Both;
+ break;
+ default:
+ OSL_ENSURE( false, "unknown MemberId" );
+ bRet = false;
+ }
+ rVal <<= bVal;
+ return bRet;
+}
+
+bool SwMirrorGrf::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ bool bVal = *o3tl::doAccess<bool>(rVal);
+ // vertical and horizontal were swapped at some point
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_MIRROR_HORZ_EVEN_PAGES:
+ case MID_MIRROR_HORZ_ODD_PAGES:
+ {
+ bool bIsVert = GetValue() == MirrorGraph::Horizontal ||
+ GetValue() == MirrorGraph::Both;
+ bool bOnOddPages = nMemberId == MID_MIRROR_HORZ_EVEN_PAGES ?
+ lcl_IsHoriOnOddPages(GetValue()) : bVal;
+ bool bOnEvenPages = nMemberId == MID_MIRROR_HORZ_ODD_PAGES ?
+ lcl_IsHoriOnEvenPages(GetValue(), IsGrfToggle()) : bVal;
+ MirrorGraph nEnum = bOnOddPages ?
+ bIsVert ? MirrorGraph::Both : MirrorGraph::Vertical :
+ bIsVert ? MirrorGraph::Horizontal : MirrorGraph::Dont;
+ bool bToggle = bOnOddPages != bOnEvenPages;
+ SetValue(nEnum);
+ SetGrfToggle( bToggle );
+ }
+ break;
+ case MID_MIRROR_VERT:
+ if ( bVal )
+ {
+ if ( GetValue() == MirrorGraph::Vertical )
+ SetValue( MirrorGraph::Both );
+ else if ( GetValue() != MirrorGraph::Both )
+ SetValue( MirrorGraph::Horizontal );
+ }
+ else
+ {
+ if ( GetValue() == MirrorGraph::Both )
+ SetValue( MirrorGraph::Vertical );
+ else if ( GetValue() == MirrorGraph::Horizontal )
+ SetValue( MirrorGraph::Dont );
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+SwCropGrf::SwCropGrf()
+ : SvxGrfCrop( RES_GRFATR_CROPGRF )
+{}
+
+SwCropGrf::SwCropGrf(sal_Int32 nL, sal_Int32 nR, sal_Int32 nT, sal_Int32 nB )
+ : SvxGrfCrop( nL, nR, nT, nB, RES_GRFATR_CROPGRF )
+{}
+
+SwCropGrf* SwCropGrf::Clone( SfxItemPool* ) const
+{
+ return new SwCropGrf( *this );
+}
+
+sal_Int16 SwRotationGrf::checkAndCorrectValue(sal_Int16 nValue)
+{
+ if(nValue < 0)
+ {
+ // smaller zero, modulo (will keep negative) and add one range
+ DBG_ASSERT(false, "SwRotationGrf: Value is in 10th degree and *has* to be in [0 .. 3600[ (!)");
+ return 3600 + (nValue % 3600);
+ }
+ else if (nValue >= 3600)
+ {
+ // bigger range, use modulo
+ DBG_ASSERT(false, "SwRotationGrf: Value is in 10th degree and *has* to be in [0 .. 3600[ (!)");
+ return nValue % 3600;
+ }
+
+ return nValue;
+}
+
+SwRotationGrf::SwRotationGrf( sal_Int16 nVal, const Size& rSz )
+ // tdf#115529 check and evtl. correct value
+: SfxUInt16Item( RES_GRFATR_ROTATION, checkAndCorrectValue(nVal) ),
+ m_aUnrotatedSize( rSz )
+{
+}
+
+SwRotationGrf* SwRotationGrf::Clone( SfxItemPool * ) const
+{
+ return new SwRotationGrf( *this );
+}
+
+bool SwRotationGrf::operator==( const SfxPoolItem& rCmp ) const
+{
+ return SfxUInt16Item::operator==( rCmp ) &&
+ GetUnrotatedSize() == static_cast<const SwRotationGrf&>(rCmp).GetUnrotatedSize();
+}
+
+bool SwRotationGrf::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ // SfxUInt16Item::QueryValue returns sal_Int32 in Any now... (srx642w)
+ // where we still want this to be a sal_Int16
+ rVal <<= static_cast<sal_Int16>(GetValue());
+ return true;
+}
+
+bool SwRotationGrf::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+ // SfxUInt16Item::QueryValue returns sal_Int32 in Any now... (srx642w)
+ // where we still want this to be a sal_Int16
+ sal_Int16 nValue = 0;
+ if (rVal >>= nValue)
+ {
+ // sal_uInt16 argument needed
+ // tdf#115529 check and evtl. correct value
+ SetValue(static_cast<sal_uInt16>(checkAndCorrectValue(nValue)));
+ return true;
+ }
+
+ OSL_FAIL( "SwRotationGrf::PutValue - Wrong type!" );
+ return false;
+}
+
+// Sw___Grf::Clone(..)
+
+SwLuminanceGrf* SwLuminanceGrf::Clone( SfxItemPool * ) const
+{
+ return new SwLuminanceGrf( *this );
+}
+
+SwContrastGrf* SwContrastGrf::Clone( SfxItemPool * ) const
+{
+ return new SwContrastGrf( *this );
+}
+
+SwChannelRGrf* SwChannelRGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelRGrf( *this );
+}
+
+SwChannelGGrf* SwChannelGGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelGGrf( *this );
+}
+
+SwChannelBGrf* SwChannelBGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelBGrf( *this );
+}
+
+SwGammaGrf* SwGammaGrf::Clone( SfxItemPool * ) const
+{
+ return new SwGammaGrf( *this );
+}
+
+// SwGammaGrf
+
+bool SwGammaGrf::operator==( const SfxPoolItem& rCmp ) const
+{
+ return SfxPoolItem::operator==( rCmp ) &&
+ m_nValue == static_cast<const SwGammaGrf&>(rCmp).GetValue();
+}
+
+bool SwGammaGrf::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ rVal <<= m_nValue;
+ return true;
+}
+
+bool SwGammaGrf::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+ return rVal >>= m_nValue;
+}
+
+// Sw___Grf::Clone(..) cont'd
+
+SwInvertGrf* SwInvertGrf::Clone( SfxItemPool * ) const
+{
+ return new SwInvertGrf( *this );
+}
+
+SwTransparencyGrf* SwTransparencyGrf::Clone( SfxItemPool * ) const
+{
+ return new SwTransparencyGrf( *this );
+}
+
+// SwTransparencyGrf
+
+bool SwTransparencyGrf::QueryValue( uno::Any& rVal,
+ sal_uInt8 ) const
+{
+ OSL_ENSURE(dynamic_cast<const SfxByteItem*>( this ) != nullptr,"Put/QueryValue should be removed!");
+ sal_Int16 nRet = GetValue();
+ OSL_ENSURE( 0 <= nRet && nRet <= 100, "value out of range" );
+ rVal <<= nRet;
+ return true;
+}
+
+bool SwTransparencyGrf::PutValue( const uno::Any& rVal,
+ sal_uInt8 )
+{
+ //temporary conversion until this is a SfxInt16Item!
+ OSL_ENSURE(dynamic_cast<const SfxByteItem*>( this ) != nullptr,"Put/QueryValue should be removed!");
+ sal_Int16 nVal = 0;
+ if(!(rVal >>= nVal) || nVal < -100 || nVal > 100)
+ return false;
+ if(nVal < 0)
+ {
+ // for compatibility with old documents
+ // introduce rounding as for SO 6.0 PP2
+ nVal = ( ( nVal * 128 ) - (99/2) ) / 100;
+ nVal += 128;
+ }
+ OSL_ENSURE( 0 <= nVal && nVal <= 100, "value out of range" );
+ SetValue(static_cast<sal_uInt8>(nVal));
+ return true;
+}
+
+// Sw___Grf::Clone(..) cont'd
+
+SwDrawModeGrf* SwDrawModeGrf::Clone( SfxItemPool * ) const
+{
+ return new SwDrawModeGrf( *this );
+}
+
+// SwDrawModeGrf
+
+sal_uInt16 SwDrawModeGrf::GetValueCount() const
+{
+ return sal_uInt16(GraphicDrawMode::Watermark) + 1;
+}
+
+bool SwDrawModeGrf::QueryValue( uno::Any& rVal,
+ sal_uInt8 ) const
+{
+ drawing::ColorMode eRet = static_cast<drawing::ColorMode>(GetEnumValue());
+ rVal <<= eRet;
+ return true;
+}
+
+bool SwDrawModeGrf::PutValue( const uno::Any& rVal,
+ sal_uInt8 )
+{
+ sal_Int32 eVal = SWUnoHelper::GetEnumAsInt32( rVal );
+ if(eVal >= 0 && eVal <= sal_uInt16(GraphicDrawMode::Watermark))
+ {
+ SetEnumValue(static_cast<sal_uInt16>(eVal));
+ return true;
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
new file mode 100644
index 000000000..bb39141cc
--- /dev/null
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -0,0 +1,874 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <tools/helpers.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/fract.hxx>
+#include <svl/fstathelper.hxx>
+#include <vcl/imap.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/boxitem.hxx>
+#include <sot/formats.hxx>
+#include <fmtfsize.hxx>
+#include <fmturl.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <frmatr.hxx>
+#include <grfatr.hxx>
+#include <swtypes.hxx>
+#include <ndgrf.hxx>
+#include <fmtcol.hxx>
+#include <hints.hxx>
+#include <swbaslnk.hxx>
+#include <pagefrm.hxx>
+
+#include <rtl/ustring.hxx>
+#include <o3tl/deleter.hxx>
+#include <retrieveinputstreamconsumer.hxx>
+#include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
+#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
+
+using namespace com::sun::star;
+
+SwGrfNode::SwGrfNode(
+ const SwNodeIndex & rWhere,
+ const OUString& rGrfName,
+ const OUString& rFltName,
+ const Graphic* pGraphic,
+ SwGrfFormatColl *pGrfColl,
+ SwAttrSet const * pAutoAttr ) :
+ SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
+ maGrfObj(),
+ mbInBaseLinkSwapIn(true),
+ // #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( false )
+{
+ mbInSwapIn = mbChangeTwipSize =
+ mbFrameInPaint = mbScaleImageMap = false;
+
+ ReRead(rGrfName, rFltName, pGraphic, false);
+}
+
+SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
+ const GraphicObject& rGrfObj,
+ SwGrfFormatColl *pGrfColl,
+ SwAttrSet const * pAutoAttr ) :
+ SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
+ maGrfObj(rGrfObj),
+ mbInBaseLinkSwapIn(true),
+ // #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( false )
+{
+ mbInSwapIn = mbChangeTwipSize =
+ mbFrameInPaint = mbScaleImageMap = false;
+}
+
+/** Create new SW/G reader.
+ *
+ * Use this ctor if you want to read a linked graphic.
+ *
+ * @note Does not read/open the image itself!
+ */
+SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
+ const OUString& rGrfName,
+ const OUString& rFltName,
+ SwGrfFormatColl *pGrfColl,
+ SwAttrSet const * pAutoAttr ) :
+ SwNoTextNode( rWhere, SwNodeType::Grf, pGrfColl, pAutoAttr ),
+ maGrfObj(),
+ mbInBaseLinkSwapIn(true),
+ // #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( false )
+{
+ Graphic aGrf; aGrf.SetDefaultType();
+ maGrfObj.SetGraphic( aGrf, rGrfName );
+
+ mbInSwapIn = mbChangeTwipSize =
+ mbFrameInPaint = mbScaleImageMap = false;
+
+ InsertLink( rGrfName, rFltName );
+ if( IsLinkedFile() )
+ {
+ INetURLObject aUrl( rGrfName );
+ if( INetProtocol::File == aUrl.GetProtocol() &&
+ FStatHelper::IsDocument( aUrl.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ))
+ {
+ // file exists, so create connection without an update
+ static_cast<SwBaseLink*>( mxLink.get() )->Connect();
+ }
+ }
+}
+
+bool SwGrfNode::ReRead(
+ const OUString& rGrfName, const OUString& rFltName,
+ const Graphic* pGraphic,
+ bool bNewGrf )
+{
+ bool bReadGrf = false;
+ bool bSetTwipSize = true;
+ mpReplacementGraphic.reset();
+
+ OSL_ENSURE( pGraphic || !rGrfName.isEmpty(),
+ "GraphicNode without a name, Graphic or GraphicObject" );
+
+ OUString sURLLink;
+ if (pGraphic)
+ {
+ Graphic aGraphic(*pGraphic);
+
+ sURLLink = aGraphic.getOriginURL();
+ if (sURLLink.isEmpty() && !rGrfName.isEmpty())
+ {
+ sURLLink = rGrfName;
+ aGraphic.setOriginURL(sURLLink);
+ }
+ }
+ else
+ {
+ sURLLink = rGrfName;
+ }
+
+ // with name
+ if( mxLink.is() )
+ {
+ OSL_ENSURE( !mbInSwapIn, "ReRead: I am still in SwapIn" );
+
+ if( !sURLLink.isEmpty() )
+ {
+ // Note: if there is DDE in the FltName, then it is a DDE-linked graphic
+ OUString sCmd( sURLLink );
+ if( !rFltName.isEmpty() )
+ {
+ sfx2::SvBaseLinkObjectType nNewType;
+ if( rFltName == "DDE" )
+ nNewType = sfx2::SvBaseLinkObjectType::ClientDde;
+ else
+ {
+ sfx2::MakeLnkName( sCmd, nullptr, sURLLink, OUString(), &rFltName );
+ nNewType = sfx2::SvBaseLinkObjectType::ClientGraphic;
+ }
+
+ if( nNewType != mxLink->GetObjType() )
+ {
+ mxLink->Disconnect();
+ static_cast<SwBaseLink*>( mxLink.get() )->SetObjType( nNewType );
+ }
+ }
+
+ mxLink->SetLinkSourceName( sCmd );
+ }
+ else // no name anymore, so remove link
+ {
+ GetDoc()->getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
+ mxLink.clear();
+ }
+
+ if( pGraphic )
+ {
+ maGrfObj.SetGraphic( *pGraphic, sURLLink );
+ onGraphicChanged();
+ bReadGrf = true;
+ }
+ else
+ {
+ // reset data of the old graphic so that the correct placeholder is
+ // shown in case the new link could not be loaded
+ Graphic aGrf; aGrf.SetDefaultType();
+ maGrfObj.SetGraphic( aGrf, sURLLink );
+
+ if( mxLink.is() )
+ {
+ if( getLayoutFrame( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() ) )
+ {
+ SwMsgPoolItem aMsgHint( RES_GRF_REREAD_AND_INCACHE );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ else if ( bNewGrf )
+ {
+ //TODO refLink->setInputStream(getInputStream());
+ static_cast<SwBaseLink*>( mxLink.get() )->SwapIn();
+ }
+ }
+ onGraphicChanged();
+ bSetTwipSize = false;
+ }
+ }
+ else if( pGraphic && sURLLink.isEmpty() )
+ {
+ maGrfObj.SetGraphic( *pGraphic );
+ onGraphicChanged();
+ bReadGrf = true;
+ }
+ // Was the graphic already loaded?
+ else if( !bNewGrf && GraphicType::NONE != maGrfObj.GetType() )
+ return true;
+ else
+ {
+ // create new link for the graphic object
+ InsertLink( sURLLink, rFltName );
+
+ if( GetNodes().IsDocNodes() )
+ {
+ if( pGraphic )
+ {
+ maGrfObj.SetGraphic( *pGraphic, sURLLink );
+ onGraphicChanged();
+ bReadGrf = true;
+ // create connection without update, as we have the graphic
+ static_cast<SwBaseLink*>( mxLink.get() )->Connect();
+ }
+ else
+ {
+ Graphic aGrf;
+ aGrf.SetDefaultType();
+ maGrfObj.SetGraphic( aGrf, sURLLink );
+ onGraphicChanged();
+ if ( bNewGrf )
+ {
+ static_cast<SwBaseLink*>( mxLink.get() )->SwapIn();
+ }
+ }
+ }
+ }
+
+ // Bug 39281: Do not delete Size immediately - Events on ImageMaps should have
+ // something to work with when swapping
+ if( bSetTwipSize )
+ SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
+
+ // create an updates for the frames
+ if( bReadGrf && bNewGrf )
+ {
+ SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ return bReadGrf;
+}
+
+SwGrfNode::~SwGrfNode()
+{
+ mpReplacementGraphic.reset();
+
+ // #i73788#
+ mpThreadConsumer.reset();
+
+ SwDoc* pDoc = GetDoc();
+ if( mxLink.is() )
+ {
+ OSL_ENSURE( !mbInSwapIn, "DTOR: I am still in SwapIn" );
+ pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
+ mxLink->Disconnect();
+ }
+ else
+ {
+ // #i40014# - A graphic node, which is in a linked
+ // section, whose link is another section in the document, doesn't
+ // have to remove the stream from the storage.
+ // Because it's hard to detect this case here and it would only fix
+ // one problem with shared graphic files - there are also problems,
+ // a certain graphic file is referenced by two independent graphic nodes,
+ // brush item or drawing objects, the stream isn't no longer removed here.
+ // To do this stuff correctly, a reference counting on shared streams
+ // inside one document has to be implemented.
+ }
+ //#39289# delete frames already here since the Frames' dtor needs the graphic for its StopAnimation
+ if( HasWriterListeners() )
+ DelFrames(nullptr);
+}
+
+/// allow reaction on change of content of GraphicObject
+void SwGrfNode::onGraphicChanged()
+{
+ // try to access SwFlyFrameFormat; since title/desc/name are set there, there is no
+ // use to continue if it is not yet set. If not yet set, call onGraphicChanged()
+ // when it is set.
+ SwFlyFrameFormat* pFlyFormat = dynamic_cast< SwFlyFrameFormat* >(GetFlyFormat());
+
+ if(pFlyFormat)
+ {
+ OUString aName;
+ OUString aTitle;
+ OUString aDesc;
+ auto const & rVectorGraphicDataPtr = GetGrf().getVectorGraphicData();
+
+ if (rVectorGraphicDataPtr)
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVectorGraphicDataPtr->getPrimitive2DSequence());
+
+ if(!aSequence.empty())
+ {
+ drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+ drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
+
+ aProcessor.process(aSequence);
+
+ const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
+
+ if(pResult)
+ {
+ aName = pResult->getName();
+ aTitle = pResult->getTitle();
+ aDesc = pResult->getDesc();
+ }
+ }
+ }
+
+ if(!aTitle.isEmpty())
+ {
+ SetTitle(aTitle);
+ }
+ else if (!aName.isEmpty())
+ {
+ SetTitle(aName);
+ }
+
+ if(!aDesc.isEmpty())
+ {
+ SetDescription(aDesc);
+ }
+ }
+}
+
+void SwGrfNode::SetGraphic(const Graphic& rGraphic)
+{
+ maGrfObj.SetGraphic(rGraphic, OUString());
+ onGraphicChanged();
+}
+
+const Graphic& SwGrfNode::GetGrf(bool bWait) const
+{
+ const_cast<SwGrfNode*>(this)->SwapIn(bWait);
+ return maGrfObj.GetGraphic();
+}
+
+const GraphicObject& SwGrfNode::GetGrfObj(bool bWait) const
+{
+ const_cast<SwGrfNode*>(this)->SwapIn(bWait);
+ return maGrfObj;
+}
+
+const GraphicObject* SwGrfNode::GetReplacementGrfObj() const
+{
+ if(!mpReplacementGraphic)
+ {
+ auto const & rVectorGraphicDataPtr = GetGrfObj().GetGraphic().getVectorGraphicData();
+
+ if (rVectorGraphicDataPtr)
+ {
+ const_cast< SwGrfNode* >(this)->mpReplacementGraphic.reset( new GraphicObject(rVectorGraphicDataPtr->getReplacement()) );
+ }
+ else if (GetGrfObj().GetGraphic().GetType() == GraphicType::GdiMetafile)
+ {
+ // Replacement graphic for PDF and metafiles is just the bitmap.
+ const_cast<SwGrfNode*>(this)->mpReplacementGraphic.reset( new GraphicObject(GetGrfObj().GetGraphic().GetBitmapEx()) );
+ }
+ }
+
+ return mpReplacementGraphic.get();
+}
+
+SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
+ const OUString& rGrfName,
+ const OUString& rFltName,
+ const Graphic* pGraphic,
+ SwGrfFormatColl* pGrfColl,
+ SwAttrSet const * pAutoAttr )
+{
+ OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer is 0." );
+ SwGrfNode *pNode;
+ // create object delayed, only from a SW/G-reader
+ if( !pGraphic )
+ pNode = new SwGrfNode( rWhere, rGrfName,
+ rFltName, pGrfColl, pAutoAttr );
+ else
+ pNode = new SwGrfNode( rWhere, rGrfName,
+ rFltName, pGraphic, pGrfColl, pAutoAttr );
+ return pNode;
+}
+
+SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
+ const GraphicObject& rGrfObj,
+ SwGrfFormatColl* pGrfColl )
+{
+ OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer is 0." );
+ return new SwGrfNode( rWhere, rGrfObj, pGrfColl, nullptr );
+}
+
+Size SwGrfNode::GetTwipSize() const
+{
+ if( !mnGrfSize.Width() && !mnGrfSize.Height() )
+ {
+ const_cast<SwGrfNode*>(this)->SwapIn();
+ }
+ return mnGrfSize;
+}
+
+/**
+ * @return true if ReRead or reading successful,
+ * false if not loaded
+ */
+bool SwGrfNode::SwapIn(bool bWaitForData)
+{
+ if(mbInSwapIn) // not recursively!
+ return true;
+
+ bool bRet = false;
+ mbInSwapIn = true;
+ SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
+
+ if( pLink )
+ {
+ if( (GraphicType::NONE == maGrfObj.GetType() ||
+ GraphicType::Default == maGrfObj.GetType()) &&
+ mbInBaseLinkSwapIn)
+ {
+ // link was not loaded yet
+ if( pLink->SwapIn( bWaitForData ) )
+ {
+ bRet = true;
+ mbInBaseLinkSwapIn = false;
+ }
+ else if( GraphicType::Default == maGrfObj.GetType() )
+ {
+ // no default bitmap anymore, thus re-paint
+ mpReplacementGraphic.reset();
+
+ maGrfObj.SetGraphic( Graphic() );
+ onGraphicChanged();
+ SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ else
+ {
+ bRet = true;
+ }
+ }
+ else
+ bRet = true;
+
+ if (bRet)
+ {
+ if( !mnGrfSize.Width() && !mnGrfSize.Height() )
+ SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
+ }
+ mbInSwapIn = false;
+ return bRet;
+}
+
+bool SwGrfNode::GetFileFilterNms( OUString* pFileNm, OUString* pFilterNm ) const
+{
+ bool bRet = false;
+ if( mxLink.is() && mxLink->GetLinkManager() )
+ {
+ sfx2::SvBaseLinkObjectType nType = mxLink->GetObjType();
+ if( sfx2::SvBaseLinkObjectType::ClientGraphic == nType )
+ bRet = sfx2::LinkManager::GetDisplayNames(
+ mxLink.get(), nullptr, pFileNm, nullptr, pFilterNm );
+ else if( sfx2::SvBaseLinkObjectType::ClientDde == nType && pFileNm && pFilterNm )
+ {
+ OUString sApp;
+ OUString sTopic;
+ OUString sItem;
+ if( sfx2::LinkManager::GetDisplayNames(
+ mxLink.get(), &sApp, &sTopic, &sItem ) )
+ {
+ *pFileNm = sApp + OUStringChar(sfx2::cTokenSeparator)
+ + sTopic + OUStringChar(sfx2::cTokenSeparator)
+ + sItem;
+ *pFilterNm = "DDE";
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+/** Make a graphic object ready for UNDO.
+ *
+ * If it is already in storage, it needs to be loaded.
+ */
+bool SwGrfNode::SavePersistentData()
+{
+ if( mxLink.is() )
+ {
+ OSL_ENSURE( !mbInSwapIn, "SavePersistentData: I am still in SwapIn" );
+ GetDoc()->getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
+ return true;
+ }
+
+ // swap in first if in storage
+ if( HasEmbeddedStreamName() && !SwapIn() )
+ return false;
+
+ // #i44367#
+ // Do not delete graphic file in storage, because the graphic file could
+ // be referenced by other graphic nodes.
+ // Because it's hard to detect this case here and it would only fix
+ // one problem with shared graphic files - there are also problems, if
+ // a certain graphic file is referenced by two independent graphic nodes,
+ // brush item or drawing objects, the stream isn't no longer removed here.
+ // To do this stuff correct, a reference counting on shared streams
+ // inside one document has to be implemented.
+ // Important note: see also fix for #i40014#
+
+ // swap out into temp file
+ return true;
+}
+
+bool SwGrfNode::RestorePersistentData()
+{
+ if( mxLink.is() )
+ {
+ IDocumentLinksAdministration& rIDLA = getIDocumentLinksAdministration();
+ mxLink->SetVisible( rIDLA.IsVisibleLinks() );
+ rIDLA.GetLinkManager().InsertDDELink( mxLink.get() );
+ if( getIDocumentLayoutAccess().GetCurrentLayout() )
+ mxLink->Update();
+ }
+ return true;
+}
+
+void SwGrfNode::InsertLink( const OUString& rGrfName, const OUString& rFltName )
+{
+ mxLink = new SwBaseLink( SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::GDIMETAFILE, this );
+
+ IDocumentLinksAdministration& rIDLA = getIDocumentLinksAdministration();
+ if( GetNodes().IsDocNodes() )
+ {
+ mxLink->SetVisible( rIDLA.IsVisibleLinks() );
+ if( rFltName == "DDE" )
+ {
+ sal_Int32 nTmp = 0;
+ const OUString sApp{ rGrfName.getToken( 0, sfx2::cTokenSeparator, nTmp ) };
+ const OUString sTopic{ rGrfName.getToken( 0, sfx2::cTokenSeparator, nTmp ) };
+ const OUString sItem{ rGrfName.copy( nTmp ) };
+ rIDLA.GetLinkManager().InsertDDELink( mxLink.get(), sApp, sTopic, sItem );
+ }
+ else
+ {
+ const bool bSync = rFltName == "SYNCHRON";
+ mxLink->SetSynchron( bSync );
+ mxLink->SetContentType( SotClipboardFormatId::SVXB );
+
+ rIDLA.GetLinkManager().InsertFileLink( *mxLink,
+ sfx2::SvBaseLinkObjectType::ClientGraphic, rGrfName,
+ (!bSync && !rFltName.isEmpty() ? &rFltName : nullptr) );
+ }
+ }
+}
+
+void SwGrfNode::ReleaseLink()
+{
+ if( mxLink.is() )
+ {
+ Graphic aLocalGraphic(maGrfObj.GetGraphic());
+ const bool bHasOriginalData(aLocalGraphic.IsGfxLink());
+
+ {
+ mbInSwapIn = true;
+ SwBaseLink* pLink = static_cast<SwBaseLink*>( mxLink.get() );
+ pLink->SwapIn( true, true );
+ mbInSwapIn = false;
+ }
+
+ getIDocumentLinksAdministration().GetLinkManager().Remove( mxLink.get() );
+ mxLink.clear();
+ aLocalGraphic.setOriginURL("");
+
+ // #i15508# added extra processing after getting rid of the link. Use whatever is
+ // known from the formerly linked graphic to get to a state as close to a directly
+ // unlinked inserted graphic as possible. Goal is to have a valid GfxLink at the
+ // ImplGraphic (see there) that holds temporary data to the original data and type
+ // information about the original data. Only when this is given will
+ // SvXMLGraphicHelper::ImplInsertGraphicURL which is used at export use that type
+ // and use the original graphic at export for the ODF, without evtl. recoding
+ // of the bitmap graphic data to something without loss (e.g. PNG) but bigger
+ if(bHasOriginalData)
+ {
+ // #i15508# if we have the original data at the Graphic, let it survive
+ // by using that Graphic again, this time at a GraphicObject without link.
+ // This happens e.g. when inserting a linked graphic and breaking the link
+ maGrfObj.SetGraphic(aLocalGraphic);
+ }
+ }
+}
+
+void SwGrfNode::SetTwipSize( const Size& rSz )
+{
+ mnGrfSize = rSz;
+ if( IsScaleImageMap() && mnGrfSize.Width() && mnGrfSize.Height() )
+ {
+ // resize Image-Map to size of the graphic
+ ScaleImageMap();
+
+ // do not re-scale Image-Map
+ SetScaleImageMap( false );
+ }
+}
+
+void SwGrfNode::ScaleImageMap()
+{
+ if( !mnGrfSize.Width() || !mnGrfSize.Height() )
+ return;
+
+ // re-scale Image-Map
+ SwFrameFormat* pFormat = GetFlyFormat();
+
+ if( !pFormat )
+ return;
+
+ SwFormatURL aURL( pFormat->GetURL() );
+ if ( !aURL.GetMap() )
+ return;
+
+ bool bScale = false;
+ Fraction aScaleX( 1, 1 );
+ Fraction aScaleY( 1, 1 );
+
+ const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize();
+ const SvxBoxItem& rBox = pFormat->GetBox();
+
+ if( !rFrameSize.GetWidthPercent() )
+ {
+ SwTwips nWidth = rFrameSize.GetWidth();
+
+ nWidth -= rBox.CalcLineSpace(SvxBoxItemLine::LEFT) +
+ rBox.CalcLineSpace(SvxBoxItemLine::RIGHT);
+
+ OSL_ENSURE( nWidth>0, "Do any 0 twip wide graphics exist!?" );
+
+ if( mnGrfSize.Width() != nWidth )
+ {
+ aScaleX = Fraction( mnGrfSize.Width(), nWidth );
+ bScale = true;
+ }
+ }
+ if( !rFrameSize.GetHeightPercent() )
+ {
+ SwTwips nHeight = rFrameSize.GetHeight();
+
+ nHeight -= rBox.CalcLineSpace(SvxBoxItemLine::TOP) +
+ rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM);
+
+ OSL_ENSURE( nHeight>0, "Do any 0 twip high graphics exist!?" );
+
+ if( mnGrfSize.Height() != nHeight )
+ {
+ aScaleY = Fraction( mnGrfSize.Height(), nHeight );
+ bScale = true;
+ }
+ }
+
+ if( bScale )
+ {
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ pFormat->SetFormatAttr( aURL );
+ }
+}
+
+SwContentNode* SwGrfNode::MakeCopy(SwDoc* pDoc, const SwNodeIndex& rIdx, bool) const
+{
+ // copy formats into the other document
+ SwGrfFormatColl* pColl = pDoc->CopyGrfColl( *GetGrfColl() );
+
+ Graphic aTmpGrf = GetGrf();
+
+ OUString sFile, sFilter;
+ if( IsLinkedFile() )
+ sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sFile, nullptr, &sFilter );
+ else if( IsLinkedDDE() )
+ {
+ OUString sTmp1, sTmp2;
+ sfx2::LinkManager::GetDisplayNames( mxLink.get(), &sTmp1, &sTmp2, &sFilter );
+ sfx2::MakeLnkName( sFile, &sTmp1, sTmp2, sFilter );
+ sFilter = "DDE";
+ }
+
+ SwGrfNode* pGrfNd = SwNodes::MakeGrfNode( rIdx, sFile, sFilter,
+ &aTmpGrf, pColl,
+ GetpSwAttrSet() );
+ pGrfNd->SetTitle( GetTitle() );
+ pGrfNd->SetDescription( GetDescription() );
+ pGrfNd->SetContour( HasContour(), HasAutomaticContour() );
+ return pGrfNd;
+}
+
+/// returns the Graphic-Attr-Structure filled with our graphic attributes
+GraphicAttr& SwGrfNode::GetGraphicAttr( GraphicAttr& rGA,
+ const SwFrame* pFrame ) const
+{
+ const SwAttrSet& rSet = GetSwAttrSet();
+
+ rGA.SetDrawMode( rSet.GetDrawModeGrf().GetValue() );
+
+ const SwMirrorGrf & rMirror = rSet.GetMirrorGrf();
+ BmpMirrorFlags nMirror = BmpMirrorFlags::NONE;
+ if( rMirror.IsGrfToggle() && pFrame && !pFrame->FindPageFrame()->OnRightPage() )
+ {
+ switch( rMirror.GetValue() )
+ {
+ case MirrorGraph::Dont:
+ nMirror = BmpMirrorFlags::Horizontal;
+ break;
+ case MirrorGraph::Vertical:
+ nMirror = BmpMirrorFlags::NONE;
+ break;
+ case MirrorGraph::Horizontal:
+ nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
+ break;
+ default:
+ nMirror = BmpMirrorFlags::Vertical;
+ break;
+ }
+ }
+ else
+ switch( rMirror.GetValue() )
+ {
+ case MirrorGraph::Both:
+ nMirror = BmpMirrorFlags::Horizontal|BmpMirrorFlags::Vertical;
+ break;
+ case MirrorGraph::Vertical:
+ nMirror = BmpMirrorFlags::Horizontal;
+ break;
+ case MirrorGraph::Horizontal:
+ nMirror = BmpMirrorFlags::Vertical;
+ break;
+ default: break;
+ }
+
+ rGA.SetMirrorFlags( nMirror );
+
+ const SwCropGrf& rCrop = rSet.GetCropGrf();
+ rGA.SetCrop( convertTwipToMm100( rCrop.GetLeft() ),
+ convertTwipToMm100( rCrop.GetTop() ),
+ convertTwipToMm100( rCrop.GetRight() ),
+ convertTwipToMm100( rCrop.GetBottom() ));
+
+ const SwRotationGrf& rRotation = rSet.GetRotationGrf();
+ rGA.SetRotation( rRotation.GetValue() );
+
+ rGA.SetLuminance( rSet.GetLuminanceGrf().GetValue() );
+ rGA.SetContrast( rSet.GetContrastGrf().GetValue() );
+ rGA.SetChannelR( rSet.GetChannelRGrf().GetValue() );
+ rGA.SetChannelG( rSet.GetChannelGGrf().GetValue() );
+ rGA.SetChannelB( rSet.GetChannelBGrf().GetValue() );
+ rGA.SetGamma( rSet.GetGammaGrf().GetValue() );
+ rGA.SetInvert( rSet.GetInvertGrf().GetValue() );
+
+ const sal_uInt16 nTrans = rSet.GetTransparencyGrf().GetValue();
+ rGA.SetTransparency( static_cast<sal_uInt8>(FRound(
+ std::min( nTrans, sal_uInt16(100) ) * 2.55 )) );
+
+ return rGA;
+}
+
+bool SwGrfNode::IsTransparent() const
+{
+ return maGrfObj.IsTransparent() ||
+ GetSwAttrSet().GetTransparencyGrf().GetValue() != 0;
+}
+
+void SwGrfNode::TriggerAsyncRetrieveInputStream()
+{
+ if ( !IsLinkedFile() )
+ {
+ OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
+ return;
+ }
+
+ if (mpThreadConsumer == nullptr)
+ {
+ mpThreadConsumer.reset(new SwAsyncRetrieveInputStreamThreadConsumer(*this), o3tl::default_delete<SwAsyncRetrieveInputStreamThreadConsumer>());
+
+ OUString sGrfNm;
+ sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
+ OUString sReferer;
+ SfxObjectShell * sh = GetDoc()->GetPersist();
+ if (sh != nullptr && sh->HasName())
+ {
+ sReferer = sh->GetMedium()->GetName();
+ }
+ mpThreadConsumer->CreateThread( sGrfNm, sReferer );
+ }
+}
+
+
+void SwGrfNode::ApplyInputStream(
+ const css::uno::Reference<css::io::XInputStream>& xInputStream,
+ const bool bIsStreamReadOnly )
+{
+ if ( IsLinkedFile() )
+ {
+ if ( xInputStream.is() )
+ {
+ mxInputStream = xInputStream;
+ mbIsStreamReadOnly = bIsStreamReadOnly;
+ mbLinkedInputStreamReady = true;
+ SwMsgPoolItem aMsgHint( RES_LINKED_GRAPHIC_STREAM_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+}
+
+void SwGrfNode::UpdateLinkWithInputStream()
+{
+ // do not work on link, if a <SwapIn> has been triggered.
+ if ( !mbInSwapIn && IsLinkedFile() )
+ {
+ GetLink()->setStreamToLoadFrom( mxInputStream, mbIsStreamReadOnly );
+ GetLink()->Update();
+ SwMsgPoolItem aMsgHint( RES_GRAPHIC_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+
+ // #i88291#
+ mxInputStream.clear();
+ GetLink()->clearStreamToLoadFrom();
+ mbLinkedInputStreamReady = false;
+ mpThreadConsumer.reset();
+ }
+}
+
+// #i90395#
+bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
+{
+ bool bRet = false;
+
+ if ( IsLinkedFile() )
+ {
+ OUString sGrfNm;
+ sfx2::LinkManager::GetDisplayNames( mxLink.get(), nullptr, &sGrfNm );
+ if ( !sGrfNm.startsWith( "vnd.sun.star.pkg:" ) )
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */