1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137

pdf / paint_aggregator.h [blame]

// Copyright 2010 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PDF_PAINT_AGGREGATOR_H_
#define PDF_PAINT_AGGREGATOR_H_

#include <vector>

#include "pdf/paint_ready_rect.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"

namespace chrome_pdf {

// 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.
//
// See http://code.google.com/p/ppapi/wiki/2DPaintingModel
class PaintAggregator {
 public:
  struct PaintUpdate {
    PaintUpdate();
    PaintUpdate(PaintUpdate&&) noexcept;
    PaintUpdate& operator=(PaintUpdate&&) noexcept;
    PaintUpdate(const PaintUpdate&) = delete;
    PaintUpdate& operator=(const PaintUpdate&) = delete;
    ~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).
    gfx::Vector2d 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.
    gfx::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<gfx::Rect> paint_rects;
  };

  PaintAggregator();
  PaintAggregator(const PaintAggregator&) = delete;
  PaintAggregator& operator=(const PaintAggregator&) = delete;
  ~PaintAggregator();

  // There is a PendingUpdate if InvalidateRect or ScrollRect were called and
  // ClearPendingUpdate was not called.
  bool HasPendingUpdate() const;
  void ClearPendingUpdate();

  PaintUpdate GetPendingUpdate();

  // Sets the result of a call to the plugin to paint.
  //
  // - `ready` includes rects that are finished painting.
  // - `pending` includes rects that are still in-progress.
  void SetIntermediateResults(std::vector<PaintReadyRect> ready,
                              std::vector<gfx::Rect> pending);

  // Returns the rectangles that are ready to be painted. Caller takes
  // ownership.
  std::vector<PaintReadyRect> TakeReadyRects();

  // The given rect should be repainted.
  void InvalidateRect(const gfx::Rect& rect);

  // The given rect should be scrolled by the given amounts.
  void ScrollRect(const gfx::Rect& clip_rect, const gfx::Vector2d& 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.
  struct InternalPaintUpdate {
    InternalPaintUpdate();
    InternalPaintUpdate(InternalPaintUpdate&&) noexcept;
    InternalPaintUpdate& operator=(InternalPaintUpdate&&) noexcept;
    InternalPaintUpdate(const InternalPaintUpdate&) = delete;
    InternalPaintUpdate& operator=(const InternalPaintUpdate&) = delete;
    ~InternalPaintUpdate();

    gfx::Vector2d scroll_delta;
    gfx::Rect scroll_rect;

    // Does not include the scroll damage rect unless
    // `synthesized_scroll_damage_rect` is set.
    std::vector<gfx::Rect> paint_rects;

    // Rectangles that are finished painting.
    std::vector<PaintReadyRect> ready_rects;

    // Whether the scroll damage rect has been added to `paint_rects` yet.
    bool synthesized_scroll_damage_rect = false;
  };

  // Computes the rect damaged by scrolling within `update_.scroll_rect` by
  // `update_.scroll_delta`. This rect must be repainted. It is not included in
  // `update_.paint_rects`.
  gfx::Rect GetScrollDamage() const;

  gfx::Rect ScrollPaintRect(const gfx::Rect& paint_rect,
                            const gfx::Vector2d& amount) const;
  void InvalidateScrollRect();

  // Internal method used by InvalidateRect. If `check_scroll` is true, then the
  // method checks if there's a pending scroll and if so also invalidates `rect`
  // in the new scroll position.
  void InvalidateRectInternal(const gfx::Rect& rect, bool check_scroll);

  InternalPaintUpdate update_;
};

}  // namespace chrome_pdf

#endif  // PDF_PAINT_AGGREGATOR_H_