diff options
author | raymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-26 05:45:27 +0000 |
---|---|---|
committer | raymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-26 05:45:27 +0000 |
commit | 499e956b97a13c20ae6e820f78bb21a0b42ce243 (patch) | |
tree | 691ff62cddc190694978becb8509f651a5b6a881 /pdf | |
parent | c0da00f011c226d181fbccef23db34dab607e4c2 (diff) | |
download | chromium_src-499e956b97a13c20ae6e820f78bb21a0b42ce243.zip chromium_src-499e956b97a13c20ae6e820f78bb21a0b42ce243.tar.gz chromium_src-499e956b97a13c20ae6e820f78bb21a0b42ce243.tar.bz2 |
Improve scrolling performance in OOP PDF
This increases the performance of scrolling in OOP PDF by not sending viewport
changes via postMessage every time a scroll event occurs on the page. Instead,
scroll events are sent along with pepper DidChangeView messages, which is a
much more responsive way of updating the scroll position.
Unfortunately this introduces some issues coordinating zoom and scroll events
on the page. When a zoom happens in the container page, a scroll message
might be sent to the plugin via DidChangeView. Then we send a zoom change
message via postMessage. The result is that the zooming and scrolling
happen asynchronously and result in a flickering effect.
To avoid this, we first notify the plugin that we are about to zoom which
causes it to stop reacting to scroll messages. After we have finished zooming
we notify the plugin again so that it can continue reacting to scroll messages.
BUG=386920
Review URL: https://codereview.chromium.org/347763007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279910 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/out_of_process_instance.cc | 83 | ||||
-rw-r--r-- | pdf/out_of_process_instance.h | 13 |
2 files changed, 59 insertions, 37 deletions
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index 9e77ec6..4d1bb8f 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc @@ -34,6 +34,7 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/point.h" #include "ppapi/cpp/private/pdf.h" +#include "ppapi/cpp/private/var_private.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/resource.h" #include "ppapi/cpp/url_request_info.h" @@ -70,6 +71,8 @@ const char* kJSViewportType = "viewport"; const char* kJSXOffset = "xOffset"; const char* kJSYOffset = "yOffset"; const char* kJSZoom = "zoom"; +// Stop scrolling message (Page -> Plugin) +const char* kJSStopScrollingType = "stopScrolling"; // Document dimension arguments (Plugin -> Page). const char* kJSDocumentDimensionsType = "documentDimensions"; const char* kJSDocumentWidth = "width"; @@ -244,7 +247,8 @@ OutOfProcessInstance::OutOfProcessInstance(PP_Instance instance) last_progress_sent_(0), recently_sent_find_update_(false), received_viewport_message_(false), - did_call_start_loading_(false) { + did_call_start_loading_(false), + stop_scrolling_(false) { loader_factory_.Initialize(this); timer_factory_.Initialize(this); form_factory_.Initialize(this); @@ -355,20 +359,17 @@ void OutOfProcessInstance::HandleMessage(const pp::Var& message) { dict.Get(pp::Var(kJSYOffset)).is_int() && dict.Get(pp::Var(kJSZoom)).is_number()) { received_viewport_message_ = true; + stop_scrolling_ = false; double zoom = dict.Get(pp::Var(kJSZoom)).AsDouble(); - int x = dict.Get(pp::Var(kJSXOffset)).AsInt(); - int y = dict.Get(pp::Var(kJSYOffset)).AsInt(); + pp::Point scroll_offset(dict.Get(pp::Var(kJSXOffset)).AsInt(), + dict.Get(pp::Var(kJSYOffset)).AsInt()); // Bound the input parameters. zoom = std::max(kMinZoom, zoom); - int max_x = document_size_.width() * zoom - plugin_dip_size_.width(); - x = std::max(std::min(x, max_x), 0); - int max_y = document_size_.height() * zoom - plugin_dip_size_.height(); - y = std::max(std::min(y, max_y), 0); - SetZoom(zoom); - engine_->ScrolledToXPosition(x * device_scale_); - engine_->ScrolledToYPosition(y * device_scale_); + scroll_offset = BoundScrollOffsetToDocument(scroll_offset); + engine_->ScrolledToXPosition(scroll_offset.x() * device_scale_); + engine_->ScrolledToYPosition(scroll_offset.y() * device_scale_); } else if (type == kJSGetPasswordCompleteType && dict.Get(pp::Var(kJSPassword)).is_string()) { if (password_callback_) { @@ -425,6 +426,8 @@ void OutOfProcessInstance::HandleMessage(const pp::Var& message) { reply.Set(pp::Var(kJSAccessibilityJSON), pp::Var(json)); } PostMessage(reply); + } else if (type == kJSStopScrollingType) { + stop_scrolling_ = true; } else { NOTREACHED(); } @@ -507,32 +510,38 @@ void OutOfProcessInstance::DidChangeView(const pp::View& view) { pp::Size view_device_size(view_rect.width() * device_scale, view_rect.height() * device_scale); - if (view_device_size == plugin_size_ && device_scale == device_scale_) - return; // We don't care about the position, only the size. - - device_scale_ = device_scale; - plugin_dip_size_ = view_rect.size(); - plugin_size_ = view_device_size; + if (view_device_size != plugin_size_ || device_scale != device_scale_) { + device_scale_ = device_scale; + plugin_dip_size_ = view_rect.size(); + plugin_size_ = view_device_size; + + paint_manager_.SetSize(view_device_size, device_scale_); + + pp::Size new_image_data_size = PaintManager::GetNewContextSize( + image_data_.size(), + plugin_size_); + if (new_image_data_size != image_data_.size()) { + image_data_ = pp::ImageData(this, + PP_IMAGEDATAFORMAT_BGRA_PREMUL, + new_image_data_size, + false); + first_paint_ = true; + } - paint_manager_.SetSize(view_device_size, device_scale_); + if (image_data_.is_null()) { + DCHECK(plugin_size_.IsEmpty()); + return; + } - pp::Size new_image_data_size = PaintManager::GetNewContextSize( - image_data_.size(), - plugin_size_); - if (new_image_data_size != image_data_.size()) { - image_data_ = pp::ImageData(this, - PP_IMAGEDATAFORMAT_BGRA_PREMUL, - new_image_data_size, - false); - first_paint_ = true; + OnGeometryChanged(zoom_, old_device_scale); } - if (image_data_.is_null()) { - DCHECK(plugin_size_.IsEmpty()); - return; + if (!stop_scrolling_) { + pp::Point scroll_offset( + BoundScrollOffsetToDocument(view.GetScrollOffset())); + engine_->ScrolledToXPosition(scroll_offset.x() * device_scale_); + engine_->ScrolledToYPosition(scroll_offset.y() * device_scale_); } - - OnGeometryChanged(zoom_, old_device_scale); } pp::Var OutOfProcessInstance::GetLinkAtPosition( @@ -786,7 +795,8 @@ void OutOfProcessInstance::Invalidate(const pp::Rect& rect) { } void OutOfProcessInstance::Scroll(const pp::Point& point) { - paint_manager_.ScrollRect(available_area_, point); + if (!image_data_.is_null()) + paint_manager_.ScrollRect(available_area_, point); } void OutOfProcessInstance::ScrollToX(int x) { @@ -1404,4 +1414,13 @@ void OutOfProcessInstance::UserMetricsRecordAction( pp::PDF::UserMetricsRecordAction(this, pp::Var(action)); } +pp::Point OutOfProcessInstance::BoundScrollOffsetToDocument( + const pp::Point& scroll_offset) { + int max_x = document_size_.width() * zoom_ - plugin_dip_size_.width(); + int x = std::max(std::min(scroll_offset.x(), max_x), 0); + int max_y = document_size_.height() * zoom_ - plugin_dip_size_.height(); + int y = std::max(std::min(scroll_offset.y(), max_y), 0); + return pp::Point(x, y); +} + } // namespace chrome_pdf diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index bd70be2..f1f8862 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h @@ -26,7 +26,6 @@ #include "ppapi/cpp/instance.h" #include "ppapi/cpp/private/find_private.h" #include "ppapi/cpp/private/uma_private.h" -#include "ppapi/cpp/private/var_private.h" #include "ppapi/cpp/url_loader.h" #include "ppapi/utility/completion_callback_factory.h" @@ -205,6 +204,9 @@ class OutOfProcessInstance : public pp::Instance, // Load the next available preview page into the blank page. void LoadAvailablePreviewPage(); + // Bound the given scroll offset to the document. + pp::Point BoundScrollOffsetToDocument(const pp::Point& scroll_offset); + pp::ImageData image_data_; // Used when the plugin is embedded in a page and we have to create the loader // ourself. @@ -284,10 +286,6 @@ class OutOfProcessInstance : public pp::Instance, DocumentLoadState document_load_state_; DocumentLoadState preview_document_load_state_; - // JavaScript interface to control this instance. - // This wraps a PDFScriptableObject in a pp::Var. - pp::VarPrivate instance_object_; - // A UMA resource for histogram reporting. pp::UMAPrivate uma_; @@ -333,6 +331,11 @@ class OutOfProcessInstance : public pp::Instance, // document finishes loading. bool did_call_start_loading_; + // If this is true, then don't scroll the plugin in response to DidChangeView + // messages. This will be true when the extension page is in the process of + // zooming the plugin so that flickering doesn't occur while zooming. + bool stop_scrolling_; + // The callback for receiving the password from the page. scoped_ptr<pp::CompletionCallbackWithOutput<pp::Var> > password_callback_; }; |