/* -*- 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 .
*/
namespace cairocanvas
{ namespace
{ /** Sprite redraw at original position
Used to repaint the whole canvas (background and all sprites)
*/ void spriteRedraw( const CairoSharedPtr& pCairo, const ::canvas::Sprite::Reference& rSprite )
{ // downcast to derived cairocanvas::Sprite interface, which // provides the actual redraw methods.
::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw( pCairo, true);
}
void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite, const CairoSharedPtr& pCairo, const ::basegfx::B2IRange& rArea )
{ // clip output to actual update region (otherwise a) // wouldn't save much render time, and b) will clutter // scrolled sprite content outside this area)
cairo_save( pCairo.get() );
cairo_rectangle( pCairo.get(), rArea.getMinX(), rArea.getMinY(),
sal::static_int_cast<sal_Int32>(rArea.getWidth()),
sal::static_int_cast<sal_Int32>(rArea.getHeight()) );
cairo_clip( pCairo.get() );
// repaint affected sprite directly to output device (at // the actual screen output position) // rendering directly to device buffer
::boost::polymorphic_downcast< Sprite* >( rSprite.get() )->redraw( pCairo, false );
// force compositing surface to be available before using it // inside forEachSpriteArea
SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize);
SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface();
CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo();
CairoSharedPtr pWindowCairo = pWindowSurface->getCairo();
// TODO(P1): Might be worthwhile to track areas of background // changes, too. if( !bUpdateAll && !io_bSurfaceDirty && !mbCompositingSurfaceDirty )
{ // background has not changed, so we're free to optimize // repaint to areas where a sprite has changed
// process each independent area of overlapping sprites // separately.
mpRedrawManager->forEachSpriteArea( *this );
} else
{
SAL_INFO("canvas.cairo", "SpriteCanvasHelper::updateScreen update ALL");
// background has changed, so we currently have no choice // but repaint everything (or caller requested that)
// repaint all active sprites on top of background into // VDev.
mpRedrawManager->forEachSprite(
[&pCompositingCairo]( const Sprite::Reference rSprite )
{ spriteRedraw( pCompositingCairo, rSprite ); }
);
// round rectangles to integer pixel. Note: have to be // extremely careful here, to avoid off-by-one errors for // the destination area: otherwise, the next scroll update // would copy pixel that are not supposed to be part of // the sprite.
::basegfx::B2IRange aSourceRect(
::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) ); const ::basegfx::B2IRange aDestRect(
::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
::basegfx::B2IPoint aDestPos( aDestRect.getMinimum() );
// TODO(E3): This is plain buggy (but copies the behaviour of // the old Impress slideshow) - the scrolled area might // actually lie _below_ another window!
// clip to output bounds (cannot properly scroll stuff // _outside_ our screen area) if( !::canvas::tools::clipScrollArea( aSourceRect,
aDestPos,
aUnscrollableAreas,
aOutputBounds ) )
{ // fully clipped scroll area: cannot simply scroll // then. Perform normal opaque update (can use that, since // one of the preconditions for scrollable update is // opaque sprite content)
ENSURE_OR_THROW( aFirst->second.getSprite().is(), "VCLCanvas::scrollUpdate(): no sprite" );
// repaint uncovered areas from sprite. Need to actually // clip here, since we're only repainting _parts_ of the // sprite for( constauto& rArea : aUnscrollableAreas )
opaqueUpdateSpriteArea( aFirst->second.getSprite(),
pCompositingCairo, rArea );
}
// repaint uncovered areas from backbuffer - take the // _rounded_ rectangles from above, to have the update // consistent with the scroll above.
std::vector< ::basegfx::B2DRange > aUncoveredAreas;
::basegfx::computeSetDifference( aUncoveredAreas,
rUpdateArea.maTotalBounds,
::basegfx::B2DRange( aDestRect ) ); for( constauto& rArea : aUncoveredAreas )
repaintBackground( pCompositingCairo,
mpOwningSpriteCanvas->getBufferSurface(), rArea );
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.