// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_
#define PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_
#include <stddef.h>
#include <vector>
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/rect.h"
/// @file
/// This file defines the API to aggregate multiple invalidation and scroll
/// commands to produce a scroll and repaint sequence.
namespace pp {
/// This class is responsible for aggregating multiple invalidation and scroll
/// commands to produce a scroll and repaint sequence. You can use this manually
/// to track your updates, but most applications will use the PaintManager to
/// additionally handle the necessary callbacks on top of the PaintAggregator
/// functionality.
///
/// Refer to <code>http://code.google.com/p/ppapi/wiki/2DPaintingModel</code>
/// for further information.
class PaintAggregator {
public:
struct PaintUpdate {
/// Default constructor for creating an is_null() <code>PaintUpdate</code>
/// object.
PaintUpdate();
/// Destructor.
~PaintUpdate();
/// True if there is a scroll applied. This indicates that the scroll delta
/// and scroll_rect are nonzero (just as a convenience).
bool has_scroll;
/// The amount to scroll by. Either the X or Y may be nonzero to indicate a
/// scroll in that direction, but there will never be a scroll in both
/// directions at the same time (this will be converted to a paint of the
/// region instead).
///
/// If there is no scroll, this will be (0, 0).
Point scroll_delta;
/// The rectangle that should be scrolled by the scroll_delta. If there is
/// no scroll, this will be (0, 0, 0, 0). We only track one scroll command
/// at once. If there are multiple ones, they will be converted to
/// invalidates.
Rect scroll_rect;
/// A list of all the individual dirty rectangles. This is an aggregated
/// list of all invalidate calls. Different rectangles may be unified to
/// produce a minimal list with no overlap that is more efficient to paint.
/// This list also contains the region exposed by any scroll command.
std::vector<Rect> paint_rects;
/// The union of all paint_rects.
Rect paint_bounds;
};
/// Default constructor.
PaintAggregator();
/// Setter function setting the max ratio of paint rect area to scroll rect
/// area that we will tolerate before downgrading the scroll into a repaint.
///
/// If the combined area of paint rects contained within the scroll
/// rect grows too large, then we might as well just treat
/// the scroll rect as a paint rect.
///
/// @param[in] area The max ratio of paint rect area to scroll rect area that
/// we will tolerate before downgrading the scroll into a repaint.
void set_max_redundant_paint_to_scroll_area(float area) {
max_redundant_paint_to_scroll_area_ = area;
}
/// Setter function for setting the maximum number of paint rects. If we
/// exceed this limit, then we'll start combining paint rects (see
/// CombinePaintRects). This limiting can be important since there is
/// typically some overhead in deciding what to paint. If your module is fast
/// at doing these computations, raise this threshold, if your module is
/// slow, lower it (probably requires some tuning to find the right value).
///
/// @param[in] max_rects The maximum number of paint rects.
void set_max_paint_rects(size_t max_rects) {
max_paint_rects_ = max_rects;
}
/// This function determines if there is a pending update. There is a
/// PendingUpdate if InvalidateRect or ScrollRect were called and
/// ClearPendingUpdate was not called.
///
/// @return true if there is a pending update, otherwise false.
bool HasPendingUpdate() const;
/// This function clears a pending update.
void ClearPendingUpdate();
/// This function gets a pending update.
///
/// @return A PaintUpdate containing the pending update.
PaintUpdate GetPendingUpdate() const;
/// This function invalidates the rect so it will be repainted.
///
/// @param[in] rect A rect to be repainted.
void InvalidateRect(const Rect& rect);
/// This function adds a pending scroll update.
///
/// @param[in] clip_rect The rect to scroll.
/// @param[in] amount A Point amount to scroll <code>rect</code>.
void ScrollRect(const Rect& clip_rect, const Point& amount);
private:
// This structure is an internal version of PaintUpdate. It's different in
// two respects:
//
// - The scroll damange (area exposed by the scroll operation, if any) is
// maintained separately from the dirty rects generated by calling
// InvalidateRect. We need to know this distinction for some operations.
//
// - The paint bounds union is computed on the fly so we don't have to keep
// a rectangle up to date as we do different operations.
class InternalPaintUpdate {
public:
InternalPaintUpdate();
~InternalPaintUpdate();
// Computes the rect damaged by scrolling within |scroll_rect| by
// |scroll_delta|. This rect must be repainted. It is not included in
// paint_rects or in the rect returned by GetPaintBounds.
Rect GetScrollDamage() const;
// Returns the smallest rect containing all paint rects, not including the
// scroll damage rect.
Rect GetPaintBounds() const;
Point scroll_delta;
Rect scroll_rect;
// Does not include the scroll damage rect.
std::vector<Rect> paint_rects;
};
Rect ScrollPaintRect(const Rect& paint_rect, const Point& amount) const;
bool ShouldInvalidateScrollRect(const Rect& rect) const;
void InvalidateScrollRect();
void CombinePaintRects();
InternalPaintUpdate update_;
// If the combined area of paint rects contained within the scroll rect grows
// too large, then we might as well just treat the scroll rect as a paint
// rect. This constant sets the max ratio of paint rect area to scroll rect
// area that we will tolerate before downgrading the scroll into a repaint.
float max_redundant_paint_to_scroll_area_;
// The maximum number of paint rects. If we exceed this limit, then we'll
// start combining paint rects (see CombinePaintRects). This limiting can be
// important since there is typically some overhead in deciding what to
// paint. If your plugin is fast at doing these computations, raise this
// threshold, if your plugin is slow, lower it (probably requires some
// tuning to find the right value).
size_t max_paint_rects_;
};
} // namespace pp
#endif // PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_