blob: df9d012c037c25c80f26a94af540140b96c8daf4 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <svx/sdr/contact/viewobjectcontactofgraphic.hxx>
#include <svx/sdr/contact/viewcontactofgraphic.hxx>
#include <svx/sdr/event/eventhandler.hxx>
#include <svx/svdograf.hxx>
#include <svx/sdr/contact/objectcontact.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
//////////////////////////////////////////////////////////////////////////////
namespace sdr
{
namespace event
{
class AsynchGraphicLoadingEvent : public BaseEvent
{
// the ViewContactOfGraphic to work with
sdr::contact::ViewObjectContactOfGraphic& mrVOCOfGraphic;
public:
// basic constructor.
AsynchGraphicLoadingEvent(EventHandler& rEventHandler, sdr::contact::ViewObjectContactOfGraphic& rVOCOfGraphic);
// destructor
virtual ~AsynchGraphicLoadingEvent();
// the called method if the event is triggered
virtual void ExecuteEvent();
};
AsynchGraphicLoadingEvent::AsynchGraphicLoadingEvent(
EventHandler& rEventHandler, sdr::contact::ViewObjectContactOfGraphic& rVOCOfGraphic)
: BaseEvent(rEventHandler),
mrVOCOfGraphic(rVOCOfGraphic)
{
}
AsynchGraphicLoadingEvent::~AsynchGraphicLoadingEvent()
{
mrVOCOfGraphic.forgetAsynchGraphicLoadingEvent(this);
}
void AsynchGraphicLoadingEvent::ExecuteEvent()
{
mrVOCOfGraphic.doAsynchGraphicLoading();
}
} // end of namespace event
} // end of namespace sdr
//////////////////////////////////////////////////////////////////////////////
namespace sdr
{
namespace contact
{
// Test graphics state and eventually trigger a SwapIn event or an Asynchronous
// load event. Return value gives info if SwapIn was triggered or not
bool ViewObjectContactOfGraphic::impPrepareGraphicWithAsynchroniousLoading()
{
bool bRetval(false);
SdrGrafObj& rGrafObj = getSdrGrafObj();
if(rGrafObj.IsSwappedOut())
{
if(rGrafObj.IsLinkedGraphic())
{
// update graphic link
rGrafObj.ImpUpdateGraphicLink();
}
else
{
// SwapIn needs to be done. Decide if it can be done asynchronious.
bool bSwapInAsynchronious(false);
ObjectContact& rObjectContact = GetObjectContact();
// only when allowed from configuration
if(rObjectContact.IsAsynchronGraphicsLoadingAllowed())
{
// direct output or vdev output (PageView buffering)
if(rObjectContact.isOutputToWindow() || rObjectContact.isOutputToVirtualDevice())
{
// only when no metafile recording
if(!rObjectContact.isOutputToRecordingMetaFile())
{
// allow asynchronious loading
bSwapInAsynchronious = true;
}
}
}
if(bSwapInAsynchronious)
{
// maybe it's on the way, then do nothing
if(!mpAsynchLoadEvent)
{
// Trigger asynchronious SwapIn.
sdr::event::TimerEventHandler& rEventHandler = rObjectContact.GetEventHandler();
mpAsynchLoadEvent = new sdr::event::AsynchGraphicLoadingEvent(rEventHandler, *this);
}
}
else
{
if(rObjectContact.isOutputToPrinter())
{
// #i76395# preview mechanism is only active if
// swapin is called from inside paint preparation, so mbInsidePaint
// has to be false to be able to print with high resolution
rGrafObj.ForceSwapIn();
}
else
{
// SwapIn direct
rGrafObj.mbInsidePaint = sal_True;
rGrafObj.ForceSwapIn();
rGrafObj.mbInsidePaint = sal_False;
}
bRetval = true;
}
}
}
else
{
// it is not swapped out, somehow it was loaded. In that case, forget
// about an existing triggered event
if(mpAsynchLoadEvent)
{
// just delete it, this will remove it from the EventHandler and
// will trigger forgetAsynchGraphicLoadingEvent from the destructor
delete mpAsynchLoadEvent;
}
}
return bRetval;
}
// Test graphics state and eventually trigger a SwapIn event. Return value
// gives info if SwapIn was triggered or not
bool ViewObjectContactOfGraphic::impPrepareGraphicWithSynchroniousLoading()
{
bool bRetval(false);
SdrGrafObj& rGrafObj = getSdrGrafObj();
if(rGrafObj.IsSwappedOut())
{
if(rGrafObj.IsLinkedGraphic())
{
// update graphic link
rGrafObj.ImpUpdateGraphicLink( sal_False );
}
else
{
ObjectContact& rObjectContact = GetObjectContact();
if(rObjectContact.isOutputToPrinter())
{
// #i76395# preview mechanism is only active if
// swapin is called from inside paint preparation, so mbInsidePaint
// has to be false to be able to print with high resolution
rGrafObj.ForceSwapIn();
}
else
{
// SwapIn direct
rGrafObj.mbInsidePaint = sal_True;
rGrafObj.ForceSwapIn();
rGrafObj.mbInsidePaint = sal_False;
}
bRetval = true;
}
}
return bRetval;
}
// This is the call from the asynch graphic loading. This may only be called from
// AsynchGraphicLoadingEvent::ExecuteEvent(). Do load the graphics. The event will
// be deleted (consumed) and forgetAsynchGraphicLoadingEvent will be called.
void ViewObjectContactOfGraphic::doAsynchGraphicLoading()
{
DBG_ASSERT(mpAsynchLoadEvent, "ViewObjectContactOfGraphic::doAsynchGraphicLoading: I did not trigger a event, why am i called (?)");
// swap it in
SdrGrafObj& rGrafObj = getSdrGrafObj();
rGrafObj.ForceSwapIn();
// #i103720# forget event to avoid possible deletion by the following ActionChanged call
// which may use createPrimitive2DSequence/impPrepareGraphicWithAsynchroniousLoading again.
// Deletion is actally done by the scheduler who leaded to coming here
mpAsynchLoadEvent = 0;
// Invalidate all paint areas and check existing animation (which may have changed).
GetViewContact().ActionChanged();
}
// This is the call from the destructor of the asynch graphic loading event.
// No one else has to call this. It is needed to let this object forget about
// the event. The parameter allows checking for the correct event.
void ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent(sdr::event::AsynchGraphicLoadingEvent* pEvent)
{
(void) pEvent; // suppress warning
if(mpAsynchLoadEvent)
{
OSL_ENSURE(!pEvent || mpAsynchLoadEvent == pEvent,
"ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent: Forced to forget another event then i have scheduled (?)");
// forget event
mpAsynchLoadEvent = 0;
}
}
SdrGrafObj& ViewObjectContactOfGraphic::getSdrGrafObj()
{
return static_cast< ViewContactOfGraphic& >(GetViewContact()).GetGrafObject();
}
drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfGraphic::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
{
// prepare primitive generation with evtl. loading the graphic when it's swapped out
SdrGrafObj& rGrafObj = const_cast< ViewObjectContactOfGraphic* >(this)->getSdrGrafObj();
bool bDoAsynchronGraphicLoading(rGrafObj.GetModel() && rGrafObj.GetModel()->IsSwapGraphics());
bool bSwapInDone(false);
bool bSwapInExclusive(false);
if( bDoAsynchronGraphicLoading && rGrafObj.IsSwappedOut() )
{
// sometimes it is needed that each graphic is completely available and swapped in
// for these cases a ForceSwapIn is called later at the graphic object
if ( rGrafObj.GetPage() && rGrafObj.GetPage()->IsMasterPage() )
{
// #i102380# force Swap-In for GraphicObjects on MasterPage to have a nicer visualisation
bDoAsynchronGraphicLoading = false;
}
else if ( GetObjectContact().isOutputToPrinter()
|| GetObjectContact().isOutputToRecordingMetaFile()
|| GetObjectContact().isOutputToPDFFile() )
{
bDoAsynchronGraphicLoading = false;
bSwapInExclusive = true;
}
}
if( bDoAsynchronGraphicLoading )
{
bSwapInDone = const_cast< ViewObjectContactOfGraphic* >(this)->impPrepareGraphicWithAsynchroniousLoading();
}
else
{
bSwapInDone = const_cast< ViewObjectContactOfGraphic* >(this)->impPrepareGraphicWithSynchroniousLoading();
}
// get return value by calling parent
drawinglayer::primitive2d::Primitive2DSequence xRetval = ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo);
if(xRetval.hasElements())
{
// #i103255# suppress when graphic needs draft visualisation and output
// is for PDF export/Printer
const ViewContactOfGraphic& rVCOfGraphic = static_cast< const ViewContactOfGraphic& >(GetViewContact());
if(rVCOfGraphic.visualisationUsesDraft())
{
const ObjectContact& rObjectContact = GetObjectContact();
if(rObjectContact.isOutputToPDFFile() || rObjectContact.isOutputToPrinter())
{
xRetval = drawinglayer::primitive2d::Primitive2DSequence();
}
}
}
// if swap in was forced only for printing metafile and pdf, swap out again
if( bSwapInDone && bSwapInExclusive )
{
rGrafObj.ForceSwapOut();
}
return xRetval;
}
ViewObjectContactOfGraphic::ViewObjectContactOfGraphic(ObjectContact& rObjectContact, ViewContact& rViewContact)
: ViewObjectContactOfSdrObj(rObjectContact, rViewContact),
mpAsynchLoadEvent(0)
{
}
ViewObjectContactOfGraphic::~ViewObjectContactOfGraphic()
{
// evtl. delete the asynch loading event
if(mpAsynchLoadEvent)
{
// just delete it, this will remove it from the EventHandler and
// will trigger forgetAsynchGraphicLoadingEvent from the destructor
delete mpAsynchLoadEvent;
}
}
} // end of namespace contact
} // end of namespace sdr
//////////////////////////////////////////////////////////////////////////////
// eof