LibreOffice Module canvas (master)  1
spritecanvashelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <boost/cast.hpp>
24 
26 #include <rtl/math.hxx>
27 #include <tools/diagnose_ex.h>
28 #include <vcl/canvastools.hxx>
29 #include <vcl/outdev.hxx>
30 #include <vcl/window.hxx>
31 
32 #include <canvas/canvastools.hxx>
33 
34 #include "canvascustomsprite.hxx"
35 #include "spritecanvashelper.hxx"
36 #include "spritecanvas.hxx"
37 
38 using namespace ::com::sun::star;
39 
40 #define FPS_BOUNDS ::tools::Rectangle(0,0,130,90)
41 #define INFO_COLOR COL_RED
42 
43 namespace vclcanvas
44 {
45  namespace
46  {
52  void spriteRedraw( OutputDevice& rOutDev,
53  const ::canvas::Sprite::Reference& rSprite )
54  {
55  // downcast to derived vclcanvas::Sprite interface, which
56  // provides the actual redraw methods.
57  ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->redraw(rOutDev,
58  true);
59  }
60 
61  double calcNumPixel( const ::canvas::Sprite::Reference& rSprite )
62  {
63  const ::basegfx::B2DSize& rSize(
64  ::boost::polymorphic_downcast< Sprite* >(rSprite.get())->getSizePixel() );
65 
66  return rSize.getX() * rSize.getY();
67  }
68 
69  void repaintBackground( OutputDevice& rOutDev,
70  OutputDevice const & rBackBuffer,
71  const ::basegfx::B2DRange& rArea )
72  {
73  const ::Point& rPos( vcl::unotools::pointFromB2DPoint( rArea.getMinimum()) );
74  const ::Size& rSize( vcl::unotools::sizeFromB2DSize( rArea.getRange()) );
75 
76  rOutDev.DrawOutDev( rPos, rSize, rPos, rSize, rBackBuffer );
77  }
78 
79  void opaqueUpdateSpriteArea( const ::canvas::Sprite::Reference& rSprite,
80  OutputDevice& rOutDev,
81  const ::basegfx::B2IRange& rArea )
82  {
83  const ::tools::Rectangle& rRequestedArea(
85 
86  // clip output to actual update region (otherwise a)
87  // wouldn't save much render time, and b) will clutter
88  // scrolled sprite content outside this area)
89  rOutDev.EnableMapMode( false );
90  rOutDev.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
91  rOutDev.SetClipRegion(vcl::Region(rRequestedArea));
92 
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
100  }
101 
102  void renderInfoText( OutputDevice& rOutDev,
103  const OUString& rStr,
104  const Point& rPos )
105  {
106  vcl::Font aVCLFont;
107  aVCLFont.SetFontHeight( 20 );
108  aVCLFont.SetColor( INFO_COLOR );
109 
110  rOutDev.SetTextAlign(ALIGN_TOP);
111  rOutDev.SetTextColor( INFO_COLOR );
112  rOutDev.SetFont( aVCLFont );
113 
114  rOutDev.DrawText( rPos, rStr );
115  }
116 
117  }
118 
120  mpRedrawManager( nullptr ),
121  mpOwningSpriteCanvas( nullptr ),
122  maVDev(VclPtr<VirtualDevice>::Create()),
123  maLastUpdate(),
124  mbShowFrameInfo( false ),
125  mbShowSpriteBounds( false ),
126  mbIsUnsafeScrolling( false )
127  {
128 #if OSL_DEBUG_LEVEL > 0
129  // inverse defaults for verbose debug mode
130  mbShowFrameInfo = true;
131  // this looks like drawing errors, enable only if explicitly asked for
132  static bool enableShowSpriteBounds = getenv("CANVAS_SPRITE_BOUNDS") != nullptr;
133  mbShowSpriteBounds = enableShowSpriteBounds;
134 #endif
135  }
136 
138  {
139  SolarMutexGuard aGuard;
141  }
142 
144  SpriteCanvas& rOwningSpriteCanvas,
145  ::canvas::SpriteRedrawManager& rManager,
146  bool bProtect,
147  bool bHaveAlpha )
148  {
149  mpOwningSpriteCanvas = &rOwningSpriteCanvas;
150  mpRedrawManager = &rManager;
151 
152  CanvasHelper::init(rOwningSpriteCanvas,rOutDev,bProtect,bHaveAlpha);
153  }
154 
156  {
157  mpRedrawManager = nullptr;
158  mpOwningSpriteCanvas = nullptr;
159 
160  // forward to base
162  }
163 
164  uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
165  const uno::Reference< rendering::XAnimation >& )
166  {
167  return uno::Reference< rendering::XAnimatedSprite >();
168  }
169 
170  uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
171  const uno::Sequence< uno::Reference< rendering::XBitmap > >& ,
172  sal_Int8 )
173  {
174  return uno::Reference< rendering::XAnimatedSprite >();
175  }
176 
177  uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
178  {
179  if( !mpRedrawManager || !mpDevice )
180  return uno::Reference< rendering::XCustomSprite >(); // we're disposed
181 
182  return uno::Reference< rendering::XCustomSprite >(
183  new CanvasCustomSprite( spriteSize,
184  *mpDevice,
187  mbShowSpriteBounds ) );
188  }
189 
190  uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& )
191  {
192  return uno::Reference< rendering::XSprite >();
193  }
194 
195  bool SpriteCanvasHelper::updateScreen( bool bUpdateAll,
196  bool& io_bSurfaceDirty )
197  {
198  if( !mpRedrawManager ||
202  {
203  return false; // disposed, or otherwise dysfunctional
204  }
205 
206  // commit to backbuffer
207  flush();
208 
209  OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
211  OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
212 
213  // actual OutputDevice is a shared resource - restore its
214  // state when done.
215  tools::OutDevStateKeeper aStateKeeper( rOutDev );
216 
217  const Size aOutDevSize( rBackOutDev.GetOutputSizePixel() );
218  const Point aEmptyPoint(0,0);
219 
220  vcl::Window* pTargetWindow = nullptr;
221  if( rOutDev.GetOutDevType() == OUTDEV_WINDOW )
222  {
223  pTargetWindow = &static_cast<vcl::Window&>(rOutDev); // TODO(Q3): Evil downcast.
224 
225  // we're double-buffered, thus no need for paint area-limiting
226  // clips. besides that, will interfere with animations (as for
227  // Window-invalidate repaints, only parts of the window will
228  // be redrawn otherwise)
229  const vcl::Region aFullWindowRegion( ::tools::Rectangle(aEmptyPoint,
230  aOutDevSize) );
231  pTargetWindow->ExpandPaintClipRegion(aFullWindowRegion);
232  }
233 
234  // TODO(P1): Might be worthwhile to track areas of background
235  // changes, too.
236  if( !bUpdateAll && !io_bSurfaceDirty )
237  {
238  if( mbShowFrameInfo )
239  {
240  // also repaint background below frame counter (fake
241  // that as a sprite vanishing in this area)
243  ::basegfx::B2DPoint(),
244  ::basegfx::B2DRectangle( 0.0, 0.0,
245  FPS_BOUNDS.Right(),
246  FPS_BOUNDS.Bottom() ) );
247  }
248 
249  // background has not changed, so we're free to optimize
250  // repaint to areas where a sprite has changed
251 
252  // process each independent area of overlapping sprites
253  // separately.
255  }
256  else
257  {
258  // background has changed, so we currently have no choice
259  // but repaint everything (or caller requested that)
260 
261  maVDev->SetOutputSizePixel( aOutDevSize );
262  maVDev->EnableMapMode( false );
263  maVDev->DrawOutDev( aEmptyPoint, aOutDevSize,
264  aEmptyPoint, aOutDevSize,
265  rBackOutDev );
266 
267  // repaint all active sprites on top of background into
268  // VDev.
269  OutputDevice& rTmpOutDev( *maVDev );
271  [&rTmpOutDev]( const ::canvas::Sprite::Reference& rSprite )
272  { spriteRedraw( rTmpOutDev, rSprite ); }
273  );
274 
275  // flush to screen
276  rOutDev.EnableMapMode( false );
277  rOutDev.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
278  rOutDev.SetClipRegion();
279  rOutDev.DrawOutDev( aEmptyPoint, aOutDevSize,
280  aEmptyPoint, aOutDevSize,
281  *maVDev );
282  }
283 
284  // change record vector must be cleared, for the next turn of
285  // rendering and sprite changing
287 
288  io_bSurfaceDirty = false;
289 
290  if( mbShowFrameInfo )
291  {
292  renderFrameCounter( rOutDev );
293  renderSpriteCount( rOutDev );
294  renderMemUsage( rOutDev );
295  }
296 
297 #if OSL_DEBUG_LEVEL > 0
298  static ::canvas::tools::ElapsedTime aElapsedTime;
299 
300  // log time immediately after surface flip
301  SAL_INFO("canvas.vcl", "SpriteCanvasHelper::updateScreen(): flip done at " <<
302  aElapsedTime.getElapsedTime() );
303 #endif
304 
305  // sync output with screen, to ensure that we don't queue up
306  // render requests (calling code might rely on timing,
307  // i.e. assume that things are visible on screen after
308  // updateScreen() returns).
309  if( pTargetWindow )
310  {
311  // commit to screen
312  pTargetWindow->Flush();
313  }
314 
315  return true;
316  }
317 
318  void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
319  {
323  "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
324 
325  OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
327  OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
328 
329  repaintBackground( rOutDev, rBackOutDev, rUpdateRect );
330  }
331 
332  void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
333  const ::basegfx::B2DRange& rMoveEnd,
334  const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
335  {
339  "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
340 
341  OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
343  OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
344 
345  const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
346  const ::basegfx::B2IRange aOutputBounds( 0,0,
347  rTargetSizePixel.Width(),
348  rTargetSizePixel.Height() );
349 
350  // round rectangles to integer pixel. Note: have to be
351  // extremely careful here, to avoid off-by-one errors for
352  // the destination area: otherwise, the next scroll update
353  // would copy pixel that are not supposed to be part of
354  // the sprite.
355  ::basegfx::B2IRange aSourceRect(
357  const ::basegfx::B2IRange& rDestRect(
359  ::basegfx::B2IPoint aDestPos( rDestRect.getMinimum() );
360 
361  std::vector< ::basegfx::B2IRange > aUnscrollableAreas;
362 
363  // Since strictly speaking, this scroll algorithm is plain
364  // buggy, the scrolled area might actually lie _below_ another
365  // window - we've made this feature configurable via
366  // mbIsUnsafeScrolling.
367 
368  // clip to output bounds (cannot properly scroll stuff
369  // _outside_ our screen area)
370  if( !mbIsUnsafeScrolling ||
371  !::canvas::tools::clipScrollArea( aSourceRect,
372  aDestPos,
373  aUnscrollableAreas,
374  aOutputBounds ) )
375  {
376  // fully clipped scroll area: cannot simply scroll
377  // then. Perform normal opaque update (can use that, since
378  // one of the preconditions for scrollable update is
379  // opaque sprite content)
380 
381  // repaint all affected sprites directly to output device
382  for( const auto& rComponent : rUpdateArea.maComponentList )
383  {
384  const ::canvas::Sprite::Reference& rSprite( rComponent.second.getSprite() );
385 
386  if( rSprite.is() )
387  ::boost::polymorphic_downcast< Sprite* >(
388  rSprite.get() )->redraw( rOutDev,
389  false );
390  }
391  }
392  else
393  {
394  // scroll rOutDev content
395  rOutDev.CopyArea( vcl::unotools::pointFromB2IPoint( aDestPos ),
396  vcl::unotools::pointFromB2IPoint( aSourceRect.getMinimum() ),
397  // TODO(Q2): use numeric_cast to check range
398  ::Size( static_cast<sal_Int32>(aSourceRect.getRange().getX()),
399  static_cast<sal_Int32>(aSourceRect.getRange().getY()) ) );
400 
401  const ::canvas::SpriteRedrawManager::SpriteConnectedRanges::ComponentListType::const_iterator
402  aFirst( rUpdateArea.maComponentList.begin() );
403 
404  ENSURE_OR_THROW( aFirst->second.getSprite().is(),
405  "VCLCanvas::scrollUpdate(): no sprite" );
406 
407  // repaint uncovered areas from sprite. Need to actually
408  // clip here, since we're only repainting _parts_ of the
409  // sprite
410  rOutDev.Push( PushFlags::CLIPREGION );
411 
412  for( const auto& rArea : aUnscrollableAreas )
413  opaqueUpdateSpriteArea( aFirst->second.getSprite(),
414  rOutDev, rArea );
415 
416  rOutDev.Pop();
417  }
418 
419  // repaint uncovered areas from backbuffer - take the
420  // _rounded_ rectangles from above, to have the update
421  // consistent with the scroll above.
422  std::vector< ::basegfx::B2DRange > aUncoveredAreas;
423  ::basegfx::computeSetDifference( aUncoveredAreas,
424  rUpdateArea.maTotalBounds,
425  ::basegfx::B2DRange( rDestRect ) );
426 
427  for( const auto& rArea : aUncoveredAreas )
428  repaintBackground( rOutDev, rBackOutDev, rArea );
429  }
430 
431  void SpriteCanvasHelper::opaqueUpdate( SAL_UNUSED_PARAMETER const ::basegfx::B2DRange&,
432  const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
433  {
437  "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
438 
439  OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
440 
441  // no need to clip output to actual update region - there will
442  // always be ALL sprites contained in the rectangular update
443  // area contained in rTotalArea (that's the way
444  // B2DConnectedRanges work). If rTotalArea appears to be
445  // smaller than the sprite - then this sprite carries a clip,
446  // and the update will be constrained to that rect.
447 
448  // repaint all affected sprites directly to output device
449  for( const auto& rSprite : rSortedUpdateSprites )
450  {
451  if( rSprite.is() )
452  ::boost::polymorphic_downcast< Sprite* >(
453  rSprite.get() )->redraw( rOutDev,
454  false );
455  }
456  }
457 
458  void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rRequestedArea,
459  const std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
460  {
464  "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
465 
466  OutputDevice& rOutDev( mpOwningSpriteCanvas->getFrontBuffer()->getOutDev() );
468  OutputDevice& rBackOutDev( pBackBuffer->getOutDev() );
469 
470  // limit size of update VDev to target outdev's size
471  const Size& rTargetSizePixel( rOutDev.GetOutputSizePixel() );
472 
473  // round output position towards zero. Don't want to truncate
474  // a fraction of a sprite pixel... Clip position at origin,
475  // otherwise, truncation of size below might leave visible
476  // areas uncovered by VDev.
477  const ::Point aOutputPosition(
478  std::max( sal_Int32( 0 ),
479  static_cast< sal_Int32 >(rRequestedArea.getMinX()) ),
480  std::max( sal_Int32( 0 ),
481  static_cast< sal_Int32 >(rRequestedArea.getMinY()) ) );
482  // round output size towards +infty. Don't want to truncate a
483  // fraction of a sprite pixel... Limit coverage of VDev to
484  // output device's area (i.e. not only to total size, but to
485  // cover _only_ the visible parts).
486  const ::Size aOutputSize(
487  std::max( sal_Int32( 0 ),
488  std::min( static_cast< sal_Int32 >(rTargetSizePixel.Width() - aOutputPosition.X()),
489  ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X() ))),
490  std::max( sal_Int32( 0 ),
491  std::min( static_cast< sal_Int32 >(rTargetSizePixel.Height() - aOutputPosition.Y()),
492  ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y() ))));
493 
494  // early exit for empty output area.
495  if( aOutputSize.Width() == 0 &&
496  aOutputSize.Height() == 0 )
497  {
498  return;
499  }
500 
501  const Point aEmptyPoint(0,0);
502  const Size aCurrOutputSize( maVDev->GetOutputSizePixel() );
503 
504  // adapt maVDev's size to the area that actually needs the
505  // repaint.
506  if( aCurrOutputSize.Width() < aOutputSize.Width() ||
507  aCurrOutputSize.Height() < aOutputSize.Height() )
508  {
509  // TODO(P1): Come up with a clever tactic to reduce maVDev
510  // from time to time. Reduction with threshold (say, if
511  // maVDev is more than twice too large) is not wise, as
512  // this might then toggle within the same updateScreen(),
513  // but for different disjunct sprite areas.
514  maVDev->SetOutputSizePixel( aOutputSize );
515  }
516 
517  // paint background
518  maVDev->EnableMapMode( false );
519  maVDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
521  maVDev->DrawOutDev( aEmptyPoint, aOutputSize,
522  aOutputPosition, aOutputSize,
523  rBackOutDev );
524 
525  // repaint all affected sprites on top of background into
526  // VDev.
527  for( const auto& rSprite : rSortedUpdateSprites )
528  {
529  if( rSprite.is() )
530  {
531  Sprite* pSprite = ::boost::polymorphic_downcast< Sprite* >( rSprite.get() );
532 
533  // calc relative sprite position in rUpdateArea (which
534  // need not be the whole screen!)
535  const ::basegfx::B2DPoint& rSpriteScreenPos( pSprite->getPosPixel() );
536  const ::basegfx::B2DPoint& rSpriteRenderPos(
537  rSpriteScreenPos - vcl::unotools::b2DPointFromPoint(aOutputPosition)
538  );
539 
540  pSprite->redraw( *maVDev, rSpriteRenderPos, true );
541  }
542  }
543 
544  // flush to screen
545  rOutDev.EnableMapMode( false );
546  rOutDev.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
547  rOutDev.DrawOutDev( aOutputPosition, aOutputSize,
548  aEmptyPoint, aOutputSize,
549  *maVDev );
550  }
551 
553  {
554  const double denominator( maLastUpdate.getElapsedTime() );
556 
557  OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
558  rtl_math_StringFormat_F,
559  2,'.',nullptr,' ') );
560 
561  // pad with leading space
562  while( text.getLength() < 6 )
563  text = " " + text;
564 
565  text += " fps";
566 
567  renderInfoText( rOutDev,
568  text,
569  Point(0, 0) );
570  }
571 
572  namespace
573  {
574  template< typename T > struct Adder
575  {
576  typedef void result_type;
577 
578  Adder( T& rAdderTarget,
579  T nIncrement ) :
580  mpTarget( &rAdderTarget ),
581  mnIncrement( nIncrement )
582  {
583  }
584 
585  void operator()( const ::canvas::Sprite::Reference& ) { *mpTarget += mnIncrement; }
586  void operator()( T nIncrement ) { *mpTarget += nIncrement; }
587 
590  };
591 
592  template< typename T> Adder<T> makeAdder( T& rAdderTarget,
593  T nIncrement )
594  {
595  return Adder<T>(rAdderTarget, nIncrement);
596  }
597  }
598 
600  {
601  if( !mpRedrawManager )
602  return;
603 
604  sal_Int32 nCount(0);
605 
606  mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
607  OUString text( OUString::number(nCount) );
608 
609  // pad with leading space
610  while( text.getLength() < 3 )
611  text = " " + text;
612 
613  text = "Sprites: " + text;
614 
615  renderInfoText( rOutDev,
616  text,
617  Point(0, 30) );
618  }
619 
621  {
623 
624  if( !(mpRedrawManager &&
625  pBackBuffer) )
626  return;
627 
628  double nPixel(0.0);
629 
630  // accumulate pixel count for each sprite into fCount
632  [&nPixel]( const ::canvas::Sprite::Reference& rSprite )
633  { makeAdder( nPixel, 1.0 )( calcNumPixel(rSprite) ); }
634  );
635 
636  static const int NUM_VIRDEV(2);
637  static const int BYTES_PER_PIXEL(3);
638 
639  const Size& rVDevSize( maVDev->GetOutputSizePixel() );
640  const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
641 
642  const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
643  rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
644  rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
645 
646  OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
647  rtl_math_StringFormat_F,
648  2,'.',nullptr,' ') );
649 
650  // pad with leading space
651  while( text.getLength() < 4 )
652  text = " " + text;
653 
654  text = "Mem: " + text + "MB";
655 
656  renderInfoText( rOutDev,
657  text,
658  Point(0, 60) );
659  }
660 }
661 
662 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetClipRegion()
void opaqueUpdate(const ::basegfx::B2DRange &rTotalArea, const std::vector< ::canvas::Sprite::Reference > &rSortedUpdateSprites)
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
tools::Rectangle rectangleFromB2IRectangle(const basegfx::B2IRange &rRect)
void clearChangeRecords()
Clear sprite change records (typically directly after a screen update)
std::shared_ptr< OutDevProvider > OutDevProviderSharedPtr
void SetAntialiasing(AntialiasingFlags nMode)
void forEachSpriteArea(Functor &rFunc) const
Call given functor for each sprite area that needs an update.
signed char sal_Int8
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
css::uno::Reference< css::rendering::XAnimatedSprite > createSpriteFromAnimation(const css::uno::Reference< css::rendering::XAnimation > &animation)
void Flush() override
#define max(a, b)
Definition: dx_winstuff.hxx:45
bool updateScreen(bool bUpdateAll, bool &io_bSurfaceDirty)
Actually perform the screen update.
void reset()
Reset the time.
Definition: elapsedtime.cxx:54
bool mbIsUnsafeScrolling
When true, canvas uses the scroll optimization (direct scrolls in front buffer)
void EnableMapMode(bool bEnable=true)
::Point pointFromB2DPoint(const basegfx::B2DPoint &rPoint)
void init(css::rendering::XGraphicDevice &rDevice, const OutDevProviderSharedPtr &rOutDev, bool bProtect, bool bHaveAlpha)
Initialize canvas helper.
void updateSprite(const Sprite::Reference &rSprite, const ::basegfx::B2DPoint &rPos, const ::basegfx::B2DRange &rUpdateArea)
OutDevProviderSharedPtr const & getFrontBuffer() const
Get backbuffer for this canvas.
#define min(a, b)
Definition: dx_winstuff.hxx:48
OUTDEV_WINDOW
void disposing()
Release all references.
int nCount
This class manages smooth SpriteCanvas updates.
css::rendering::XGraphicDevice * mpDevice
Phyical output device.
bool mbShowSpriteBounds
When true, canvas creates all new sprites with red lines in the corners.
virtual void redraw(OutputDevice &rOutDev, bool bBufferedUpdate) const =0
Redraw sprite at the stored position.
T * mpTarget
#define FPS_BOUNDS
::basegfx::B2IRange spritePixelAreaFromB2DRange(const ::basegfx::B2DRange &rRange)
Clip a blit between two differently surfaces.
exports com.sun.star. text
Product of this component's factory.
bool mbShowFrameInfo
When true, canvas displays debug info on each frame.
css::uno::Reference< css::rendering::XSprite > createClonedSprite(const css::uno::Reference< css::rendering::XSprite > &original)
#define nPixel
bool SetOutputSizePixel(const Size &rNewSize, bool bErase=true)
void scrollUpdate(const ::basegfx::B2DRange &rMoveStart, const ::basegfx::B2DRange &rMoveEnd, const ::canvas::SpriteRedrawManager::UpdateArea &rUpdateArea)
Gets called when area can be handled by scrolling.
std::shared_ptr< BackBuffer > BackBufferSharedPtr
Definition: backbuffer.hxx:54
void SetTextColor(const Color &rColor)
Size GetOutputSizePixel() const
::Size sizeFromB2DSize(const basegfx::B2DVector &rVec)
void forEachSprite(const Functor &rFunc) const
Call given functor for each active sprite.
#define INFO_COLOR
css::uno::Reference< css::rendering::XAnimatedSprite > createSpriteFromBitmaps(const css::uno::Sequence< css::uno::Reference< css::rendering::XBitmap > > &animationBitmaps, sal_Int8 interpolationMode)
void ExpandPaintClipRegion(const vcl::Region &rRegion)
css::uno::Reference< css::rendering::XCustomSprite > createCustomSprite(const css::geometry::RealSize2D &spriteSize)
VclPtr< VirtualDevice > maVDev
Background compositing surface.
void disposing()
Dispose all internal references.
void SetColor(const Color &)
#define ENSURE_OR_THROW(c, m)
T mnIncrement
sal_Int32 roundUp(const double &rVal)
Round given floating point value up to next integer.
ALIGN_TOP
Specialization of canvas::Sprite interface, to also provide redraw methods.
void backgroundPaint(const ::basegfx::B2DRange &rUpdateRect)
Gets called for simple background repaints.
void flush() const
Flush drawing queue.
void SetFont(const vcl::Font &rNewFont)
#define SAL_INFO(area, stream)
bool clipScrollArea(::basegfx::B2IRange &io_rSourceArea,::basegfx::B2IPoint &io_rDestPoint, std::vector< ::basegfx::B2IRange > &o_ClippedAreas, const ::basegfx::B2IRange &rBounds)
void SetFontHeight(long nHeight)
virtual void DrawOutDev(const Point &rDestPt, const Size &rDestSize, const Point &rSrcPt, const Size &rSrcSize)
BackBufferSharedPtr const & getBackBuffer() const
Get window for this canvas.
void init(const OutDevProviderSharedPtr &rOutDev, SpriteCanvas &rOwningSpriteCanvas,::canvas::SpriteRedrawManager &rManager, bool bProtect, bool bHaveAlpha)
::canvas::tools::ElapsedTime maLastUpdate
For the frame counter timings.
SpriteCanvas * mpOwningSpriteCanvas
Set from the init method. used to generate sprites.
::canvas::SpriteRedrawManager * mpRedrawManager
Set from the SpriteCanvas: instance coordinating sprite redraw.
double getElapsedTime() const
Query the elapsed time.
Definition: elapsedtime.cxx:80
void renderFrameCounter(OutputDevice &rOutDev)
Point pointFromB2IPoint(const basegfx::B2IPoint &rPoint)
void genericUpdate(const ::basegfx::B2DRange &rTotalArea, const std::vector< ::canvas::Sprite::Reference > &rSortedUpdateSprites)
void renderMemUsage(OutputDevice &rOutDev)
basegfx::B2DPoint b2DPointFromPoint(const ::Point &rPoint)
void renderSpriteCount(OutputDevice &rOutDev)
virtual ::basegfx::B2DPoint getPosPixel() const =0
Query position of the left, top pixel of the sprite.
void SetTextAlign(TextAlign eAlign)
SAL_DLLPRIVATE void DrawOutDev(const Point &, const Size &, const Point &, const Size &, const Printer &)=delete