LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / canvas / inc / spriteredrawmanager.hxx
blob87c692f6d7dc9cbab99b05c3245bd3d9f4b9c837
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 .
20 #pragma once
22 #include <basegfx/range/b2dconnectedranges.hxx>
23 #include <basegfx/point/b2dpoint.hxx>
24 #include <basegfx/vector/b2dvector.hxx>
25 #include <basegfx/range/b2drange.hxx>
26 #include <basegfx/range/b2drectangle.hxx>
28 #include <vector>
29 #include <algorithm>
31 #include "base/sprite.hxx"
32 #include <canvas/canvastoolsdllapi.h>
34 /* Definition of SpriteRedrawManager class */
36 namespace canvas
38 /** This class manages smooth SpriteCanvas updates
40 Use this class to handle the ::canvas::SpriteSurface methods,
41 that track and process sprite update events. Recorded update
42 events are later grouped by connected areas (i.e. all sprites
43 that somehow overlap over a rectangular area are grouped
44 together); the forEachSpriteArea() method calls the passed
45 functor for each of those connected areas.
47 Note that, although this class generally works with IEEE
48 doubles, the calculation of connected areas happens in the
49 integer domain - it is generally expected that repaints can
50 only be divided at pixel boundaries, without causing visible
51 artifacts. Therefore, sprites that touch the same pixel (but
52 don't necessarily have the same floating point coordinates
53 there) will reside in a common sprite area and handled
54 together in the forEachSpriteArea functor call.
56 class CANVASTOOLS_DLLPUBLIC SpriteRedrawManager
58 public:
59 /** Data container for the connected components list
61 class SpriteInfo
63 public:
64 /** Create sprite info
66 @param rRef
67 Sprite this info represents (might be the NULL ref)
69 @param rTrueUpdateArea
70 True (un-rounded) update area this sprite has recorded
72 @param bNeedsUpdate
73 When false, this sprite is not a member of the change
74 record list. Thus, it only needs redraw if within the
75 update area of other, changed sprites.
77 @internal
79 SpriteInfo( const Sprite::Reference& rRef,
80 const ::basegfx::B2DRange& rTrueUpdateArea,
81 bool bNeedsUpdate ) :
82 mpSprite( rRef ),
83 maTrueUpdateArea( rTrueUpdateArea ),
84 mbNeedsUpdate( bNeedsUpdate ),
85 mbIsPureMove( false )
89 /** Create sprite info, specify move type
91 @param rRef
92 Sprite this info represents (might be the NULL ref)
94 @param rTrueUpdateArea
95 True (un-rounded) update area this sprite has recorded
97 @param bNeedsUpdate
98 When false, this sprite is not a member of the change
99 record list. Thus, it only needs redraw if within the
100 update area of other, changed sprites.
102 @param bIsPureMove
103 When true, this sprite is _only_ moved, no other
104 changes happened.
106 @internal
108 SpriteInfo( const Sprite::Reference& rRef,
109 const ::basegfx::B2DRange& rTrueUpdateArea,
110 bool bNeedsUpdate,
111 bool bIsPureMove ) :
112 mpSprite( rRef ),
113 maTrueUpdateArea( rTrueUpdateArea ),
114 mbNeedsUpdate( bNeedsUpdate ),
115 mbIsPureMove( bIsPureMove )
119 const Sprite::Reference& getSprite() const { return mpSprite; }
121 // #i61843# need to return by value here, to be used safely from bind
122 const ::basegfx::B2DRange& getUpdateArea() const { return maTrueUpdateArea; }
123 bool needsUpdate() const { return mbNeedsUpdate; }
124 bool isPureMove() const { return mbIsPureMove; }
126 private:
127 Sprite::Reference mpSprite;
128 ::basegfx::B2DRange maTrueUpdateArea;
129 bool mbNeedsUpdate;
130 bool mbIsPureMove;
134 /** Helper struct for SpriteTracer template
136 This struct stores change information to a sprite's visual
137 appearance (move, content updated, and the like).
139 struct SpriteChangeRecord
141 enum class ChangeType { move, update };
143 SpriteChangeRecord( const Sprite::Reference& rSprite,
144 const ::basegfx::B2DPoint& rOldPos,
145 const ::basegfx::B2DPoint& rNewPos,
146 const ::basegfx::B2DVector& rSpriteSize ) :
147 meChangeType( ChangeType::move ),
148 mpAffectedSprite( rSprite ),
149 maOldPos( rOldPos ),
150 maUpdateArea( rNewPos.getX(),
151 rNewPos.getY(),
152 rNewPos.getX() + rSpriteSize.getX(),
153 rNewPos.getY() + rSpriteSize.getY() )
157 SpriteChangeRecord( const Sprite::Reference& rSprite,
158 const ::basegfx::B2DPoint& rPos,
159 const ::basegfx::B2DRange& rUpdateArea ) :
160 meChangeType( ChangeType::update ),
161 mpAffectedSprite( rSprite ),
162 maOldPos( rPos ),
163 maUpdateArea( rUpdateArea )
167 const Sprite::Reference& getSprite() const { return mpAffectedSprite; }
169 ChangeType meChangeType;
170 Sprite::Reference mpAffectedSprite;
171 ::basegfx::B2DPoint maOldPos;
172 ::basegfx::B2DRange maUpdateArea;
175 typedef ::std::vector< SpriteChangeRecord > VectorOfChangeRecords;
176 typedef ::basegfx::B2DConnectedRanges< SpriteInfo > SpriteConnectedRanges;
177 typedef SpriteConnectedRanges::ComponentType AreaComponent;
178 typedef SpriteConnectedRanges::ConnectedComponents UpdateArea;
179 typedef ::std::vector< Sprite::Reference > VectorOfSprites;
181 SpriteRedrawManager();
182 SpriteRedrawManager(const SpriteRedrawManager&) = delete;
183 SpriteRedrawManager& operator=( const SpriteRedrawManager& ) = delete;
185 /** Must be called when user of this object gets
186 disposed. Frees all internal references.
188 void disposing();
190 /** Functor, to be used from forEachSpriteArea
192 template< typename Functor > struct AreaUpdateCaller
194 AreaUpdateCaller( Functor& rFunc,
195 const SpriteRedrawManager& rManager ) :
196 mrFunc( rFunc ),
197 mrManager( rManager )
201 void operator()( const UpdateArea& rUpdateArea )
203 mrManager.handleArea( mrFunc, rUpdateArea );
206 Functor& mrFunc;
207 const SpriteRedrawManager& mrManager;
210 /** Call given functor for each sprite area that needs an
211 update.
213 This method calls the given functor for each update area
214 (calculated from the sprite change records).
216 @tpl Functor
217 Must provide the following four methods:
218 <pre>
219 void backgroundPaint( ::basegfx::B2DRange aUpdateRect );
220 void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart,
221 ::basegfx::B2DRange& o_rMoveEnd,
222 UpdateArea aUpdateArea );
223 void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
224 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
225 void genericUpdate( const ::basegfx::B2DRange& rTotalArea,
226 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
227 </pre>
228 The backgroundPaint() method is called to simply repaint
229 background content, the scrollUpdate() method is used to
230 scroll a given area, and paint background in the uncovered
231 areas, the opaqueUpdate() method is called when a sprite
232 can be painted in the given area without taking background
233 content into account, and finally, genericUpdate() is
234 called for complex updates, where first the background and
235 then all sprites consecutively have to be repainted.
237 template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const
239 SpriteConnectedRanges aUpdateAreas;
241 setupUpdateAreas( aUpdateAreas );
243 aUpdateAreas.forEachAggregate(
244 AreaUpdateCaller< Functor >( rFunc, *this ) );
247 /** Call given functor for each active sprite.
249 This method calls the given functor for each active
250 sprite, in the order of sprite priority.
252 @tpl Functor
253 Must provide a Functor::operator( Sprite::Reference& )
254 method.
256 template< typename Functor > void forEachSprite( const Functor& rFunc ) const
258 ::std::for_each( maSprites.begin(),
259 maSprites.end(),
260 rFunc );
263 /// Clear sprite change records (typically directly after a screen update)
264 void clearChangeRecords();
266 // SpriteSurface interface, is delegated to e.g. from SpriteCanvas
267 void showSprite( const Sprite::Reference& rSprite );
268 void hideSprite( const Sprite::Reference& rSprite );
269 void moveSprite( const Sprite::Reference& rSprite,
270 const ::basegfx::B2DPoint& rOldPos,
271 const ::basegfx::B2DPoint& rNewPos,
272 const ::basegfx::B2DVector& rSpriteSize );
273 void updateSprite( const Sprite::Reference& rSprite,
274 const ::basegfx::B2DPoint& rPos,
275 const ::basegfx::B2DRange& rUpdateArea );
277 /** Internal, handles each distinct component for forEachAggregate()
279 The reason why this must be public is that it needs to be
280 accessible from the AreaUpdateCaller functor.
282 @internal
284 template< typename Functor > void handleArea( Functor& rFunc,
285 const UpdateArea& rUpdateArea ) const
287 // check whether this area contains changed sprites at all
288 // (if not, just ignore it)
289 if( areSpritesChanged( rUpdateArea ) )
291 // at least one of the sprites actually needs an
292 // update - process whole area.
294 // check whether this area could be handled special
295 // (background paint, direct update, scroll, etc.)
296 ::basegfx::B2DRange aMoveStart;
297 ::basegfx::B2DRange aMoveEnd;
298 if( rUpdateArea.maComponentList.empty() )
300 rFunc.backgroundPaint( rUpdateArea.maTotalBounds );
302 else
304 // cache number of sprites in this area (it's a
305 // list, and both isAreaUpdateScroll() and
306 // isAreaUpdateOpaque() need it).
307 const ::std::size_t nNumSprites(
308 rUpdateArea.maComponentList.size() );
310 if( isAreaUpdateScroll( aMoveStart,
311 aMoveEnd,
312 rUpdateArea,
313 nNumSprites ) )
315 rFunc.scrollUpdate( aMoveStart,
316 aMoveEnd,
317 rUpdateArea );
319 else
321 // potentially, more than a single sprite
322 // involved. Have to sort component lists for
323 // sprite prio.
324 VectorOfSprites aSortedUpdateSprites;
325 for (auto const& elem : rUpdateArea.maComponentList)
327 const Sprite::Reference& rSprite( elem.second.getSprite() );
328 if( rSprite.is() )
329 aSortedUpdateSprites.push_back( rSprite );
332 ::std::sort( aSortedUpdateSprites.begin(),
333 aSortedUpdateSprites.end(),
334 SpriteWeakOrder() );
336 if( isAreaUpdateOpaque( rUpdateArea,
337 nNumSprites ) )
339 rFunc.opaqueUpdate( rUpdateArea.maTotalBounds,
340 aSortedUpdateSprites );
342 else
344 rFunc.genericUpdate( rUpdateArea.maTotalBounds,
345 aSortedUpdateSprites );
352 private:
353 /** Central method of this class. Calculates the set of
354 disjunct components that need an update.
356 void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const;
358 bool areSpritesChanged( const UpdateArea& rUpdateArea ) const;
360 bool isAreaUpdateNotOpaque( const ::basegfx::B2DRectangle& rUpdateRect,
361 const AreaComponent& rComponent ) const;
363 bool isAreaUpdateOpaque( const UpdateArea& rUpdateArea,
364 ::std::size_t nNumSprites ) const;
366 /** Check whether given update area can be handled by a simple
367 scroll
369 @param o_rMoveStart
370 Start rect of the move
372 @param o_rMoveEnd
373 End rect of the move. The content must be moved from start
374 to end rect
376 @param rUpdateArea
377 Area to check for scroll update optimization
379 bool isAreaUpdateScroll( ::basegfx::B2DRectangle& o_rMoveStart,
380 ::basegfx::B2DRectangle& o_rMoveEnd,
381 const UpdateArea& rUpdateArea,
382 ::std::size_t nNumSprites ) const;
385 VectorOfSprites maSprites; // list of active
386 // sprite
387 // objects. this
388 // list is only
389 // used for full
390 // repaints,
391 // otherwise, we
392 // rely on the
393 // active sprites
394 // itself to notify
395 // us.
397 VectorOfChangeRecords maChangeRecords; // vector of
398 // sprites
399 // changes
400 // since last
401 // updateScreen()
402 // call
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */