0

[unseasoned-pdf] Avoid scaling down window_rect to DIPS in PdfViewWebPlugin::UpdateGeometry().

PdfViewPluginBase::UpdateGeometryOnViewChanged() is shared by both
Pepper and Pepper-free plugins, which currently requires `new_view_rect`
in DIPs as an input. This input parameter may cause rounding issue in
the Pepper-free plugin when using zoom for DSF is enabled and the device
scale is larger than 1 because UpdateGeometry() needs to scale down
`window_rect` first before UpdateGeometryOnViewChanged() scale it back
up.

To avoid this rounding issue, this CL changes
PdfViewPluginBase::UpdateGeometryOnViewChanged() to accept a
`new_plugin_rect` in device pixels instead of a view rect in DIPs as an
input, also renames this function to
PdfViewPluginBase::UpdateGeometryOnPluginRectChanged().

Also fixes a unit test which was previously affected by the rounding
issue and add `device_to_css_scale_` and `plugin_rect_in_css_pixels_`
to PdfViewWebPlugin to simplify Paint().

Bug: 1238395
Change-Id: I6235ac878e5ee3d5b96f5c4c504c9db402621fb0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3161413
Reviewed-by: K. Moon <kmoon@chromium.org>
Commit-Queue: Hui Yingst <nigi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#922272}
This commit is contained in:
Hui Yingst
2021-09-16 19:59:39 +00:00
committed by Chromium LUCI CQ
parent 6758273675
commit 9cb2226c7a
6 changed files with 55 additions and 41 deletions

