diff options
author | leandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-06 23:15:21 +0000 |
---|---|---|
committer | leandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-06 23:15:21 +0000 |
commit | 5a18337b03c700f0a7c3b1efb92d0616b66e6c78 (patch) | |
tree | 43689158fb8501d26bf80ce39191f5faa6b20b34 | |
parent | fde91bd820596f19b5fac0b453c735988dd678e3 (diff) | |
download | chromium_src-5a18337b03c700f0a7c3b1efb92d0616b66e6c78.zip chromium_src-5a18337b03c700f0a7c3b1efb92d0616b66e6c78.tar.gz chromium_src-5a18337b03c700f0a7c3b1efb92d0616b66e6c78.tar.bz2 |
Fix page scaling in Android Webview SW rendering.
BUG=
Review URL: https://chromiumcodereview.appspot.com/12310136
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186532 0039d316-1c4b-4281-b951-d872f2087c98
7 files changed, 139 insertions, 61 deletions
diff --git a/android_webview/browser/browser_view_renderer_impl.cc b/android_webview/browser/browser_view_renderer_impl.cc index cc3cd8f..ef1f9d1 100644 --- a/android_webview/browser/browser_view_renderer_impl.cc +++ b/android_webview/browser/browser_view_renderer_impl.cc @@ -21,8 +21,9 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkGraphics.h" -#include "ui/gfx/size.h" +#include "ui/gfx/size_conversions.h" #include "ui/gfx/transform.h" +#include "ui/gfx/vector2d_f.h" #include "ui/gl/gl_bindings.h" // TODO(leandrogracia): remove when crbug.com/164140 is closed. @@ -115,6 +116,7 @@ BrowserViewRendererImpl::BrowserViewRendererImpl( JavaHelper* java_helper) : client_(client), java_helper_(java_helper), + view_renderer_host_(new ViewRendererHost(NULL, this)), ALLOW_THIS_IN_INITIALIZER_LIST(compositor_(Compositor::Create(this))), view_clip_layer_(cc::Layer::create()), transform_layer_(cc::Layer::create()), @@ -123,9 +125,14 @@ BrowserViewRendererImpl::BrowserViewRendererImpl( compositor_visible_(false), is_composite_pending_(false), dpi_scale_(1.0f), + page_scale_(1.0f), on_new_picture_mode_(kOnNewPictureDisabled), last_frame_context_(NULL), - web_contents_(NULL) { + web_contents_(NULL), + update_frame_info_callback_( + base::Bind(&BrowserViewRendererImpl::OnFrameInfoUpdated, + base::Unretained(ALLOW_THIS_IN_INITIALIZER_LIST(this)))) { + DCHECK(java_helper); // Define the view hierarchy. @@ -137,6 +144,7 @@ BrowserViewRendererImpl::BrowserViewRendererImpl( } BrowserViewRendererImpl::~BrowserViewRendererImpl() { + SetContents(NULL); } // static @@ -150,12 +158,24 @@ void BrowserViewRendererImpl::SetAwDrawSWFunctionTable( } void BrowserViewRendererImpl::SetContents(ContentViewCore* content_view_core) { + if (web_contents_) { + ContentViewCore* previous_content_view_core = + ContentViewCore::FromWebContents(web_contents_); + if (previous_content_view_core) { + previous_content_view_core->RemoveFrameInfoCallback( + update_frame_info_callback_); + } + } + + web_contents_ = content_view_core ? + content_view_core->GetWebContents() : NULL; + view_renderer_host_->Observe(web_contents_); + + if (!content_view_core) + return; + + content_view_core->AddFrameInfoCallback(update_frame_info_callback_); dpi_scale_ = content_view_core->GetDpiScale(); - web_contents_ = content_view_core->GetWebContents(); - if (!view_renderer_host_) - view_renderer_host_.reset(new ViewRendererHost(web_contents_, this)); - else - view_renderer_host_->Observe(web_contents_); view_clip_layer_->removeAllChildren(); view_clip_layer_->addChild(content_view_core->GetLayer()); @@ -532,7 +552,6 @@ skia::RefPtr<SkPicture> BrowserViewRendererImpl::GetLastCapturedPicture() { // If not available or not in listener mode get it synchronously. if (!picture) { - DCHECK(view_renderer_host_); view_renderer_host_->CapturePictureSync(); picture = RendererPictureMap::GetInstance()->GetRendererPicture( web_contents_->GetRoutingID()); @@ -580,10 +599,20 @@ void BrowserViewRendererImpl::Invalidate() { } bool BrowserViewRendererImpl::RenderSW(SkCanvas* canvas) { - // TODO(leandrogracia): once Ubercompositor is ready and we support software - // rendering mode, we should avoid this as much as we can, ideally always. - // This includes finding a proper replacement for onDraw calls in hardware - // mode with software canvases. http://crbug.com/170086. + float content_scale = dpi_scale_ * page_scale_; + canvas->scale(content_scale, content_scale); + + // Clear to white any parts of the view not covered by the scaled contents. + // TODO(leandrogracia): this should be automatically done by the SW rendering + // path once multiple layers are supported. + gfx::Size physical_content_size = gfx::ToCeiledSize( + gfx::ScaleSize(content_size_css_, content_scale)); + if (physical_content_size.width() < view_size_.width() || + physical_content_size.height() < view_size_.height()) + canvas->clear(SK_ColorWHITE); + + // TODO(leandrogracia): use the appropriate SW rendering path when available + // instead of abusing CapturePicture. return RenderPicture(canvas); } @@ -592,11 +621,16 @@ bool BrowserViewRendererImpl::RenderPicture(SkCanvas* canvas) { if (!picture) return false; - // Correct device scale. - canvas->scale(dpi_scale_, dpi_scale_); - picture->draw(canvas); return true; } +void BrowserViewRendererImpl::OnFrameInfoUpdated( + const gfx::SizeF& content_size, + const gfx::Vector2dF& scroll_offset, + float page_scale_factor) { + page_scale_ = page_scale_factor; + content_size_css_ = content_size; +} + } // namespace android_webview diff --git a/android_webview/browser/browser_view_renderer_impl.h b/android_webview/browser/browser_view_renderer_impl.h index 323ddcb..050645d 100644 --- a/android_webview/browser/browser_view_renderer_impl.h +++ b/android_webview/browser/browser_view_renderer_impl.h @@ -8,10 +8,12 @@ #include "android_webview/browser/browser_view_renderer.h" #include "android_webview/browser/renderer_host/view_renderer_host.h" #include "content/public/browser/android/compositor.h" +#include "content/public/browser/android/content_view_core.h" #include "content/public/browser/web_contents_observer.h" #include "skia/ext/refptr.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" +#include "ui/gfx/size_f.h" typedef void* EGLContext; struct AwDrawSWFunctionTable; @@ -23,6 +25,10 @@ namespace content { class WebContents; } +namespace gfx { +class Vector2dF; +} + namespace android_webview { class BrowserViewRendererImpl @@ -38,6 +44,7 @@ class BrowserViewRendererImpl static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table); // BrowserViewRenderer implementation. + // |content_view_core| must not outlive |this| BrowserViewRenderer instance. virtual void SetContents( content::ContentViewCore* content_view_core) OVERRIDE; virtual void DrawGL(AwDrawGLInfo* draw_info) OVERRIDE; @@ -74,6 +81,10 @@ class BrowserViewRendererImpl bool RenderSW(SkCanvas* canvas); bool RenderPicture(SkCanvas* canvas); + void OnFrameInfoUpdated(const gfx::SizeF& content_size, + const gfx::Vector2dF& scroll_offset, + float page_scale_factor); + BrowserViewRenderer::Client* client_; BrowserViewRenderer::JavaHelper* java_helper_; @@ -97,7 +108,9 @@ class BrowserViewRendererImpl bool compositor_visible_; bool is_composite_pending_; float dpi_scale_; + float page_scale_; gfx::Size view_size_; + gfx::SizeF content_size_css_; OnNewPictureMode on_new_picture_mode_; // Used only for detecting Android View System context changes. @@ -107,6 +120,9 @@ class BrowserViewRendererImpl // Set via SetContents. Used to recognize updates to the local WebView. content::WebContents* web_contents_; + // Used to observe frame metadata updates. + content::ContentViewCore::UpdateFrameInfoCallback update_frame_info_callback_; + DISALLOW_COPY_AND_ASSIGN(BrowserViewRendererImpl); }; diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 0ae2b94..c882c2d 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -392,36 +392,36 @@ void ContentViewCoreImpl::OnTabCrashed() { // Note that viewport_width/height is a best effort based. // ContentViewCore has the actual information about the physical viewport size. void ContentViewCoreImpl::UpdateFrameInfo( - float scroll_offset_x, float scroll_offset_y, + const gfx::Vector2dF& scroll_offset, float page_scale_factor, - float min_page_scale_factor, float max_page_scale_factor, - float content_width, float content_height, - float viewport_width, float viewport_height) { + const gfx::Vector2dF& page_scale_factor_limits, + const gfx::SizeF& content_size, + const gfx::SizeF& viewport_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); if (obj.is_null()) return; + Java_ContentViewCore_updateFrameInfo( env, obj.obj(), - scroll_offset_x, - scroll_offset_y, + scroll_offset.x(), + scroll_offset.y(), page_scale_factor, - min_page_scale_factor, max_page_scale_factor, - content_width, - content_height, - viewport_width, - viewport_height); -} - -void ContentViewCoreImpl::UpdateOffsetsForFullscreen(float controls_offset_y, - float content_offset_y) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (obj.is_null()) - return; - Java_ContentViewCore_updateOffsetsForFullscreen(env, obj.obj(), - controls_offset_y, - content_offset_y); + page_scale_factor_limits.x(), + page_scale_factor_limits.y(), + content_size.width(), + content_size.height(), + viewport_size.width(), + viewport_size.height(), + controls_offset.y(), + content_offset.y()); + + for (size_t i = 0; i < update_frame_info_callbacks_.size(); ++i) { + update_frame_info_callbacks_[i].Run( + content_size, scroll_offset, page_scale_factor); + } } void ContentViewCoreImpl::SetTitle(const string16& title) { @@ -563,6 +563,22 @@ unsigned int ContentViewCoreImpl::GetScaledContentTexture( return view->GetScaledContentTexture(scale, out_size); } +void ContentViewCoreImpl::AddFrameInfoCallback( + const UpdateFrameInfoCallback& callback) { + update_frame_info_callbacks_.push_back(callback); +} + +void ContentViewCoreImpl::RemoveFrameInfoCallback( + const UpdateFrameInfoCallback& callback) { + for (size_t i = 0; i < update_frame_info_callbacks_.size(); ++i) { + if (update_frame_info_callbacks_[i].Equals(callback)) { + update_frame_info_callbacks_.erase( + update_frame_info_callbacks_.begin() + i); + return; + } + } +} + void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index eacf25f..34550d5 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -58,6 +58,10 @@ class ContentViewCoreImpl : public ContentViewCore, float scale, gfx::Size* out_size) OVERRIDE; virtual float GetDpiScale() const OVERRIDE; + virtual void AddFrameInfoCallback( + const UpdateFrameInfoCallback& callback) OVERRIDE; + virtual void RemoveFrameInfoCallback( + const UpdateFrameInfoCallback& callback) OVERRIDE; // -------------------------------------------------------------------------- // Methods called from Java via JNI @@ -219,15 +223,13 @@ class ContentViewCoreImpl : public ContentViewCore, void OnTabCrashed(); // All sizes and offsets are in CSS pixels as cached by the renderer. - void UpdateFrameInfo( - float scroll_offset_x, float scroll_offset_y, - float page_scale_factor, - float min_page_scale_factor, float max_page_scale_factor, - float content_width, float content_height, - float viewport_width, float viewport_height); - - void UpdateOffsetsForFullscreen(float controls_offset_y, - float content_offset_y); + void UpdateFrameInfo(const gfx::Vector2dF& scroll_offset, + float page_scale_factor, + const gfx::Vector2dF& page_scale_factor_limits, + const gfx::SizeF& content_size, + const gfx::SizeF& viewport_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset); void UpdateImeAdapter(int native_ime_adapter, int text_input_type, const std::string& text, @@ -324,11 +326,14 @@ class ContentViewCoreImpl : public ContentViewCore, // browser compositor. bool renderer_frame_pending_; + // Device scale factor. float dpi_scale_; // The owning window that has a hold of main application activity. ui::WindowAndroid* window_android_; + std::vector<UpdateFrameInfoCallback> update_frame_info_callbacks_; + DISALLOW_COPY_AND_ASSIGN(ContentViewCoreImpl); }; diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index bb95339..8b08ad3 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -695,13 +695,8 @@ void RenderWidgetHostViewAndroid::UpdateFrameInfo( if (content_view_core_) { // All offsets and sizes are in CSS pixels. content_view_core_->UpdateFrameInfo( - scroll_offset.x(), scroll_offset.y(), - page_scale_factor, - page_scale_factor_limits.x(), page_scale_factor_limits.y(), - content_size.width(), content_size.height(), - viewport_size.width(), viewport_size.height()); - content_view_core_->UpdateOffsetsForFullscreen(controls_offset.y(), - content_offset.y()); + scroll_offset, page_scale_factor, page_scale_factor_limits, + content_size, viewport_size, controls_offset, content_offset); } } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index f7d3c4b..92b2474 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -1914,7 +1914,8 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { float scrollOffsetX, float scrollOffsetY, float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor, float contentWidth, float contentHeight, - float viewportWidth, float viewportHeight) { + float viewportWidth, float viewportHeight, + float controlsOffsetYCss, float contentOffsetYCss) { // Adjust contentWidth/Height to be always at least as big as // the actual viewport (as set by onSizeChanged). @@ -1976,14 +1977,11 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { if (needTemporarilyHideHandles) temporarilyHideTextHandles(); if (needUpdateZoomControls) mZoomManager.updateZoomControls(); - } - @SuppressWarnings("unused") - @CalledByNative - private void updateOffsetsForFullscreen(float controlsOffsetYCss, float contentOffsetYCss) { - final float scale = mRenderCoordinates.getDeviceScaleFactor(); - final float controlsOffsetPix = controlsOffsetYCss * scale; - final float contentOffsetYPix = contentOffsetYCss * scale; + // Update offsets for fullscreen. + final float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); + final float controlsOffsetPix = controlsOffsetYCss * deviceScale; + final float contentOffsetYPix = contentOffsetYCss * deviceScale; getContentViewClient().onOffsetsForFullscreenChanged(controlsOffsetPix, contentOffsetYPix); } diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h index cf5f7b1..52d3f9c 100644 --- a/content/public/browser/android/content_view_core.h +++ b/content/public/browser/android/content_view_core.h @@ -8,6 +8,7 @@ #include <jni.h> #include "base/android/scoped_java_ref.h" +#include "base/callback.h" #include "content/common/content_export.h" #include "content/public/browser/navigation_controller.h" @@ -17,6 +18,8 @@ class Layer; namespace gfx { class Size; +class SizeF; +class Vector2dF; } namespace ui { @@ -50,6 +53,17 @@ class CONTENT_EXPORT ContentViewCore { gfx::Size* out_size) = 0; virtual float GetDpiScale() const = 0; + // Observer callback for frame metadata updates. + typedef base::Callback<void( + const gfx::SizeF& content_size, + const gfx::Vector2dF& scroll_offset, + float page_scale_factor)> UpdateFrameInfoCallback; + + virtual void AddFrameInfoCallback( + const UpdateFrameInfoCallback& callback) = 0; + virtual void RemoveFrameInfoCallback( + const UpdateFrameInfoCallback& callback) = 0; + protected: virtual ~ContentViewCore() {}; }; |