blob: 67f801fea167454f282004d24547b72d2947652e [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/pdf_view_plugin_base.h"
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <utility>
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/ppapi_migration/url_loader.h"
#include "ui/gfx/geometry/rect.h"
namespace chrome_pdf {
// static
constexpr double PdfViewPluginBase::kMinZoom;
PdfViewPluginBase::PdfViewPluginBase() = default;
PdfViewPluginBase::~PdfViewPluginBase() = default;
uint32_t PdfViewPluginBase::GetBackgroundColor() {
return background_color_;
}
void PdfViewPluginBase::OnPaint(const std::vector<gfx::Rect>& paint_rects,
std::vector<PaintReadyRect>* ready,
std::vector<gfx::Rect>* pending) {
base::AutoReset<bool> auto_reset_in_paint(&in_paint_, true);
DoPaint(paint_rects, ready, pending);
}
void PdfViewPluginBase::InitializeEngine(
PDFiumFormFiller::ScriptOption script_option) {
engine_ = std::make_unique<PDFiumEngine>(this, script_option);
}
void PdfViewPluginBase::DestroyEngine() {
engine_.reset();
}
void PdfViewPluginBase::LoadUrl(const std::string& url, bool is_print_preview) {
UrlRequest request;
request.url = url;
request.method = "GET";
request.ignore_redirects = true;
std::unique_ptr<UrlLoader> loader = CreateUrlLoaderInternal();
UrlLoader* raw_loader = loader.get();
raw_loader->Open(
request,
base::BindOnce(is_print_preview ? &PdfViewPluginBase::DidOpenPreview
: &PdfViewPluginBase::DidOpen,
GetWeakPtr(), std::move(loader)));
}
void PdfViewPluginBase::RecalculateAreas(double old_zoom,
float old_device_scale) {
if (zoom_ != old_zoom || device_scale_ != old_device_scale)
engine()->ZoomUpdated(zoom_ * device_scale_);
available_area_ = gfx::Rect(plugin_size_);
int doc_width = GetDocumentPixelWidth();
if (doc_width < available_area_.width()) {
// Center the document horizontally inside the plugin rectangle.
available_area_.Offset((plugin_size_.width() - doc_width) / 2, 0);
available_area_.set_width(doc_width);
}
// The distance between top of the plugin and the bottom of the document in
// pixels.
int bottom_of_document =
GetDocumentPixelHeight() +
(top_toolbar_height_in_viewport_coords() * device_scale());
if (bottom_of_document < plugin_size_.height())
available_area_.set_height(bottom_of_document);
CalculateBackgroundParts();
engine()->PageOffsetUpdated(available_area_.OffsetFromOrigin());
engine()->PluginSizeUpdated(available_area_.size());
if (document_size_.IsEmpty())
return;
paint_manager().InvalidateRect(gfx::Rect(plugin_size_));
}
void PdfViewPluginBase::CalculateBackgroundParts() {
background_parts_.clear();
int left_width = available_area_.x();
int right_start = available_area_.right();
int right_width = std::abs(plugin_size().width() - available_area_.right());
int bottom = std::min(available_area_.bottom(), plugin_size().height());
// Note: we assume the display of the PDF document is always centered
// horizontally, but not necessarily centered vertically.
// Add the left rectangle.
BackgroundPart part = {gfx::Rect(left_width, bottom), GetBackgroundColor()};
if (!part.location.IsEmpty())
background_parts_.push_back(part);
// Add the right rectangle.
part.location = gfx::Rect(right_start, 0, right_width, bottom);
if (!part.location.IsEmpty())
background_parts_.push_back(part);
// Add the bottom rectangle.
part.location = gfx::Rect(0, bottom, plugin_size().width(),
plugin_size().height() - bottom);
if (!part.location.IsEmpty())
background_parts_.push_back(part);
}
int PdfViewPluginBase::GetDocumentPixelWidth() const {
return static_cast<int>(
std::ceil(document_size_.width() * zoom() * device_scale()));
}
int PdfViewPluginBase::GetDocumentPixelHeight() const {
return static_cast<int>(
std::ceil(document_size_.height() * zoom() * device_scale()));
}
void PdfViewPluginBase::SetZoom(double scale) {
double old_zoom = zoom_;
zoom_ = scale;
OnGeometryChanged(old_zoom, device_scale_);
}
} // namespace chrome_pdf