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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
pdf / paint_manager.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_MANAGER_H_
#define PDF_PAINT_MANAGER_H_
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "pdf/paint_aggregator.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/size.h"
class SkImage;
class SkSurface;
namespace gfx {
class Point;
class Rect;
class Vector2d;
class Vector2dF;
} // namespace gfx
namespace chrome_pdf {
// Custom PaintManager for the PDF plugin. This is branched from the Pepper
// version. The difference is that this supports progressive rendering of dirty
// rects, where multiple calls to the rendering engine are needed. It also
// supports having higher-priority rects flushing right away, i.e. the
// scrollbars.
//
// The client's OnPaint
class PaintManager {
public:
class Client {
public:
// Invalidates the entire plugin container, scheduling a repaint.
virtual void InvalidatePluginContainer() = 0;
// Paints the given invalid area of the plugin to the given graphics
// device. Returns true if anything was painted.
//
// You are given the list of rects to paint in `paint_rects`. You can
// combine painting into less rectangles if it's more efficient. When a
// rect is painted, information about that paint should be inserted into
// `ready`. Otherwise if a paint needs more work, add the rect to
// `pending`. If `pending` is not empty, your OnPaint function will get
// called again. Once OnPaint is called and it returns no pending rects,
// all the previously ready rects will be flushed on screen. The exception
// is for ready rects that have `flush_now` set to true. These will be
// flushed right away.
//
// Do not call Flush() on the graphics device, this will be done
// automatically if you return true from this function since the
// PaintManager needs to handle the callback.
//
// Calling Invalidate/Scroll is not allowed while inside an OnPaint
virtual void OnPaint(const std::vector<gfx::Rect>& paint_rects,
std::vector<PaintReadyRect>& ready,
std::vector<gfx::Rect>& pending) = 0;
// Updates the client with the latest snapshot created by `Flush()`.
virtual void UpdateSnapshot(sk_sp<SkImage> snapshot) = 0;
// Updates the client with the latest output scale.
virtual void UpdateScale(float scale) = 0;
// Updates the client with the latest output layer transform.
virtual void UpdateLayerTransform(float scale,
const gfx::Vector2dF& translate) = 0;
protected:
// You shouldn't delete through this interface.
~Client() = default;
};
// The Client is a non-owning pointer and must remain valid (normally the
// object implementing the Client interface will own the paint manager).
//
// You will need to call SetSize() before this class will do anything.
// Normally you do this from UpdateGeometryOnViewChanged() of your plugin
// instance.
explicit PaintManager(Client* client);
PaintManager(const PaintManager&) = delete;
PaintManager& operator=(const PaintManager&) = delete;
~PaintManager();
// Returns the size of the graphics context to allocate for a given plugin
// size. We may allocated a slightly larger buffer than required so that we
// don't have to resize the context when scrollbars appear/dissapear due to
// zooming (which can result in flickering).
static gfx::Size GetNewContextSize(const gfx::Size& current_context_size,
const gfx::Size& plugin_size);
// Sets the size of the plugin. If the size is the same as the previous call,
// this will be a NOP. If the size has changed, a new device will be
// allocated to the given size and a paint to that device will be scheduled.
//
// This is intended to be called from ViewChanged with the size of the
// plugin. Since it tracks the old size and only allocates when the size
// changes, you can always call this function without worrying about whether
// the size changed or ViewChanged is called for another reason (like the
// position changed).
void SetSize(const gfx::Size& new_size, float new_device_scale);
// Invalidate the entire plugin.
void Invalidate();
// Invalidate the given rect.
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);
// Returns the size of the graphics context for the next paint operation.
// This is the pending size if a resize is pending (the plugin has called
// SetSize but we haven't actually painted it yet), or the current size of
// no resize is pending.
gfx::Size GetEffectiveSize() const;
float GetEffectiveDeviceScale() const;
// Set the transform for the graphics layer.
// If `schedule_flush` is true, it ensures a flush will be scheduled for
// this change. If `schedule_flush` is false, then the change will not take
// effect until another change causes a flush.
void SetTransform(float scale,
const gfx::Point& origin,
const gfx::Vector2d& translate,
bool schedule_flush);
// Resets any transform for the graphics layer.
// This does not schedule a flush.
void ClearTransform();
private:
// Makes sure there is a callback that will trigger a paint at a later time.
// This will be either a Flush callback telling us we're allowed to generate
// more data, or, if there's no flush callback pending, a manual call back
// to the message loop via ExecuteOnMainThread.
void EnsureCallbackPending();
// Does the client paint and executes a Flush if necessary.
void DoPaint();
// Executes a Flush.
void Flush();
// Callback for asynchronous completion of Flush.
void OnFlushComplete();
// Callback for manual scheduling of paints when there is no flush callback
// pending.
void OnManualCallbackComplete();
// Non-owning pointer. See the constructor.
const raw_ptr<Client> client_;
// Backing Skia surface.
sk_sp<SkSurface> surface_;
PaintAggregator aggregator_;
// See comment for EnsureCallbackPending for more on how these work.
bool manual_callback_pending_ = false;
bool flush_pending_ = false;
bool flush_requested_ = false;
// When we get a resize, we don't do so right away (see `SetSize()`). The
// `has_pending_resize_` tells us that we need to do a resize for the next
// paint operation. When true, the new size is in `pending_size_`.
bool has_pending_resize_ = false;
gfx::Size pending_size_;
gfx::Size plugin_size_;
float pending_device_scale_ = 1.0f;
float device_scale_ = 1.0f;
// True iff we're in the middle of a paint.
bool in_paint_ = false;
// True if we haven't painted the plugin viewport yet.
bool first_paint_ = true;
// True when the view size just changed and we're waiting for a paint.
bool view_size_changed_waiting_for_paint_ = false;
base::WeakPtrFactory<PaintManager> weak_factory_{this};
};
} // namespace chrome_pdf
#endif // PDF_PAINT_MANAGER_H_