Kaydet (Commit) 611be3d7 authored tarafından László Németh's avatar László Németh Kaydeden (comit) Andras Timar

tdf#95614 fix freezing with linked graphic

When an unloaded linked picture comes into the visible view
(including repainting a page), SwNoTextFrm::PaintPicture()
starts a thread to load it in the background using the
TriggerAsyncRetrieveInputStream() method of the graphic node.

To avoid to start a second thread on the same graphic node,
TriggerAsyncRetrieveInputStream() checks mpThreadConsumer,
the graphic node member variable for the possible thread object.

The problem is that when the thread finished and
SwGrfNode::UpdateLinkWithInputStream() reset mpThreadConsumer,
the graphic object of the graphic node is still in unloaded
state (its type is GRAPHIC_DEFAULT or GRAPHIC_NONE instead of
GRAPHIC_BITMAP or GRAPHIC_GDIMETAFILE) for a while, because
its modification is solved asynchronously after several
SvFileObject::GetData() calls. In the intermediate state
of the graphic object, with the high priority repaints of
the new scheduler, PaintPicture() could start new thread
to load the image again.

Using the new member variable SwGrfNode::mbUpdateLinkInProgress,
this patch will prevent the graphic node to start newer thread
unnecessarily.

Change-Id: I9433f0fa4613294103a00a3955fc2f35d8863b59
üst 30b19ad1
...@@ -51,6 +51,7 @@ class SW_DLLPUBLIC SwGrfNode: public SwNoTextNode ...@@ -51,6 +51,7 @@ class SW_DLLPUBLIC SwGrfNode: public SwNoTextNode
boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer; boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer;
bool mbLinkedInputStreamReady; bool mbLinkedInputStreamReady;
bool mbUpdateLinkInProgress;
com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream; com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream;
bool mbIsStreamReadOnly; bool mbIsStreamReadOnly;
...@@ -198,6 +199,8 @@ public: ...@@ -198,6 +199,8 @@ public:
boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > GetThreadConsumer() { return mpThreadConsumer;} boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > GetThreadConsumer() { return mpThreadConsumer;}
bool IsLinkedInputStreamReady() const { return mbLinkedInputStreamReady;} bool IsLinkedInputStreamReady() const { return mbLinkedInputStreamReady;}
bool IsUpdateLinkInProgress() const { return mbUpdateLinkInProgress;}
void SetUpdateLinkInProgress(bool b) { mbUpdateLinkInProgress = b; }
void TriggerAsyncRetrieveInputStream(); void TriggerAsyncRetrieveInputStream();
void ApplyInputStream( void ApplyInputStream(
com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream, com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
......
...@@ -897,10 +897,11 @@ void SwNoTextFrm::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfArea ...@@ -897,10 +897,11 @@ void SwNoTextFrm::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfArea
{ {
Size aTmpSz; Size aTmpSz;
::sfx2::SvLinkSource* pGrfObj = pGrfNd->GetLink()->GetObj(); ::sfx2::SvLinkSource* pGrfObj = pGrfNd->GetLink()->GetObj();
if( !pGrfObj || if ( ( !pGrfObj ||
!pGrfObj->IsDataComplete() || !pGrfObj->IsDataComplete() ||
!(aTmpSz = pGrfNd->GetTwipSize()).Width() || !(aTmpSz = pGrfNd->GetTwipSize()).Width() ||
!aTmpSz.Height() || !pGrfNd->GetAutoFormatLvl() ) !aTmpSz.Height() || !pGrfNd->GetAutoFormatLvl() ) &&
!pGrfNd->IsUpdateLinkInProgress() )
{ {
pGrfNd->TriggerAsyncRetrieveInputStream(); // #i73788# pGrfNd->TriggerAsyncRetrieveInputStream(); // #i73788#
} }
...@@ -909,9 +910,13 @@ void SwNoTextFrm::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfArea ...@@ -909,9 +910,13 @@ void SwNoTextFrm::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfArea
GetRealURL( *pGrfNd, aText ); GetRealURL( *pGrfNd, aText );
::lcl_PaintReplacement( aAlignedGrfArea, aText, *pShell, this, false ); ::lcl_PaintReplacement( aAlignedGrfArea, aText, *pShell, this, false );
bContinue = false; bContinue = false;
} else if ( rGrfObj.GetType() != GRAPHIC_DEFAULT &&
rGrfObj.GetType() != GRAPHIC_NONE &&
pGrfNd->IsUpdateLinkInProgress() )
{
pGrfNd->SetUpdateLinkInProgress( false );
} }
} }
if( bContinue ) if( bContinue )
{ {
if( rGrfObj.GetGraphic().IsSupportedGraphic()) if( rGrfObj.GetGraphic().IsSupportedGraphic())
......
...@@ -71,6 +71,7 @@ SwGrfNode::SwGrfNode( ...@@ -71,6 +71,7 @@ SwGrfNode::SwGrfNode(
mpReplacementGraphic(0), mpReplacementGraphic(0),
// #i73788# // #i73788#
mbLinkedInputStreamReady( false ), mbLinkedInputStreamReady( false ),
mbUpdateLinkInProgress( false ),
mbIsStreamReadOnly( false ) mbIsStreamReadOnly( false )
{ {
maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) ); maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) );
...@@ -89,6 +90,7 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere, ...@@ -89,6 +90,7 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
mpReplacementGraphic(0), mpReplacementGraphic(0),
// #i73788# // #i73788#
mbLinkedInputStreamReady( false ), mbLinkedInputStreamReady( false ),
mbUpdateLinkInProgress( false ),
mbIsStreamReadOnly( false ) mbIsStreamReadOnly( false )
{ {
maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) ); maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) );
...@@ -112,6 +114,7 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere, ...@@ -112,6 +114,7 @@ SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
mpReplacementGraphic(0), mpReplacementGraphic(0),
// #i73788# // #i73788#
mbLinkedInputStreamReady( false ), mbLinkedInputStreamReady( false ),
mbUpdateLinkInProgress( false ),
mbIsStreamReadOnly( false ) mbIsStreamReadOnly( false )
{ {
maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) ); maGrfObj.SetSwapStreamHdl( LINK(this, SwGrfNode, SwapGraphic) );
...@@ -521,7 +524,6 @@ bool SwGrfNode::SwapIn( bool bWaitForData ) ...@@ -521,7 +524,6 @@ bool SwGrfNode::SwapIn( bool bWaitForData )
bool bRet = false; bool bRet = false;
bInSwapIn = true; bInSwapIn = true;
SwBaseLink* pLink = static_cast<SwBaseLink*>((::sfx2::SvBaseLink*) refLink); SwBaseLink* pLink = static_cast<SwBaseLink*>((::sfx2::SvBaseLink*) refLink);
if( pLink ) if( pLink )
{ {
if( GRAPHIC_NONE == maGrfObj.GetType() || if( GRAPHIC_NONE == maGrfObj.GetType() ||
...@@ -1089,7 +1091,6 @@ void SwGrfNode::TriggerAsyncRetrieveInputStream() ...@@ -1089,7 +1091,6 @@ void SwGrfNode::TriggerAsyncRetrieveInputStream()
OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" ); OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
return; return;
} }
if ( mpThreadConsumer.get() == 0 ) if ( mpThreadConsumer.get() == 0 )
{ {
mpThreadConsumer.reset( new SwAsyncRetrieveInputStreamThreadConsumer( *this ) ); mpThreadConsumer.reset( new SwAsyncRetrieveInputStreamThreadConsumer( *this ) );
...@@ -1104,6 +1105,7 @@ void SwGrfNode::TriggerAsyncRetrieveInputStream() ...@@ -1104,6 +1105,7 @@ void SwGrfNode::TriggerAsyncRetrieveInputStream()
} }
mpThreadConsumer->CreateThread( sGrfNm, sReferer ); mpThreadConsumer->CreateThread( sGrfNm, sReferer );
} }
} }
...@@ -1137,6 +1139,7 @@ void SwGrfNode::UpdateLinkWithInputStream() ...@@ -1137,6 +1139,7 @@ void SwGrfNode::UpdateLinkWithInputStream()
// #i88291# // #i88291#
mxInputStream.clear(); mxInputStream.clear();
GetLink()->clearStreamToLoadFrom(); GetLink()->clearStreamToLoadFrom();
mbUpdateLinkInProgress = true;
mbLinkedInputStreamReady = false; mbLinkedInputStreamReady = false;
mpThreadConsumer.reset(); mpThreadConsumer.reset();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment