fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / canvas / source / vcl / spritecanvashelper.cxx
blobc62795066f936801174bdc11fc546c1829030083
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <canvas/verbosetrace.hxx>
24 #include <canvas/canvastools.hxx>
26 #include <vcl/canvastools.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/window.hxx>
29 #include <vcl/bitmapex.hxx>
31 #include <basegfx/range/b2drectangle.hxx>
32 #include <basegfx/tools/canvastools.hxx>
34 #include <boost/cast.hpp>
36 #include "spritecanvashelper.hxx"
37 #include "canvascustomsprite.hxx"
39 using namespace ::com::sun::star;
41 #define FPS_BOUNDS Rectangle(0,0,130,90)
42 #define INFO_COLOR COL_RED
44 namespace vclcanvas
46 namespace
48 /** Sprite redraw at original position
50 Used to repaint the whole canvas (background and all
51 sprites)
53 void spriteRedraw( OutputDevice& rOutDev,
54 const ::canvas::Sprite::Reference& rSprite )
56 // downcast to derived vclcanvas::Sprite interface, which
57 // provides the actual redraw methods.
58 ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw(rOutDev,
59 true);
62 double calcNumPixel( const ::canvas::Sprite::Reference& rSprite )
64 const ::basegfx::B2DSize& rSize(
65 ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->getSizePixel() );
67 return rSize.getX() * rSize.getY();
70 void repaintBackground( OutputDevice& rOutDev,
71 OutputDevice& rBackBuffer,
72 const ::basegfx::B2DRange& rArea )
74 const ::Point& rPos( ::vcl::unotools::pointFromB2DPoint( rArea.getMinimum()) );
75 const ::Size& rSize( ::vcl::unotools::sizeFromB2DSize( rArea.getRange()) );
77 rOutDev.DrawOutDev( rPos, rSize, rPos, rSize, rBackBuffer );
80 void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
81 OutputDevice& rOutDev,
82 const ::basegfx::B2IRange& rArea )
84 const Rectangle& rRequestedArea(
85 ::vcl::unotools::rectangleFromB2IRectangle( rArea ) );
87 // clip output to actual update region (otherwise a)
88 // wouldn't save much render time, and b) will clutter
89 // scrolled sprite content outside this area)
90 rOutDev.EnableMapMode( sal_False );
91 rOutDev.SetClipRegion(Region(rRequestedArea));
93 // repaint affected sprite directly to output device (at
94 // the actual screen output position)
95 ::boost::polymorphic_downcast< Sprite* >(
96 rSprite.get() )->redraw( rOutDev,
97 false ); // rendering
98 // directly to
99 // frontbuffer
102 /** Repaint sprite at original position
104 Used for opaque updates, which render directly to the
105 front buffer.
107 void spriteRedrawStub( OutputDevice& rOutDev,
108 const ::canvas::Sprite::Reference& rSprite )
110 if( rSprite.is() )
112 ::boost::polymorphic_downcast< Sprite* >(
113 rSprite.get() )->redraw( rOutDev,
114 false );
118 /** Repaint sprite at given position
120 Used for generic update, which renders into vdev of
121 adapted size.
123 void spriteRedrawStub2( OutputDevice& rOutDev,
124 const ::basegfx::B2DPoint& rOutPos,
125 const ::canvas::Sprite::Reference& rSprite )
127 if( rSprite.is() )
129 Sprite* pSprite = ::boost::polymorphic_downcast< Sprite* >(
130 rSprite.get() );
132 // calc relative sprite position in rUpdateArea (which
133 // need not be the whole screen!)
134 const ::basegfx::B2DPoint& rSpriteScreenPos( pSprite->getPosPixel() );
135 const ::basegfx::B2DPoint& rSpriteRenderPos( rSpriteScreenPos - rOutPos );
137 pSprite->redraw( rOutDev, rSpriteRenderPos, true );
141 /** Repaint sprite at original position
143 Used for opaque updates from scrollUpdate(), which render
144 directly to the front buffer.
146 void spriteRedrawStub3( OutputDevice& rOutDev,
147 const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
149 const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
151 if( rSprite.is() )
153 ::boost::polymorphic_downcast< Sprite* >(
154 rSprite.get() )->redraw( rOutDev,
155 false );
159 void renderInfoText( OutputDevice& rOutDev,
160 const OUString& rStr,
161 const Point& rPos )
163 Font aVCLFont;
164 aVCLFont.SetHeight( 20 );
165 aVCLFont.SetColor( Color( INFO_COLOR ) );
167 rOutDev.SetTextAlign(ALIGN_TOP);
168 rOutDev.SetTextColor( Color( INFO_COLOR ) );
169 rOutDev.SetFont( aVCLFont );
171 rOutDev.DrawText( rPos, rStr );
176 SpriteCanvasHelper::SpriteCanvasHelper() :
177 mpRedrawManager( NULL ),
178 mpOwningSpriteCanvas( NULL ),
179 maVDev(),
180 maLastUpdate(),
181 mbShowFrameInfo( false ),
182 mbShowSpriteBounds( false ),
183 mbIsUnsafeScrolling( false )
185 #if OSL_DEBUG_LEVEL > 2
186 // inverse defaults for verbose debug mode
187 mbShowSpriteBounds = mbShowFrameInfo = true;
188 #endif
191 void SpriteCanvasHelper::init( const OutDevProviderSharedPtr& rOutDev,
192 SpriteCanvas& rOwningSpriteCanvas,
193 ::canvas::SpriteRedrawManager& rManager,
194 bool bProtect,
195 bool bHaveAlpha )
197 mpOwningSpriteCanvas = &rOwningSpriteCanvas;
198 mpRedrawManager = &rManager;
200 CanvasHelper::init(rOwningSpriteCanvas,rOutDev,bProtect,bHaveAlpha);
203 void SpriteCanvasHelper::disposing()
205 mpRedrawManager = NULL;
206 mpOwningSpriteCanvas = NULL;
208 // forward to base
209 CanvasHelper::disposing();
212 uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
213 const uno::Reference< rendering::XAnimation >& )
215 return uno::Reference< rendering::XAnimatedSprite >();
218 uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
219 const uno::Sequence< uno::Reference< rendering::XBitmap > >& ,
220 sal_Int8 )
222 return uno::Reference< rendering::XAnimatedSprite >();
225 uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
227 if( !mpRedrawManager || !mpDevice )
228 return uno::Reference< rendering::XCustomSprite >(); // we're disposed
230 return uno::Reference< rendering::XCustomSprite >(
231 new CanvasCustomSprite( spriteSize,
232 *mpDevice,
233 mpOwningSpriteCanvas,
234 mpOwningSpriteCanvas->getFrontBuffer(),
235 mbShowSpriteBounds ) );
238 uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& )
240 return uno::Reference< rendering::XSprite >();
243 sal_Bool SpriteCanvasHelper::updateScreen( sal_Bool bUpdateAll,
244 bool& io_bSurfaceDirty )
246 if( !mpRedrawManager ||
247 !mpOwningSpriteCanvas ||
248 !mpOwningSpriteCanvas->getFrontBuffer() ||
249 !mpOwningSpriteCanvas->getBackBuffer() )
251 return sal_False; // disposed, or otherwise dysfunctional
254 // commit to backbuffer
255 flush();
257 OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
258 BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
259 OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
261 // actual OutputDevice is a shared resource - restore its
262 // state when done.
263 tools::OutDevStateKeeper aStateKeeper( rOutDev );
265 const Size aOutDevSize( rBackOutDev.GetOutputSizePixel() );
266 const Point aEmptyPoint(0,0);
268 Window* pTargetWindow = NULL;
269 if( rOutDev.GetOutDevType() == OUTDEV_WINDOW )
271 pTargetWindow = &static_cast<Window&>(rOutDev); // TODO(Q3): Evil downcast.
273 // we're double-buffered, thus no need for paint area-limiting
274 // clips. besides that, will interfere with animations (as for
275 // Window-invalidate repaints, only parts of the window will
276 // be redrawn otherwise)
277 const Region aFullWindowRegion( Rectangle(aEmptyPoint,
278 aOutDevSize) );
279 pTargetWindow->ExpandPaintClipRegion(aFullWindowRegion);
282 // TODO(P1): Might be worthwile to track areas of background
283 // changes, too.
284 if( !bUpdateAll && !io_bSurfaceDirty )
286 if( mbShowFrameInfo )
288 // also repaint background below frame counter (fake
289 // that as a sprite vanishing in this area)
290 mpRedrawManager->updateSprite( ::canvas::Sprite::Reference(),
291 ::basegfx::B2DPoint(),
292 ::basegfx::B2DRectangle( 0.0, 0.0,
293 FPS_BOUNDS.Right(),
294 FPS_BOUNDS.Bottom() ) );
297 // background has not changed, so we're free to optimize
298 // repaint to areas where a sprite has changed
300 // process each independent area of overlapping sprites
301 // separately.
302 mpRedrawManager->forEachSpriteArea( *this );
304 else
306 // background has changed, so we currently have no choice
307 // but repaint everything (or caller requested that)
309 maVDev->SetOutputSizePixel( aOutDevSize );
310 maVDev->EnableMapMode( sal_False );
311 maVDev->DrawOutDev( aEmptyPoint, aOutDevSize,
312 aEmptyPoint, aOutDevSize,
313 rBackOutDev );
315 // repaint all active sprites on top of background into
316 // VDev.
317 mpRedrawManager->forEachSprite(
318 ::boost::bind(
319 &spriteRedraw,
320 ::boost::ref( maVDev.get() ),
321 _1 ) );
323 // flush to screen
324 rOutDev.EnableMapMode( sal_False );
325 rOutDev.SetClipRegion();
326 rOutDev.DrawOutDev( aEmptyPoint, aOutDevSize,
327 aEmptyPoint, aOutDevSize,
328 *maVDev );
331 // change record vector must be cleared, for the next turn of
332 // rendering and sprite changing
333 mpRedrawManager->clearChangeRecords();
335 io_bSurfaceDirty = false;
337 if( mbShowFrameInfo )
339 renderFrameCounter( rOutDev );
340 renderSpriteCount( rOutDev );
341 renderMemUsage( rOutDev );
344 #if OSL_DEBUG_LEVEL > 2
345 static ::canvas::tools::ElapsedTime aElapsedTime;
347 // log time immediately after surface flip
348 OSL_TRACE( "SpriteCanvasHelper::updateScreen(): flip done at %f",
349 aElapsedTime.getElapsedTime() );
350 #endif
352 // sync output with screen, to ensure that we don't queue up
353 // render requests (calling code might rely on timing,
354 // i.e. assume that things are visible on screen after
355 // updateScreen() returns).
356 if( pTargetWindow )
358 // commit to screen
359 pTargetWindow->Sync();
362 return sal_True;
365 void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
367 ENSURE_OR_THROW( mpOwningSpriteCanvas &&
368 mpOwningSpriteCanvas->getBackBuffer() &&
369 mpOwningSpriteCanvas->getFrontBuffer(),
370 "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
372 OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
373 BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
374 OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
376 repaintBackground( rOutDev, rBackOutDev, rUpdateRect );
379 void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
380 const ::basegfx::B2DRange& rMoveEnd,
381 const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
383 ENSURE_OR_THROW( mpOwningSpriteCanvas &&
384 mpOwningSpriteCanvas->getBackBuffer() &&
385 mpOwningSpriteCanvas->getFrontBuffer(),
386 "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
388 OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
389 BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
390 OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
392 const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
393 const ::basegfx::B2IRange aOutputBounds( 0,0,
394 rTargetSizePixel.Width(),
395 rTargetSizePixel.Height() );
397 // round rectangles to integer pixel. Note: have to be
398 // extremely careful here, to avoid off-by-one errors for
399 // the destination area: otherwise, the next scroll update
400 // would copy pixel that are not supposed to be part of
401 // the sprite.
402 ::basegfx::B2IRange aSourceRect(
403 ::canvas::tools::spritePixelAreaFromB2DRange( rMoveStart ) );
404 const ::basegfx::B2IRange& rDestRect(
405 ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
406 ::basegfx::B2IPoint aDestPos( rDestRect.getMinimum() );
408 ::std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
410 // Since strictly speaking, this scroll algorithm is plain
411 // buggy, the scrolled area might actually lie _below_ another
412 // window - we've made this feature configurable via
413 // mbIsUnsafeScrolling.
415 // clip to output bounds (cannot properly scroll stuff
416 // _outside_ our screen area)
417 if( !mbIsUnsafeScrolling ||
418 !::canvas::tools::clipScrollArea( aSourceRect,
419 aDestPos,
420 aUnscrollableAreas,
421 aOutputBounds ) )
423 // fully clipped scroll area: cannot simply scroll
424 // then. Perform normal opaque update (can use that, since
425 // one of the preconditions for scrollable update is
426 // opaque sprite content)
428 // repaint all affected sprites directly to output device
429 ::std::for_each( rUpdateArea.maComponentList.begin(),
430 rUpdateArea.maComponentList.end(),
431 ::boost::bind(
432 &spriteRedrawStub3,
433 ::boost::ref( rOutDev ),
434 _1 ) );
436 else
438 // scroll rOutDev content
439 rOutDev.CopyArea( ::vcl::unotools::pointFromB2IPoint( aDestPos ),
440 ::vcl::unotools::pointFromB2IPoint( aSourceRect.getMinimum() ),
441 // TODO(Q2): use numeric_cast to check range
442 ::Size( static_cast<sal_Int32>(aSourceRect.getRange().getX()),
443 static_cast<sal_Int32>(aSourceRect.getRange().getY()) ) );
445 const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
446 aFirst( rUpdateArea.maComponentList.begin() );
448 ENSURE_OR_THROW( aFirst->second.getSprite().is(),
449 "VCLCanvas::scrollUpdate(): no sprite" );
451 // repaint uncovered areas from sprite. Need to actually
452 // clip here, since we're only repainting _parts_ of the
453 // sprite
454 rOutDev.Push( PUSH_CLIPREGION );
455 ::std::for_each( aUnscrollableAreas.begin(),
456 aUnscrollableAreas.end(),
457 ::boost::bind( &opaqueUpdateSpriteArea,
458 ::boost::cref(aFirst->second.getSprite()),
459 ::boost::ref(rOutDev),
460 _1 ) );
461 rOutDev.Pop();
464 // repaint uncovered areas from backbuffer - take the
465 // _rounded_ rectangles from above, to have the update
466 // consistent with the scroll above.
467 ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
468 ::basegfx::computeSetDifference( aUncoveredAreas,
469 rUpdateArea.maTotalBounds,
470 ::basegfx::B2DRange( rDestRect ) );
471 ::std::for_each( aUncoveredAreas.begin(),
472 aUncoveredAreas.end(),
473 ::boost::bind( &repaintBackground,
474 ::boost::ref(rOutDev),
475 ::boost::ref(rBackOutDev),
476 _1 ) );
479 void SpriteCanvasHelper::opaqueUpdate( SAL_UNUSED_PARAMETER const ::basegfx::B2DRange&,
480 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
482 ENSURE_OR_THROW( mpOwningSpriteCanvas &&
483 mpOwningSpriteCanvas->getBackBuffer() &&
484 mpOwningSpriteCanvas->getFrontBuffer(),
485 "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
487 OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
489 // no need to clip output to actual update region - there will
490 // always be ALL sprites contained in the rectangular update
491 // area containd in rTotalArea (that's the way
492 // B2DConnectedRanges work). If rTotalArea appears to be
493 // smaller than the sprite - then this sprite carries a clip,
494 // and the update will be constrained to that rect.
496 // repaint all affected sprites directly to output device
497 ::std::for_each( rSortedUpdateSprites.begin(),
498 rSortedUpdateSprites.end(),
499 ::boost::bind(
500 &spriteRedrawStub,
501 ::boost::ref( rOutDev ),
502 _1 ) );
505 void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rRequestedArea,
506 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
508 ENSURE_OR_THROW( mpOwningSpriteCanvas &&
509 mpOwningSpriteCanvas->getBackBuffer() &&
510 mpOwningSpriteCanvas->getFrontBuffer(),
511 "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
513 OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
514 BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
515 OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
517 // limit size of update VDev to target outdev's size
518 const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
520 // round output position towards zero. Don't want to truncate
521 // a fraction of a sprite pixel... Clip position at origin,
522 // otherwise, truncation of size below might leave visible
523 // areas uncovered by VDev.
524 const ::Point aOutputPosition(
525 ::std::max( sal_Int32( 0 ),
526 static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
527 ::std::max( sal_Int32( 0 ),
528 static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
529 // round output size towards +infty. Don't want to truncate a
530 // fraction of a sprite pixel... Limit coverage of VDev to
531 // output device's area (i.e. not only to total size, but to
532 // cover _only_ the visible parts).
533 const ::Size aOutputSize(
534 ::std::max( sal_Int32( 0 ),
535 ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Width() - aOutputPosition.X()),
536 ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X() ))),
537 ::std::max( sal_Int32( 0 ),
538 ::std::min( static_cast< sal_Int32 >(rTargetSizePixel.Height() - aOutputPosition.Y()),
539 ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y() ))));
541 // early exit for empty output area.
542 if( aOutputSize.Width() == 0 &&
543 aOutputSize.Height() == 0 )
545 return;
548 const Point aEmptyPoint(0,0);
549 const Size aCurrOutputSize( maVDev->GetOutputSizePixel() );
551 // adapt maVDev's size to the area that actually needs the
552 // repaint.
553 if( aCurrOutputSize.Width() < aOutputSize.Width() ||
554 aCurrOutputSize.Height() < aOutputSize.Height() )
556 // TODO(P1): Come up with a clever tactic to reduce maVDev
557 // from time to time. Reduction with threshold (say, if
558 // maVDev is more than twice too large) is not wise, as
559 // this might then toggle within the same updateScreen(),
560 // but for different disjunct sprite areas.
561 maVDev->SetOutputSizePixel( aOutputSize );
564 // paint background
565 maVDev->EnableMapMode( sal_False );
566 maVDev->SetClipRegion();
567 maVDev->DrawOutDev( aEmptyPoint, aOutputSize,
568 aOutputPosition, aOutputSize,
569 rBackOutDev );
571 // repaint all affected sprites on top of background into
572 // VDev.
573 ::std::for_each( rSortedUpdateSprites.begin(),
574 rSortedUpdateSprites.end(),
575 ::boost::bind( &spriteRedrawStub2,
576 ::boost::ref( maVDev.get() ),
577 ::boost::cref(
578 ::vcl::unotools::b2DPointFromPoint(aOutputPosition)),
579 _1 ) );
581 // flush to screen
582 rOutDev.EnableMapMode( sal_False );
583 rOutDev.DrawOutDev( aOutputPosition, aOutputSize,
584 aEmptyPoint, aOutputSize,
585 *maVDev );
588 void SpriteCanvasHelper::renderFrameCounter( OutputDevice& rOutDev )
590 const double denominator( maLastUpdate.getElapsedTime() );
591 maLastUpdate.reset();
593 OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
594 rtl_math_StringFormat_F,
595 2,'.',NULL,' ') );
597 // pad with leading space
598 while( text.getLength() < 6 )
599 text = " " + text;
601 text += " fps";
603 renderInfoText( rOutDev,
604 text,
605 Point(0, 0) );
608 namespace
610 template< typename T > struct Adder
612 typedef void result_type;
614 Adder( T& rAdderTarget,
615 T nIncrement ) :
616 mpTarget( &rAdderTarget ),
617 mnIncrement( nIncrement )
621 void operator()() { *mpTarget += mnIncrement; }
622 void operator()( const ::canvas::Sprite::Reference& ) { *mpTarget += mnIncrement; }
623 void operator()( T nIncrement ) { *mpTarget += nIncrement; }
625 T* mpTarget;
626 T mnIncrement;
629 template< typename T> Adder<T> makeAdder( T& rAdderTarget,
630 T nIncrement )
632 return Adder<T>(rAdderTarget, nIncrement);
636 void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev )
638 if( mpRedrawManager )
640 sal_Int32 nCount(0);
642 mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
643 OUString text(
644 OUString::valueOf(
645 // disambiguate overload...
646 static_cast<sal_Int64>(nCount) ) );
648 // pad with leading space
649 while( text.getLength() < 3 )
650 text = " " + text;
652 text = "Sprites: " + text;
654 renderInfoText( rOutDev,
655 text,
656 Point(0, 30) );
660 void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev )
662 BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
664 if( mpRedrawManager &&
665 pBackBuffer )
667 double nPixel(0.0);
669 // accumulate pixel count for each sprite into fCount
670 mpRedrawManager->forEachSprite( ::boost::bind(
671 makeAdder(nPixel,1.0),
672 ::boost::bind(
673 &calcNumPixel,
674 _1 ) ) );
676 static const int NUM_VIRDEV(2);
677 static const int BYTES_PER_PIXEL(3);
679 const Size& rVDevSize( maVDev->GetOutputSizePixel() );
680 const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
682 const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
683 rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
684 rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
686 OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
687 rtl_math_StringFormat_F,
688 2,'.',NULL,' ') );
690 // pad with leading space
691 while( text.getLength() < 4 )
692 text = " " + text;
694 text = "Mem: " + text + "MB";
696 renderInfoText( rOutDev,
697 text,
698 Point(0, 60) );
703 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */