0

Migrate PDF painting to use abstract Graphics

Switches the painting code in pdf/ to use the new abstract Graphics API,
instead of using pp::Graphics2D directly. This eliminates direct
dependencies on Pepper in the painting code.

Bug: 1099020
Change-Id: Ib848d6824fa0cedd5737d56ceae9927754348cdd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2321706
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: K. Moon <kmoon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792478}
This commit is contained in:
K. Moon
2020-07-29 00:36:43 +00:00
committed by Commit Bot
parent 79ff6542a5
commit 944dd5fedc
6 changed files with 69 additions and 84 deletions

@ -33,6 +33,7 @@
#include "pdf/pdf_features.h"
#include "pdf/ppapi_migration/bitmap.h"
#include "pdf/ppapi_migration/geometry_conversions.h"
#include "pdf/ppapi_migration/graphics.h"
#include "ppapi/c/dev/ppb_cursor_control_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_pdf.h"
@ -974,13 +975,15 @@ void OutOfProcessInstance::StopFind() {
SetTickmarks(tickmarks_);
}
pp::Graphics2D OutOfProcessInstance::CreatePaintGraphics(
std::unique_ptr<Graphics> OutOfProcessInstance::CreatePaintGraphics(
const gfx::Size& size) {
return pp::Graphics2D(this, PPSizeFromSize(size), /*is_always_opaque=*/true);
auto graphics = std::make_unique<PepperGraphics>(this, size);
DCHECK(!graphics->pepper_graphics().is_null());
return graphics;
}
bool OutOfProcessInstance::BindPaintGraphics(pp::Graphics2D& graphics) {
return BindGraphics(graphics);
bool OutOfProcessInstance::BindPaintGraphics(Graphics& graphics) {
return BindGraphics(static_cast<PepperGraphics&>(graphics).pepper_graphics());
}
void OutOfProcessInstance::OnPaint(const std::vector<gfx::Rect>& paint_rects,

@ -36,13 +36,13 @@ class Vector2d;
} // namespace gfx
namespace pp {
class Graphics2D;
class Size;
class TextInput_Dev;
} // namespace pp
namespace chrome_pdf {
class Graphics;
class PaintReadyRect;
class OutOfProcessInstance : public pp::Instance,
@ -68,8 +68,8 @@ class OutOfProcessInstance : public pp::Instance,
void StopFind() override;
// pp::PaintManager::Client implementation.
pp::Graphics2D CreatePaintGraphics(const gfx::Size& size) override;
bool BindPaintGraphics(pp::Graphics2D& graphics) override;
std::unique_ptr<Graphics> CreatePaintGraphics(const gfx::Size& size) override;
bool BindPaintGraphics(Graphics& graphics) override;
void OnPaint(const std::vector<gfx::Rect>& paint_rects,
std::vector<PaintReadyRect>* ready,
std::vector<gfx::Rect>* pending) override;

@ -10,13 +10,15 @@
#include <algorithm>
#include "base/auto_reset.h"
#include "base/check_op.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "pdf/paint_ready_rect.h"
#include "pdf/ppapi_migration/callback.h"
#include "pdf/ppapi_migration/geometry_conversions.h"
#include "ppapi/c/pp_errors.h"
#include "pdf/ppapi_migration/graphics.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/rect.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@ -24,22 +26,8 @@
namespace chrome_pdf {
namespace {
// Not part of ppapi_migration because `gfx::Vector2d` only needs to be
// converted to `pp::Point` at the boundary with `pp::Graphics2D`.
pp::Point ToPepperPoint(const gfx::Vector2d& vector) {
return pp::Point(vector.x(), vector.y());
}
} // namespace
PaintManager::PaintManager(Client* client) : client_(client) {
DCHECK(client_);
// Set the callback object outside of the initializer list to avoid a
// compiler warning about using "this" in an initializer list.
callback_factory_.Initialize(this);
}
PaintManager::~PaintManager() = default;
@ -98,11 +86,10 @@ void PaintManager::SetTransform(float scale,
const gfx::Point& origin,
const gfx::Vector2d& translate,
bool schedule_flush) {
if (graphics_.is_null())
if (!graphics_)
return;
graphics_.SetLayerTransform(scale, PPPointFromPoint(origin),
ToPepperPoint(translate));
graphics_->SetLayerTransform(scale, origin, translate);
if (!schedule_flush)
return;
@ -119,7 +106,7 @@ void PaintManager::ClearTransform() {
}
void PaintManager::Invalidate() {
if (graphics_.is_null() && !has_pending_resize_)
if (!graphics_ && !has_pending_resize_)
return;
EnsureCallbackPending();
@ -129,7 +116,7 @@ void PaintManager::Invalidate() {
void PaintManager::InvalidateRect(const gfx::Rect& rect) {
DCHECK(!in_paint_);
if (graphics_.is_null() && !has_pending_resize_)
if (!graphics_ && !has_pending_resize_)
return;
// Clip the rect to the device area.
@ -146,7 +133,7 @@ void PaintManager::ScrollRect(const gfx::Rect& clip_rect,
const gfx::Vector2d& amount) {
DCHECK(!in_paint_);
if (graphics_.is_null() && !has_pending_resize_)
if (!graphics_ && !has_pending_resize_)
return;
EnsureCallbackPending();
@ -175,7 +162,9 @@ void PaintManager::EnsureCallbackPending() {
return;
pp::Module::Get()->core()->CallOnMainThread(
0, callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete),
0,
PPCompletionCallbackFromResultCallback(base::BindOnce(
&PaintManager::OnManualCallbackComplete, weak_factory_.GetWeakPtr())),
0);
manual_callback_pending_ = true;
}
@ -193,27 +182,28 @@ void PaintManager::DoPaint() {
// However, the bind must not happen until afterward since we don't want to
// have an unpainted device bound. The needs_binding flag tells us whether to
// do this later.
//
// Note that |has_pending_resize_| will always be set on the first DoPaint().
DCHECK(graphics_ || has_pending_resize_);
if (has_pending_resize_) {
plugin_size_ = pending_size_;
// Extra call to pp_size() required here because the operator for converting
// to PP_Size is non-const.
const gfx::Size old_size = SizeFromPPSize(graphics_.size().pp_size());
// Only create a new graphics context if the current context isn't big
// enough or if it is far too big. This avoids creating a new context if
// we only resize by a small amount.
gfx::Size old_size = graphics_ ? graphics_->size() : gfx::Size();
gfx::Size new_size = GetNewContextSize(old_size, pending_size_);
if (old_size != new_size) {
if (old_size != new_size || !graphics_) {
graphics_ = client_->CreatePaintGraphics(new_size);
graphics_need_to_be_bound_ = true;
// Since we're binding a new one, all of the callbacks have been canceled.
manual_callback_pending_ = false;
flush_pending_ = false;
callback_factory_.CancelAll();
weak_factory_.InvalidateWeakPtrs();
}
if (pending_device_scale_ != 1.0)
graphics_.SetScale(1.0 / pending_device_scale_);
graphics_->SetScale(1.0 / pending_device_scale_);
device_scale_ = pending_device_scale_;
// This must be cleared before calling into the plugin since it may do
@ -235,10 +225,8 @@ void PaintManager::DoPaint() {
aggregator_.ClearPendingUpdate();
// Apply any scroll first.
if (update.has_scroll) {
graphics_.Scroll(PPRectFromRect(update.scroll_rect),
ToPepperPoint(update.scroll_delta));
}
if (update.has_scroll)
graphics_->Scroll(update.scroll_rect, update.scroll_delta);
view_size_changed_waiting_for_paint_ = false;
} else {
@ -267,8 +255,7 @@ void PaintManager::DoPaint() {
}
for (const auto& ready_rect : ready_now) {
graphics_.PaintImageData(ready_rect.image_data(), pp::Point(),
PPRectFromRect(ready_rect.rect()));
graphics_->PaintImage(ready_rect.image(), ready_rect.rect());
}
Flush();
@ -276,33 +263,16 @@ void PaintManager::DoPaint() {
first_paint_ = false;
if (graphics_need_to_be_bound_) {
client_->BindPaintGraphics(graphics_);
client_->BindPaintGraphics(*graphics_);
graphics_need_to_be_bound_ = false;
}
}
void PaintManager::Flush() {
flush_requested_ = false;
int32_t result = graphics_.Flush(
callback_factory_.NewCallback(&PaintManager::OnFlushComplete));
// If you trigger this assertion, then your plugin has called Flush()
// manually. When using the PaintManager, you should not call Flush, it will
// handle that for you because it needs to know when it can do the next paint
// by implementing the flush callback.
//
// Another possible cause of this assertion is re-using devices. If you
// use one device, swap it with another, then swap it back, we won't know
// that we've already scheduled a Flush on the first device. It's best to not
// re-use devices in this way.
DCHECK_NE(PP_ERROR_INPROGRESS, result);
if (result == PP_OK_COMPLETIONPENDING) {
flush_pending_ = true;
} else {
DCHECK_EQ(PP_OK, result); // Catch all other errors in debug mode.
}
flush_pending_ = graphics_->Flush(base::BindOnce(
&PaintManager::OnFlushComplete, weak_factory_.GetWeakPtr()));
DCHECK(flush_pending_);
}
void PaintManager::OnFlushComplete(int32_t) {

@ -7,11 +7,11 @@
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "pdf/paint_aggregator.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/utility/completion_callback_factory.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
@ -22,6 +22,8 @@ class Vector2d;
namespace chrome_pdf {
class Graphics;
// 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
@ -33,13 +35,14 @@ class PaintManager {
public:
class Client {
public:
// Creates a new, unbound `pp::Graphics2D` for the paint manager, with the
// given |size| and always-opaque rendering.
virtual pp::Graphics2D CreatePaintGraphics(const gfx::Size& size) = 0;
// Creates a new, unbound `Graphics` for the paint manager, with the given
// |size| and always-opaque rendering.
virtual std::unique_ptr<Graphics> CreatePaintGraphics(
const gfx::Size& size) = 0;
// Binds a `pp::Graphics2D` created by `CreatePaintGraphics()`, returning
// `true` if binding was successful.
virtual bool BindPaintGraphics(pp::Graphics2D& graphics) = 0;
// Binds a `Graphics` created by `CreatePaintGraphics()`, returning `true`
// if binding was successful.
virtual bool BindPaintGraphics(Graphics& graphics) = 0;
// Paints the given invalid area of the plugin to the given graphics
// device. Returns true if anything was painted.
@ -147,11 +150,8 @@ class PaintManager {
// Non-owning pointer. See the constructor.
Client* const client_;
pp::CompletionCallbackFactory<PaintManager> callback_factory_;
// This graphics device will be is_null() if no graphics has been manually
// set yet.
pp::Graphics2D graphics_;
// This graphics device will be null if no graphics has been set yet.
std::unique_ptr<Graphics> graphics_;
PaintAggregator aggregator_;
@ -178,6 +178,8 @@ class PaintManager {
// 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

@ -13,9 +13,12 @@ namespace chrome_pdf {
PaintReadyRect::PaintReadyRect(const pp::Rect& rect,
const pp::ImageData& image_data,
bool flush_now)
: rect_(RectFromPPRect(rect)),
image_data_(image_data),
flush_now_(flush_now) {}
: rect_(RectFromPPRect(rect)), image_(image_data), flush_now_(flush_now) {}
PaintReadyRect::PaintReadyRect(const gfx::Rect& rect,
const SkBitmap& bitmap,
bool flush_now)
: rect_(rect), image_(bitmap), flush_now_(flush_now) {}
PaintReadyRect::PaintReadyRect(const PaintReadyRect& other) = default;

@ -5,10 +5,13 @@
#ifndef PDF_PAINT_READY_RECT_H_
#define PDF_PAINT_READY_RECT_H_
#include "ppapi/cpp/image_data.h"
#include "pdf/ppapi_migration/image.h"
#include "ui/gfx/geometry/rect.h"
class SkBitmap;
namespace pp {
class ImageData;
class Rect;
} // namespace pp
@ -22,6 +25,10 @@ class PaintReadyRect {
PaintReadyRect(const pp::Rect& rect,
const pp::ImageData& image_data,
bool flush_now = false);
PaintReadyRect(const gfx::Rect& rect,
const SkBitmap& bitmap,
bool flush_now = false);
PaintReadyRect(const PaintReadyRect& other);
PaintReadyRect& operator=(const PaintReadyRect& other);
~PaintReadyRect();
@ -29,7 +36,7 @@ class PaintReadyRect {
const gfx::Rect& rect() const { return rect_; }
void set_rect(const gfx::Rect& rect) { rect_ = rect; }
const pp::ImageData& image_data() const { return image_data_; }
const Image& image() const { return image_; }
// Whether to flush to screen immediately; otherwise, when the rest of the
// plugin viewport is ready.
@ -37,7 +44,7 @@ class PaintReadyRect {
private:
gfx::Rect rect_;
pp::ImageData image_data_;
Image image_;
bool flush_now_;
};