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
|
// 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_
|