/* -*- 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 .
*/
// TODO(F2): Rework SlideBitmap to no longer be based on XBitmap, // but on canvas-independent basegfx bitmaps virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const override;
If the slide doesn't have animations, show() displays only static content. If an event is registered with registerSlideEndEvent(), this event will be immediately activated at the end of the show() method.
@return true, if this slide has animations, false otherwise
*/ bool isAnimated();
/// Set all Shapes to their initial attributes for slideshow bool applyInitialShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode );
/// Set shapes to attributes corresponding to initial or final state of slide void applyShapeAttributes( const css::uno::Reference< css::animations::XAnimationNode >& xRootAnimationNode, bool bInitial) const;
/// Renders current slide content to bitmap
SlideBitmapSharedPtr createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
::basegfx::B2ISize const & rSlideSize ) const;
/// Prefetch all shapes (not the animations) bool loadShapes();
/// Retrieve slide size from XDrawPage
basegfx::B2ISize getSlideSizeImpl() const;
/// Prefetch show, but don't call applyInitialShapeAttributes() bool implPrefetchShow();
/// Add Polygons to the member maPolygons void addPolygons(const PolyPolygonVector& rPolygons);
typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps; /** Vector of slide bitmaps.
Since the bitmap content is sensitive to animation effects, we have an inner vector containing a distinct bitmap for each of the SlideAnimationStates.
*/ typedef ::std::vector< std::pair< UnoViewSharedPtr,
VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
// Member variables // ================
/// The page model object
uno::Reference< drawing::XDrawPage > mxDrawPage;
uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
uno::Reference< animations::XAnimationNode > mxRootNode;
/// Bitmaps with slide content at various states mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
SlideAnimationState meAnimationState;
const basegfx::B2ISize maSlideSize;
sal_Int16 mnCurrentCursor;
/// True, when intrinsic shape animations are allowed bool mbIntrinsicAnimationsAllowed;
/// True, when user paint overlay is enabled bool mbUserPaintOverlayEnabled;
/// True, if initial load of all page shapes succeeded bool mbShapesLoaded;
/// True, if initial load of all animation info succeeded bool mbShowLoaded;
/** True, if this slide is not static.
If this slide has animated content, this variable will be true, and false otherwise.
*/ bool mbHaveAnimations;
/** True, if this slide has a main animation sequence.
If this slide has animation content, which in turn has a main animation sequence (which must be fully run before EventMultiplexer::notifySlideAnimationsEnd() is called), this member is true.
*/ bool mbMainSequenceFound;
/// When true, show() was called. Slide hidden otherwise. bool mbActive;
/// When true, enablePaintOverlay was called and mbUserPaintOverlay = true bool mbPaintOverlayActive;
/// When true, final state attributes are already applied to shapes bool mbFinalStateApplied;
};
void slideRenderer( SlideImpl const * pSlide, const UnoViewSharedPtr& rView )
{ // fully clear view content to background color
rView->clearAll();
// setup a canvas with device coordinate space, the slide // bitmap already has the correct dimension.
::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
// render at given output position
pBitmap->move( aOutPosPixel );
// clear clip (might have been changed, e.g. from comb // transition)
pBitmap->clip( ::basegfx::B2DPolyPolygon() );
pBitmap->draw( pDevicePixelCanvas );
}
// TODO(Q3): Make sure LayerManager (and thus Shapes) dies // first, because SlideShowContext has SubsettableShapeManager // as reference member.
mpLayerManager.reset();
}
}
// Try to prefetch all graphics from the page. This will be done // in threads to be more efficient than loading them on-demand one by one.
std::vector<Graphic*> graphics; for (sal_Int32 i = 0; i < mxDrawPage->getCount(); i++)
{
css::uno::Reference<css::drawing::XShape> xShape(mxDrawPage->getByIndex(i), css::uno::UNO_QUERY_THROW);
SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); if (!pObj) continue; if( SdrGrafObj* grafObj = dynamic_cast<SdrGrafObj*>(pObj)) if( !grafObj->GetGraphic().isAvailable())
graphics.push_back( const_cast<Graphic*>(&grafObj->GetGraphic()));
} if(graphics.size() > 1) // threading does not help with loading just one
GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded( graphics );
// set initial shape attributes (e.g. hide shapes that have // 'appear' effect set) if( !applyInitialShapeAttributes(mxRootNode) ) return;
// activate and take over view - clears view, if necessary
mbActive = true;
requestCursor( mnCurrentCursor );
// enable shape management & event broadcasting for shapes of this // slide. Also enables LayerManager to record updates. Currently, // never let LayerManager render initial slide content, use // buffered slide bitmaps instead.
mpShapeManager->activate();
// fire up animations constbool bIsAnimated( isAnimated() ); if( bIsAnimated )
maAnimations.start(); // feeds initial events into queue
// NOTE: this looks slightly weird, but is indeed correct: // as isAnimated() might return false, _although_ there is // a main sequence (because the animation nodes don't // contain any executable effects), we gotta check both // conditions here. if( !bIsAnimated || !mbMainSequenceFound )
{ // manually trigger a slide animation end event (we don't have // animations at all, or we don't have a main animation // sequence, but if we had, it'd end now). Note that having // animations alone does not matter here, as only main // sequence animations prevents showing the next slide on // nextEvent().
maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
}
SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
{ // search corresponding entry in maSlideBitmaps (which // contains the views as the key)
VectorOfVectorOfSlideBitmaps::iterator aIter; const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() ); if( (aIter=std::find_if( maSlideBitmaps.begin(),
aEnd,
[&rView]
( const VectorOfVectorOfSlideBitmaps::value_type& cp )
{ return rView == cp.first; } ) ) == aEnd )
{ // corresponding view not found - maybe view was not // added to Slide?
ENSURE_OR_THROW( false, "SlideImpl::getInitialSlideBitmap(): view does not " "match any of the added ones" );
}
// ensure that the show is loaded if( !mbShowLoaded )
{ // only prefetch and init shapes when not done already // (otherwise, at least applyInitialShapeAttributes() will be // called twice for initial slide rendering). Furthermore, // applyInitialShapeAttributes() _always_ performs // initializations, which would be highly unwanted during a // running show. OTOH, a slide whose mbShowLoaded is false is // guaranteed not be running a show.
// is the bitmap valid (actually existent, and of correct // size)? if( !rBitmap || rBitmap->getSize() != rSlideSize )
{ // no bitmap there yet, or wrong size - create one
rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
}
// tdf#96083 ensure end state settings are applied to shapes once when bitmap gets re-rendered // in that state if(!mbFinalStateApplied && FINAL_STATE == meAnimationState && mxRootNode.is())
{ const_cast< SlideImpl* >(this)->mbFinalStateApplied = true;
applyShapeAttributes(mxRootNode, false);
}
// apply linear part of destination canvas transformation (linear means in this context: // transformation without any translational components)
::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
aLinearTransform.set( 0, 2, 0.0 );
aLinearTransform.set( 1, 2, 0.0 );
pBitmapCanvas->setTransformation( aLinearTransform );
// output all shapes to bitmap
initSlideBackground( pBitmapCanvas, rBmpSize );
mpLayerManager->renderTo( pBitmapCanvas );
// could not import animation framework, // _although_ some animation nodes are there - // this is an error (not finding animations at // all is okay - might be a static slide) returnfalse;
}
// now check whether we've got a main sequence (if // not, we must manually call // EventMultiplexer::notifySlideAnimationsEnd() // above, as e.g. interactive sequences alone // don't block nextEvent() from issuing the next // slide)
MainSequenceSearcher aSearcher; if( for_each_childNode( mxRootNode, aSearcher ) )
mbMainSequenceFound = aSearcher.getMainSequence().is();
if( !pAttrShape )
{
OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not " "implement AttributableShape interface" ); continue;
}
if( nParaIndex != -1 )
{ // our target is a paragraph subset, thus look // this up first. const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
if( rNodeSupplier.getNumberOfTreeNodes(
DocTreeNode::NodeType::LogicalParagraph ) <= nParaIndex )
{
OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not " "provide a subset for requested paragraph index" ); continue;
}
if( !pAttrShape )
{
OSL_FAIL( "SlideImpl::applyInitialShapeAttributes(): shape found does not " "provide a subset for requested paragraph index" ); continue;
}
}
if( xMasterPage.is() && xMasterPageShapes.is() )
{ // TODO(P2): maybe cache master pages here (or treat the // masterpage as a single metafile. At least currently, // masterpages do not contain animation effects) try
{ // load the masterpage shapes
ShapeImporter aMPShapesFunctor( xMasterPage,
mxDrawPage,
mxDrawPagesSupplier,
maContext,
0, /* shape num starts at 0 */ true );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.