@ -530,8 +530,9 @@ bool OutOfProcessInstance::HandleInputEvent(const pp::InputEvent& event) {
}
void OutOfProcessInstance::DidChangeView(const pp::View& view) {
UpdateGeometryOnViewChanged(RectFromPPRect(view.GetRect()),
view.GetDeviceScale());
const gfx::Rect new_plugin_rect = gfx::ScaleToEnclosingRectSafe(
RectFromPPRect(view.GetRect()), view.GetDeviceScale());
UpdateGeometryOnPluginRectChanged(new_plugin_rect, view.GetDeviceScale());
if (IsPrintPreview() && !stop_scrolling()) {
set_scroll_position(PointFromPPPoint(view.GetScrollOffset()));

@ -797,12 +797,10 @@ void PdfViewPluginBase::PrintEnd() {
engine_->PrintEnd();
}
void PdfViewPluginBase::UpdateGeometryOnViewChanged(
const gfx::Rect& new_view_rect,
void PdfViewPluginBase::UpdateGeometryOnPluginRectChanged(
const gfx::Rect& new_plugin_rect,
float new_device_scale) {
DCHECK_GT(new_device_scale, 0.0f);
const gfx::Rect new_plugin_rect =
gfx::ScaleToEnclosingRectSafe(new_view_rect, new_device_scale);
if (new_device_scale == device_scale_ && new_plugin_rect == plugin_rect_)
return;
@ -810,7 +808,13 @@ void PdfViewPluginBase::UpdateGeometryOnViewChanged(
const float old_device_scale = device_scale_;
device_scale_ = new_device_scale;
plugin_rect_ = new_plugin_rect;
plugin_dip_size_ = new_view_rect.size();
// TODO(crbug.com/1250173): For the Pepper-free plugin, `plugin_dip_size_` is
// calculated from the `window_rect` in PdfViewWebPlugin::UpdateGeometry().
// We should try to avoid the downscaling during this calculation process and
// maybe migrate off `plugin_dip_size_`.
plugin_dip_size_ =
gfx::ScaleToEnclosingRectSafe(new_plugin_rect, 1.0f / new_device_scale)
.size();
paint_manager_.SetSize(plugin_rect_.size(), device_scale_);

@ -237,11 +237,11 @@ class PdfViewPluginBase : public PDFEngine::Client,
// Returns the plugin-specific image data buffer.
virtual Image GetPluginImageData() const;
// Updates the geometry of the plugin and its image data if the view's
// size or scale has changed. `new_view_rect` must be in CSS pixels (without
// device scale applied).
void UpdateGeometryOnViewChanged(const gfx::Rect& new_view_rect,
float new_device_scale);
// Updates the geometry of the plugin and its image data if the plugin rect
// or the device scale has changed. `new_plugin_rect` must be in device
// pixels (with the device scale applied).
void UpdateGeometryOnPluginRectChanged(const gfx::Rect& new_plugin_rect,
float new_device_scale);
// A helper of OnGeometryChanged() which updates the available area and
// the background parts, and notifies the PDF engine of geometry changes.

@ -357,19 +357,12 @@ void PdfViewWebPlugin::UpdateAllLifecyclePhases(
blink::DocumentUpdateReason reason) {}
void PdfViewWebPlugin::Paint(cc::PaintCanvas* canvas, const gfx::Rect& rect) {
// The scale level used to convert DIPs to CSS pixels.
float inverse_scale = 1.0f / (device_scale() * viewport_to_dip_scale_);
// `rect` is in CSS pixels, and the plugin rect is in DIPs. The plugin rect
// needs to be converted into CSS pixels before calculating the rect area to
// be invalidated.
gfx::Rect plugin_rect_in_css_pixels =
gfx::ScaleToEnclosingRectSafe(plugin_rect(), inverse_scale);
// Clip the intersection of the paint rect and the plugin rect, so that
// painting outside the plugin or the paint rect area can be avoided.
// Note: `rect` is in CSS pixels. We need to use `css_plugin_rect_`
// to calculate the intersection.
SkRect invalidate_rect =
gfx::RectToSkRect(gfx::IntersectRects(plugin_rect_in_css_pixels, rect));
gfx::RectToSkRect(gfx::IntersectRects(css_plugin_rect_, rect));
cc::PaintCanvasAutoRestore auto_restore(canvas, /*save=*/true);
canvas->clipRect(invalidate_rect);
@ -382,8 +375,8 @@ void PdfViewWebPlugin::Paint(cc::PaintCanvas* canvas, const gfx::Rect& rect) {
return;
}
if (inverse_scale != 1.0f)
canvas->scale(inverse_scale, inverse_scale);
if (device_to_css_scale_ != 1.0f)
canvas->scale(device_to_css_scale_, device_to_css_scale_);
canvas->drawImage(snapshot_, plugin_rect().x(), plugin_rect().y());
}
@ -392,16 +385,7 @@ void PdfViewWebPlugin::UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
const gfx::Rect& unobscured_rect,
bool is_visible) {
float device_scale = container_wrapper_->DeviceScaleFactor();
viewport_to_dip_scale_ =
client_->IsUseZoomForDSFEnabled() ? 1.0f / device_scale : 1.0f;
// Note that `window_rect` is in viewport coordinates. It needs to be
// converted to DIPs before getting passed into
// PdfViewPluginBase::UpdateGeometryOnViewChanged().
OnViewportChanged(
gfx::ScaleToEnclosingRectSafe(window_rect, viewport_to_dip_scale_),
device_scale);
OnViewportChanged(window_rect, container_wrapper_->DeviceScaleFactor());
}
void PdfViewWebPlugin::UpdateFocus(bool focused,
@ -882,9 +866,27 @@ void PdfViewWebPlugin::UserMetricsRecordAction(const std::string& action) {
client_->RecordComputedAction(action);
}
void PdfViewWebPlugin::OnViewportChanged(const gfx::Rect& view_rect,
float new_device_scale) {
UpdateGeometryOnViewChanged(view_rect, new_device_scale);
void PdfViewWebPlugin::OnViewportChanged(
const gfx::Rect& plugin_rect_in_css_pixel,
float new_device_scale) {
css_plugin_rect_ = plugin_rect_in_css_pixel;
float css_to_device_pixel_scale;
if (client_->IsUseZoomForDSFEnabled()) {
viewport_to_dip_scale_ = 1.0f / new_device_scale;
device_to_css_scale_ = 1.0f;
css_to_device_pixel_scale = 1.0f;
} else {
viewport_to_dip_scale_ = 1.0f;
device_to_css_scale_ = 1.0f / new_device_scale;
css_to_device_pixel_scale = new_device_scale;
}
// `plugin_rect_in_css_pixel` needs to be converted to device pixels before
// getting passed into PdfViewPluginBase::UpdateGeometryOnPluginRectChanged().
UpdateGeometryOnPluginRectChanged(
gfx::ScaleToEnclosingRectSafe(plugin_rect_in_css_pixel,
css_to_device_pixel_scale),
new_device_scale);
if (IsPrintPreview() && !stop_scrolling()) {
DCHECK_EQ(new_device_scale, device_scale());

@ -286,7 +286,8 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
bool InitializeCommon(std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine);
void OnViewportChanged(const gfx::Rect& view_rect, float new_device_scale);
void OnViewportChanged(const gfx::Rect& plugin_rect_in_css_pixel,
float new_device_scale);
// Invalidates the entire web plugin container and schedules a paint of the
// page in it.
@ -343,6 +344,12 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// The viewport coordinates to DIP (device-independent pixel) ratio.
float viewport_to_dip_scale_ = 1.0f;
// The device pixel to CSS pixel ratio.
float device_to_css_scale_ = 1.0f;
// The plugin rect in CSS pixels.
gfx::Rect css_plugin_rect_;
// May be null in unit tests.
std::unique_ptr<PdfAccessibilityDataHandler> const
pdf_accessibility_data_handler_;

@ -292,7 +292,7 @@ class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
const gfx::Rect& window_rect,
const gfx::Rect& paint_rect) {
EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
.WillOnce(Return(use_zoom_for_dsf));
.WillRepeatedly(Return(use_zoom_for_dsf));
UpdatePluginGeometry(device_scale, window_rect);
canvas_.DrawColor(kDefaultColor);
@ -315,7 +315,7 @@ class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
const gfx::Rect& window_rect,
const gfx::Rect& paint_rect) {
EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
.WillOnce(Return(use_zoom_for_dsf));
.WillRepeatedly(Return(use_zoom_for_dsf));
UpdatePluginGeometry(device_scale, window_rect);
canvas_.DrawColor(kDefaultColor);
@ -397,7 +397,7 @@ TEST_F(PdfViewWebPluginTest,
static constexpr UpdateGeometryParams kUpdateGeometryParams[] = {
{1.0f, gfx::Rect(3, 4, 5, 6), gfx::Rect(3, 4, 5, 6)},
{2.0f, gfx::Rect(4, 4, 12, 12), gfx::Rect(4, 4, 12, 12)},
{2.0f, gfx::Rect(5, 6, 7, 8), gfx::Rect(4, 6, 8, 8)},
{2.0f, gfx::Rect(5, 6, 7, 8), gfx::Rect(5, 6, 7, 8)},
};
for (const auto& params : kUpdateGeometryParams) {