Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3892)

Unified Diff: cc/pinch_zoom_scrollbar_layer_impl.cc

Issue 11550035: Implement pinch-zoom scaling for main-frame scrollbars and pinch-zoom overlay scrollbars. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor for cleaner state/scrollbar split. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/pinch_zoom_scrollbar_layer_impl.cc
diff --git a/cc/pinch_zoom_scrollbar_layer_impl.cc b/cc/pinch_zoom_scrollbar_layer_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dc592911e3f28884cc3d66c75e960432705cb950
--- /dev/null
+++ b/cc/pinch_zoom_scrollbar_layer_impl.cc
@@ -0,0 +1,248 @@
+// Copyright 2013 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 "cc/pinch_zoom_scrollbar_layer_impl.h"
+
+#include "cc/layer_tree_host_impl.h"
+#include "cc/layer_tree_impl.h"
+#include "cc/quad_sink.h"
+#include "cc/renderer.h"
+#include "cc/texture_draw_quad.h"
+#include "skia/ext/platform_canvas.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/rect_conversions.h"
+
+namespace cc {
+
+PinchZoomScrollbarState::PinchZoomScrollbarState(
+ WebKit::WebScrollbar::Orientation orientation, PinchZoomViewport* owner)
+ : owner_(owner),
+ orientation_(orientation) {
+ DCHECK(owner_);
+}
+
+PinchZoomScrollbarState::~PinchZoomScrollbarState() {}
+
+gfx::SizeF PinchZoomScrollbarState::layout_viewport_size() const {
+ return owner_->layout_viewport_size();
+}
+
+gfx::Vector2dF PinchZoomScrollbarState::zoomed_viewport_offset() const {
+ return owner_->zoomed_viewport_offset();
+}
+
+float PinchZoomScrollbarState::total_page_scale_factor() const {
+ return owner_->total_page_scale_factor();
+}
+
+float PinchZoomScrollbarState::device_scale_factor() const {
+ return owner_->device_scale_factor();
+}
+
+LayerImpl* PinchZoomScrollbarState::root_scroll_layer() {
+ return owner_->root_scroll_layer();
+}
+
+void PinchZoomScrollbarState::RefreshSizeAndPosition(LayerImpl* layer_impl)
+{
+ gfx::SizeF size = owner_->layout_viewport_size();
+ if (orientation_ == WebKit::WebScrollbar::Vertical) {
+ gfx::Size bounds = gfx::Size(kTrackWidth, size.height());
+ layer_impl->setContentBounds(bounds);
+ layer_impl->setBounds(bounds);
+ layer_impl->setPosition(gfx::Point(size.width() - kTrackWidth, 0));
+ } else {
+ gfx::Size bounds = gfx::Size(size.width(), kTrackWidth);
+ layer_impl->setContentBounds(bounds);
+ layer_impl->setBounds(bounds);
+ layer_impl->setPosition(gfx::Point(0, size.height() - kTrackWidth));
+ }
+}
+
+bool PinchZoomScrollbarState::ShouldDisplayPinchZoomScrollbars() {
+ return owner_->total_page_scale_factor() > 1 && owner_->currently_scrolling_layer();
+}
+
+scoped_ptr<PinchZoomScrollbarLayerImpl> PinchZoomScrollbarLayerImpl::create(
+ LayerTreeImpl* treeImpl,
+ int id,
+ PinchZoomScrollbarState* state) {
+ return make_scoped_ptr(new PinchZoomScrollbarLayerImpl(treeImpl, id, state));
+}
+
+PinchZoomScrollbarLayerImpl::PinchZoomScrollbarLayerImpl(
+ LayerTreeImpl* treeImpl,
+ int id, PinchZoomScrollbarState* state)
+ : ScrollbarLayerImplBase(treeImpl, id),
+ state_(state) {
+ DCHECK(state_);
+ std::string debugName = "Layer for Pinch Zoom Scrollbar ";
+ debugName += ((state_->orientation() == WebKit::WebScrollbar::Vertical) ?
+ "(vertical)" : "(horizontal)");
+ setDebugName(debugName);
+
+ state_->RefreshSizeAndPosition(this);
+}
+
+PinchZoomScrollbarLayerImpl::~PinchZoomScrollbarLayerImpl() {}
+
+float PinchZoomScrollbarLayerImpl::currentPos() const {
+ return state_->thumb_position();
+}
+
+int PinchZoomScrollbarLayerImpl::totalSize() const {
+ return state_->track_length();
+}
+
+int PinchZoomScrollbarLayerImpl::maximum() const {
+ return state_->maximum_position();
+}
+
+WebKit::WebScrollbar::Orientation PinchZoomScrollbarLayerImpl::orientation()
+ const {
+ return state_->orientation();
+}
+
+void PinchZoomScrollbarLayerImpl::appendQuads(
+ QuadSink& quad_sink, AppendQuadsData& append_quads_data) {
+ if (!state_->ShouldDisplayPinchZoomScrollbars())
+ return;
+
+ if (state_->thumb_rect().IsEmpty() || !state_->thumb_texture()->id())
+ return;
+
+ bool premultipled_alpha = false;
+ bool flipped = false;
+ gfx::RectF uv_rect(0, 0, 1, 1);
+
+ SharedQuadState* shared_quad_state =
+ quad_sink.useSharedQuadState(createSharedQuadState());
+ appendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
+
+ gfx::Rect quad_rect(gfx::ToEnclosingRect(
+ gfx::ScaleRect(state_->thumb_rect(),
+ contentsScaleX(), contentsScaleY())));
+
+ gfx::Rect opaque_rect;
+ const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
+ quad->SetNew(shared_quad_state, quad_rect, opaque_rect,
+ state_->thumb_texture()->id(),
+ premultipled_alpha, uv_rect, opacity, flipped);
+ quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data);
+}
+
+void PinchZoomScrollbarLayerImpl::willDraw(
+ ResourceProvider* resource_provider) {
+ LayerImpl::willDraw(resource_provider);
+
+ if (!state_->ShouldDisplayPinchZoomScrollbars())
+ return;
+
+ gfx::Size layout_document_size(layerTreeImpl()->ContentSize());
+
+ gfx::SizeF layout_viewport_size = state_->layout_viewport_size();
+ gfx::Vector2dF layout_viewport_position = state_->zoomed_viewport_offset();
+ float page_scale_factor = state_->total_page_scale_factor();
+ float device_scale_factor = state_->device_scale_factor();
+
+ DCHECK(!layout_document_size.IsEmpty());
+
+ gfx::Vector2d root_scroll_offset;
+ gfx::Vector2d root_max_scroll_offset;
+ LayerImpl* root_scroll_layer = state_->root_scroll_layer();
+ if (root_scroll_layer) {
+ root_scroll_offset = root_scroll_layer->scrollOffset();
+ root_max_scroll_offset = root_scroll_layer->maxScrollOffset();
+ }
+
+ gfx::Rect new_thumb_rect;
+ int& track_length = state_->track_length();
+ float& thumb_position = state_->thumb_position();
+ int& maximum_position = state_->maximum_position();
+ int track_width = state_->track_width();
+
+ int thumb_length;
+ if (state_->orientation() == WebKit::WebScrollbar::Vertical) {
+ track_length = layout_viewport_size.height() - track_width;
+ thumb_length = layout_viewport_size.height() /
+ layout_document_size.height() * device_scale_factor * track_length;
+ maximum_position = state_->track_length() - thumb_length;
+
+ float max_offset = root_max_scroll_offset.y() + (page_scale_factor - 1)
+ / page_scale_factor * layout_viewport_size.height();
+ float offset = (max_offset >= 1) ? root_scroll_offset.y() +
+ layout_viewport_position.y() : 0;
+ thumb_position = offset / max_offset * maximum_position;
+
+ // Thumb rect position is with respect to the layer, so the x-coordinate
+ // should be 0.
+ new_thumb_rect = gfx::Rect(0, thumb_position, track_width, thumb_length);
+ } else {
+ track_length = layout_viewport_size.width() - track_width;
+ thumb_length = layout_viewport_size.width() / layout_document_size.width() *
+ device_scale_factor * track_length;
+ maximum_position = track_length - thumb_length;
+
+ float max_offset = root_max_scroll_offset.x() + (page_scale_factor - 1)
+ / page_scale_factor * layout_viewport_size.width();
+ float offset = (max_offset >= 1) ? root_scroll_offset.x() +
+ layout_viewport_position.x() : 0;
+ thumb_position = offset / max_offset * maximum_position;
+
+ // Thumb rect position is with respect to the layer, so the y-coordinate
+ // should be 0.
+ new_thumb_rect = gfx::Rect(thumb_position, 0, thumb_length, track_width);
+ }
+
+ gfx::Rect& thumb_rect = state_->thumb_rect();
+ scoped_ptr<ScopedResource>& thumb_texture = state_->thumb_texture();
+
+ bool thumb_size_not_changed = thumb_rect.size() == new_thumb_rect.size();
+ thumb_rect = new_thumb_rect;
+ if (thumb_size_not_changed && thumb_texture)
+ return;
+
+ // Does texture exist, if not, create it.
+ if (!thumb_texture)
+ thumb_texture = ScopedResource::create(resource_provider);
+
+ if (thumb_texture->size() != thumb_rect.size())
+ thumb_texture->Free();
+
+ if (!thumb_texture->id())
+ thumb_texture->Allocate(thumb_rect.size(), GL_RGBA,
+ ResourceProvider::TextureUsageAny);
+
+ // Paint canvas and upload to texture.
+ scoped_ptr<SkCanvas> canvas = make_scoped_ptr(
+ skia::CreateBitmapCanvas(thumb_rect.width(), thumb_rect.height(),
+ false /* opaque */));
+ canvas->clear(SkColorSetARGB(0, 0, 0, 0));
+ SkPaint paint;
+ // Below 255 refers to blue, not red, but we do this to avoid an
+ // explicit swizzle.
+ paint.setColor(SkColorSetARGB(128, 255, 0, 0));
+ SkScalar border = device_scale_factor;
+ SkScalar corner_radius = device_scale_factor * (track_width / 3);
+ DCHECK(corner_radius);
+ SkRect rect = SkRect::MakeXYWH(border, border,
+ thumb_rect.width() - 2 * border,
+ thumb_rect.height() - 2 * border);
+ canvas->drawRoundRect(rect, corner_radius, corner_radius, paint);
+
+ const SkBitmap* bitmap = &canvas->getDevice()->accessBitmap(false);
+ SkAutoLockPixels locker(*bitmap);
+ gfx::Rect layer_rect(gfx::Point(), thumb_rect.size());
+ DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
+ resource_provider->setPixels(thumb_texture->id(), static_cast<const uint8_t*>(
+ bitmap->getPixels()), layer_rect, layer_rect,
+ gfx::Vector2d());
+}
+
+void PinchZoomScrollbarLayerImpl::didLoseOutputSurface() {
+ state_->thumb_texture().reset(0);;
+}
+
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698